[gnome-disk-utility] Use GtkInfoBar to show job progress



commit 133e101c904ca589bfece83cfd82bab27e775120
Author: David Zeuthen <davidz redhat com>
Date:   Thu Jun 18 18:47:23 2009 -0400

    Use GtkInfoBar to show job progress
    
    Also use a spinner when the progress is indeterminate. Screenshots
    
     http://people.freedesktop.org/~david/palimpsest-progress.png
     http://people.freedesktop.org/~david/palimpsest-spinner.png
    
    Yes, the background color is fugly but that's a gtk+/theme issue....

 configure.ac                                |    2 +-
 src/palimpsest/Makefile.am                  |    8 +-
 src/palimpsest/bling-color.c                |   86 ++++++++
 src/palimpsest/bling-color.h                |   35 +++
 src/palimpsest/bling-spinner.c              |  309 +++++++++++++++++++++++++++
 src/palimpsest/bling-spinner.h              |   58 +++++
 src/palimpsest/gdu-section-job.c            |  230 --------------------
 src/palimpsest/gdu-section-job.h            |   58 -----
 src/palimpsest/gdu-section-linux-md-drive.c |    2 +-
 src/palimpsest/gdu-shell.c                  |  233 ++++++++++++++-------
 10 files changed, 652 insertions(+), 369 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index b9e3f93..361373c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -122,7 +122,7 @@ GOBJECT2_REQUIRED=2.16
 GIO2_REQUIRED=2.16
 DBUS_GLIB_REQUIRED=0.74
 GNOME_KEYRING_REQUIRED=2.22
-GTK2_REQUIRED=2.6.0
+GTK2_REQUIRED=2.17.2
 LIBSEXY_REQUIRED=0.1.11
 UNIQUE_REQUIRED=1.0
 LIBNOTIFY_REQUIRED=0.3.0
diff --git a/src/palimpsest/Makefile.am b/src/palimpsest/Makefile.am
index 3dfdd2e..16db71d 100644
--- a/src/palimpsest/Makefile.am
+++ b/src/palimpsest/Makefile.am
@@ -1,7 +1,11 @@
 
+NULL =
+
 bin_PROGRAMS = palimpsest
 
 palimpsest_SOURCES = 									\
+	bling-color.h				bling-color.c				\
+	bling-spinner.h				bling-spinner.c				\
 						gdu-main.c				\
 	gdu-shell.h				gdu-shell.c				\
 	gdu-section.h				gdu-section.c				\
@@ -15,8 +19,8 @@ palimpsest_SOURCES = 									\
 	gdu-section-encrypted.h			gdu-section-encrypted.c			\
 	gdu-section-linux-md-drive.h		gdu-section-linux-md-drive.c		\
 	gdu-section-no-media.h			gdu-section-no-media.c			\
-	gdu-section-job.h			gdu-section-job.c			\
-	gdu-tree.h				gdu-tree.c
+	gdu-tree.h				gdu-tree.c				\
+	$(NULL)
 
 palimpsest_CPPFLAGS = 					\
 	-I$(top_srcdir)/src/				\
