[gtk+/gtk-2-22] Bug 596428 - GtkAssistant: Support ending with a progress page



commit 01e2fc5b5a99fc9c5096b13bfe6323174465fd35
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed Jun 2 16:00:16 2010 -0400

    Bug 596428 - GtkAssistant: Support ending with a progress page
    
    - Add gtk_assistant_commit()
    
      This function discards the visited pages list so the back button is not
      shown on the current page, and removes the cancel button from subsequent
      pages.  Use this when information provided thus far cannot be revisited.
    
    - Don't show the Forward button on a GTK_ASSISTANT_PAGE_PROGRESS if it's
      the last page (according to the forward page function).
    
    - Append a progress page to the GtkAssistant demo.

 demos/gtk-demo/assistant.c          |   55 +++++++++++++++++++++++++++++-
 docs/reference/gtk/gtk-sections.txt |    1 +
 gtk/gtk.symbols                     |    1 +
 gtk/gtkassistant.c                  |   64 +++++++++++++++++++++++++++++++----
 gtk/gtkassistant.h                  |    4 ++-
 5 files changed, 115 insertions(+), 10 deletions(-)
---
diff --git a/demos/gtk-demo/assistant.c b/demos/gtk-demo/assistant.c
index 6cb5399..a00c595 100644
--- a/demos/gtk-demo/assistant.c
+++ b/demos/gtk-demo/assistant.c
@@ -9,12 +9,35 @@
 #include "demo-common.h"
 
 static GtkWidget *assistant = NULL;
+static GtkWidget *progress_bar = NULL;
+
+static gboolean
+apply_changes_gradually (gpointer data)
+{
+  gdouble fraction;
+
+  /* Work, work, work... */
+  fraction = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (progress_bar));
+  fraction += 0.05;
+
+  if (fraction < 1.0)
+    {
+      gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress_bar), fraction);
+      return TRUE;
+    }
+  else
+    {
+      /* Close automatically once changes are fully applied. */
+      gtk_widget_destroy (assistant);
+      return FALSE;
+    }
+}
 
 static void
 on_assistant_apply (GtkWidget *widget, gpointer data)
 {
-  /* Apply here changes, this is a fictional
-     example, so we just do nothing here */
+  /* Start a timer to simulate changes taking a few seconds to apply. */
+  g_timeout_add (100, apply_changes_gradually, NULL);
 }
 
 static void
@@ -38,6 +61,13 @@ on_assistant_prepare (GtkWidget *widget, GtkWidget *page, gpointer data)
   title = g_strdup_printf ("Sample assistant (%d of %d)", current_page + 1, n_pages);
   gtk_window_set_title (GTK_WINDOW (widget), title);
   g_free (title);
+
+  /* The fourth page (counting from zero) is the progress page.  The
+  * user clicked Apply to get here so we tell the assistant to commit,
+  * which means the changes up to this point are permanent and cannot
+  * be cancelled or revisited. */
+  if (current_page == 3)
+      gtk_assistant_commit (GTK_ASSISTANT (widget));
 }
 
 static void
@@ -127,6 +157,26 @@ create_page3 (GtkWidget *assistant)
   g_object_unref (pixbuf);
 }
 
