1 /********************************************************************\
2 * dialog-progress.c -- GnuCash progress dialog *
3 * Copyright (C) 2000 Dave Peticolas *
4 * *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License as *
7 * published by the Free Software Foundation; either version 2 of *
8 * the License, or (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License*
16 * along with this program; if not, contact: *
17 * *
18 * Free Software Foundation Voice: +1-617-542-5942 *
19 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
20 * Boston, MA 02110-1301, USA gnu@gnu.org *
21 * *
22 \********************************************************************/
23
24 #include <config.h>
25
26 #include <gtk/gtk.h>
27 #include <glib/gi18n.h>
28 #include <libguile.h>
29 #include "guile-mappings.h"
30
31 #include "dialog-progress.h"
32 #include "dialog-utils.h"
33
34
35 struct _GNCProgressDialog
36 {
37 GtkWidget *dialog;
38
39 GtkWidget *primary_label;
40 GtkWidget *secondary_label;
41 GtkWidget *progress_bar;
42 GtkWidget *sub_label;
43 GtkWidget *log;
44
45 GtkWidget *ok_button;
46 GtkWidget *cancel_button;
47
48 /* The stack of virtual progress bars. */
49 GList *bars;
50 /* The fraction of the current bar that is filled. */
51 gdouble bar_value;
52 /* The value of the real (top-level) bar before the last push. */
53 gdouble total_offset;
54 /* The product of all weights in the stack. */
55 gdouble total_weight;
56
57 GNCProgressCancelFunc cancel_func;
58 gpointer user_data;
59
60 SCM cancel_scm_func;
61
62 gboolean use_ok_button;
63 gboolean closed;
64 gboolean finished;
65 gboolean destroyed;
66 gboolean title_set;
67 };
68
69 typedef struct
70 {
71 gdouble offset;
72 gdouble weight;
73 } VirtualBar;
74
75 static void
gnc_progress_maybe_destroy(GNCProgressDialog * progress)76 gnc_progress_maybe_destroy(GNCProgressDialog *progress)
77 {
78 g_return_if_fail(progress);
79
80 if (!(progress->closed && progress->destroyed))
81 return;
82
83 if (progress->dialog != NULL)
84 gtk_widget_destroy(progress->dialog);
85 }
86
87
88 static void
ok_cb(GtkWidget * widget,gpointer data)89 ok_cb(GtkWidget * widget, gpointer data)
90 {
91 GNCProgressDialog *progress = data;
92
93 g_return_if_fail(progress);
94
95 if (progress->dialog != NULL)
96 gtk_widget_hide(progress->dialog);
97 progress->closed = TRUE;
98 gnc_progress_maybe_destroy(progress);
99 }
100
101
102 static void
cancel_cb(GtkWidget * widget,gpointer data)103 cancel_cb(GtkWidget * widget, gpointer data)
104 {
105 GNCProgressDialog *progress = data;
106
107 g_return_if_fail(progress);
108
109 if (progress->cancel_func && !progress->cancel_func(progress->user_data))
110 return;
111
112 if (progress->cancel_scm_func != SCM_UNDEFINED)
113 {
114 SCM result;
115
116 result = scm_call_0(progress->cancel_scm_func);
117
118 if (!scm_is_true(result))
119 return;
120 }
121
122 if (progress->dialog != NULL)
123 gtk_widget_hide(progress->dialog);
124 progress->closed = TRUE;
125 gnc_progress_maybe_destroy(progress);
126 }
127
128
129 static gboolean
delete_cb(GtkWidget * widget,GdkEvent * event,gpointer data)130 delete_cb(GtkWidget *widget, GdkEvent *event, gpointer data)
131 {
132 GNCProgressDialog *progress = data;
133
134 g_return_val_if_fail(progress, TRUE);
135
136 if (progress->finished)
137 {
138 if (progress->dialog != NULL)
139 gtk_widget_hide(progress->dialog);
140 progress->closed = TRUE;
141 gnc_progress_maybe_destroy(progress);
142 return TRUE;
143 }
144
145 if (progress->cancel_func)
146 {
147 if (progress->cancel_func(progress->user_data))
148 {
149 if (progress->dialog != NULL)
150 gtk_widget_hide(progress->dialog);
151 progress->closed = TRUE;
152 gnc_progress_maybe_destroy(progress);
153 return TRUE;
154 }
155 }
156
157 if (progress->cancel_scm_func != SCM_UNDEFINED)
158 {
159 SCM result;
160
161 result = scm_call_0(progress->cancel_scm_func);
162
163 if (scm_is_true(result))
164 {
165 if (progress->dialog != NULL)
166 gtk_widget_hide(progress->dialog);
167 progress->closed = TRUE;
168 gnc_progress_maybe_destroy(progress);
169 return TRUE;
170 }
171 }
172
173 /* Don't delete the window, wait for gnc_progress_dialog_destroy. */
174 return TRUE;
175 }
176
177
178 static void
destroy_cb(GtkWidget * object,gpointer data)179 destroy_cb(GtkWidget *object, gpointer data)
180 {
181 GNCProgressDialog *progress = data;
182
183 g_return_if_fail(progress);
184
185 /* Make sure the callbacks aren't invoked */
186 progress->cancel_func = NULL;
187 if (progress->cancel_scm_func != SCM_UNDEFINED)
188 scm_gc_unprotect_object(progress->cancel_scm_func);
189 progress->cancel_scm_func = SCM_UNDEFINED;
190
191 g_free(progress);
192 }
193
194
195 static void
gnc_progress_dialog_create(GtkWidget * parent,GNCProgressDialog * progress)196 gnc_progress_dialog_create(GtkWidget * parent, GNCProgressDialog *progress)
197 {
198 GtkWidget *dialog;
199 GtkBuilder *builder;
200
201 g_return_if_fail(progress);
202
203 builder = gtk_builder_new();
204 gnc_builder_add_from_file (builder, "dialog-progress.glade", "progress_dialog");
205
206
207 dialog = GTK_WIDGET(gtk_builder_get_object (builder, "progress_dialog"));
208 progress->dialog = dialog;
209
210 // Set the name for this dialog so it can be easily manipulated with css
211 gtk_widget_set_name (GTK_WIDGET(dialog), "gnc-id-progress");
212
213 /* parent */
214 if (parent != NULL)
215 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(parent));
216
217 g_signal_connect(G_OBJECT(dialog), "delete_event", G_CALLBACK(delete_cb), progress);
218
219 g_signal_connect(G_OBJECT(dialog), "destroy", G_CALLBACK(destroy_cb), progress);
220
221 progress->primary_label = GTK_WIDGET(gtk_builder_get_object (builder, "primary_label"));
222 gtk_widget_hide(progress->primary_label);
223
224 progress->secondary_label = GTK_WIDGET(gtk_builder_get_object (builder, "secondary_label"));
225 gtk_widget_hide(progress->secondary_label);
226
227 progress->progress_bar = GTK_WIDGET(gtk_builder_get_object (builder, "progress_bar"));
228 progress->total_offset = 0;
229 progress->total_weight = 1;
230 progress->bar_value = 0;
231
232 progress->sub_label = GTK_WIDGET(gtk_builder_get_object (builder, "sub_label"));
233 gtk_widget_hide(progress->sub_label);
234
235 progress->log = GTK_WIDGET(gtk_builder_get_object (builder, "progress_log"));
236 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object (builder, "progress_log_window")));
237
238 progress->ok_button = GTK_WIDGET(gtk_builder_get_object (builder, "ok_button"));
239
240 g_signal_connect(progress->ok_button, "clicked",
241 G_CALLBACK(ok_cb), progress);
242
243 if (!progress->use_ok_button)
244 gtk_widget_hide(progress->ok_button);
245
246 progress->cancel_button = GTK_WIDGET(gtk_builder_get_object (builder, "cancel_button"));
247
248 g_signal_connect(progress->cancel_button, "clicked",
249 G_CALLBACK(cancel_cb), progress);
250
251 progress->cancel_func = NULL;
252 progress->user_data = NULL;
253
254 progress->cancel_scm_func = SCM_UNDEFINED;
255
256 progress->closed = FALSE;
257 progress->finished = FALSE;
258 progress->destroyed = FALSE;
259 progress->title_set = FALSE;
260
261 gtk_builder_connect_signals_full (builder, gnc_builder_connect_full_func, progress);
262 g_object_unref(G_OBJECT(builder));
263 }
264
265
266 GNCProgressDialog *
gnc_progress_dialog_new(GtkWidget * parent,gboolean use_ok_button)267 gnc_progress_dialog_new(GtkWidget * parent, gboolean use_ok_button)
268 {
269 GNCProgressDialog *progress;
270
271 progress = g_new0(GNCProgressDialog, 1);
272
273 progress->use_ok_button = use_ok_button;
274
275 gnc_progress_dialog_create(parent, progress);
276
277 gtk_widget_show(progress->dialog);
278
279 gnc_progress_dialog_update(progress);
280
281 return progress;
282 }
283
284
285 GNCProgressDialog *
gnc_progress_dialog_custom(GtkLabel * primary,GtkLabel * secondary,GtkProgressBar * bar,GtkLabel * suboperation,GtkTextView * log)286 gnc_progress_dialog_custom(GtkLabel *primary,
287 GtkLabel *secondary,
288 GtkProgressBar *bar,
289 GtkLabel *suboperation,
290 GtkTextView *log)
291 {
292 GNCProgressDialog *progress;
293
294 progress = g_new0(GNCProgressDialog, 1);
295
296 /* Set up widgets. */
297 progress->dialog = NULL;
298 progress->primary_label = GTK_WIDGET(primary);
299 progress->secondary_label = GTK_WIDGET(secondary);
300 progress->progress_bar = GTK_WIDGET(bar);
301 progress->sub_label = GTK_WIDGET(suboperation);
302 progress->log = GTK_WIDGET(log);
303 progress->ok_button = NULL;
304 progress->cancel_button = NULL;
305
306 /* Initialize all other items. */
307 progress->total_offset = 0;
308 progress->total_weight = 1;
309 progress->bar_value = 0;
310 progress->cancel_func = NULL;
311 progress->user_data = NULL;
312 progress->cancel_scm_func = SCM_UNDEFINED;
313 progress->use_ok_button = FALSE;
314 progress->closed = FALSE;
315 progress->finished = FALSE;
316 progress->destroyed = FALSE;
317 progress->title_set = FALSE;
318
319 return progress;
320 }
321
322
323 void
gnc_progress_dialog_set_title(GNCProgressDialog * progress,const char * title)324 gnc_progress_dialog_set_title(GNCProgressDialog *progress, const char *title)
325 {
326 g_return_if_fail(progress);
327
328 if (!progress->dialog)
329 return;
330
331 if (title == NULL)
332 title = "";
333
334 gtk_window_set_title(GTK_WINDOW(progress->dialog), title);
335
336 progress->title_set = TRUE;
337
338 gnc_progress_dialog_update(progress);
339 }
340
341
342 void
gnc_progress_dialog_set_primary(GNCProgressDialog * progress,const gchar * str)343 gnc_progress_dialog_set_primary(GNCProgressDialog *progress,
344 const gchar *str)
345 {
346 g_return_if_fail(progress);
347
348 if (progress->primary_label == NULL)
349 return;
350
351 if (str == NULL || *str == '\0')
352 gtk_widget_hide(progress->primary_label);
353 else
354 {
355 /* Display the primary text with the HIG-recommended style. */
356 char *markup = g_markup_printf_escaped("<span weight=\"bold\" size=\"larger\">%s</span>", str);
357
358 gtk_label_set_markup(GTK_LABEL(progress->primary_label), markup);
359 g_free(markup);
360 gtk_widget_show(progress->primary_label);
361 }
362
363 gnc_progress_dialog_update(progress);
364 }
365
366
367 void
gnc_progress_dialog_set_heading(GNCProgressDialog * progress,const char * heading)368 gnc_progress_dialog_set_heading(GNCProgressDialog *progress,
369 const char *heading)
370 {
371 g_return_if_fail(progress);
372
373 if (progress->primary_label == NULL)
374 return;
375
376 if (heading == NULL || *heading == '\0')
377 gtk_widget_hide(progress->primary_label);
378 else
379 {
380 gtk_label_set_text(GTK_LABEL(progress->primary_label), heading);
381 gtk_widget_show(progress->primary_label);
382 }
383
384 gnc_progress_dialog_update(progress);
385 }
386
387
388 void
gnc_progress_dialog_set_secondary(GNCProgressDialog * progress,const gchar * str)389 gnc_progress_dialog_set_secondary(GNCProgressDialog *progress,
390 const gchar *str)
391 {
392 g_return_if_fail(progress);
393
394 if (progress->secondary_label == NULL)
395 return;
396
397 if (str == NULL || *str == '\0')
398 gtk_widget_hide(progress->secondary_label);
399 else
400 {
401 gtk_label_set_text(GTK_LABEL(progress->secondary_label), str);
402 gtk_widget_show(progress->secondary_label);
403 }
404
405 gnc_progress_dialog_update(progress);
406 }
407
408
409 void
gnc_progress_dialog_set_sub(GNCProgressDialog * progress,const gchar * str)410 gnc_progress_dialog_set_sub(GNCProgressDialog *progress,
411 const gchar *str)
412 {
413 g_return_if_fail(progress);
414
415 if (progress->sub_label == NULL)
416 return;
417
418 if (str == NULL || *str == '\0')
419 gtk_widget_hide(progress->sub_label);
420 else
421 {
422 /* Display the suboperation text with the HIG-recommended style. */
423 char *markup = g_markup_printf_escaped("<span style=\"italic\">%s</span>", str);
424
425 gtk_label_set_markup(GTK_LABEL(progress->sub_label), markup);
426 g_free(markup);
427 gtk_widget_show(progress->sub_label);
428 }
429
430 gnc_progress_dialog_update(progress);
431 }
432
433
434 void
gnc_progress_dialog_reset_log(GNCProgressDialog * progress)435 gnc_progress_dialog_reset_log(GNCProgressDialog *progress)
436 {
437 GtkTextBuffer *buf;
438
439 g_return_if_fail(progress);
440
441 if (progress->log == NULL)
442 return;
443
444 /* Reset the text buffer. */
445 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(progress->log));
446 gtk_text_buffer_set_text(buf, "", -1);
447 gtk_text_buffer_set_modified(buf, FALSE);
448
449 /* Show the log and its parent (in case it is in a scrolled window). */
450 gtk_widget_show(progress->log);
451 gtk_widget_show(gtk_widget_get_parent(progress->log));
452
453 gnc_progress_dialog_update(progress);
454 }
455
456
457 void
gnc_progress_dialog_append_log(GNCProgressDialog * progress,const gchar * str)458 gnc_progress_dialog_append_log(GNCProgressDialog *progress, const gchar *str)
459 {
460 GtkTextBuffer *buf;
461 GtkTextIter iter;
462
463 g_return_if_fail(progress);
464
465 if (progress->log == NULL || !str || !*str)
466 return;
467
468 /* Append to the text buffer. */
469 buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(progress->log));
470 gtk_text_buffer_get_end_iter(buf, &iter);
471 gtk_text_buffer_insert(buf, &iter, str, -1);
472
473 gnc_progress_dialog_update(progress);
474 }
475
476
477 void
gnc_progress_dialog_pause(GNCProgressDialog * progress)478 gnc_progress_dialog_pause(GNCProgressDialog *progress)
479 {
480 gchar *suffix;
481
482 g_return_if_fail(progress);
483
484 suffix = g_strconcat(" ", _("(paused)"), NULL);
485
486 if (progress->sub_label && gtk_widget_get_visible(progress->sub_label))
487 {
488 const gchar *txt = gtk_label_get_text(GTK_LABEL(progress->sub_label));
489
490 if (txt && !g_str_has_suffix(txt, suffix))
491 {
492 gchar *newtxt = g_strconcat(txt, suffix, NULL);
493 gnc_progress_dialog_set_sub(progress, newtxt);
494 g_free(newtxt);
495 }
496 }
497 else if (progress->dialog)
498 {
499 const gchar *txt = gtk_window_get_title(GTK_WINDOW(progress->dialog));
500
501 if (txt && !g_str_has_suffix(txt, suffix))
502 {
503 gchar *newtxt = g_strconcat(txt, suffix, NULL);
504 gtk_window_set_title(GTK_WINDOW(progress->dialog), newtxt);
505 g_free(newtxt);
506 }
507 }
508 else if (progress->primary_label &&
509 gtk_widget_get_visible(progress->primary_label))
510 {
511 const gchar *txt = gtk_label_get_text(GTK_LABEL(progress->primary_label));
512
513 if (txt && !g_str_has_suffix(txt, suffix))
514 {
515 gchar *newtxt = g_strconcat(txt, suffix, NULL);
516 gnc_progress_dialog_set_primary(progress, newtxt);
517 g_free(newtxt);
518 }
519 }
520
521 g_free(suffix);
522
523 gnc_progress_dialog_update(progress);
524 }
525
526 void
gnc_progress_dialog_resume(GNCProgressDialog * progress)527 gnc_progress_dialog_resume(GNCProgressDialog *progress)
528 {
529 gchar *suffix;
530
531 g_return_if_fail(progress);
532
533 suffix = g_strconcat(" ", _("(paused)"), NULL);
534
535 /* Remove any pause indication from the suboperation label. */
536 if (progress->sub_label)
537 {
538 const gchar *txt = gtk_label_get_text(GTK_LABEL(progress->sub_label));
539
540 if (txt && g_str_has_suffix(txt, suffix))
541 {
542 gchar *newtxt = g_strndup(txt, strlen(txt) - strlen(suffix));
543 gnc_progress_dialog_set_sub(progress, newtxt);
544 g_free(newtxt);
545 }
546 }
547
548 /* Remove any pause indication from the window title. */
549 if (progress->dialog)
550 {
551 const gchar *txt = gtk_window_get_title(GTK_WINDOW(progress->dialog));
552
553 if (txt && g_str_has_suffix(txt, suffix))
554 {
555 gchar *newtxt = g_strndup(txt, strlen(txt) - strlen(suffix));
556 gtk_window_set_title(GTK_WINDOW(progress->dialog), newtxt);
557 g_free(newtxt);
558 }
559 }
560
561 /* Remove any pause indication from the primary text. */
562 if (progress->primary_label)
563 {
564 const gchar *txt = gtk_label_get_text(GTK_LABEL(progress->primary_label));
565
566 if (txt && g_str_has_suffix(txt, suffix))
567 {
568 gchar *newtxt = g_strndup(txt, strlen(txt) - strlen(suffix));
569 gnc_progress_dialog_set_primary(progress, newtxt);
570 g_free(newtxt);
571 }
572 }
573
574 g_free(suffix);
575
576 gnc_progress_dialog_update(progress);
577 }
578
579
580 void
gnc_progress_dialog_set_cancel_func(GNCProgressDialog * progress,GNCProgressCancelFunc cancel_func,gpointer user_data)581 gnc_progress_dialog_set_cancel_func(GNCProgressDialog *progress,
582 GNCProgressCancelFunc cancel_func,
583 gpointer user_data)
584 {
585 g_return_if_fail(progress);
586
587 if (progress->cancel_button == NULL)
588 return;
589
590 progress->cancel_func = cancel_func;
591 progress->user_data = user_data;
592
593 if (cancel_func)
594 gtk_widget_show(progress->cancel_button);
595 }
596
597
598 void
gnc_progress_dialog_set_cancel_scm_func(GNCProgressDialog * progress,SCM cancel_scm_func)599 gnc_progress_dialog_set_cancel_scm_func(GNCProgressDialog *progress,
600 SCM cancel_scm_func)
601 {
602 g_return_if_fail(progress);
603
604 if (progress->cancel_button == NULL)
605 return;
606
607 if (progress->cancel_scm_func != SCM_UNDEFINED)
608 scm_gc_unprotect_object(progress->cancel_scm_func);
609
610 if (scm_is_procedure(cancel_scm_func))
611 {
612 progress->cancel_scm_func = cancel_scm_func;
613 scm_gc_protect_object(cancel_scm_func);
614 gtk_widget_show(progress->cancel_button);
615 }
616 else
617 progress->cancel_scm_func = SCM_UNDEFINED;
618 }
619
620
621 void
gnc_progress_dialog_set_value(GNCProgressDialog * progress,gdouble value)622 gnc_progress_dialog_set_value(GNCProgressDialog *progress, gdouble value)
623 {
624 GtkProgressBar *bar;
625
626 g_return_if_fail(progress);
627
628 /* Get the progress bar widget. */
629 bar = GTK_PROGRESS_BAR(progress->progress_bar);
630 if (bar == NULL)
631 return;
632
633 /* Update the progress bar. If value is over 1,
634 * the bar will pulse instead of fill. */
635 if (value > 1)
636 gtk_progress_bar_pulse(bar);
637 else
638 {
639 progress->bar_value = value > 0 ? value : 0;
640 gtk_progress_bar_set_fraction(bar,
641 progress->total_offset + progress->bar_value * progress->total_weight);
642 }
643
644 gnc_progress_dialog_update(progress);
645 }
646
647
648 guint
gnc_progress_dialog_push(GNCProgressDialog * progress,gdouble weight)649 gnc_progress_dialog_push(GNCProgressDialog *progress, gdouble weight)
650 {
651 GtkProgressBar *bar;
652 VirtualBar *newbar;
653
654 g_return_val_if_fail(progress, 0);
655 g_return_val_if_fail(weight > 0, 0);
656
657 /* Get the progress bar widget. */
658 bar = GTK_PROGRESS_BAR(progress->progress_bar);
659 if (bar == NULL)
660 return 0;
661
662 /* Create the new virtual progress bar. */
663 newbar = g_new0(VirtualBar, 1);
664 newbar->offset = progress->bar_value;
665 if (newbar->offset + weight > 1)
666 /* The requested weight is more than the unfilled portion of the bar. */
667 newbar->weight = 1 - newbar->offset;
668 else
669 newbar->weight = weight;
670 progress->bars = g_list_prepend(progress->bars, newbar);
671
672 /* Set the total effective offset and weight */
673 progress->total_offset = gtk_progress_bar_get_fraction(bar);
674 progress->total_weight *= newbar->weight;
675
676 /* Set the new bar as unfilled. */
677 progress->bar_value = 0;
678
679 return g_list_length(progress->bars);
680 }
681
682
683 guint
gnc_progress_dialog_pop(GNCProgressDialog * progress)684 gnc_progress_dialog_pop(GNCProgressDialog *progress)
685 {
686 VirtualBar *bar;
687
688 g_return_val_if_fail(progress, 0);
689
690 /* Get the progress bar widget. */
691 if (progress->progress_bar == NULL || progress->bars == NULL)
692 return 0;
693
694 /* Pop the bar off the bar stack. */
695 bar = progress->bars->data;
696 progress->bars = g_list_delete_link(progress->bars, progress->bars);
697
698 /* Determine the value of the current bar. */
699 progress->bar_value = bar->offset + bar->weight * progress->bar_value;
700
701 /* Set the total effective offset and weight. */
702 if (progress->bars == NULL)
703 {
704 progress->total_offset = 0;
705 progress->total_weight = 1;
706 }
707 else
708 {
709 progress->total_offset -= bar->offset *
710 ((VirtualBar *) progress->bars->data)->weight;
711 progress->total_weight /= bar->weight;
712 }
713 g_free(bar);
714
715 if (progress->bars == NULL)
716 return 0;
717 return g_list_length(progress->bars);
718 }
719
720
721 guint
gnc_progress_dialog_pop_full(GNCProgressDialog * progress)722 gnc_progress_dialog_pop_full(GNCProgressDialog *progress)
723 {
724 gnc_progress_dialog_set_value(progress, 1);
725 return gnc_progress_dialog_pop(progress);
726 }
727
728
729 void
gnc_progress_dialog_reset_value(GNCProgressDialog * progress)730 gnc_progress_dialog_reset_value(GNCProgressDialog *progress)
731 {
732 g_return_if_fail(progress);
733
734 /* Return to the top level. */
735 while (gnc_progress_dialog_pop(progress));
736
737 /* Reset the bar to empty. */
738 gnc_progress_dialog_set_value(progress, 0);
739 }
740
741
742 void
gnc_progress_dialog_update(GNCProgressDialog * progress)743 gnc_progress_dialog_update(GNCProgressDialog *progress)
744 {
745 while (gtk_events_pending())
746 gtk_main_iteration();
747 }
748
749
750 void
gnc_progress_dialog_finish(GNCProgressDialog * progress)751 gnc_progress_dialog_finish(GNCProgressDialog *progress)
752 {
753 g_return_if_fail(progress);
754
755 if (!progress->use_ok_button)
756 {
757 if (progress->dialog != NULL)
758 gtk_widget_hide(progress->dialog);
759 progress->closed = TRUE;
760 }
761
762 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress->progress_bar), 1.0);
763
764 gtk_widget_set_sensitive(progress->ok_button, TRUE);
765 gtk_widget_set_sensitive(progress->cancel_button, FALSE);
766
767 if (gtk_widget_get_visible(progress->primary_label))
768 gnc_progress_dialog_set_heading(progress, _("Complete"));
769
770 if (!progress->title_set)
771 gtk_window_set_title(GTK_WINDOW(progress->dialog), _("Complete"));
772
773 gtk_window_set_modal(GTK_WINDOW(progress->dialog), FALSE);
774
775 progress->finished = TRUE;
776
777 gnc_progress_dialog_update(progress);
778 }
779
780
781 void
gnc_progress_dialog_destroy(GNCProgressDialog * progress)782 gnc_progress_dialog_destroy(GNCProgressDialog *progress)
783 {
784 g_return_if_fail(progress);
785
786 /* Make sure the callbacks aren't invoked */
787 progress->cancel_func = NULL;
788 if (progress->cancel_scm_func != SCM_UNDEFINED)
789 scm_gc_unprotect_object(progress->cancel_scm_func);
790 progress->cancel_scm_func = SCM_UNDEFINED;
791
792 if (!progress->finished)
793 {
794 if (progress->dialog != NULL)
795 gtk_widget_hide(progress->dialog);
796 progress->closed = TRUE;
797 }
798
799 progress->destroyed = TRUE;
800
801 gnc_progress_maybe_destroy(progress);
802 }
803