413 lines
13 KiB
C
413 lines
13 KiB
C
|
/* 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 <mitch@gimp.org>
|
||
|
*
|
||
|
* 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 <https://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include "config.h"
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||
|
#include <gegl.h>
|
||
|
|
||
|
#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 guint32 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 gdouble
|
||
|
pika_pdb_progress_run_callback (PikaPdbProgress *progress,
|
||
|
PikaProgressCommand command,
|
||
|
const gchar *text,
|
||
|
gdouble value)
|
||
|
{
|
||
|
gdouble retval = 0;
|
||
|
|
||
|
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 &&
|
||
|
G_VALUE_HOLDS_DOUBLE (pika_value_array_index (return_vals, 1)))
|
||
|
{
|
||
|
retval = g_value_get_double (pika_value_array_index (return_vals, 1));
|
||
|
}
|
||
|
|
||
|
pika_value_array_unref (return_vals);
|
||
|
|
||
|
progress->callback_busy = FALSE;
|
||
|
}
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
|
||
|
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);
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
static guint32
|
||
|
pika_pdb_progress_progress_get_window_id (PikaProgress *progress)
|
||
|
{
|
||
|
PikaPdbProgress *pdb_progress = PIKA_PDB_PROGRESS (progress);
|
||
|
|
||
|
return (guint32)
|
||
|
pika_pdb_progress_run_callback (pdb_progress,
|
||
|
PIKA_PROGRESS_COMMAND_GET_WINDOW,
|
||
|
NULL, 0.0);
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|