GnuCash 2.3.0
Files | Typedefs | Functions
Progress Dialog
Dialogs

Dialog for displaying progress of long-running operations. More...

Files

file  dialog-progress.h
 

API for displaying progress of long-running operations.


Typedefs

typedef struct _GNCProgressDialog GNCProgressDialog
typedef gboolean(* GNCProgressCancelFunc )(gpointer user_data)

Functions

GNCProgressDialoggnc_progress_dialog_new (GtkWidget *parent, gboolean use_ok_button)
GNCProgressDialoggnc_progress_dialog_custom (GtkLabel *primary, GtkLabel *secondary, GtkProgressBar *bar, GtkLabel *suboperation, GtkTextView *log)
void gnc_progress_dialog_set_title (GNCProgressDialog *progress, const char *title)
void gnc_progress_dialog_set_primary (GNCProgressDialog *progress, const gchar *str)
void gnc_progress_dialog_set_heading (GNCProgressDialog *progress, const char *heading)
void gnc_progress_dialog_set_secondary (GNCProgressDialog *progress, const gchar *str)
void gnc_progress_dialog_set_sub (GNCProgressDialog *progress, const gchar *str)
void gnc_progress_dialog_reset_log (GNCProgressDialog *progress)
void gnc_progress_dialog_append_log (GNCProgressDialog *progress, const gchar *str)
void gnc_progress_dialog_pause (GNCProgressDialog *progress)
void gnc_progress_dialog_resume (GNCProgressDialog *progress)
void gnc_progress_dialog_set_cancel_func (GNCProgressDialog *progress, GNCProgressCancelFunc cancel_func, gpointer user_data)
void gnc_progress_dialog_set_cancel_scm_func (GNCProgressDialog *progress, SCM cancel_scm_func)
void gnc_progress_dialog_set_value (GNCProgressDialog *progress, gdouble value)
guint gnc_progress_dialog_push (GNCProgressDialog *progress, gdouble weight)
guint gnc_progress_dialog_pop (GNCProgressDialog *progress)
guint gnc_progress_dialog_pop_full (GNCProgressDialog *progress)
void gnc_progress_dialog_reset_value (GNCProgressDialog *progress)
void gnc_progress_dialog_update (GNCProgressDialog *progress)
void gnc_progress_dialog_finish (GNCProgressDialog *progress)
void gnc_progress_dialog_destroy (GNCProgressDialog *progress)

Detailed Description

Dialog for displaying progress of long-running operations.

These functions constitute an API for streamlining the creation and management of progress dialogs. Once registered with the API, the dialog's display and behavior can be controlled via simple calls that prevent the caller from needing to know anything about the underlying GUI.

A pop-up progress dialog can be created, displayed, and registered with the API by calling gnc_progress_dialog_new(). Alternatively, existing widgets can be registered with the API by calling gnc_progress_dialog_custom(). This method allows custom-made dialogs to hand off the management of typical progress-related widgets, and allows long-running operations report progress in a standard way.


Function Documentation

void gnc_progress_dialog_append_log ( GNCProgressDialog progress,
const gchar *  str 
)

Append str to the progress log.

Parameters:
progressa ::GNCProgressDialog
strthe text to be appended

Definition at line 457 of file dialog-progress.c.

{
    GtkTextBuffer *buf;
    GtkTextIter    iter;

    g_return_if_fail(progress);

    if (progress->log == NULL || !str || !*str)
        return;

    /* Append to the text buffer. */
    buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(progress->log));
    gtk_text_buffer_get_end_iter(buf, &iter);
    gtk_text_buffer_insert(buf, &iter, str, -1);

    gnc_progress_dialog_update(progress);
}
GNCProgressDialog* gnc_progress_dialog_custom ( GtkLabel *  primary,
GtkLabel *  secondary,
GtkProgressBar *  bar,
GtkLabel *  suboperation,
GtkTextView *  log 
)

Creates a dialog for displaying the progress of an activity using existing widgets. This allows long-running operations to update the progress in a custom dialog instead of a new pop-up.

