/* PIKA - Photo and Image Kooker Application * a rebranding of The GNU Image Manipulation Program (created with heckimp) * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio * * Original copyright, applying to most contents (license remains unchanged): * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * pikapdbprogress.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 "libpikabase/pikabase.h" #include "core-types.h" #include "core/pikacontext.h" #include "pdb/pikapdb.h" #include "pika.h" #include "pikaparamspecs.h" #include "pikapdbprogress.h" #include "pikaprogress.h" #include "pika-intl.h" enum { PROP_0, PROP_PDB, PROP_CONTEXT, PROP_CALLBACK_NAME }; static void pika_pdb_progress_class_init (PikaPdbProgressClass *klass); static void pika_pdb_progress_init (PikaPdbProgress *progress, PikaPdbProgressClass *klass); static void pika_pdb_progress_progress_iface_init (PikaProgressInterface *iface); static void pika_pdb_progress_constructed (GObject *object); static void pika_pdb_progress_dispose (GObject *object); static void pika_pdb_progress_finalize (GObject *object); static void pika_pdb_progress_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static PikaProgress * pika_pdb_progress_progress_start (PikaProgress *progress, gboolean cancellable, const gchar *message); static void pika_pdb_progress_progress_end (PikaProgress *progress); static gboolean pika_pdb_progress_progress_is_active (PikaProgress *progress); static void pika_pdb_progress_progress_set_text (PikaProgress *progress, const gchar *message); static void pika_pdb_progress_progress_set_value (PikaProgress *progress, gdouble percentage); static gdouble pika_pdb_progress_progress_get_value (PikaProgress *progress); static void pika_pdb_progress_progress_pulse (PikaProgress *progress); static GBytes * pika_pdb_progress_progress_get_window_id (PikaProgress *progress); static GObjectClass *parent_class = NULL; GType pika_pdb_progress_get_type (void) { static GType type = 0; if (! type) { const GTypeInfo info = { sizeof (PikaPdbProgressClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) pika_pdb_progress_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (PikaPdbProgress), 0, /* n_preallocs */ (GInstanceInitFunc) pika_pdb_progress_init, }; const GInterfaceInfo progress_iface_info = { (GInterfaceInitFunc) pika_pdb_progress_progress_iface_init, NULL, /* iface_finalize */ NULL /* iface_data */ }; type = g_type_register_static (G_TYPE_OBJECT, "PikaPdbProgress", &info, 0); g_type_add_interface_static (type, PIKA_TYPE_PROGRESS, &progress_iface_info); } return type; } static void pika_pdb_progress_class_init (PikaPdbProgressClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->constructed = pika_pdb_progress_constructed; object_class->dispose = pika_pdb_progress_dispose; object_class->finalize = pika_pdb_progress_finalize; object_class->set_property = pika_pdb_progress_set_property; g_object_class_install_property (object_class, PROP_PDB, g_param_spec_object ("pdb", NULL, NULL, PIKA_TYPE_PDB, PIKA_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (object_class, PROP_CONTEXT, g_param_spec_object ("context", NULL, NULL, PIKA_TYPE_CONTEXT, PIKA_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, PIKA_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); } static void pika_pdb_progress_init (PikaPdbProgress *progress, PikaPdbProgressClass *klass) { klass->progresses = g_list_prepend (klass->progresses, progress); } static void pika_pdb_progress_progress_iface_init (PikaProgressInterface *iface) { iface->start = pika_pdb_progress_progress_start; iface->end = pika_pdb_progress_progress_end; iface->is_active = pika_pdb_progress_progress_is_active; iface->set_text = pika_pdb_progress_progress_set_text; iface->set_value = pika_pdb_progress_progress_set_value; iface->get_value = pika_pdb_progress_progress_get_value; iface->pulse = pika_pdb_progress_progress_pulse; iface->get_window_id = pika_pdb_progress_progress_get_window_id; } static void pika_pdb_progress_constructed (GObject *object) { PikaPdbProgress *progress = PIKA_PDB_PROGRESS (object); G_OBJECT_CLASS (parent_class)->constructed (object); pika_assert (PIKA_IS_PDB (progress->pdb)); pika_assert (PIKA_IS_CONTEXT (progress->context)); } static void pika_pdb_progress_dispose (GObject *object) { PikaPdbProgressClass *klass = PIKA_PDB_PROGRESS_GET_CLASS (object); klass->progresses = g_list_remove (klass->progresses, object); G_OBJECT_CLASS (parent_class)->dispose (object); } static void pika_pdb_progress_finalize (GObject *object) { PikaPdbProgress *progress = PIKA_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 pika_pdb_progress_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PikaPdbProgress *progress = PIKA_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 void pika_pdb_progress_run_callback (PikaPdbProgress *progress, PikaProgressCommand command, const gchar *text, gdouble value, GBytes **handle) { if (progress->callback_name && ! progress->callback_busy) { PikaValueArray *return_vals; progress->callback_busy = TRUE; return_vals = pika_pdb_execute_procedure_by_name (progress->pdb, progress->context, NULL, NULL, progress->callback_name, PIKA_TYPE_PROGRESS_COMMAND, command, G_TYPE_STRING, text, G_TYPE_DOUBLE, value, G_TYPE_NONE); if (g_value_get_enum (pika_value_array_index (return_vals, 0)) != PIKA_PDB_SUCCESS) { pika_message (progress->context->pika, NULL, PIKA_MESSAGE_ERROR, _("Unable to run %s callback. " "The corresponding plug-in may have crashed."), g_type_name (G_TYPE_FROM_INSTANCE (progress))); } else if (pika_value_array_length (return_vals) >= 2 && handle != NULL && G_VALUE_HOLDS_BOXED (pika_value_array_index (return_vals, 1))) { *handle = g_value_dup_boxed (pika_value_array_index (return_vals, 1)); } pika_value_array_unref (return_vals); progress->callback_busy = FALSE; } } static PikaProgress * pika_pdb_progress_progress_start (PikaProgress *progress, gboolean cancellable, const gchar *message) { PikaPdbProgress *pdb_progress = PIKA_PDB_PROGRESS (progress); if (! pdb_progress->active) { pika_pdb_progress_run_callback (pdb_progress, PIKA_PROGRESS_COMMAND_START, message, 0.0, NULL); pdb_progress->active = TRUE; pdb_progress->value = 0.0; return progress; } return NULL; } static void pika_pdb_progress_progress_end (PikaProgress *progress) { PikaPdbProgress *pdb_progress = PIKA_PDB_PROGRESS (progress); if (pdb_progress->active) { pika_pdb_progress_run_callback (pdb_progress, PIKA_PROGRESS_COMMAND_END, NULL, 0.0, NULL); pdb_progress->active = FALSE; pdb_progress->value = 0.0; } } static gboolean pika_pdb_progress_progress_is_active (PikaProgress *progress) { PikaPdbProgress *pdb_progress = PIKA_PDB_PROGRESS (progress); return pdb_progress->active; } static void pika_pdb_progress_progress_set_text (PikaProgress *progress, const gchar *message) { PikaPdbProgress *pdb_progress = PIKA_PDB_PROGRESS (progress); if (pdb_progress->active) pika_pdb_progress_run_callback (pdb_progress, PIKA_PROGRESS_COMMAND_SET_TEXT, message, 0.0, NULL); } static void pika_pdb_progress_progress_set_value (PikaProgress *progress, gdouble percentage) { PikaPdbProgress *pdb_progress = PIKA_PDB_PROGRESS (progress); if (pdb_progress->active) { pika_pdb_progress_run_callback (pdb_progress, PIKA_PROGRESS_COMMAND_SET_VALUE, NULL, percentage, NULL); pdb_progress->value = percentage; } } static gdouble pika_pdb_progress_progress_get_value (PikaProgress *progress) { PikaPdbProgress *pdb_progress = PIKA_PDB_PROGRESS (progress); return pdb_progress->value; } static void pika_pdb_progress_progress_pulse (PikaProgress *progress) { PikaPdbProgress *pdb_progress = PIKA_PDB_PROGRESS (progress); if (pdb_progress->active) pika_pdb_progress_run_callback (pdb_progress, PIKA_PROGRESS_COMMAND_PULSE, NULL, 0.0, NULL); } static GBytes * pika_pdb_progress_progress_get_window_id (PikaProgress *progress) { PikaPdbProgress *pdb_progress = PIKA_PDB_PROGRESS (progress); GBytes *handle = NULL; pika_pdb_progress_run_callback (pdb_progress, PIKA_PROGRESS_COMMAND_GET_WINDOW, NULL, 0.0, &handle); return handle; } PikaPdbProgress * pika_pdb_progress_get_by_callback (PikaPdbProgressClass *klass, const gchar *callback_name) { GList *list; g_return_val_if_fail (PIKA_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)) { PikaPdbProgress *progress = list->data; if (! g_strcmp0 (callback_name, progress->callback_name)) return progress; } return NULL; }