+static void
+create_page4 (GtkWidget *assistant)
+{
+  GtkWidget *page;
+
+  page = gtk_alignment_new (0.5, 0.5, 0.5, 0.0);
+
+  progress_bar = gtk_progress_bar_new ();
+  gtk_container_add (GTK_CONTAINER (page), progress_bar);
+
+  gtk_widget_show_all (page);
+  gtk_assistant_append_page (GTK_ASSISTANT (assistant), page);
+  gtk_assistant_set_page_type (GTK_ASSISTANT (assistant), page, GTK_ASSISTANT_PAGE_PROGRESS);
+  gtk_assistant_set_page_title (GTK_ASSISTANT (assistant), page, "Applying changes");
+
+  /* This prevents the assistant window from being
+   * closed while we're "busy" applying changes. */
+  gtk_assistant_set_page_complete (GTK_ASSISTANT (assistant), page, FALSE);
+}
+
 GtkWidget*
 do_assistant (GtkWidget *do_widget)
 {
@@ -142,6 +192,7 @@ do_assistant (GtkWidget *do_widget)
       create_page1 (assistant);
       create_page2 (assistant);
       create_page3 (assistant);
+      create_page4 (assistant);
 
       g_signal_connect (G_OBJECT (assistant), "cancel",
 			G_CALLBACK (on_assistant_close_cancel), &assistant);
diff --git a/docs/reference/gtk/gtk-sections.txt b/docs/reference/gtk/gtk-sections.txt
index dda9c47..733e32c 100644
--- a/docs/reference/gtk/gtk-sections.txt
+++ b/docs/reference/gtk/gtk-sections.txt
@@ -371,6 +371,7 @@ gtk_assistant_get_page_complete
 gtk_assistant_add_action_widget
 gtk_assistant_remove_action_widget
 gtk_assistant_update_buttons_state
+gtk_assistant_commit
 
 <SUBSECTION Standard>
 GtkAssistantClass
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 24ad5da..a4d54cf 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -302,6 +302,7 @@ gtk_assistant_get_page_complete
 gtk_assistant_add_action_widget
 gtk_assistant_remove_action_widget
 gtk_assistant_update_buttons_state
+gtk_assistant_commit
 #endif
 #endif
 
diff --git a/gtk/gtkassistant.c b/gtk/gtkassistant.c
index 41ecd13..8f18f13 100644
--- a/gtk/gtkassistant.c
+++ b/gtk/gtkassistant.c
@@ -103,6 +103,8 @@ struct _GtkAssistantPrivate
   GtkAssistantPageFunc forward_function;
   gpointer forward_function_data;
   GDestroyNotify forward_data_destroy;
+
+  guint committed : 1;
 };
 
 static void     gtk_assistant_class_init         (GtkAssistantClass *class);
@@ -267,7 +269,7 @@ gtk_assistant_class_init (GtkAssistantClass *class)
    *
    * A handler for the ::apply signal should carry out the actions for which
    * the wizard has collected data. If the action takes a long time to complete,
-   * you might consider to put a page of type %GTK_ASSISTANT_PAGE_PROGRESS
+   * you might consider putting a page of type %GTK_ASSISTANT_PAGE_PROGRESS
    * after the confirmation page and handle this operation within the
    * #GtkAssistant::prepare signal of the progress page.
    *
@@ -473,6 +475,23 @@ compute_last_button_state (GtkAssistant *assistant)
 }
 
 static void
+compute_progress_state (GtkAssistant *assistant)
+{
+  GtkAssistantPrivate *priv = assistant->priv;
+  gint page_num, n_pages;
+
+  n_pages = gtk_assistant_get_n_pages (assistant);
+  page_num = gtk_assistant_get_current_page (assistant);
+
+  page_num = (priv->forward_function) (page_num, priv->forward_function_data);
+
+  if (page_num >= 0 && page_num < n_pages)
+    gtk_widget_show (assistant->forward);
+  else
+    gtk_widget_hide (assistant->forward);
+}
+
+static void
 set_assistant_header_image (GtkAssistant *assistant)
 {
   GtkAssistantPrivate *priv = assistant->priv;
@@ -509,7 +528,6 @@ set_assistant_buttons_state (GtkAssistant *assistant)
       gtk_widget_set_sensitive (assistant->cancel, TRUE);
       gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
       gtk_widget_grab_default (assistant->forward);
-      gtk_widget_show (assistant->cancel);
       gtk_widget_show (assistant->forward);
       gtk_widget_hide (assistant->back);
       gtk_widget_hide (assistant->apply);
@@ -521,7 +539,6 @@ set_assistant_buttons_state (GtkAssistant *assistant)
       gtk_widget_set_sensitive (assistant->back, TRUE);
       gtk_widget_set_sensitive (assistant->apply, priv->current_page->complete);
       gtk_widget_grab_default (assistant->apply);
-      gtk_widget_show (assistant->cancel);
       gtk_widget_show (assistant->back);
       gtk_widget_show (assistant->apply);
       gtk_widget_hide (assistant->forward);
@@ -533,7 +550,6 @@ set_assistant_buttons_state (GtkAssistant *assistant)
       gtk_widget_set_sensitive (assistant->back, TRUE);
       gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
       gtk_widget_grab_default (assistant->forward);
-      gtk_widget_show (assistant->cancel);
       gtk_widget_show (assistant->back);
       gtk_widget_show (assistant->forward);
       gtk_widget_hide (assistant->apply);
@@ -544,7 +560,6 @@ set_assistant_buttons_state (GtkAssistant *assistant)
       gtk_widget_set_sensitive (assistant->close, priv->current_page->complete);
       gtk_widget_grab_default (assistant->close);
       gtk_widget_show (assistant->close);
-      gtk_widget_hide (assistant->cancel);
       gtk_widget_hide (assistant->back);
       gtk_widget_hide (assistant->forward);
       gtk_widget_hide (assistant->apply);
@@ -555,17 +570,23 @@ set_assistant_buttons_state (GtkAssistant *assistant)
       gtk_widget_set_sensitive (assistant->back, priv->current_page->complete);
       gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
       gtk_widget_grab_default (assistant->forward);
-      gtk_widget_show (assistant->cancel);
       gtk_widget_show (assistant->back);
-      gtk_widget_show (assistant->forward);
       gtk_widget_hide (assistant->apply);
       gtk_widget_hide (assistant->close);
       gtk_widget_hide (assistant->last);
+      compute_progress_state (assistant);
       break;
     default:
       g_assert_not_reached ();
     }
 
