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.
This commit is contained in:
Matthew Barnes 2010-06-02 16:00:16 -04:00
parent 112d97d498
commit bb5c585777
5 changed files with 115 additions and 10 deletions

View File

@ -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);

View File

@ -367,6 +367,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

View File

@ -283,6 +283,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

View File

@ -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.
*
@ -472,6 +474,23 @@ compute_last_button_state (GtkAssistant *assistant)
gtk_widget_hide (assistant->last);
}
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)
{
@ -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)
@ -2264,6 +2285,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 */

View File

@ -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