Parameters:
primarya GtkLabel widget to use for primary text
secondarya GtkLabel widget to use for secondary text
bara GtkProgressBar widget for filling or pulsing
suboperationa GtkLabel widget to use for suboperation text
loga GtkTextView widget for logging progress textually

Any of the parameters may be passed as NULL if management of that visual element is not desired.

Returns:
A ::GNCProgressDialog that identifies the dialog and is needed when making subsequent API calls.

Definition at line 285 of file dialog-progress.c.

{
    GNCProgressDialog *progress;

    progress = g_new0(GNCProgressDialog, 1);

    /* Set up widgets. */
    progress->dialog = NULL;
    progress->primary_label = GTK_WIDGET(primary);
    progress->secondary_label = GTK_WIDGET(secondary);
    progress->progress_bar = GTK_WIDGET(bar);
    progress->sub_label = GTK_WIDGET(suboperation);
    progress->log = GTK_WIDGET(log);
    progress->ok_button = NULL;
    progress->cancel_button = NULL;

    /* Initialize all other items. */
    progress->total_offset = 0;
    progress->total_weight = 1;
    progress->bar_value = 0;
    progress->cancel_func = NULL;
    progress->user_data = NULL;
    progress->cancel_scm_func = SCM_UNDEFINED;
    progress->use_ok_button = FALSE;
    progress->closed = FALSE;
    progress->finished = FALSE;
    progress->destroyed = FALSE;
    progress->title_set = FALSE;

    return progress;
}
void gnc_progress_dialog_destroy ( GNCProgressDialog progress)

Destroy the dialog. If gnc_progress_dialog_finish has been called, the dialog will not be destroyed until the user dismisses the window. This function must be called in order to reclaim the dialog's memory.

Parameters:
progressa ::GNCProgressDialog

Definition at line 781 of file dialog-progress.c.

{
    g_return_if_fail(progress);

    /* Make sure the callbacks aren't invoked */
    progress->cancel_func = NULL;
    if (progress->cancel_scm_func != SCM_UNDEFINED)
        scm_gc_unprotect_object(progress->cancel_scm_func);
    progress->cancel_scm_func = SCM_UNDEFINED;

    if (!progress->finished)
    {
        if (progress->dialog != NULL)
            gtk_widget_hide(progress->dialog);
        progress->closed = TRUE;
    }

    progress->destroyed = TRUE;

    gnc_progress_maybe_destroy(progress);
}
void gnc_progress_dialog_finish ( GNCProgressDialog progress)

Set the progress meter to fully complete, change the heading, if any, to "Complete", enable the 'OK' button, and make the dialog non-modal.

Parameters:
progressa ::GNCProgressDialog

Definition at line 750 of file dialog-progress.c.

{
    g_return_if_fail(progress);

    if (!progress->use_ok_button)
    {
        if (progress->dialog != NULL)
            gtk_widget_hide(progress->dialog);
        progress->closed = TRUE;
    }

    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress->progress_bar), 1.0);

    gtk_widget_set_sensitive(progress->ok_button, TRUE);
    gtk_widget_set_sensitive(progress->cancel_button, FALSE);

    if (GTK_WIDGET_VISIBLE(progress->primary_label))
        gnc_progress_dialog_set_heading(progress, _("Complete"));

    if (!progress->title_set)
        gtk_window_set_title(GTK_WINDOW(progress->dialog), _("Complete"));

    gtk_window_set_modal(GTK_WINDOW(progress->dialog), FALSE);

    progress->finished = TRUE;

    gnc_progress_dialog_update(progress);
}
GNCProgressDialog* gnc_progress_dialog_new ( GtkWidget *  parent,
gboolean  use_ok_button 
)

Displays a pop-up dialog for showing the progress of a long-running activity.

By default only a title and progress bar are shown, but additional visual elements such as a Cancel button, text log, and additional labels can be activated by following with calls to some of the other API functions.

Parameters:
parentThe parent window for which the progress dialog becomes modal.
use_ok_buttonIf TRUE, an OK button is shown and must be clicked when progress is completed.
Returns:
A ::GNCProgressDialog that identifies the dialog and is needed when making subsequent API calls.

Definition at line 266 of file dialog-progress.c.

