diff options
Diffstat (limited to '')
-rw-r--r-- | libgimp/gimpprogress.c | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/libgimp/gimpprogress.c b/libgimp/gimpprogress.c new file mode 100644 index 0000000..58846c4 --- /dev/null +++ b/libgimp/gimpprogress.c @@ -0,0 +1,452 @@ +/* LIBGIMP - The GIMP Library + * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball + * + * gimpprogress.c + * + * This library is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <gio/gio.h> + +#include "libgimpbase/gimpbase.h" + +#undef GIMP_DISABLE_DEPRECATED +#include "gimpprogress.h" +#define GIMP_DISABLE_DEPRECATED + +#include "gimp.h" + + +typedef struct +{ + gchar *progress_callback; + GimpProgressVtable vtable; + gpointer data; +} GimpProgressData; + + +/* local function prototypes */ + +static void gimp_progress_data_free (GimpProgressData *data); + +static void gimp_temp_progress_run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals); + + +/* private variables */ + +static GHashTable * gimp_progress_ht = NULL; +static gdouble gimp_progress_current = 0.0; +static const gdouble gimp_progress_step = (1.0 / 256.0); + + +/* public functions */ + +/** + * gimp_progress_install: + * @start_callback: the function to call when progress starts + * @end_callback: the function to call when progress finishes + * @text_callback: the function to call to change the text + * @value_callback: the function to call to change the value + * @user_data: a pointer that is returned when uninstalling the progress + * + * Note that since GIMP 2.4, @value_callback can be called with + * negative values. This is triggered by calls to gimp_progress_pulse(). + * The callback should then implement a progress indicating business, + * e.g. by calling gtk_progress_bar_pulse(). + * + * Return value: the name of the temporary procedure that's been installed + * + * Since: 2.2 + **/ +const gchar * +gimp_progress_install (GimpProgressStartCallback start_callback, + GimpProgressEndCallback end_callback, + GimpProgressTextCallback text_callback, + GimpProgressValueCallback value_callback, + gpointer user_data) +{ + GimpProgressVtable vtable = { 0, }; + + g_return_val_if_fail (start_callback != NULL, NULL); + g_return_val_if_fail (end_callback != NULL, NULL); + g_return_val_if_fail (text_callback != NULL, NULL); + g_return_val_if_fail (value_callback != NULL, NULL); + + vtable.start = start_callback; + vtable.end = end_callback; + vtable.set_text = text_callback; + vtable.set_value = value_callback; + + return gimp_progress_install_vtable (&vtable, user_data); +} + +/** + * gimp_progress_install_vtable: + * @vtable: a pointer to a @GimpProgressVtable. + * @user_data: a pointer that is passed as user_data to all vtable functions. + * + * Return value: the name of the temporary procedure that's been installed + * + * Since: 2.4 + **/ +const gchar * +gimp_progress_install_vtable (const GimpProgressVtable *vtable, + gpointer user_data) +{ + static const GimpParamDef args[] = + { + { GIMP_PDB_INT32, "command", "" }, + { GIMP_PDB_STRING, "text", "" }, + { GIMP_PDB_FLOAT, "value", "" } + }; + + static const GimpParamDef values[] = + { + { GIMP_PDB_FLOAT, "value", "" } + }; + + gchar *progress_callback; + + g_return_val_if_fail (vtable != NULL, NULL); + g_return_val_if_fail (vtable->start != NULL, NULL); + g_return_val_if_fail (vtable->end != NULL, NULL); + g_return_val_if_fail (vtable->set_text != NULL, NULL); + g_return_val_if_fail (vtable->set_value != NULL, NULL); + + progress_callback = gimp_procedural_db_temp_name (); + + gimp_install_temp_proc (progress_callback, + "Temporary progress callback procedure", + "", + "", + "", + "", + NULL, + "", + GIMP_TEMPORARY, + G_N_ELEMENTS (args), G_N_ELEMENTS (values), + args, values, + gimp_temp_progress_run); + + if (_gimp_progress_install (progress_callback)) + { + GimpProgressData *progress_data; + + gimp_extension_enable (); /* Allow callbacks to be watched */ + + /* Now add to hash table so we can find it again */ + if (! gimp_progress_ht) + { + gimp_progress_ht = + g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, + (GDestroyNotify) gimp_progress_data_free); + } + + progress_data = g_slice_new0 (GimpProgressData); + + progress_data->progress_callback = progress_callback; + progress_data->vtable.start = vtable->start; + progress_data->vtable.end = vtable->end; + progress_data->vtable.set_text = vtable->set_text; + progress_data->vtable.set_value = vtable->set_value; + progress_data->vtable.pulse = vtable->pulse; + progress_data->vtable.get_window = vtable->get_window; + progress_data->data = user_data; + + g_hash_table_insert (gimp_progress_ht, progress_callback, progress_data); + + return progress_callback; + } + + gimp_uninstall_temp_proc (progress_callback); + g_free (progress_callback); + + return NULL; +} + +/** + * gimp_progress_uninstall: + * @progress_callback: the name of the temporary procedure to uninstall + * + * Uninstalls a temporary progress procedure that was installed using + * gimp_progress_install(). + * + * Return value: the @user_data that was passed to gimp_progress_install(). + * + * Since: 2.2 + **/ +gpointer +gimp_progress_uninstall (const gchar *progress_callback) +{ + GimpProgressData *progress_data; + gpointer user_data; + + g_return_val_if_fail (progress_callback != NULL, NULL); + g_return_val_if_fail (gimp_progress_ht != NULL, NULL); + + progress_data = g_hash_table_lookup (gimp_progress_ht, progress_callback); + + if (! progress_data) + { + g_warning ("Can't find internal progress data"); + return NULL; + } + + _gimp_progress_uninstall (progress_callback); + gimp_uninstall_temp_proc (progress_callback); + + user_data = progress_data->data; + + g_hash_table_remove (gimp_progress_ht, progress_callback); + + return user_data; +} + + +/** + * gimp_progress_init: + * @message: Message to use in the progress dialog. + * + * Initializes the progress bar for the current plug-in. + * + * Initializes the progress bar for the current plug-in. It is only + * valid to call this procedure from a plug-in. + * + * Returns: TRUE on success. + */ +gboolean +gimp_progress_init (const gchar *message) +{ + gimp_progress_current = 0.0; + + return _gimp_progress_init (message, gimp_default_display ()); +} + +/** + * gimp_progress_init_printf: + * @format: a standard printf() format string + * @...: arguments for @format + * + * Initializes the progress bar for the current plug-in. + * + * Initializes the progress bar for the current plug-in. It is only + * valid to call this procedure from a plug-in. + * + * Returns: %TRUE on success. + * + * Since: 2.4 + **/ +gboolean +gimp_progress_init_printf (const gchar *format, + ...) +{ + gchar *text; + gboolean retval; + va_list args; + + g_return_val_if_fail (format != NULL, FALSE); + + va_start (args, format); + text = g_strdup_vprintf (format, args); + va_end (args); + + retval = gimp_progress_init (text); + + g_free (text); + + return retval; +} + +/** + * gimp_progress_set_text_printf: + * @format: a standard printf() format string + * @...: arguments for @format + * + * Changes the text in the progress bar for the current plug-in. + * + * This function changes the text in the progress bar for the current + * plug-in. Unlike gimp_progress_init() it does not change the + * displayed value. + * + * Returns: %TRUE on success. + * + * Since: 2.4 + **/ +gboolean +gimp_progress_set_text_printf (const gchar *format, + ...) +{ + gchar *text; + gboolean retval; + va_list args; + + g_return_val_if_fail (format != NULL, FALSE); + + va_start (args, format); + text = g_strdup_vprintf (format, args); + va_end (args); + + retval = gimp_progress_set_text (text); + + g_free (text); + + return retval; +} + +/** + * gimp_progress_update: + * @percentage: Percentage of progress completed (in the range from 0.0 to 1.0). + * + * Updates the progress bar for the current plug-in. + * + * Returns: TRUE on success. + */ +gboolean +gimp_progress_update (gdouble percentage) +{ + gboolean changed; + + if (percentage <= 0.0) + { + changed = (gimp_progress_current != 0.0); + percentage = 0.0; + } + else if (percentage >= 1.0) + { + changed = (gimp_progress_current != 1.0); + percentage = 1.0; + } + else + { + changed = + (fabs (gimp_progress_current - percentage) > gimp_progress_step); + +#ifdef GIMP_UNSTABLE + if (! changed) + { + static gboolean warned = FALSE; + static gint count = 0; + + count++; + + if (count > 3 && ! warned) + { + g_printerr ("%s is updating the progress too often\n", + g_get_prgname ()); + warned = TRUE; + } + } +#endif + } + + /* Suppress the update if the change was only marginal. */ + if (! changed) + return TRUE; + + gimp_progress_current = percentage; + + return _gimp_progress_update (gimp_progress_current); +} + + +/* private functions */ + +static void +gimp_progress_data_free (GimpProgressData *data) +{ + g_slice_free (GimpProgressData, data); +} + +static void +gimp_temp_progress_run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[2]; + GimpProgressData *progress_data; + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = GIMP_PDB_SUCCESS; + + progress_data = g_hash_table_lookup (gimp_progress_ht, name); + + if (! progress_data) + { + g_warning ("Can't find internal progress data"); + + values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; + } + else + { + GimpProgressCommand command = param[0].data.d_int32; + + switch (command) + { + case GIMP_PROGRESS_COMMAND_START: + progress_data->vtable.start (param[1].data.d_string, + param[2].data.d_float != 0.0, + progress_data->data); + break; + + case GIMP_PROGRESS_COMMAND_END: + progress_data->vtable.end (progress_data->data); + break; + + case GIMP_PROGRESS_COMMAND_SET_TEXT: + progress_data->vtable.set_text (param[1].data.d_string, + progress_data->data); + break; + + case GIMP_PROGRESS_COMMAND_SET_VALUE: + progress_data->vtable.set_value (param[2].data.d_float, + progress_data->data); + break; + + case GIMP_PROGRESS_COMMAND_PULSE: + if (progress_data->vtable.pulse) + progress_data->vtable.pulse (progress_data->data); + else + progress_data->vtable.set_value (-1, progress_data->data); + break; + + case GIMP_PROGRESS_COMMAND_GET_WINDOW: + *nreturn_vals = 2; + values[1].type = GIMP_PDB_FLOAT; + + if (progress_data->vtable.get_window) + values[1].data.d_float = + (gdouble) progress_data->vtable.get_window (progress_data->data); + else + values[1].data.d_float = 0; + break; + + default: + values[0].data.d_status = GIMP_PDB_CALLING_ERROR; + break; + } + } +} |