[nautilus] progress-info: split UI of NautilusProgressInfo into its own object



commit b9fe2ecb4894895e063c4cbda5f62b7ad54b7449
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Wed Feb 2 21:52:27 2011 -0500

    progress-info: split UI of NautilusProgressInfo into its own object

 libnautilus-private/nautilus-progress-info.c |  290 --------------------------
 src/Makefile.am                              |    2 +
 src/nautilus-progress-info-widget.c          |  237 +++++++++++++++++++++
 src/nautilus-progress-info-widget.h          |   63 ++++++
 src/nautilus-progress-ui-handler.c           |  135 ++++++++++++
 5 files changed, 437 insertions(+), 290 deletions(-)
---
diff --git a/libnautilus-private/nautilus-progress-info.c b/libnautilus-private/nautilus-progress-info.c
index 906b653..b66e8b1 100644
--- a/libnautilus-private/nautilus-progress-info.c
+++ b/libnautilus-private/nautilus-progress-info.c
@@ -25,7 +25,6 @@
 #include <config.h>
 #include <math.h>
 #include <glib/gi18n.h>
-#include <gtk/gtk.h>
 #include <eel/eel-string.h>
 #include <eel/eel-glib-extensions.h>
 #include "nautilus-progress-info.h"
@@ -40,11 +39,6 @@ enum {
   LAST_SIGNAL
 };
 
-/* TODO:
- * Want an icon for the operation.
- * Add and implement cancel button
- */
-
 #define SIGNAL_DELAY_MSEC 100
 
 static guint signals[LAST_SIGNAL] = { 0 };
@@ -77,10 +71,6 @@ struct _NautilusProgressInfoClass
 	GObjectClass parent_class;
 };
 
-static GtkStatusIcon *status_icon = NULL;
-static int n_progress_ops = 0;
-
-
 G_LOCK_DEFINE_STATIC(progress_info);
 
 G_DEFINE_TYPE (NautilusProgressInfo, nautilus_progress_info, G_TYPE_OBJECT)
@@ -167,284 +157,6 @@ nautilus_progress_info_class_init (NautilusProgressInfoClass *klass)
 	
 }
 
