Create a progress dialog with a guile-wrapped API.

Add an extensions menu item for testing the progess dialog.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3041 57a11ea4-9604-0410-9ed3-97b8803252fd
zzzoldreleases/1.6
Dave Peticolas 26 years ago
parent 417a9fba57
commit 5b7f7130ba

@ -5,6 +5,7 @@ po/pseudo-source.c
po/guile_strings.txt
src/gnome/dialog-account-picker.c
src/gnome/dialog-fincalc.c
src/gnome/dialog-progress.c
src/gnome/dialog-qif-import.c
src/gnome/glade-gnc-dialogs.c
src/gnome/print-session.c

@ -12,6 +12,7 @@ libgncgnome_a_SOURCES = \
dialog-find-transactions.c \
dialog-options.c \
dialog-print-check.c \
dialog-progress.c \
dialog-qif-import.c \
dialog-totd.c \
dialog-transfer.c \
@ -49,6 +50,7 @@ noinst_HEADERS = \
dialog-find-transactions.h \
dialog-options.h \
dialog-print-check.h \
dialog-progress.h \
dialog-qif-import.h \
dialog-totd.h \
dialog-transfer.h \

@ -0,0 +1,364 @@
/********************************************************************\
* dialog-progress.c -- GnuCash progress dialog *
* Copyright (C) 2000 Dave Peticolas *
* *
* 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, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#include "config.h"
#include <gnome.h>
#include <guile/gh.h>
#include "dialog-progress.h"
#include "glade-gnc-dialogs.h"
#include "messages.h"
struct _GNCProgressDialog
{
GtkWidget *dialog;
GtkWidget *heading_label;
GtkWidget *progress_bar;
GtkWidget *ok_button;
GtkWidget *cancel_button;
GNCProgressCancelFunc cancel_func;
gpointer user_data;
SCM cancel_scm_func;
gboolean closed;
gboolean finished;
gboolean destroyed;
gboolean title_set;
};
static void
gnc_progress_maybe_destroy (GNCProgressDialog *progress)
{
if (!(progress->closed && progress->destroyed))
return;
gtk_widget_destroy(progress->dialog);
}
static void
ok_cb(GtkWidget * widget, gpointer data)
{
GNCProgressDialog *progress = data;
gtk_widget_hide(progress->dialog);
progress->closed = TRUE;
gnc_progress_maybe_destroy (progress);
}
static void
cancel_cb(GtkWidget * widget, gpointer data)
{
GNCProgressDialog *progress = data;
if (progress->cancel_func && !progress->cancel_func (progress->user_data))
return;
if (progress->cancel_scm_func != SCM_UNDEFINED)
{
SCM result;
result = gh_call0(progress->cancel_scm_func);
if (!gh_scm2bool (result))
return;
}
gtk_widget_hide(progress->dialog);
progress->closed = TRUE;
gnc_progress_maybe_destroy (progress);
}
static gboolean
delete_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
{
GNCProgressDialog *progress = data;
if (progress->finished)
{
gtk_widget_hide(progress->dialog);
progress->closed = TRUE;
gnc_progress_maybe_destroy (progress);
return TRUE;
}
if (progress->cancel_func)
{
if (progress->cancel_func (progress->user_data))
{
gtk_widget_hide(progress->dialog);
progress->closed = TRUE;
gnc_progress_maybe_destroy (progress);
return TRUE;
}
}
if (progress->cancel_scm_func != SCM_UNDEFINED)
{
SCM result;
result = gh_call0(progress->cancel_scm_func);
if (gh_scm2bool (result))
{
gtk_widget_hide(progress->dialog);
progress->closed = TRUE;
gnc_progress_maybe_destroy (progress);
return TRUE;
}
}
/* Don't delete the window, wait for gnc_progress_dialog_destroy. */
return TRUE;
}
static void
destroy_cb(GtkObject *object, gpointer data)
{
GNCProgressDialog *progress = data;
/* Make sure the callbacks aren't invoked */
progress->cancel_func = NULL;
if (progress->cancel_scm_func != SCM_UNDEFINED)
scm_unprotect_object (progress->cancel_scm_func);
progress->cancel_scm_func = SCM_UNDEFINED;
g_free(progress);
}
static void
gnc_progress_dialog_create(GtkWidget * parent, GNCProgressDialog *progress)
{
GtkWidget *dialog;
GtkObject *tdo;
dialog = create_Progress_Dialog();
progress->dialog = dialog;
tdo = GTK_OBJECT (dialog);
/* parent */
if (parent != NULL)
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(parent));
gtk_signal_connect (tdo, "delete_event",
GTK_SIGNAL_FUNC (delete_cb), progress);
gtk_signal_connect (tdo, "destroy", GTK_SIGNAL_FUNC (destroy_cb), progress);
progress->heading_label = gtk_object_get_data(tdo, "heading_label");
gtk_widget_hide(progress->heading_label);
progress->progress_bar = gtk_object_get_data(tdo, "progress_bar");
gtk_progress_set_show_text (GTK_PROGRESS(progress->progress_bar), TRUE);
gtk_progress_configure (GTK_PROGRESS(progress->progress_bar),
0.0, 0.0, 100.0);
progress->ok_button = gtk_object_get_data(tdo, "ok_button");
gtk_signal_connect(GTK_OBJECT(progress->ok_button), "clicked",
GTK_SIGNAL_FUNC(ok_cb), progress);
progress->cancel_button = gtk_object_get_data(tdo, "cancel_button");
gtk_signal_connect(GTK_OBJECT(progress->cancel_button), "clicked",
GTK_SIGNAL_FUNC(cancel_cb), progress);
progress->cancel_func = NULL;
progress->user_data = NULL;
progress->cancel_scm_func = SCM_UNDEFINED;
progress->closed = FALSE;
progress->finished = FALSE;
progress->destroyed = FALSE;
progress->title_set = FALSE;
}
GNCProgressDialog *
gnc_progress_dialog_new (GtkWidget * parent)
{
GNCProgressDialog *progress;
progress = g_new0(GNCProgressDialog, 1);
gnc_progress_dialog_create(parent, progress);
gtk_widget_show(progress->dialog);
gnc_progress_dialog_update (progress);
return progress;
}
void
gnc_progress_dialog_set_title (GNCProgressDialog *progress, const char *title)
{
if (progress == NULL)
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_heading (GNCProgressDialog *progress,
const char *heading)
{
if (progress == NULL)
return;
if (heading == NULL || *heading == '\0')
gtk_widget_hide (progress->heading_label);
else
{
gtk_label_set_text (GTK_LABEL (progress->heading_label), heading);
gtk_widget_show (progress->heading_label);
}
gnc_progress_dialog_update (progress);
}
void
gnc_progress_dialog_set_limits (GNCProgressDialog *progress,
gfloat min, gfloat max)
{
if (progress == NULL)
return;
gtk_progress_configure (GTK_PROGRESS (progress->progress_bar),
min, min, max);
gnc_progress_dialog_update (progress);
}
void
gnc_progress_dialog_set_cancel_func (GNCProgressDialog *progress,
GNCProgressCancelFunc cancel_func,
gpointer user_data)
{
if (progress == 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)
{
if (progress == NULL)
return;
if (progress->cancel_scm_func != SCM_UNDEFINED)
scm_unprotect_object (progress->cancel_scm_func);
if (gh_procedure_p(cancel_scm_func))
{
progress->cancel_scm_func = cancel_scm_func;
scm_protect_object (cancel_scm_func);
gtk_widget_show (progress->cancel_button);
}
else
progress->cancel_scm_func = SCM_UNDEFINED;
}
void
gnc_progress_dialog_set_value (GNCProgressDialog *progress, gfloat value)
{
if (progress == NULL)
return;
gtk_progress_set_value (GTK_PROGRESS (progress->progress_bar), value);
gnc_progress_dialog_update (progress);
}
void
gnc_progress_dialog_update (GNCProgressDialog *progress)
{
while (gtk_events_pending())
gtk_main_iteration();
}
void
gnc_progress_dialog_finish (GNCProgressDialog *progress)
{
if (progress == NULL)
return;
gtk_progress_set_percentage (GTK_PROGRESS (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->heading_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);
}
void
gnc_progress_dialog_destroy (GNCProgressDialog *progress)
{
if (progress == NULL)
return;
/* Make sure the callbacks aren't invoked */
progress->cancel_func = NULL;
if (progress->cancel_scm_func != SCM_UNDEFINED)
scm_unprotect_object (progress->cancel_scm_func);
progress->cancel_scm_func = SCM_UNDEFINED;
if (!progress->finished)
{
gtk_widget_hide (progress->dialog);
progress->closed = TRUE;
}
progress->destroyed = TRUE;
gnc_progress_maybe_destroy (progress);
}

@ -0,0 +1,85 @@
/********************************************************************\
* dialog-progress.h -- public GnuCash progress dialog functions *
* Copyright (C) 2000 Dave Peticolas *
* *
* 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, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
#ifndef __DIALOG_PROGRESS_H__
#define __DIALOG_PROGRESS_H__
#include <glib.h>
typedef struct _GNCProgressDialog GNCProgressDialog;
typedef gboolean (*GNCProgressCancelFunc) (gpointer user_data);
/* Create and return a dialog for displaying the progress of
* an activity. Useful for long-running operations. */
GNCProgressDialog * gnc_progress_dialog_new (GtkWidget *parent);
/* Set the title of the progress dialog. */
void gnc_progress_dialog_set_title (GNCProgressDialog *progress,
const char *title);
/* Set the heading (the text above the progress meter) of
* the progress dialog. If it is NULL or blank, the heading
* is hidden (this is the default state). */
void gnc_progress_dialog_set_heading (GNCProgressDialog *progress,
const char *heading);
/* Set the upper and lower bound of the progress meter. */
void gnc_progress_dialog_set_limits (GNCProgressDialog *progress,
gfloat min, gfloat max);
/* Set the C function which will be called if the user hits the
* 'cancel' button. The cancel function returns a boolean value.
* If the value is TRUE, the window is hidden. */
void gnc_progress_dialog_set_cancel_func (GNCProgressDialog *progress,
GNCProgressCancelFunc cancel_func,
gpointer user_data);
/* Set a guile function which will be called if the user hits cancel.
* Will be called after the C function, if any. The function should
* return #t if the dialog should be hidden. If there is no C or guile
* cancel callback (the default state), the cancel button is inactive. */
void gnc_progress_dialog_set_cancel_scm_func (GNCProgressDialog *progress,
SCM cancel_scm_func);
/* Set the value of the progress dialog. */
void gnc_progress_dialog_set_value (GNCProgressDialog *progress, gfloat value);
/* 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. */
void gnc_progress_dialog_update (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. */
void gnc_progress_dialog_finish (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. */
void gnc_progress_dialog_destroy (GNCProgressDialog *progress);
#endif

@ -4528,3 +4528,69 @@ create_Transfer_Dialog (void)
return Transfer_Dialog;
}
GtkWidget*
create_Progress_Dialog (void)
{
GtkWidget *Progress_Dialog;
GtkWidget *vbox85;
GtkWidget *heading_label;
GtkWidget *progress_bar;
GtkWidget *hbuttonbox3;
GtkWidget *ok_button;
GtkWidget *cancel_button;
Progress_Dialog = gtk_window_new (GTK_WINDOW_DIALOG);
gtk_object_set_data (GTK_OBJECT (Progress_Dialog), "Progress_Dialog", Progress_Dialog);
gtk_window_set_title (GTK_WINDOW (Progress_Dialog), _("Working..."));
gtk_window_set_modal (GTK_WINDOW (Progress_Dialog), TRUE);
gtk_window_set_policy (GTK_WINDOW (Progress_Dialog), FALSE, FALSE, FALSE);
vbox85 = gtk_vbox_new (FALSE, 5);
gtk_widget_ref (vbox85);
gtk_object_set_data_full (GTK_OBJECT (Progress_Dialog), "vbox85", vbox85,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (vbox85);
gtk_container_add (GTK_CONTAINER (Progress_Dialog), vbox85);
gtk_container_set_border_width (GTK_CONTAINER (vbox85), 5);
heading_label = gtk_label_new (_("Heading"));
gtk_widget_ref (heading_label);
gtk_object_set_data_full (GTK_OBJECT (Progress_Dialog), "heading_label", heading_label,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (heading_label);
gtk_box_pack_start (GTK_BOX (vbox85), heading_label, FALSE, FALSE, 0);
progress_bar = gtk_progress_bar_new ();
gtk_widget_ref (progress_bar);
gtk_object_set_data_full (GTK_OBJECT (Progress_Dialog), "progress_bar", progress_bar,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (progress_bar);
gtk_box_pack_start (GTK_BOX (vbox85), progress_bar, FALSE, FALSE, 0);
gtk_progress_set_show_text (GTK_PROGRESS (progress_bar), TRUE);
hbuttonbox3 = gtk_hbutton_box_new ();
gtk_widget_ref (hbuttonbox3);
gtk_object_set_data_full (GTK_OBJECT (Progress_Dialog), "hbuttonbox3", hbuttonbox3,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbuttonbox3);
gtk_box_pack_start (GTK_BOX (vbox85), hbuttonbox3, TRUE, TRUE, 0);
ok_button = gnome_stock_button (GNOME_STOCK_BUTTON_OK);
gtk_widget_ref (ok_button);
gtk_object_set_data_full (GTK_OBJECT (Progress_Dialog), "ok_button", ok_button,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (ok_button);
gtk_container_add (GTK_CONTAINER (hbuttonbox3), ok_button);
gtk_widget_set_sensitive (ok_button, FALSE);
GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT);
cancel_button = gnome_stock_button (GNOME_STOCK_BUTTON_CANCEL);
gtk_widget_ref (cancel_button);
gtk_object_set_data_full (GTK_OBJECT (Progress_Dialog), "cancel_button", cancel_button,
(GtkDestroyNotify) gtk_widget_unref);
gtk_container_add (GTK_CONTAINER (hbuttonbox3), cancel_button);
GTK_WIDGET_SET_FLAGS (cancel_button, GTK_CAN_DEFAULT);
return Progress_Dialog;
}

@ -15,3 +15,4 @@ GtkWidget* create_Financial_Calculator_Dialog (void);
GtkWidget* create_Amortization_Schedule_Dialog (void);
GtkWidget* create_Account_Dialog (void);
GtkWidget* create_Transfer_Dialog (void);
GtkWidget* create_Progress_Dialog (void);

@ -6679,4 +6679,95 @@ Daily (365)
</widget>
</widget>
<widget>
<class>GtkWindow</class>
<name>Progress Dialog</name>
<title>Working...</title>
<type>GTK_WINDOW_DIALOG</type>
<position>GTK_WIN_POS_NONE</position>
<modal>True</modal>
<allow_shrink>False</allow_shrink>
<allow_grow>False</allow_grow>
<auto_shrink>False</auto_shrink>
<widget>
<class>GtkVBox</class>
<name>vbox85</name>
<border_width>5</border_width>
<homogeneous>False</homogeneous>
<spacing>5</spacing>
<widget>
<class>GtkLabel</class>
<name>heading_label</name>
<label>Heading</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkProgressBar</class>
<name>progress_bar</name>
<value>0</value>
<lower>0</lower>
<upper>100</upper>
<bar_style>GTK_PROGRESS_CONTINUOUS</bar_style>
<orientation>GTK_PROGRESS_LEFT_TO_RIGHT</orientation>
<activity_mode>False</activity_mode>
<show_text>True</show_text>
<format>%P %%</format>
<text_xalign>0.5</text_xalign>
<text_yalign>0.5</text_yalign>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkHButtonBox</class>
<name>hbuttonbox3</name>
<layout_style>GTK_BUTTONBOX_DEFAULT_STYLE</layout_style>
<spacing>30</spacing>
<child_min_width>85</child_min_width>
<child_min_height>27</child_min_height>
<child_ipad_x>7</child_ipad_x>
<child_ipad_y>0</child_ipad_y>
<child>
<padding>0</padding>
<expand>True</expand>
<fill>True</fill>
</child>
<widget>
<class>GtkButton</class>
<name>ok_button</name>
<sensitive>False</sensitive>
<can_default>True</can_default>
<can_focus>True</can_focus>
<stock_button>GNOME_STOCK_BUTTON_OK</stock_button>
</widget>
<widget>
<class>GtkButton</class>
<name>cancel_button</name>
<visible>False</visible>
<can_default>True</can_default>
<can_focus>True</can_focus>
<stock_button>GNOME_STOCK_BUTTON_CANCEL</stock_button>
</widget>
</widget>
</widget>
</widget>
</GTK-Interface>

@ -68,6 +68,30 @@
(list "Extensions" "")
(lambda () (gnc:main-win-export-data-as-text win))))
(define export-item
(gnc:make-menu-item "Test progress dialog"
"Test progress dialog"
(list "Extensions" "")
(lambda ()
(let ((dialog (gnc:progress-dialog-new
(gnc:get-ui-data)))
(canceled #f))
(gnc:progress-dialog-set-cancel-scm-func
dialog
(lambda ()
(display "User canceled.") (newline)
(set! canceled #t)
#t))
(let loop ((value 0.0))
(gnc:progress-dialog-set-value dialog value)
(gnc:progress-dialog-set-heading
dialog (number->string value))
(sleep 1)
(if (and (not canceled) (< value 90.0))
(loop (+ value 5.0))))
(gnc:progress-dialog-finish dialog)
(gnc:progress-dialog-destroy dialog)))))
(define strings-item
(gnc:make-menu-item
"Save Translatable Strings"

Loading…
Cancel
Save