/* 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 * * 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 "libpikaconfig/pikaconfig.h" #include "libpikawidgets/pikawidgets.h" #include "actions-types.h" #include "operations/pika-operation-config.h" #include "operations/pikaoperationsettings.h" #include "core/pika.h" #include "core/pika-filter-history.h" #include "core/pikaimage.h" #include "core/pikaprogress.h" #include "widgets/pikaaction.h" #include "actions.h" #include "filters-commands.h" #include "pikageglprocedure.h" #include "procedure-commands.h" /* local function prototypes */ static gchar * filters_parse_operation (Pika *pika, const gchar *operation_str, const gchar *icon_name, PikaObject **settings); static void filters_run_procedure (Pika *pika, PikaDisplay *display, PikaProcedure *procedure, PikaRunMode run_mode); /* public functions */ void filters_apply_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *drawables; gchar *operation; PikaObject *settings; PikaProcedure *procedure; GVariant *variant; return_if_no_drawables (image, drawables, data); if (g_list_length (drawables) != 1) { /* We only support running filters on single drawable for now. */ g_list_free (drawables); return; } operation = filters_parse_operation (image->pika, g_variant_get_string (value, NULL), pika_action_get_icon_name (action), &settings); procedure = pika_gegl_procedure_new (image->pika, PIKA_RUN_NONINTERACTIVE, settings, operation, pika_action_get_name (action), pika_action_get_label (action), pika_action_get_tooltip (action), pika_action_get_icon_name (action), pika_action_get_help_id (action)); g_free (operation); if (settings) g_object_unref (settings); pika_filter_history_add (image->pika, procedure); variant = g_variant_new_uint64 (GPOINTER_TO_SIZE (procedure)); g_variant_take_ref (variant); filters_history_cmd_callback (NULL, variant, data); g_variant_unref (variant); g_object_unref (procedure); g_list_free (drawables); } void filters_apply_interactive_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaImage *image; GList *drawables; PikaProcedure *procedure; GVariant *variant; return_if_no_drawables (image, drawables, data); if (g_list_length (drawables) != 1) { /* We only support running filters on single drawable for now. */ g_list_free (drawables); return; } procedure = pika_gegl_procedure_new (image->pika, PIKA_RUN_INTERACTIVE, NULL, g_variant_get_string (value, NULL), pika_action_get_name (action), pika_action_get_label (action), pika_action_get_tooltip (action), pika_action_get_icon_name (action), pika_action_get_help_id (action)); pika_filter_history_add (image->pika, procedure); variant = g_variant_new_uint64 (GPOINTER_TO_SIZE (procedure)); g_variant_take_ref (variant); filters_history_cmd_callback (NULL, variant, data); g_variant_unref (variant); g_object_unref (procedure); g_list_free (drawables); } void filters_repeat_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { Pika *pika; PikaDisplay *display; PikaProcedure *procedure; PikaRunMode run_mode; return_if_no_pika (pika, data); return_if_no_display (display, data); run_mode = (PikaRunMode) g_variant_get_int32 (value); procedure = pika_filter_history_nth (pika, 0); if (procedure) filters_run_procedure (pika, display, procedure, run_mode); } void filters_history_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { Pika *pika; PikaDisplay *display; PikaProcedure *procedure; gsize hack; return_if_no_pika (pika, data); return_if_no_display (display, data); hack = g_variant_get_uint64 (value); procedure = GSIZE_TO_POINTER (hack); filters_run_procedure (pika, display, procedure, PIKA_RUN_INTERACTIVE); } /* private functions */ static gchar * filters_parse_operation (Pika *pika, const gchar *operation_str, const gchar *icon_name, PikaObject **settings) { const gchar *newline = strchr (operation_str, '\n'); *settings = NULL; if (newline) { gchar *operation; const gchar *serialized; operation = g_strndup (operation_str, newline - operation_str); serialized = newline + 1; if (*serialized) { GError *error = NULL; *settings = g_object_new (pika_operation_config_get_type (pika, operation, icon_name, PIKA_TYPE_OPERATION_SETTINGS), NULL); if (! pika_config_deserialize_string (PIKA_CONFIG (*settings), serialized, -1, NULL, &error)) { g_warning ("filters_parse_operation: deserializing hardcoded " "operation settings failed: %s", error->message); g_clear_error (&error); g_object_unref (*settings); *settings = NULL; } } return operation; } return g_strdup (operation_str); } static void filters_run_procedure (Pika *pika, PikaDisplay *display, PikaProcedure *procedure, PikaRunMode run_mode) { PikaObject *settings = NULL; PikaValueArray *args; if (PIKA_IS_GEGL_PROCEDURE (procedure)) { PikaGeglProcedure *gegl_procedure = PIKA_GEGL_PROCEDURE (procedure); if (gegl_procedure->default_run_mode == PIKA_RUN_NONINTERACTIVE) run_mode = PIKA_RUN_NONINTERACTIVE; settings = gegl_procedure->default_settings; } args = procedure_commands_get_display_args (procedure, display, settings); if (args) { gboolean success = FALSE; if (run_mode == PIKA_RUN_NONINTERACTIVE) { success = procedure_commands_run_procedure (procedure, pika, PIKA_PROGRESS (display), args); } else { success = procedure_commands_run_procedure_async (procedure, pika, PIKA_PROGRESS (display), run_mode, args, display); } if (success) pika_filter_history_add (pika, procedure); pika_value_array_unref (args); } }