/** * @file * Routines to show a progress dialog, indicating that the * application is doing something. * * @author Jeremy A. Mowery jmowery@tresys.com * @author Jason Tang jtang@tresys.com * * Copyright (C) 2006-2007 Tresys Technology, LLC * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "progress.h" #include "utilgui.h" #include #include #include struct progress { toplevel_t *top; GtkWidget *progress; GtkWidget *label1, *label2; char *s; int done; GCond *cond; GMutex *mutex; }; progress_t *progress_create(toplevel_t * top) { progress_t *p; GtkWidget *vbox; if ((p = calloc(1, sizeof(*p))) == NULL) { return NULL; } p->top = top; p->progress = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_modal(GTK_WINDOW(p->progress), TRUE); gtk_window_set_transient_for(GTK_WINDOW(p->progress), toplevel_get_window(top)); gtk_window_set_default_size(GTK_WINDOW(p->progress), 300, 100); vbox = gtk_vbox_new(FALSE, 2); gtk_container_add(GTK_CONTAINER(p->progress), vbox); p->label1 = gtk_label_new(NULL); gtk_container_add(GTK_CONTAINER(vbox), p->label1); p->label2 = gtk_label_new(NULL); gtk_container_add(GTK_CONTAINER(vbox), p->label2); gtk_widget_show(p->label1); gtk_widget_show(p->label2); gtk_widget_show(vbox); util_cursor_wait(p->progress); p->cond = g_cond_new(); p->mutex = g_mutex_new(); return p; } void progress_destroy(progress_t ** progress) { if (progress != NULL && *progress != NULL) { free((*progress)->s); g_cond_free((*progress)->cond); g_mutex_free((*progress)->mutex); free(*progress); *progress = NULL; } } void progress_show(progress_t * progress, const char *title) { gtk_label_set_text(GTK_LABEL(progress->label1), title); gtk_label_set_text(GTK_LABEL(progress->label2), ""); gtk_widget_show(progress->progress); gtk_window_deiconify(GTK_WINDOW(progress->progress)); gtk_window_set_title(GTK_WINDOW(progress->progress), title); progress->done = 0; } void progress_hide(progress_t * progress) { gtk_widget_hide(progress->progress); } int progress_wait(progress_t * progress) { gint64 end_time; g_mutex_lock(progress->mutex); while (!progress->done) { end_time = g_get_monotonic_time () + 50000; // need to be set before each wait g_cond_wait_until(progress->cond, progress->mutex, end_time); if (progress->s != NULL) { gtk_label_set_text(GTK_LABEL(progress->label2), progress->s); free(progress->s); progress->s = NULL; } while (gtk_events_pending()) gtk_main_iteration(); } g_mutex_unlock(progress->mutex); if (progress->done < 0) { toplevel_ERR(progress->top, "%s", GTK_LABEL(progress->label2)->label); return progress->done; } else if (progress->done > 1) { toplevel_WARN(progress->top, "%s", GTK_LABEL(progress->label2)->label); return progress->done - 1; } else { progress->done = 0; return 0; } } void progress_done(progress_t * progress) { g_mutex_lock(progress->mutex); progress->done = 1; g_cond_signal(progress->cond); g_mutex_unlock(progress->mutex); } void progress_warn(progress_t * progress, char *reason, ...) { gchar *s; va_list ap; g_mutex_lock(progress->mutex); if (reason != NULL) { va_start(ap, reason); g_vasprintf(&s, reason, ap); free(progress->s); progress->s = s; va_end(ap); } progress->done = 2; g_cond_signal(progress->cond); g_mutex_unlock(progress->mutex); } void progress_abort(progress_t * progress, char *reason, ...) { gchar *s; va_list ap; g_mutex_lock(progress->mutex); if (reason != NULL) { va_start(ap, reason); g_vasprintf(&s, reason, ap); free(progress->s); progress->s = s; va_end(ap); } progress->done = -1; g_cond_signal(progress->cond); g_mutex_unlock(progress->mutex); } static void progress_update_label(progress_t * progress, const char *fmt, va_list va_args) { gchar *s = NULL; g_vasprintf(&s, fmt, va_args); g_mutex_lock(progress->mutex); free(progress->s); progress->s = s; g_cond_signal(progress->cond); g_mutex_unlock(progress->mutex); } void progress_update(progress_t * progress, char *fmt, ...) { va_list ap; va_start(ap, fmt); progress_update_label(progress, fmt, ap); va_end(ap); } void progress_seaudit_handle_func(void *arg, const seaudit_log_t * log __attribute__ ((unused)), int level __attribute__ ((unused)), const char *fmt, va_list va_args) { progress_t *progress = arg; progress_update_label(progress, fmt, va_args); } void progress_apol_handle_func(void *varg, const apol_policy_t * p __attribute__ ((unused)), int level __attribute__ ((unused)), const char *fmt, va_list argp) { progress_t *progress = varg; progress_update_label(progress, fmt, argp); }