{
    GNCProgressDialog *progress;

    progress = g_new0(GNCProgressDialog, 1);

    progress->use_ok_button = use_ok_button;

    gnc_progress_dialog_create(parent, progress);

    gtk_widget_show(progress->dialog);

    gnc_progress_dialog_update(progress);

    return progress;
}
void gnc_progress_dialog_pause ( GNCProgressDialog progress)

Show that progress has been paused by appending "(paused)" to the suboperation text, the window title, or the primary text. The first that is both known and currently shown will be the one used.

Parameters:
progressa ::GNCProgressDialog

Definition at line 477 of file dialog-progress.c.

{
    gchar *suffix;

    g_return_if_fail(progress);

    suffix = g_strconcat(" ", _("(paused)"), NULL);

    if (progress->sub_label && GTK_WIDGET_VISIBLE(progress->sub_label))
    {
        const gchar *txt = gtk_label_get_text(GTK_LABEL(progress->sub_label));

        if (txt && !g_str_has_suffix(txt, suffix))
        {
            gchar *newtxt = g_strconcat(txt, suffix, NULL);
            gnc_progress_dialog_set_sub(progress, newtxt);
            g_free(newtxt);
        }
    }
    else if (progress->dialog)
    {
        const gchar *txt = gtk_window_get_title(GTK_WINDOW(progress->dialog));

        if (txt && !g_str_has_suffix(txt, suffix))
        {
            gchar *newtxt = g_strconcat(txt, suffix, NULL);
            gtk_window_set_title(GTK_WINDOW(progress->dialog), newtxt);
            g_free(newtxt);
        }
    }
    else if (progress->primary_label &&
             GTK_WIDGET_VISIBLE(progress->primary_label))
    {
        const gchar *txt = gtk_label_get_text(GTK_LABEL(progress->primary_label));

        if (txt && !g_str_has_suffix(txt, suffix))
        {
            gchar *newtxt = g_strconcat(txt, suffix, NULL);
            gnc_progress_dialog_set_primary(progress, newtxt);
            g_free(newtxt);
        }
    }

    g_free(suffix);

    gnc_progress_dialog_update(progress);
}
guint gnc_progress_dialog_pop ( GNCProgressDialog progress)

Moves up one level in the stack of virtual bars. See gnc_progress_dialog_push() for an explanation of virtual bars.

Parameters:
progressa ::GNCProgressDialog
Returns:
the number of times that gnc_progress_dialog_pop() would have to be called again to return to the top level.

Definition at line 683 of file dialog-progress.c.

{
    VirtualBar     *bar;

    g_return_val_if_fail(progress, 0);

    /* Get the progress bar widget. */
    if (progress->progress_bar == NULL || progress->bars == NULL)
        return 0;

    /* Pop the bar off the bar stack. */
    bar = progress->bars->data;
    progress->bars = g_list_delete_link(progress->bars, progress->bars);

    /* Determine the value of the current bar. */
    progress->bar_value = bar->offset + bar->weight * progress->bar_value;

    /* Set the total effective offset and weight. */
    if (progress->bars == NULL)
    {
        progress->total_offset = 0;
        progress->total_weight = 1;
    }
    else
    {
        progress->total_offset -= bar->offset *
                                  ((VirtualBar *) progress->bars->data)->weight;
        progress->total_weight /= bar->weight;
    }
    g_free(bar);

    if (progress->bars == NULL)
        return 0;
    return g_list_length(progress->bars);
}
guint gnc_progress_dialog_pop_full ( GNCProgressDialog progress)

Fills the current progress bar, then calls gnc_progress_dialog_pop().

Parameters:
progressa ::GNCProgressDialog
Returns:
the value returned by gnc_progress_dialog_pop()

Definition at line 721 of file dialog-progress.c.

{
    gnc_progress_dialog_set_value(progress, 1);
    return gnc_progress_dialog_pop(progress);
}
guint gnc_progress_dialog_push ( GNCProgressDialog progress,
gdouble  weight 
)

Create a new "virtual" progress bar that, as it becomes full, will fill the current bar by the fraction specified by weight. All calls to gnc_progress_dialog_set_value() will operate on the new bar until gnc_progress_dialog_pop() is called.