diff --git a/src/palimpsest/bling-color.c b/src/palimpsest/bling-color.c
new file mode 100644
index 0000000..fd7f503
--- /dev/null
+++ b/src/palimpsest/bling-color.c
@@ -0,0 +1,86 @@
+/*
+ * @file libbling/bling-window.c A RGBA color type, for use with libbling.
+ *
+ * @Copyright (C) 2007 John Stowers, Neil Jagdish Patel.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; 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 <gtk/gtk.h>
+#include <string.h>
+#include <bling-color.h>
+
+
+static int 
+getdec(char hexchar)
+{
+   if ((hexchar >= '0') && (hexchar <= '9')) return hexchar - '0';
+   if ((hexchar >= 'A') && (hexchar <= 'F')) return hexchar - 'A' + 10;
+   if ((hexchar >= 'a') && (hexchar <= 'f')) return hexchar - 'a' + 10;
+
+   return -1; // Wrong character
+
+}
+
+static void
+hex2float(const char* HexColor, float* FloatColor)
+{
+   const char* HexColorPtr = HexColor;
+
+   int i = 0;
+   for (i = 0; i < 4; i++)
+   {
+     int IntColor = (getdec(HexColorPtr[0]) * 16) +
+                     getdec(HexColorPtr[1]);
+
+     FloatColor[i] = (float) IntColor / 255.0;
+     HexColorPtr += 2;
+   }
+
+}
+
+void 
+bling_color_parse_string (BlingColor *color, const gchar *str)
+{
+	gfloat colors[4];
+	size_t len;
+	
+	len = strlen (str);
+	if (len != 8) {
+		/* Always return a valid color */
+		color->red = 0.0;
+		color->green = 0.0;
+		color->blue = 0.0;
+		color->alpha = 1.0;
+	} else {
+		hex2float (str, colors);
+		color->red = colors[0];
+		color->green = colors[1];
+		color->blue = colors[2];
+		color->alpha = colors[3];
+	}
+}
+
+
+
+
+
+
+
diff --git a/src/palimpsest/bling-color.h b/src/palimpsest/bling-color.h
new file mode 100644
index 0000000..b12ae71
--- /dev/null
+++ b/src/palimpsest/bling-color.h
@@ -0,0 +1,35 @@
+/* @Copyright (C) 2007 John Stowers, Neil Jagdish Patel.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA  02111-1307, USA.
+ */
+
+
+#ifndef _BLING_COLOR_H_
+#define _BLING_COLOR_H_
+
+typedef struct {
+	gfloat red;
+	gfloat green;
+	gfloat blue;
+	gfloat alpha;
+	
+} BlingColor;
+
+
+void bling_color_parse_string (BlingColor *color, const gchar *str);
+
+
+#endif /* _BLING_COLOR_H_ */
diff --git a/src/palimpsest/bling-spinner.c b/src/palimpsest/bling-spinner.c
new file mode 100644
index 0000000..1376e7c
--- /dev/null
+++ b/src/palimpsest/bling-spinner.c
@@ -0,0 +1,309 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * @file libbling/bling-spinner.c A apple-esque spinner widger
+ *
+ * @Copyright (C) 2007 John Stowers, Neil Jagdish Patel.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA  02111-1307, USA.
+ *
+ * Code adapted from egg-spinner
+ * by Christian Hergert <christian hergert gmail com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <math.h>
+
+#include "bling-spinner.h"
+#include "bling-color.h"
+
+#define BLING_SPINNER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), BLING_TYPE_SPINNER, BlingSpinnerPrivate))
+
+G_DEFINE_TYPE (BlingSpinner, bling_spinner, GTK_TYPE_DRAWING_AREA);
+
+enum
+{
+	PROP_0,
+	PROP_COLOR,
+	PROP_NUM_LINES
+};
+
+/* STRUCTS & ENUMS */
+struct _BlingSpinnerPrivate
+{
+	/* state */
+	gboolean have_alpha;
+	guint current;
+	guint timeout;
+
+	/* appearance */
+	BlingColor color;
+	guint lines;
+};
+
+/* FORWARDS */
+static void bling_spinner_class_init(BlingSpinnerClass *klass);
+static void bling_spinner_init(BlingSpinner *spinner);
+static void bling_spinner_finalize(GObject *obj);
+static void bling_spinner_set_property(GObject *gobject, guint prop_id, const GValue *value, GParamSpec *pspec);
+static gboolean bling_spinner_expose(GtkWidget *widget, GdkEventExpose *event);
+static void bling_spinner_screen_changed (GtkWidget* widget, GdkScreen* old_screen);
+
+static GtkDrawingAreaClass *parent_class;
+
+/* DRAWING FUNCTIONS */
+static void
+draw (GtkWidget *widget, cairo_t *cr)
+{
+	double x, y;
+	double radius;
+	double half;
+	int i;
+	int width, height;
+
+	BlingSpinnerPrivate *priv;
+
+	priv = BLING_SPINNER_GET_PRIVATE (widget);
+
+	cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+	width = widget->allocation.width;
+	height = widget->allocation.height;
+
+	if ( (width < 12) || (height <12) )
+		gtk_widget_set_size_request(widget, 12, 12);
+
+	//x = widget->allocation.x + widget->allocation.width / 2;
+	//y = widget->allocation.y + widget->allocation.height / 2;
+	x = widget->allocation.width / 2;
+	y = widget->allocation.height / 2;
+	radius = MIN (widget->allocation.width	/ 2,
+				  widget->allocation.height / 2);
+	half = priv->lines / 2;
+
+	/*FIXME: render in B&W for non transparency */
+
+	for (i = 0; i < priv->lines; i++) {
+		int inset = 0.7 * radius;
+		/* transparency is a function of time and intial value */
+		double t = (double) ((i + priv->lines - priv->current)
+				   % priv->lines) / priv->lines;
+
+		cairo_save (cr);
+
+		cairo_set_source_rgba (cr, 0, 0, 0, t);
+		//cairo_set_line_width (cr, 2 * cairo_get_line_width (cr));
+		cairo_set_line_width (cr, 2.0);
+		cairo_move_to (cr,
+					   x + (radius - inset) * cos (i * M_PI / half),
+					   y + (radius - inset) * sin (i * M_PI / half));
+		cairo_line_to (cr,
+					   x + radius * cos (i * M_PI / half),
+					   y + radius * sin (i * M_PI / half));
+		cairo_stroke (cr);
+
+		cairo_restore (cr);
+	}
+}
+
+
+/*	GOBJECT INIT CODE */
+static void
+bling_spinner_class_init(BlingSpinnerClass *klass)
+{
+	GObjectClass *gobject_class;
+	GtkWidgetClass *widget_class;
+
+	parent_class = g_type_class_peek_parent(klass);
+
+	gobject_class = G_OBJECT_CLASS(klass);
+	g_type_class_add_private (gobject_class, sizeof (BlingSpinnerPrivate));
+	gobject_class->set_property = bling_spinner_set_property;
+
+	widget_class = GTK_WIDGET_CLASS(klass);
+	widget_class->expose_event = bling_spinner_expose;
+	widget_class->screen_changed = bling_spinner_screen_changed;
+
+	g_object_class_install_property(gobject_class, PROP_COLOR,
+		g_param_spec_string("color", "Color",
+							"Main color",
+							"454545C8",
+							G_PARAM_CONSTRUCT | G_PARAM_WRITABLE));
+
+	g_object_class_install_property(gobject_class, PROP_NUM_LINES,
+		g_param_spec_uint("lines", "Num Lines",
+							"The number of lines to animate",
+							0,20,12,
+							G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+
+}
+
+static void
+bling_spinner_init (BlingSpinner *spinner)
+{
+	BlingSpinnerPrivate *priv;
+
+	priv = BLING_SPINNER_GET_PRIVATE (spinner);
+	priv->current = 0;
+	priv->timeout = 0;
+
+	GTK_WIDGET_SET_FLAGS (GTK_WIDGET (spinner), GTK_NO_WINDOW);
+}
+
+static gboolean
+bling_spinner_expose (GtkWidget *widget, GdkEventExpose *event)
+{
+	cairo_t *cr;
+
+	/* get cairo context */
+	cr = gdk_cairo_create (widget->window);
+
+	/* set a clip region for the expose event */
+	cairo_rectangle (cr,
+					 event->area.x, event->area.y,
+					 event->area.width, event->area.height);
+	cairo_clip (cr);
+
+	cairo_translate (cr, event->area.x, event->area.y);
+
+	/* draw clip region */
+	draw (widget, cr);
+
+	/* free memory */
+	cairo_destroy (cr);
+
+	return FALSE;
+}
+
+static void
+bling_spinner_screen_changed (GtkWidget* widget, GdkScreen* old_screen)
+{
+	BlingSpinner *spinner;
+	BlingSpinnerPrivate *priv;
+	GdkScreen* new_screen;
+	GdkColormap* colormap;
+
+	spinner = BLING_SPINNER(widget);
+	priv = BLING_SPINNER_GET_PRIVATE (spinner);
+
+	new_screen = gtk_widget_get_screen (widget);
+	colormap = gdk_screen_get_rgba_colormap (new_screen);
+
+	if (!colormap) {
+		colormap = gdk_screen_get_rgb_colormap (new_screen);
+		priv->have_alpha = FALSE;
+	} else
+		priv->have_alpha = TRUE;
+
+	gtk_widget_set_colormap (widget, colormap);
+}
+
+static gboolean
+bling_spinner_timeout (gpointer data)
+{
+	BlingSpinner *spinner;
+	BlingSpinnerPrivate *priv;
+
+	spinner = BLING_SPINNER (data);
+	priv = BLING_SPINNER_GET_PRIVATE (spinner);
+
+	if (priv->current + 1 >= priv->lines) {
+		priv->current = 0;
+	} else {
+		priv->current++;
+	}
+
+	gtk_widget_queue_draw (GTK_WIDGET (data));
+
+	return TRUE;
+}
+
+static void
+bling_spinner_set_property(GObject *gobject, guint prop_id,
+					const GValue *value, GParamSpec *pspec)
+{
+	BlingSpinner *spinner;
+	BlingSpinnerPrivate *priv;
+
+	spinner = BLING_SPINNER(gobject);
+	priv = BLING_SPINNER_GET_PRIVATE (spinner);
+
+	switch (prop_id)
+	{
+		case PROP_COLOR:
+			bling_color_parse_string (&priv->color, g_value_get_string(value));
+			break;
+		case PROP_NUM_LINES:
+			priv->lines = g_value_get_uint(value);
+			break;
+		default:
+			G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
+			break;
+	}
+}
+
+/**
+ * bling_spinner_new
+ *
+ * Returns a default spinner. Not yet started.
+ *
+ * Returns: a new #BlingSpinner
+ */
+GtkWidget *
+bling_spinner_new (void)
+{
+	return g_object_new (BLING_TYPE_SPINNER, NULL);
+}
+
+/**
+ * bling_spinner_start
+ *
+ * Starts the animation
+ */
+void
+bling_spinner_start (BlingSpinner *spinner)
+{
+	BlingSpinnerPrivate *priv;
+
+	g_return_if_fail (BLING_IS_SPINNER (spinner));
+
+	priv = BLING_SPINNER_GET_PRIVATE (spinner);
+	if (priv->timeout != 0)
+		return;
+	priv->timeout = g_timeout_add (80, bling_spinner_timeout, spinner);
+}
+
+/**
+ * bling_spinner_stop
+ *
+ * Stops the animation
+ */
+void
+bling_spinner_stop (BlingSpinner *spinner)
+{
+	BlingSpinnerPrivate *priv;
+
+	g_return_if_fail (BLING_IS_SPINNER (spinner));
+
+	priv = BLING_SPINNER_GET_PRIVATE (spinner);
+	if (priv->timeout == 0)
+		return;
+	g_source_remove (priv->timeout);
+	priv->timeout = 0;
+}
diff --git a/src/palimpsest/bling-spinner.h b/src/palimpsest/bling-spinner.h
new file mode 100644
index 0000000..8bc153c
--- /dev/null
+++ b/src/palimpsest/bling-spinner.h
@@ -0,0 +1,58 @@
+/* @Copyright (C) 2007 John Stowers, Neil Jagdish Patel.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA  02111-1307, USA.
+ */
+
+
+#ifndef _BLING_SPINNER_H_
+#define _BLING_SPINNER_H_
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define BLING_TYPE_SPINNER           (bling_spinner_get_type ())
+#define BLING_SPINNER(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), BLING_TYPE_SPINNER, BlingSpinner))
+#define BLING_SPINNER_CLASS(obj)     (G_TYPE_CHECK_CLASS_CAST ((obj), BLING_SPINNER,  BlingSpinnerClass))
+#define BLING_IS_SPINNER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BLING_TYPE_SPINNER))
+#define BLING_IS_SPINNER_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE ((obj), BLING_TYPE_SPINNER))
+#define BLING_SPINNER_GET_CLASS      (G_TYPE_INSTANCE_GET_CLASS ((obj), BLING_TYPE_SPINNER, BlingSpinnerClass))
+
+typedef struct _BlingSpinner      BlingSpinner;
+typedef struct _BlingSpinnerClass BlingSpinnerClass;
+typedef struct _BlingSpinnerPrivate  BlingSpinnerPrivate;
+
+struct _BlingSpinner
+{
+	GtkDrawingArea parent;
+};
+
+struct _BlingSpinnerClass
+{
+	GtkDrawingAreaClass parent_class;
+	BlingSpinnerPrivate *priv;
+};
+
+GType bling_spinner_get_type (void);
+
+GtkWidget * bling_spinner_new (void);
+
+void bling_spinner_start (BlingSpinner *spinner);
+void bling_spinner_stop  (BlingSpinner *spinner);
+
+G_END_DECLS
+
+#endif
diff --git a/src/palimpsest/gdu-section-linux-md-drive.c b/src/palimpsest/gdu-section-linux-md-drive.c
index 3df571d..e032ea3 100644
--- a/src/palimpsest/gdu-section-linux-md-drive.c
+++ b/src/palimpsest/gdu-section-linux-md-drive.c
@@ -1091,7 +1091,7 @@ gdu_section_linux_md_drive_init (GduSectionLinuxMdDrive *section)
         gtk_widget_set_tooltip_text (button, _("Adds a new component to the running RAID array. Use this "
                                                "when replacing a failed component or adding a hot spare."));
 
-        button = gtk_button_new_with_mnemonic (_("_Check"));
+        button = gtk_button_new_with_mnemonic (_("Chec_k"));
         gtk_container_add (GTK_CONTAINER (button_box), button);
         section->priv->add_button = button;
         g_signal_connect (button, "clicked", G_CALLBACK (on_check_clicked), section);
diff --git a/src/palimpsest/gdu-shell.c b/src/palimpsest/gdu-shell.c
index 7c56ea3..4e00d31 100644
--- a/src/palimpsest/gdu-shell.c
+++ b/src/palimpsest/gdu-shell.c
@@ -46,7 +46,7 @@
 #include "gdu-section-encrypted.h"
 #include "gdu-section-linux-md-drive.h"
 #include "gdu-section-no-media.h"
-#include "gdu-section-job.h"
+#include "bling-spinner.h"
 
 struct _GduShellPrivate
 {
@@ -64,6 +64,11 @@ struct _GduShellPrivate
 
         /* -------------------------------------------------------------------------------- */
 
+        GtkWidget *job_bar;
+        GtkWidget *job_description_label;
+        GtkWidget *job_progress_bar;
+        GtkWidget *job_spinner;
+
         GtkWidget *sections_vbox;
 
         /* -------------------------------------------------------------------------------- */
@@ -456,7 +461,7 @@ update_section (GtkWidget *section, gpointer callback_data)
 }
 
 static GList *
-compute_sections_to_show (GduShell *shell, gboolean showing_job)
+compute_sections_to_show (GduShell *shell)
 {
         GduDevice *device;
         GList *sections_to_show;
@@ -464,94 +469,102 @@ compute_sections_to_show (GduShell *shell, gboolean showing_job)
         sections_to_show = NULL;
         device = gdu_presentable_get_device (shell->priv->presentable_now_showing);
 
-        /* compute sections we want to show */
-        if (showing_job) {
+        if (GDU_IS_LINUX_MD_DRIVE (shell->priv->presentable_now_showing)) {
 
                 sections_to_show = g_list_append (sections_to_show,
-                                                  (gpointer) GDU_TYPE_SECTION_JOB);
+                                                  (gpointer) GDU_TYPE_SECTION_LINUX_MD_DRIVE);
 
-        } else {
-                if (GDU_IS_LINUX_MD_DRIVE (shell->priv->presentable_now_showing)) {
 
-                        sections_to_show = g_list_append (sections_to_show,
-                                                          (gpointer) GDU_TYPE_SECTION_LINUX_MD_DRIVE);
+        } else if (GDU_IS_DRIVE (shell->priv->presentable_now_showing) && device != NULL) {
 
+                if (gdu_device_is_removable (device) && !gdu_device_is_media_available (device)) {
 
-                } else if (GDU_IS_DRIVE (shell->priv->presentable_now_showing) && device != NULL) {
+                        sections_to_show = g_list_append (sections_to_show, (gpointer) GDU_TYPE_SECTION_NO_MEDIA);
 
-                        if (gdu_device_is_removable (device) && !gdu_device_is_media_available (device)) {
+                } else {
 
-                                sections_to_show = g_list_append (
-                                        sections_to_show, (gpointer) GDU_TYPE_SECTION_NO_MEDIA);
+                        if (gdu_device_drive_ata_smart_get_is_available (device)) {
+                                sections_to_show = g_list_append (sections_to_show,
+                                                                  (gpointer) GDU_TYPE_SECTION_HEALTH);
+                        }
 
-                        } else {
+                }
 
-                                if (gdu_device_drive_ata_smart_get_is_available (device)) {
-                                                sections_to_show = g_list_append (sections_to_show,
-                                                                                  (gpointer) GDU_TYPE_SECTION_HEALTH);
-                                }
+        } else if (GDU_IS_VOLUME (shell->priv->presentable_now_showing) && device != NULL) {
 
-                        }
+                if (gdu_device_is_partition (device))
+                        sections_to_show = g_list_append (sections_to_show, (gpointer) GDU_TYPE_SECTION_PARTITION);
 
-                } else if (GDU_IS_VOLUME (shell->priv->presentable_now_showing) && device != NULL) {
+                if (gdu_presentable_is_recognized (shell->priv->presentable_now_showing)) {
+                        const char *usage;
+                        const char *type;
 
-                        if (gdu_device_is_partition (device))
-                                sections_to_show = g_list_append (sections_to_show, (gpointer) GDU_TYPE_SECTION_PARTITION);
+                        usage = gdu_device_id_get_usage (device);
+                        type = gdu_device_id_get_type (device);
 
-                        if (gdu_presentable_is_recognized (shell->priv->presentable_now_showing)) {
-                                const char *usage;
-                                const char *type;
+                        if (usage != NULL && strcmp (usage, "filesystem") == 0) {
+                                sections_to_show = g_list_append (sections_to_show, (gpointer) GDU_TYPE_SECTION_FILESYSTEM);
+                        } else if (usage != NULL && strcmp (usage, "crypto") == 0) {
+                                sections_to_show = g_list_append (sections_to_show, (gpointer) GDU_TYPE_SECTION_ENCRYPTED);
+                        } else if (usage != NULL && strcmp (usage, "other") == 0 &&
+                                   type != NULL && strcmp (type, "swap") == 0) {
+                                sections_to_show = g_list_append (sections_to_show, (gpointer) GDU_TYPE_SECTION_SWAPSPACE);
+                        }
+                } else {
+                        GduPresentable *toplevel_presentable;
+                        GduDevice *toplevel_device;
 
-                                usage = gdu_device_id_get_usage (device);
-                                type = gdu_device_id_get_type (device);
+                        sections_to_show = g_list_append (sections_to_show, (gpointer) GDU_TYPE_SECTION_UNRECOGNIZED);
 
-                                if (usage != NULL && strcmp (usage, "filesystem") == 0) {
-                                        sections_to_show = g_list_append (
-                                                sections_to_show, (gpointer) GDU_TYPE_SECTION_FILESYSTEM);
-                                } else if (usage != NULL && strcmp (usage, "crypto") == 0) {
-                                        sections_to_show = g_list_append (
-                                                sections_to_show, (gpointer) GDU_TYPE_SECTION_ENCRYPTED);
-                                } else if (usage != NULL && strcmp (usage, "other") == 0 &&
-                                           type != NULL && strcmp (type, "swap") == 0) {
-                                        sections_to_show = g_list_append (
-                                                sections_to_show, (gpointer) GDU_TYPE_SECTION_SWAPSPACE);
-                                }
-                        } else {
-                                GduPresentable *toplevel_presentable;
-                                GduDevice *toplevel_device;
-
-                                sections_to_show = g_list_append (
-                                        sections_to_show, (gpointer) GDU_TYPE_SECTION_UNRECOGNIZED);
-
-                                /* Also show a "Create partition table" section for a volume if the drive isn't partitioned */
-                                toplevel_presentable = gdu_presentable_get_toplevel (shell->priv->presentable_now_showing);
-                                if (toplevel_presentable != NULL) {
-                                        toplevel_device = gdu_presentable_get_device (toplevel_presentable);
-
-                                        if (toplevel_device != NULL) {
-                                                if (!gdu_device_is_partition_table (toplevel_device)) {
-                                                        sections_to_show = g_list_append (
-                                                                sections_to_show, (gpointer) GDU_TYPE_SECTION_CREATE_PARTITION_TABLE);
-                                                }
-                                                g_object_unref (toplevel_device);
+                        /* Also show a "Create partition table" section for a volume if the drive isn't partitioned */
+                        toplevel_presentable = gdu_presentable_get_toplevel (shell->priv->presentable_now_showing);
+                        if (toplevel_presentable != NULL) {
+                                toplevel_device = gdu_presentable_get_device (toplevel_presentable);
+
+                                if (toplevel_device != NULL) {
+                                        if (!gdu_device_is_partition_table (toplevel_device)) {
+                                                sections_to_show = g_list_append (
+                                                                                  sections_to_show, (gpointer) GDU_TYPE_SECTION_CREATE_PARTITION_TABLE);
                                         }
-                                        g_object_unref (toplevel_presentable);
+                                        g_object_unref (toplevel_device);
                                 }
+                                g_object_unref (toplevel_presentable);
                         }
+                }
 
-                } else if (GDU_IS_VOLUME_HOLE (shell->priv->presentable_now_showing)) {
+        } else if (GDU_IS_VOLUME_HOLE (shell->priv->presentable_now_showing)) {
 
-                        sections_to_show = g_list_append (sections_to_show,
-                                                          (gpointer) GDU_TYPE_SECTION_UNALLOCATED);
-                }
+                sections_to_show = g_list_append (sections_to_show,
+                                                  (gpointer) GDU_TYPE_SECTION_UNALLOCATED);
         }
 
+
         if (device != NULL)
                 g_object_unref (device);
 
         return sections_to_show;
 }
 
+static void
+on_job_bar_response (GtkInfoBar *info_bar,
+                     gint        response_id,
+                     gpointer    user_data)
+{
+        GduShell *shell = GDU_SHELL (user_data);
+
+        if (response_id == GTK_RESPONSE_CANCEL) {
+                if (shell->priv->presentable_now_showing != NULL) {
+                        GduDevice *device;
+
+                        device = gdu_presentable_get_device (shell->priv->presentable_now_showing);
+                        if (device != NULL) {
+                                gdu_device_op_cancel_job (device, NULL, NULL);
+                                g_object_unref (device);
+                        }
+                }
+        }
+}
+
 /* called when a new presentable is selected
  *  - or a presentable changes
  *  - or the job state of a presentable changes
@@ -574,8 +587,6 @@ gdu_shell_update (GduShell *shell)
         gboolean can_fsck;
         gboolean can_erase;
         static GduPresentable *last_presentable = NULL;
-        static gboolean last_showing_job = FALSE;
-        gboolean showing_job;
         gboolean reset_sections;
         GList *sections_to_show;
         uid_t unlocked_by_uid;
@@ -678,17 +689,45 @@ gdu_shell_update (GduShell *shell)
         gtk_action_set_sensitive (gtk_action_group_get_action (shell->priv->action_group, "stop"), can_stop);
         gtk_action_set_sensitive (gtk_action_group_get_action (shell->priv->action_group, "erase"), can_erase);
 
-        showing_job = job_in_progress;
-
-        reset_sections =
-                (shell->priv->presentable_now_showing != last_presentable) ||
-                (showing_job != last_showing_job);
+        reset_sections = (shell->priv->presentable_now_showing != last_presentable);
 
         last_presentable = shell->priv->presentable_now_showing;
-        last_showing_job = showing_job;
 
+        sections_to_show = compute_sections_to_show (shell);
+
+        if (job_in_progress) {
+                gchar *desc;
+                gchar *s;
+                gdouble percentage;
 
-        sections_to_show = compute_sections_to_show (shell, showing_job);
+                desc = gdu_get_job_description (gdu_device_job_get_id (device));
+
+                s = g_strdup_printf ("<small><b>%s</b></small>", desc);
+                gtk_label_set_markup (GTK_LABEL (shell->priv->job_description_label), s);
+                g_free (s);
+                g_free (desc);
+
+                gtk_widget_set_no_show_all (shell->priv->job_bar, FALSE);
+                gtk_widget_show_all (shell->priv->job_bar);
+
+                gtk_info_bar_set_response_sensitive (GTK_INFO_BAR (shell->priv->job_bar),
+                                                     GTK_RESPONSE_CANCEL,
+                                                     gdu_device_job_is_cancellable (device));
+
+                percentage = gdu_device_job_get_percentage (device);
+                if (percentage >= 0) {
+                        gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (shell->priv->job_progress_bar),
+                                                       percentage / 100.0);
+                        gtk_widget_hide (shell->priv->job_spinner);
+                } else {
+                        bling_spinner_start (BLING_SPINNER (shell->priv->job_spinner));
+                        gtk_widget_hide (shell->priv->job_progress_bar);
+                }
+
+        } else {
+                bling_spinner_stop (BLING_SPINNER (shell->priv->job_spinner));
+                gtk_widget_hide_all (shell->priv->job_bar);
+        }
 
         /* if this differs from what we currently show, prompt a reset */
         if (!reset_sections) {
@@ -1825,6 +1864,7 @@ static void
 create_window (GduShell *shell)
 {
         GtkWidget *vbox;
+        GtkWidget *vbox1;
         GtkWidget *vbox2;
         GtkWidget *menubar;
         GtkWidget *toolbar;
@@ -1832,6 +1872,13 @@ create_window (GduShell *shell)
         GtkWidget *hpane;
         GtkWidget *treeview_scrolled_window;
         GtkTreeSelection *select;
+        GtkWidget *content_area;
+        GtkWidget *button;
+        GtkWidget *label;
+        GtkWidget *align;
+        GtkWidget *vbox3;
+        GtkWidget *hbox;
+        GtkWidget *image;
 
         shell->priv->pool = gdu_pool_new ();
 
@@ -1862,15 +1909,48 @@ create_window (GduShell *shell)
         shell->priv->treeview = gdu_device_tree_new (shell->priv->pool);
         gtk_container_add (GTK_CONTAINER (treeview_scrolled_window), shell->priv->treeview);
 
+        /* --- */
+
+        vbox1 = gtk_vbox_new (FALSE, 0);
+
+        /* --- */
+
+        shell->priv->job_bar = gtk_info_bar_new ();
+        button = gtk_button_new ();
+        label = gtk_label_new (NULL);
+        gtk_label_set_markup_with_mnemonic (GTK_LABEL (label),
+                                            _("<small>_Cancel</small>"));
+        gtk_container_add (GTK_CONTAINER (button), label);
+        gtk_info_bar_add_action_widget (GTK_INFO_BAR (shell->priv->job_bar),
+                                        button,
+                                        GTK_RESPONSE_CANCEL);
+        g_signal_connect (shell->priv->job_bar,
+                          "response",
+                          G_CALLBACK (on_job_bar_response),
+                          shell);
+        gtk_widget_set_no_show_all (shell->priv->job_bar, TRUE);
+        gtk_info_bar_set_message_type (GTK_INFO_BAR (shell->priv->job_bar),
+                                       GTK_MESSAGE_INFO);
+        gtk_box_pack_start (GTK_BOX (vbox1), shell->priv->job_bar, FALSE, FALSE, 0);
+
+        content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (shell->priv->job_bar));
+        shell->priv->job_description_label = gtk_label_new (NULL);
+        gtk_misc_set_alignment (GTK_MISC (shell->priv->job_description_label), 0.0, 0.5);
+        gtk_box_pack_start (GTK_BOX (content_area), shell->priv->job_description_label, FALSE, FALSE, 0);
+        shell->priv->job_progress_bar = gtk_progress_bar_new ();
+        gtk_box_pack_start (GTK_BOX (content_area), shell->priv->job_progress_bar, FALSE, FALSE, 0);
+
+        shell->priv->job_spinner = bling_spinner_new ();
+        gtk_widget_set_size_request (shell->priv->job_spinner, 16, 16);
+        gtk_box_pack_start (GTK_BOX (content_area), shell->priv->job_spinner, FALSE, FALSE, 0);
+
+        /* --- */
+
         vbox2 = gtk_vbox_new (FALSE, 0);
         gtk_container_set_border_width (GTK_CONTAINER (vbox2), 12);
+        gtk_box_pack_start (GTK_BOX (vbox1), vbox2, TRUE, TRUE, 0);
 
         /* --- */
-        GtkWidget *label;
-        GtkWidget *align;
-        GtkWidget *vbox3;
-        GtkWidget *hbox;
-        GtkWidget *image;
 
         hbox = gtk_hbox_new (FALSE, 12);
         gtk_box_pack_start (GTK_BOX (vbox2), hbox, FALSE, TRUE, 0);
@@ -1919,11 +1999,10 @@ create_window (GduShell *shell)
         gtk_container_set_border_width (GTK_CONTAINER (shell->priv->sections_vbox), 8);
         gtk_box_pack_start (GTK_BOX (vbox2), shell->priv->sections_vbox, TRUE, TRUE, 0);
 
-
         /* setup and add horizontal pane */
         hpane = gtk_hpaned_new ();
         gtk_paned_add1 (GTK_PANED (hpane), treeview_scrolled_window);
-        gtk_paned_add2 (GTK_PANED (hpane), vbox2);
+        gtk_paned_add2 (GTK_PANED (hpane), vbox1);
         //gtk_paned_set_position (GTK_PANED (hpane), 260);
 
         gtk_box_pack_start (GTK_BOX (vbox), hpane, TRUE, TRUE, 0);



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