/* GIMP - The GNU Image Manipulation Program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * gimppdbprogress.c * Copyright (C) 2004 Michael Natterer * * 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 3 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, see . */ #include "config.h" #include #include #include #include "libgimpbase/gimpbase.h" #include "core-types.h" #include "core/gimpcontext.h" #include "pdb/gimppdb.h" #include "gimp.h" #include "gimpparamspecs.h" #include "gimppdbprogress.h" #include "gimpprogress.h" #include "gimp-intl.h" enum { PROP_0, PROP_PDB, PROP_CONTEXT, PROP_CALLBACK_NAME }; static void gimp_pdb_progress_class_init (GimpPdbProgressClass *klass); static void gimp_pdb_progress_init (GimpPdbProgress *progress, GimpPdbProgressClass *klass); static void gimp_pdb_progress_progress_iface_init (GimpProgressInterface *iface); static void gimp_pdb_progress_constructed (GObject *object); static void gimp_pdb_progress_dispose (GObject *object); static void gimp_pdb_progress_finalize (GObject *object); static void gimp_pdb_progress_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static GimpProgress * gimp_pdb_progress_progress_start (GimpProgress *progress, gboolean cancellable, const gchar *message); static void gimp_pdb_progress_progress_end (GimpProgress *progress); static gboolean gimp_pdb_progress_progress_is_active (GimpProgress *progress); static void gimp_pdb_progress_progress_set_text (GimpProgress *progress, const gchar *message); static void gimp_pdb_progress_progress_set_value (GimpProgress *progress, gdouble percentage); static gdouble gimp_pdb_progress_progress_get_value (GimpProgress *progress); static void gimp_pdb_progress_progress_pulse (GimpProgress *progress); static guint32 gimp_pdb_progress_progress_get_window_id (GimpProgress *progress); static GObjectClass *parent_class = NULL; GType gimp_pdb_progress_get_type (void) { static GType type = 0; if (! type) { const GTypeInfo info = { sizeof (GimpPdbProgressClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gimp_pdb_progress_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GimpPdbProgress), 0, /* n_preallocs */ (GInstanceInitFunc) gimp_pdb_progress_init, }; const GInterfaceInfo progress_iface_info = { (GInterfaceInitFunc) gimp_pdb_progress_progress_iface_init, NULL, /* iface_finalize */ NULL /* iface_data */ }; type = g_type_register_static (G_TYPE_OBJECT, "GimpPdbProgress", &info, 0); g_type_add_interface_static (type, GIMP_TYPE_PROGRESS, &progress_iface_info); } return type; } static void gimp_pdb_progress_class_init (GimpPdbProgressClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->constructed = gimp_pdb_progress_constructed; object_class->dispose = gimp_pdb_progress_dispose; object_class->finalize = gimp_pdb_progress_finalize; object_class->set_property = gimp_pdb_progress_set_property; g_object_class_install_property (object_class, PROP_PDB, g_param_spec_object ("pdb", NULL, NULL, GIMP_TYPE_PDB, GIMP_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_CONTEXT, g_param_spec_object ("context", NULL, NULL, GIMP_TYPE_CONTEXT, GIMP_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_CALLBACK_NAME, g_param_spec_string ("callback-name", NULL, NULL, NULL, GIMP_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } static void gimp_pdb_progress_init (GimpPdbProgress *progress, GimpPdbProgressClass *klass) { klass->progresses = g_list_prepend (klass->progresses, progress); } static void gimp_pdb_progress_progress_iface_init (GimpProgressInterface *iface) { iface->start = gimp_pdb_progress_progress_start; iface->end = gimp_pdb_progress_progress_end; iface->is_active = gimp_pdb_progress_progress_is_active; iface->set_text = gimp_pdb_progress_progress_set_text; iface->set_value = gimp_pdb_progress_progress_set_value; iface->get_value = gimp_pdb_progress_progress_get_value; iface->pulse = gimp_pdb_progress_progress_pulse; iface->get_window_id = gimp_pdb_progress_progress_get_window_id; } static void gimp_pdb_progress_constructed (GObject *object) { GimpPdbProgress *progress = GIMP_PDB_PROGRESS (object); G_OBJECT_CLASS (parent_class)->constructed (object); gimp_assert (GIMP_IS_PDB (progress->pdb)); gimp_assert (GIMP_IS_CONTEXT (progress->context)); } static void gimp_pdb_progress_dispose (GObject *object) { GimpPdbProgressClass *klass = GIMP_PDB_PROGRESS_GET_CLASS (object); klass->progresses = g_list_remove (klass->progresses, object); G_OBJECT_CLASS (parent_class)->dispose (object); } static void gimp_pdb_progress_finalize (GObject *object) { GimpPdbProgress *progress = GIMP_PDB_PROGRESS (object); g_clear_object (&progress->pdb); g_clear_object (&progress->context); g_clear_pointer (&progress->callback_name, g_free); G_OBJECT_CLASS (parent_class)->finalize (object); } static void gimp_pdb_progress_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GimpPdbProgress *progress = GIMP_PDB_PROGRESS (object); switch (property_id) { case PROP_PDB: if (progress->pdb) g_object_unref (progress->pdb); progress->pdb = g_value_dup_object (value); break; case PROP_CONTEXT: if (progress->context) g_object_unref (progress->context); progress->context = g_value_dup_object (value); break; case PROP_CALLBACK_NAME: if (progress->callback_name) g_free (progress->callback_name); progress->callback_name = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static gdouble gimp_pdb_progress_run_callback (GimpPdbProgress *progress, GimpProgressCommand command, const gchar *text, gdouble value) { gdouble retval = 0; if (progress->callback_name && ! progress->callback_busy) { GimpValueArray *return_vals; progress->callback_busy = TRUE; return_vals = gimp_pdb_execute_procedure_by_name (progress->pdb, progress->context, NULL, NULL, progress->callback_name, GIMP_TYPE_INT32, command, G_TYPE_STRING, text, G_TYPE_DOUBLE, value, G_TYPE_NONE); if (g_value_get_enum (gimp_value_array_index (return_vals, 0)) != GIMP_PDB_SUCCESS) { gimp_message (progress->context->gimp, NULL, GIMP_MESSAGE_ERROR, _("Unable to run %s callback. " "The corresponding plug-in may have crashed."), g_type_name (G_TYPE_FROM_INSTANCE (progress))); } else if (gimp_value_array_length (return_vals) >= 2 && G_VALUE_HOLDS_DOUBLE (gimp_value_array_index (return_vals, 1))) { retval = g_value_get_double (gimp_value_array_index (return_vals, 1)); } gimp_value_array_unref (return_vals); progress->callback_busy = FALSE; } return retval; } static GimpProgress * gimp_pdb_progress_progress_start (GimpProgress *progress, gboolean cancellable, const gchar *message) { GimpPdbProgress *pdb_progress = GIMP_PDB_PROGRESS (progress); if (! pdb_progress->active) { gimp_pdb_progress_run_callback (pdb_progress, GIMP_PROGRESS_COMMAND_START, message, 0.0); pdb_progress->active = TRUE; pdb_progress->value = 0.0; return progress; } return NULL; } static void gimp_pdb_progress_progress_end (GimpProgress *progress) { GimpPdbProgress *pdb_progress = GIMP_PDB_PROGRESS (progress); if (pdb_progress->active) { gimp_pdb_progress_run_callback (pdb_progress, GIMP_PROGRESS_COMMAND_END, NULL, 0.0); pdb_progress->active = FALSE; pdb_progress->value = 0.0; } } static gboolean gimp_pdb_progress_progress_is_active (GimpProgress *progress) { GimpPdbProgress *pdb_progress = GIMP_PDB_PROGRESS (progress); return pdb_progress->active; } static void gimp_pdb_progress_progress_set_text (GimpProgress *progress, const gchar *message) { GimpPdbProgress *pdb_progress = GIMP_PDB_PROGRESS (progress); if (pdb_progress->active) gimp_pdb_progress_run_callback (pdb_progress, GIMP_PROGRESS_COMMAND_SET_TEXT, message, 0.0); } static void gimp_pdb_progress_progress_set_value (GimpProgress *progress, gdouble percentage) { GimpPdbProgress *pdb_progress = GIMP_PDB_PROGRESS (progress); if (pdb_progress->active) { gimp_pdb_progress_run_callback (pdb_progress, GIMP_PROGRESS_COMMAND_SET_VALUE, NULL, percentage); pdb_progress->value = percentage; } } static gdouble gimp_pdb_progress_progress_get_value (GimpProgress *progress) { GimpPdbProgress *pdb_progress = GIMP_PDB_PROGRESS (progress); return pdb_progress->value; } static void gimp_pdb_progress_progress_pulse (GimpProgress *progress) { GimpPdbProgress *pdb_progress = GIMP_PDB_PROGRESS (progress); if (pdb_progress->active) gimp_pdb_progress_run_callback (pdb_progress, GIMP_PROGRESS_COMMAND_PULSE, NULL, 0.0); } static guint32 gimp_pdb_progress_progress_get_window_id (GimpProgress *progress) { GimpPdbProgress *pdb_progress = GIMP_PDB_PROGRESS (progress); return (guint32) gimp_pdb_progress_run_callback (pdb_progress, GIMP_PROGRESS_COMMAND_GET_WINDOW, NULL, 0.0); } GimpPdbProgress * gimp_pdb_progress_get_by_callback (GimpPdbProgressClass *klass, const gchar *callback_name) { GList *list; g_return_val_if_fail (GIMP_IS_PDB_PROGRESS_CLASS (klass), NULL); g_return_val_if_fail (callback_name != NULL, NULL); for (list = klass->progresses; list; list = g_list_next (list)) { GimpPdbProgress *progress = list->data; if (! g_strcmp0 (callback_name, progress->callback_name)) return progress; } return NULL; }