This can be used to split an operation into weighted sub-operations. For example, if a particular suboperation should fill 30% of the bar, call gnc_progress_dialog_push() with a weight of 0.3. Calls to gnc_progress_dialog_set_value() will fill the virtual bar, which in turn trickles up at the 0.3 rate.

Multiple calls to gnc_progress_dialog_push() can be used to create a stack of virtual bars, each subordinate to the last. This allows a task to be split into any number of levels of sub-tasks.

Parameters:
progressa ::GNCProgressDialog
weightthe requested fraction of the current bar that the new bar will represent (The fraction actually assigned will be the lesser of the requested amount and the amount of the bar that is unfilled.)
Returns:
the number of times that gnc_progress_dialog_pop() would have to be called to return to the top level.

Definition at line 648 of file dialog-progress.c.

{
    GtkProgressBar *bar;
    VirtualBar     *newbar;

    g_return_val_if_fail(progress, 0);
    g_return_val_if_fail(weight > 0, 0);

    /* Get the progress bar widget. */
    bar = GTK_PROGRESS_BAR(progress->progress_bar);
    if (bar == NULL)
        return 0;

    /* Create the new virtual progress bar. */
    newbar = g_new0(VirtualBar, 1);
    newbar->offset = progress->bar_value;
    if (newbar->offset + weight > 1)
        /* The requested weight is more than the unfilled portion of the bar. */
        newbar->weight = 1 - newbar->offset;
    else
        newbar->weight = weight;
    progress->bars = g_list_prepend(progress->bars, newbar);

    /* Set the total effective offset and weight */
    progress->total_offset = gtk_progress_bar_get_fraction(bar);
    progress->total_weight *= newbar->weight;

    /* Set the new bar as unfilled. */
    progress->bar_value = 0;

    return g_list_length(progress->bars);
}
void gnc_progress_dialog_reset_log ( GNCProgressDialog progress)

Show the progress log and delete any existing text. If the dialog was created via gnc_progress_dialog_new(), the log is not shown by default. Calling this function will make it appear.

Parameters:
progressa ::GNCProgressDialog

Definition at line 434 of file dialog-progress.c.

{
    GtkTextBuffer *buf;

    g_return_if_fail(progress);

    if (progress->log == NULL)
        return;

    /* Reset the text buffer. */
    buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(progress->log));
    gtk_text_buffer_set_text(buf, "", -1);
    gtk_text_buffer_set_modified(buf, FALSE);

    /* Show the log and its parent (in case it is in a scrolled window). */
    gtk_widget_show(progress->log);
    gtk_widget_show(gtk_widget_get_parent(progress->log));

    gnc_progress_dialog_update(progress);
}
void gnc_progress_dialog_reset_value ( GNCProgressDialog progress)

Pop up to the top level and clear the progress bar.

Parameters:
progressa ::GNCProgressDialog

Definition at line 729 of file dialog-progress.c.

{
    g_return_if_fail(progress);

    /* Return to the top level. */
    while (gnc_progress_dialog_pop(progress));

    /* Reset the bar to empty. */
    gnc_progress_dialog_set_value(progress, 0);
}
void gnc_progress_dialog_resume ( GNCProgressDialog progress)

Remove any indication that progress has paused by removing any existing "(paused)" suffix from the suboperation text, the window title, and the primary text.

Parameters:
progressa ::GNCProgressDialog

Definition at line 526 of file dialog-progress.c.