-static gboolean
-delete_event (GtkWidget *widget,
-	      GdkEventAny *event)
-{
-	gtk_widget_hide (widget);
-	return TRUE;
-}
-
-static void
-status_icon_activate_cb (GtkStatusIcon *icon,
-			 GtkWidget *progress_window)
-{
-	if (gtk_widget_get_visible (progress_window)) {
-		gtk_widget_hide (progress_window);
-	} else {
-		gtk_window_present (GTK_WINDOW (progress_window));
-	}
-}
-
-static GtkWidget *
-get_progress_window (void)
-{
-	static GtkWidget *progress_window = NULL;
-	GtkWidget *vbox;
-	GIcon *icon;
-	
-	if (progress_window != NULL) {
-		return progress_window;
-	}
-	
-	progress_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-	gtk_window_set_resizable (GTK_WINDOW (progress_window),
-				  FALSE);
-	gtk_container_set_border_width (GTK_CONTAINER (progress_window), 10);
- 
-	gtk_window_set_title (GTK_WINDOW (progress_window),
-			      _("File Operations"));
-	gtk_window_set_wmclass (GTK_WINDOW (progress_window),
-				"file_progress", "Nautilus");
-	gtk_window_set_position (GTK_WINDOW (progress_window),
-				 GTK_WIN_POS_CENTER);
-	gtk_window_set_icon_name (GTK_WINDOW (progress_window),
-				"system-file-manager");
-
-	vbox = gtk_vbox_new (FALSE, 0);
-	gtk_box_set_spacing (GTK_BOX (vbox), 5);
-		
-	gtk_container_add (GTK_CONTAINER (progress_window),
-			   vbox);
-
-	gtk_widget_show_all (progress_window);
-
-	g_signal_connect (progress_window,
-			  "delete_event",
-			  (GCallback)delete_event, NULL);
-
-	icon = g_themed_icon_new_with_default_fallbacks ("system-file-manager-symbolic");
-	status_icon = gtk_status_icon_new_from_gicon (icon);
-	g_signal_connect (status_icon, "activate",
-			  (GCallback)status_icon_activate_cb,
-			  progress_window);
-
-	gtk_status_icon_set_visible (status_icon, FALSE);
-	g_object_unref (icon);
-
-	return progress_window;
-}
-
-
-typedef struct {
-	GtkWidget *widget;
-	NautilusProgressInfo *info;
-	GtkLabel *status;
-	GtkLabel *details;
-	GtkProgressBar *progress_bar;
-} ProgressWidgetData;
-
-static void
-progress_widget_data_free (ProgressWidgetData *data)
-{
-	g_object_unref (data->info);
-	g_free (data);
-}
-
-static void
-update_data (ProgressWidgetData *data)
-{
-	char *status, *details;
-	char *markup;
-
-	status = nautilus_progress_info_get_status (data->info);
-	gtk_label_set_text (data->status, status);
-	g_free (status);
-
-	details = nautilus_progress_info_get_details (data->info);
-	markup = g_markup_printf_escaped ("<span size='small'>%s</span>", details);
-	gtk_label_set_markup (data->details, markup);
-	g_free (details);
-	g_free (markup);
-}
-
-static void
-update_progress (ProgressWidgetData *data)
-{
-	double progress;
-
-	progress = nautilus_progress_info_get_progress (data->info);
-	if (progress < 0) {
-		gtk_progress_bar_pulse (data->progress_bar);
-	} else {
-		gtk_progress_bar_set_fraction (data->progress_bar, progress);
-	}
-}
-
-static void
-update_status_icon_and_window (void)
-{
-	char *tooltip;
-
-	tooltip = g_strdup_printf (ngettext ("%'d file operation active",
-					     "%'d file operations active",
-					     n_progress_ops),
-				   n_progress_ops);
-	gtk_status_icon_set_tooltip_text (status_icon, tooltip);
-	g_free (tooltip);
-	
-	if (n_progress_ops == 0) {
-		gtk_status_icon_set_visible (status_icon, FALSE);
-		gtk_widget_hide (get_progress_window ());
-	} else {
-		gtk_status_icon_set_visible (status_icon, TRUE);
-	}
-}
-
-static void
-op_finished (ProgressWidgetData *data)
-{
-	gtk_widget_destroy (data->widget);
-	
-	n_progress_ops--;
-	update_status_icon_and_window ();
-}
-
-static void
-cancel_clicked (GtkWidget *button,
-		ProgressWidgetData *data)
-{
-	nautilus_progress_info_cancel (data->info);
-	gtk_widget_set_sensitive (button, FALSE);
-}
-
-
-static GtkWidget *
-progress_widget_new (NautilusProgressInfo *info)
-{
-	ProgressWidgetData *data;
-	GtkWidget *label, *progress_bar, *hbox, *vbox, *box, *button, *image;
-
-	data = g_new0 (ProgressWidgetData, 1);
-	data->info = g_object_ref (info);
-	
-	vbox = gtk_vbox_new (FALSE, 0);
-	gtk_box_set_spacing (GTK_BOX (vbox), 5);
-
-	     
-	data->widget = vbox;
-	g_object_set_data_full (G_OBJECT (data->widget),
-				"data", data, 
-				(GDestroyNotify)progress_widget_data_free);
-	
-	label = gtk_label_new ("status");
-	gtk_widget_set_size_request (label, 500, -1);
-	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
-	gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR);
-	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-	gtk_box_pack_start (GTK_BOX (vbox),
-			    label,
-			    TRUE, FALSE,
-			    0);
-	data->status = GTK_LABEL (label);			   
-	
-	hbox = gtk_hbox_new (FALSE,10);
-
-	progress_bar = gtk_progress_bar_new ();
-	data->progress_bar = GTK_PROGRESS_BAR (progress_bar);
-	gtk_progress_bar_set_pulse_step (data->progress_bar, 0.05);
-	box = gtk_vbox_new (FALSE,0);
-	gtk_box_pack_start(GTK_BOX (box),
-			   progress_bar,
-			   TRUE,FALSE,
-			   0);
-	gtk_box_pack_start(GTK_BOX (hbox),
-			   box,
-			   TRUE,TRUE,
-			   0);
-	
-	image = gtk_image_new_from_stock (GTK_STOCK_CANCEL,
-					  GTK_ICON_SIZE_BUTTON);
-	button = gtk_button_new ();
-	gtk_container_add (GTK_CONTAINER (button), image);
-	gtk_box_pack_start (GTK_BOX (hbox),
-			    button,
-			    FALSE,FALSE,
-			    0);
-	g_signal_connect (button, "clicked", (GCallback)cancel_clicked, data);
-	
-	gtk_box_pack_start (GTK_BOX (vbox),
-			    hbox,
-			    FALSE,FALSE,
-			    0);
-
-	label = gtk_label_new ("details");
-	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
-	gtk_box_pack_start (GTK_BOX (vbox),
-			    label,
-			    TRUE, FALSE,
-			    0);
-	data->details = GTK_LABEL (label);
-	
-	gtk_widget_show_all (data->widget);
-	
-	update_data (data);
-	update_progress (data);
-
-	g_signal_connect_swapped (data->info,
-				  "changed",
-				  (GCallback)update_data, data);
-	g_signal_connect_swapped (data->info,
-				  "progress_changed",
-				  (GCallback)update_progress, data);
-	g_signal_connect_swapped (data->info,
-				  "finished",
-				  (GCallback)op_finished, data);
-	
-	return data->widget;
-}
-
-static void
-handle_new_progress_info (NautilusProgressInfo *info)
-{
-	GtkWidget *window, *progress;
-
-	window = get_progress_window ();
-	
-	progress = progress_widget_new (info);
-	gtk_box_pack_start (GTK_BOX (gtk_bin_get_child (GTK_BIN (window))),
-			    progress,
-			    FALSE, FALSE, 6);
-
-	gtk_window_present (GTK_WINDOW (window));
-
-	n_progress_ops++;
-	update_status_icon_and_window ();	
-}
-
-static gboolean
-new_op_started_timeout (NautilusProgressInfo *info)
-{
-	if (nautilus_progress_info_get_is_paused (info)) {
-		return TRUE;
-	}
-	if (!nautilus_progress_info_get_is_finished (info)) {
-		handle_new_progress_info (info);
-	}
-	g_object_unref (info);
-	return FALSE;
-}
-
-static void
-new_op_started (NautilusProgressInfo *info)
-{
-	g_signal_handlers_disconnect_by_func (info, (GCallback)new_op_started, NULL);
-	g_timeout_add_seconds (2,
-			       (GSourceFunc)new_op_started_timeout,
-			       g_object_ref (info));
-}
-
 static void
 nautilus_progress_info_init (NautilusProgressInfo *info)
 {
@@ -452,8 +164,6 @@ nautilus_progress_info_init (NautilusProgressInfo *info)
 
 	info->cancellable = g_cancellable_new ();
 
-	g_signal_connect (info, "started", (GCallback)new_op_started, NULL);
-
 	manager = nautilus_progress_info_manager_new ();
 	nautilus_progress_info_manager_add_new_info (manager, info);
 	g_object_unref (manager);
diff --git a/src/Makefile.am b/src/Makefile.am
index a21da0f..aee0997 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -109,6 +109,8 @@ nautilus_SOURCES = \
 	nautilus-pathbar.h			\
 	nautilus-places-sidebar.c		\
 	nautilus-places-sidebar.h		\
+	nautilus-progress-info-widget.c		\
+	nautilus-progress-info-widget.h		\
 	nautilus-progress-ui-handler.c		\
 	nautilus-progress-ui-handler.h		\
 	nautilus-properties-window.c		\
diff --git a/src/nautilus-progress-info-widget.c b/src/nautilus-progress-info-widget.c
new file mode 100644
index 0000000..d5cb27b
--- /dev/null
+++ b/src/nautilus-progress-info-widget.c
@@ -0,0 +1,237 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * nautilus-progress-info-widget.h: file operation progress user interface.
+ *
+ * Copyright (C) 2007, 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Alexander Larsson <alexl redhat com>
+ *          Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#include <config.h>
+
+#include "nautilus-progress-info-widget.h"
+
+struct _NautilusProgressInfoWidgetPriv {
+	NautilusProgressInfo *info;
+
+	GtkWidget *status; /* GtkLabel */
+	GtkWidget *details; /* GtkLabel */
+	GtkWidget *progress_bar;
+};
+
+enum {
+	PROP_INFO = 1,
+	NUM_PROPERTIES
+};
+
+static GParamSpec *properties[NUM_PROPERTIES] = { NULL };
+
+G_DEFINE_TYPE (NautilusProgressInfoWidget, nautilus_progress_info_widget,
+               GTK_TYPE_BOX);
+
+static void
+info_finished (NautilusProgressInfoWidget *self)
+{
+	gtk_widget_destroy (GTK_WIDGET (self));
+}
+
+static void
+update_data (NautilusProgressInfoWidget *self)
+{
+	char *status, *details;
+	char *markup;
+
+	status = nautilus_progress_info_get_status (self->priv->info);
+	gtk_label_set_text (GTK_LABEL (self->priv->status), status);
+	g_free (status);
+
+	details = nautilus_progress_info_get_details (self->priv->info);
+	markup = g_markup_printf_escaped ("<span size='small'>%s</span>", details);
+	gtk_label_set_markup (GTK_LABEL (self->priv->details), markup);
+	g_free (details);
+	g_free (markup);
+}
+
+static void
+update_progress (NautilusProgressInfoWidget *self)
+{
+	double progress;
+
+	progress = nautilus_progress_info_get_progress (self->priv->info);
+	if (progress < 0) {
+		gtk_progress_bar_pulse (GTK_PROGRESS_BAR (self->priv->progress_bar));
+	} else {
+		gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (self->priv->progress_bar), progress);
+	}
+}
+
+static void
+cancel_clicked (GtkWidget *button,
+		NautilusProgressInfoWidget *self)
+{
+	nautilus_progress_info_cancel (self->priv->info);
+	gtk_widget_set_sensitive (button, FALSE);
+}
+
+static void
+nautilus_progress_info_widget_constructed (GObject *obj)
+{
+	GtkWidget *label, *progress_bar, *hbox, *box, *button, *image;
+	NautilusProgressInfoWidget *self = NAUTILUS_PROGRESS_INFO_WIDGET (obj);
+
+	G_OBJECT_CLASS (nautilus_progress_info_widget_parent_class)->constructed (obj);
+
+	label = gtk_label_new ("status");
+	gtk_widget_set_size_request (label, 500, -1);
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+	gtk_label_set_line_wrap_mode (GTK_LABEL (label), PANGO_WRAP_WORD_CHAR);
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (self),
+			    label,
+			    TRUE, FALSE,
+			    0);
+	self->priv->status = label;
+
+	hbox = gtk_hbox_new (FALSE, 10);
+
+	progress_bar = gtk_progress_bar_new ();
+	self->priv->progress_bar = progress_bar;
+	gtk_progress_bar_set_pulse_step (GTK_PROGRESS_BAR (progress_bar), 0.05);
+	box = gtk_vbox_new (FALSE,0);
+	gtk_box_pack_start(GTK_BOX (box),
+			   progress_bar,
+			   TRUE, FALSE,
+			   0);
+	gtk_box_pack_start(GTK_BOX (hbox),
+			   box,
+			   TRUE, TRUE,
+			   0);
+
+	image = gtk_image_new_from_stock (GTK_STOCK_CANCEL,
+					  GTK_ICON_SIZE_BUTTON);
+	button = gtk_button_new ();
+	gtk_container_add (GTK_CONTAINER (button), image);
+	gtk_box_pack_start (GTK_BOX (hbox),
+			    button,
+			    FALSE,FALSE,
+			    0);
+	g_signal_connect (button, "clicked",
+			  G_CALLBACK (cancel_clicked), self);
+
+	gtk_box_pack_start (GTK_BOX (self),
+			    hbox,
+			    FALSE,FALSE,
+			    0);
+
+	label = gtk_label_new ("details");
+	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+	gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+	gtk_box_pack_start (GTK_BOX (self),
+			    label,
+			    TRUE, FALSE,
+			    0);
+	self->priv->details = label;
+	
+	gtk_widget_show_all (GTK_WIDGET (self));
+
+	update_data (self);
+	update_progress (self);
+
+	g_signal_connect_swapped (self->priv->info,
+				  "changed",
+				  G_CALLBACK (update_data), self);
+	g_signal_connect_swapped (self->priv->info,
+				  "progress-changed",
+				  G_CALLBACK (update_progress), self);
+	g_signal_connect_swapped (self->priv->info,
+				  "finished",
+				  G_CALLBACK (info_finished), self);
+}
+
+static void
+nautilus_progress_info_widget_dispose (GObject *obj)
+{
+	NautilusProgressInfoWidget *self = NAUTILUS_PROGRESS_INFO_WIDGET (obj);
+
+	g_clear_object (&self->priv->info);
+
+	G_OBJECT_CLASS (nautilus_progress_info_widget_parent_class)->dispose (obj);
+}
+
+static void
+nautilus_progress_info_widget_set_property (GObject *object,
+					    guint property_id,
+					    const GValue *value,
+					    GParamSpec *pspec)
+{
+	NautilusProgressInfoWidget *self = NAUTILUS_PROGRESS_INFO_WIDGET (object);
+
+	switch (property_id) {
+	case PROP_INFO:
+		self->priv->info = g_value_dup_object (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+		break;
+	}		
+}
+
+static void
+nautilus_progress_info_widget_init (NautilusProgressInfoWidget *self)
+{
+	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NAUTILUS_TYPE_PROGRESS_INFO_WIDGET,
+						  NautilusProgressInfoWidgetPriv);
+
+	
+}
+
+static void
+nautilus_progress_info_widget_class_init (NautilusProgressInfoWidgetClass *klass)
+{
+	GObjectClass *oclass;
+
+	oclass = G_OBJECT_CLASS (klass);
+	oclass->set_property = nautilus_progress_info_widget_set_property;
+	oclass->constructed = nautilus_progress_info_widget_constructed;
+	oclass->dispose = nautilus_progress_info_widget_dispose;
+
+	properties[PROP_INFO] =
+		g_param_spec_object ("info",
+				     "NautilusProgressInfo",
+				     "The NautilusProgressInfo associated with this widget",
+				     NAUTILUS_TYPE_PROGRESS_INFO,
+				     G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
+				     G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
+
+	g_type_class_add_private (klass, sizeof (NautilusProgressInfoWidgetPriv));
+}
+
+GtkWidget *
+nautilus_progress_info_widget_new (NautilusProgressInfo *info)
+{
+	return g_object_new (NAUTILUS_TYPE_PROGRESS_INFO_WIDGET,
+			     "info", info,
+			     "orientation", GTK_ORIENTATION_VERTICAL,
+			     "homogeneous", FALSE,
+			     "spacing", 5,
+			     NULL);
+}
diff --git a/src/nautilus-progress-info-widget.h b/src/nautilus-progress-info-widget.h
new file mode 100644
index 0000000..4b0373d
--- /dev/null
+++ b/src/nautilus-progress-info-widget.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/*
+ * nautilus-progress-info-widget.h: file operation progress user interface.
+ *
+ * Copyright (C) 2007, 2011 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Alexander Larsson <alexl redhat com>
+ *          Cosimo Cecchi <cosimoc redhat com>
+ *
+ */
+
+#ifndef __NAUTILUS_PROGRESS_INFO_WIDGET_H__
+#define __NAUTILUS_PROGRESS_INFO_WIDGET_H__
+
+#include <gtk/gtk.h>
+
+#include <libnautilus-private/nautilus-progress-info.h>
+
+#define NAUTILUS_TYPE_PROGRESS_INFO_WIDGET nautilus_progress_info_widget_get_type()
+#define NAUTILUS_PROGRESS_INFO_WIDGET(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_PROGRESS_INFO_WIDGET, NautilusProgressInfoWidget))
+#define NAUTILUS_PROGRESS_INFO_WIDGET_CLASS(klass) \
+	(G_TYPE_CHECK_CLASS_CAST ((klass), NAUTILUS_TYPE_PROGRESS_INFO_WIDGET, NautilusProgressInfoWidgetClass))
+#define NAUTILUS_IS_PROGRESS_INFO_WIDGET(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE ((obj), NAUTILUS_TYPE_PROGRESS_INFO_WIDGET))
+#define NAUTILUS_IS_PROGRESS_INFO_WIDGET_CLASS(klass) \
+	(G_TYPE_CHECK_CLASS_TYPE ((klass), NAUTILUS_TYPE_PROGRESS_INFO_WIDGET))
+#define NAUTILUS_PROGRESS_INFO_WIDGET_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_PROGRESS_INFO_WIDGET, NautilusProgressInfoWidgetClass))
+
+typedef struct _NautilusProgressInfoWidgetPriv NautilusProgressInfoWidgetPriv;
+
+typedef struct {
+	GtkBox parent;
+
+	/* private */
+	NautilusProgressInfoWidgetPriv *priv;
+} NautilusProgressInfoWidget;
+
+typedef struct {
+	GtkBoxClass parent_class;
+} NautilusProgressInfoWidgetClass;
+
+GType nautilus_progress_info_widget_get_type (void);
+
+GtkWidget * nautilus_progress_info_widget_new (NautilusProgressInfo *info);
+
+#endif /* __NAUTILUS_PROGRESS_INFO_WIDGET_H__ */
diff --git a/src/nautilus-progress-ui-handler.c b/src/nautilus-progress-ui-handler.c
index 9ab8f03..8eb7a2d 100644
--- a/src/nautilus-progress-ui-handler.c
+++ b/src/nautilus-progress-ui-handler.c
@@ -29,16 +29,143 @@
 #include "nautilus-progress-ui-handler.h"
 
 #include "nautilus-application.h"
+#include "nautilus-progress-info-widget.h"
 
 #include <libnautilus-private/nautilus-progress-info.h>
 #include <libnautilus-private/nautilus-progress-info-manager.h>
 
+static GtkStatusIcon *status_icon = NULL;
+static int n_progress_ops = 0;
+
 struct _NautilusProgressUIHandlerPriv {
 	NautilusProgressInfoManager *manager;
+
+	GtkWidget *progress_window;
 };
 
 G_DEFINE_TYPE (NautilusProgressUIHandler, nautilus_progress_ui_handler, G_TYPE_OBJECT);
 
+static gboolean
+delete_event (GtkWidget *widget,
+	      GdkEventAny *event)
+{
+	gtk_widget_hide (widget);
+	return TRUE;
+}
+
+static void
+status_icon_activate_cb (GtkStatusIcon *icon,
+			 GtkWidget *progress_window)
+{
+	if (gtk_widget_get_visible (progress_window)) {
+		gtk_widget_hide (progress_window);
+	} else {
+		gtk_window_present (GTK_WINDOW (progress_window));
+	}
+}
+
+static GtkWidget *
+get_progress_window (void)
+{
+	static GtkWidget *progress_window = NULL;
+	GtkWidget *vbox;
+	GIcon *icon;
+	
+	if (progress_window != NULL) {
+		return progress_window;
+	}
+	
+	progress_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_resizable (GTK_WINDOW (progress_window),
+				  FALSE);
+	gtk_container_set_border_width (GTK_CONTAINER (progress_window), 10);
+ 
+	gtk_window_set_title (GTK_WINDOW (progress_window),
+			      _("File Operations"));
+	gtk_window_set_wmclass (GTK_WINDOW (progress_window),
+				"file_progress", "Nautilus");
+	gtk_window_set_position (GTK_WINDOW (progress_window),
+				 GTK_WIN_POS_CENTER);
+	gtk_window_set_icon_name (GTK_WINDOW (progress_window),
+				"system-file-manager");
+
+	vbox = gtk_vbox_new (FALSE, 0);
+	gtk_box_set_spacing (GTK_BOX (vbox), 5);
+		
+	gtk_container_add (GTK_CONTAINER (progress_window),
+			   vbox);
+
+	gtk_widget_show_all (progress_window);
+
+	g_signal_connect (progress_window,
+			  "delete_event",
+			  (GCallback)delete_event, NULL);
+
+	icon = g_themed_icon_new_with_default_fallbacks ("system-file-manager-symbolic");
+	status_icon = gtk_status_icon_new_from_gicon (icon);
+	g_signal_connect (status_icon, "activate",
+			  (GCallback)status_icon_activate_cb,
+			  progress_window);
+
+	gtk_status_icon_set_visible (status_icon, FALSE);
+	g_object_unref (icon);
+
+	return progress_window;
+}
+
+static void
+update_status_icon_and_window (void)
+{
+	char *tooltip;
+
+	tooltip = g_strdup_printf (ngettext ("%'d file operation active",
+					     "%'d file operations active",
+					     n_progress_ops),
+				   n_progress_ops);
+	gtk_status_icon_set_tooltip_text (status_icon, tooltip);
+	g_free (tooltip);
+	
+	if (n_progress_ops == 0) {
+		gtk_status_icon_set_visible (status_icon, FALSE);
+		gtk_widget_hide (get_progress_window ());
+	} else {
+		gtk_status_icon_set_visible (status_icon, TRUE);
+	}
+}
+
+static void
+handle_new_progress_info (NautilusProgressInfo *info)
+{
+	GtkWidget *window, *progress;
+
+	window = get_progress_window ();
+	
+	progress = nautilus_progress_info_widget_new (info);
+	gtk_box_pack_start (GTK_BOX (gtk_bin_get_child (GTK_BIN (window))),
+			    progress,
+			    FALSE, FALSE, 6);
+
+	gtk_window_present (GTK_WINDOW (window));
+
+	n_progress_ops++;
+	update_status_icon_and_window ();	
+}
+
+static gboolean
+new_op_started_timeout (NautilusProgressInfo *info)
+{
+	if (nautilus_progress_info_get_is_paused (info)) {
+		return TRUE;
+	}
+
+	if (!nautilus_progress_info_get_is_finished (info)) {
+		handle_new_progress_info (info);
+	}
+
+	g_object_unref (info);
+	return FALSE;
+}
+
 static void
 progress_info_finished_cb (NautilusProgressInfo *info,
 			   NautilusProgressUIHandler *self)
@@ -49,6 +176,9 @@ progress_info_finished_cb (NautilusProgressInfo *info,
 	g_application_release (G_APPLICATION (app));
 
 	g_object_unref (app);
+
+	n_progress_ops--;
+	update_status_icon_and_window ();
 }
 
 static void
@@ -64,6 +194,11 @@ progress_info_started_cb (NautilusProgressInfo *info,
 			  G_CALLBACK (progress_info_finished_cb), self);
 
 	g_object_unref (app);
+
+	/* timeout for the progress window to appear */
+	g_timeout_add_seconds (2,
+			       (GSourceFunc) new_op_started_timeout,
+			       g_object_ref (info));
 }
 
 static void



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]