+  if (priv->committed)
+    gtk_widget_hide (assistant->cancel);
+  else if (priv->current_page->type == GTK_ASSISTANT_PAGE_SUMMARY)
+    gtk_widget_hide (assistant->cancel);
+  else
+    gtk_widget_show (assistant->cancel);
+
   /* this is quite general, we don't want to
    * go back if it's the first page */
   if (!priv->visited_pages)
@@ -2259,6 +2280,35 @@ gtk_assistant_update_buttons_state (GtkAssistant *assistant)
   set_assistant_buttons_state (assistant);
 }
 
+/**
+ * gtk_assistant_commit:
+ * @assistant: a #GtkAssistant
+ *
+ * Erases the visited page history so the back button is not
+ * shown on the current page, and removes the cancel button
+ * from subsequent pages.
+ *
+ * Use this when the information provided up to the current
+ * page is hereafter deemed permanent and cannot be modified
+ * or undone.  For example, showing a progress page to track
+ * a long-running, unreversible operation after the user has
+ * clicked apply on a confirmation page.
+ *
+ * Since: 2.22
+ **/
+void
+gtk_assistant_commit (GtkAssistant *assistant)
+{
+  g_return_if_fail (GTK_IS_ASSISTANT (assistant));
+
+  g_slist_free (assistant->priv->visited_pages);
+  assistant->priv->visited_pages = NULL;
+
+  assistant->priv->committed = TRUE;
+
+  set_assistant_buttons_state (assistant);
+}
+
 
 
 /* accessible implementation */
diff --git a/gtk/gtkassistant.h b/gtk/gtkassistant.h
index 5f26325..766b9d0 100644
--- a/gtk/gtkassistant.h
+++ b/gtk/gtkassistant.h
@@ -57,7 +57,8 @@ G_BEGIN_DECLS
  * used to handle buttons sensitivity and visibility.
  *
  * Note that an assistant needs to end its page flow with a page of type
- * %GTK_ASSISTANT_PAGE_CONFIRM or %GTK_ASSISTANT_PAGE_SUMMARY to be correct.
+ * %GTK_ASSISTANT_PAGE_CONFIRM, %GTK_ASSISTANT_PAGE_SUMMARY or
+ * %GTK_ASSISTANT_PAGE_PROGRESS to be correct.
  */
 typedef enum
 {
@@ -168,6 +169,7 @@ void                  gtk_assistant_remove_action_widget  (GtkAssistant
 							   GtkWidget            *child);
 
 void                  gtk_assistant_update_buttons_state  (GtkAssistant *assistant);
+void                  gtk_assistant_commit                (GtkAssistant *assistant);
 
 G_END_DECLS
 



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