{
    gchar *suffix;

    g_return_if_fail(progress);

    suffix = g_strconcat(" ", _("(paused)"), NULL);

    /* Remove any pause indication from the suboperation label. */
    if (progress->sub_label)
    {
        const gchar *txt = gtk_label_get_text(GTK_LABEL(progress->sub_label));

        if (txt && g_str_has_suffix(txt, suffix))
        {
            gchar *newtxt = g_strndup(txt, strlen(txt) - strlen(suffix));
            gnc_progress_dialog_set_sub(progress, newtxt);
            g_free(newtxt);
        }
    }

    /* Remove any pause indication from the window title. */
    if (progress->dialog)
    {
        const gchar *txt = gtk_window_get_title(GTK_WINDOW(progress->dialog));

        if (txt && g_str_has_suffix(txt, suffix))
        {
            gchar *newtxt = g_strndup(txt, strlen(txt) - strlen(suffix));
            gtk_window_set_title(GTK_WINDOW(progress->dialog), newtxt);
            g_free(newtxt);
        }
    }

    /* Remove any pause indication from the primary text. */
    if (progress->primary_label)
    {
        const gchar *txt = gtk_label_get_text(GTK_LABEL(progress->primary_label));

        if (txt && g_str_has_suffix(txt, suffix))
        {
            gchar *newtxt = g_strndup(txt, strlen(txt) - strlen(suffix));
            gnc_progress_dialog_set_primary(progress, newtxt);
            g_free(newtxt);
        }
    }

    g_free(suffix);

    gnc_progress_dialog_update(progress);
}
void gnc_progress_dialog_set_cancel_func ( GNCProgressDialog progress,
GNCProgressCancelFunc  cancel_func,
gpointer  user_data 
)

Show a Cancel button and set the C function which will be called when it is pressed by the user. The cancel function must return a boolean value. If the value is TRUE, the window is hidden.

Parameters:
progressa ::GNCProgressDialog
cancel_functhe callback function
user_datauser data to be passed to cancel_func

Definition at line 580 of file dialog-progress.c.

{
    g_return_if_fail(progress);

    if (progress->cancel_button == NULL)
        return;

    progress->cancel_func = cancel_func;
    progress->user_data = user_data;

    if (cancel_func)
        gtk_widget_show(progress->cancel_button);
}
void gnc_progress_dialog_set_cancel_scm_func ( GNCProgressDialog progress,
SCM  cancel_scm_func 
)

Show a Cancel button and set the Guile procedure that will be called when it is pressed by the user. It will be called after any C function registered with gnc_progress_dialog_set_cancel_func(). The procedure must return #t if the dialog should be hidden. If there is no C or Guile cancel callback (the default state), the Cancel button is hidden.

Parameters:
progressa ::GNCProgressDialog
cancel_scm_functhe Guile callback procedure

Definition at line 598 of file dialog-progress.c.

{
    g_return_if_fail(progress);

    if (progress->cancel_button == NULL)
        return;

    if (progress->cancel_scm_func != SCM_UNDEFINED)
        scm_gc_unprotect_object(progress->cancel_scm_func);

    if (scm_is_procedure(cancel_scm_func))
    {
        progress->cancel_scm_func = cancel_scm_func;
        scm_gc_protect_object(cancel_scm_func);
        gtk_widget_show(progress->cancel_button);
    }
    else
        progress->cancel_scm_func = SCM_UNDEFINED;
}
void gnc_progress_dialog_set_heading ( GNCProgressDialog progress,
const char *  heading 
)

Set the primary text of the progress dialog. If str is NULL or blank, the label is hidden (this is the default state).

Parameters:
progressa ::GNCProgressDialog
headingthe text to be displayed

NOTE: For HIG-compliant dialogs, use gnc_progress_dialog_set_primary() instead.

Definition at line 367 of file dialog-progress.c.

{
    g_return_if_fail(progress);

    if (progress->primary_label == NULL)
        return;

    if (heading == NULL || *heading == '\0')
        gtk_widget_hide(progress->primary_label);
    else
    {
        gtk_label_set_text(GTK_LABEL(progress->primary_label), heading);
        gtk_widget_show(progress->primary_label);
    }

    gnc_progress_dialog_update(progress);
}
void gnc_progress_dialog_set_primary ( GNCProgressDialog progress,
const gchar *  str 
)

Set the primary text of the progress dialog. The text will be displayed using the HIG-recommended style. If str is NULL or blank, the label is hidden (this is the default state).

Parameters:
progressa ::GNCProgressDialog
strthe text to be displayed

Definition at line 342 of file dialog-progress.c.

{
    g_return_if_fail(progress);

    if (progress->primary_label == NULL)
        return;

    if (str == NULL || *str == '\0')
        gtk_widget_hide(progress->primary_label);
    else
    {
        /* Display the primary text with the HIG-recommended style. */
        char *markup = g_markup_printf_escaped("<span weight=\"bold\" size=\"larger\">%s</span>", str);

        gtk_label_set_markup(GTK_LABEL(progress->primary_label), markup);
        g_free(markup);
        gtk_widget_show(progress->primary_label);
    }

    gnc_progress_dialog_update(progress);
}
void gnc_progress_dialog_set_secondary ( GNCProgressDialog progress,
const gchar *  str 
)

Set the secondary text of the progress dialog. The text will be displayed using the HIG-recommended style. If str is NULL or blank, the label is hidden (this is the default state).

Parameters:
progressa ::GNCProgressDialog
strthe text to be displayed

Definition at line 388 of file dialog-progress.c.

{
    g_return_if_fail(progress);

    if (progress->secondary_label == NULL)
        return;

    if (str == NULL || *str == '\0')
        gtk_widget_hide(progress->secondary_label);
    else
    {
        gtk_label_set_text(GTK_LABEL(progress->secondary_label), str);
        gtk_widget_show(progress->secondary_label);
    }

    gnc_progress_dialog_update(progress);
}
void gnc_progress_dialog_set_sub ( GNCProgressDialog progress,
const gchar *  str 
)

Set the suboperation text of the progress dialog. The text will be displayed using the HIG-recommended style. If str is NULL or blank, the label is hidden (this is the default state).

Parameters:
progressa ::GNCProgressDialog
strthe text to be displayed

Definition at line 409 of file dialog-progress.c.

{
    g_return_if_fail(progress);

    if (progress->sub_label == NULL)
        return;

    if (str == NULL || *str == '\0')
        gtk_widget_hide(progress->sub_label);
    else
    {
        /* Display the suboperation text with the HIG-recommended style. */
        char *markup = g_markup_printf_escaped("<span style=\"italic\">%s</span>", str);

        gtk_label_set_markup(GTK_LABEL(progress->sub_label), markup);
        g_free(markup);
        gtk_widget_show(progress->sub_label);
    }

    gnc_progress_dialog_update(progress);
}
void gnc_progress_dialog_set_title ( GNCProgressDialog progress,
const char *  title 
)

Set the title of a pop-up progress dialog. This function has no effect on dialogs registered using gnc_progress_dialog_custom().

Parameters:
progressa ::GNCProgressDialog
titlethe window title to display

Definition at line 323 of file dialog-progress.c.

{
    g_return_if_fail(progress);

    if (!progress->dialog)
        return;

    if (title == NULL)
        title = "";

    gtk_window_set_title(GTK_WINDOW(progress->dialog), title);

    progress->title_set = TRUE;

    gnc_progress_dialog_update(progress);
}
void gnc_progress_dialog_set_value ( GNCProgressDialog progress,
gdouble  value 
)

Set the fraction of the progress bar to fill, where 0 is empty and 1 is full. If value is over 1, the bar will pulse instead of fill.

Parameters:
progressa ::GNCProgressDialog
valuethe fraction of the bar to fill

Definition at line 621 of file dialog-progress.c.

{
    GtkProgressBar *bar;

    g_return_if_fail(progress);

    /* Get the progress bar widget. */
    bar = GTK_PROGRESS_BAR(progress->progress_bar);
    if (bar == NULL)
        return;

    /* Update the progress bar. If value is over 1,
     * the bar will pulse instead of fill. */
    if (value > 1)
        gtk_progress_bar_pulse(bar);
    else
    {
        progress->bar_value = value > 0 ? value : 0;
        gtk_progress_bar_set_fraction(bar,
                                      progress->total_offset + progress->bar_value * progress->total_weight);
    }

    gnc_progress_dialog_update(progress);
}
void gnc_progress_dialog_update ( GNCProgressDialog progress)

Update the GUI of the progress dialog, and call any pending cancel callbacks. This function will be called automatically by the other functions, including gnc_progress_dialog_set_value.

Parameters:
progressa ::GNCProgressDialog

Definition at line 742 of file dialog-progress.c.

{
    while (gtk_events_pending())
        gtk_main_iteration();
}
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines