/* 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 "libpikathumb/pikathumb.h" #include "libpikawidgets/pikawidgets.h" #include "actions-types.h" #include "config/pikacoreconfig.h" #include "core/pika.h" #include "core/pikacontainer.h" #include "core/pikacontext.h" #include "core/pikaimagefile.h" #include "core/pikaimage.h" #include "file/file-open.h" #include "widgets/pikaclipboard.h" #include "widgets/pikacontainerview.h" #include "widgets/pikacontainerview-utils.h" #include "widgets/pikadocumentview.h" #include "widgets/pikamessagebox.h" #include "widgets/pikamessagedialog.h" #include "widgets/pikawidgets-utils.h" #include "display/pikadisplay.h" #include "display/pikadisplay-foreach.h" #include "display/pikadisplayshell.h" #include "documents-commands.h" #include "file-commands.h" #include "pika-intl.h" typedef struct { const gchar *name; gboolean found; } RaiseClosure; /* local function prototypes */ static void documents_open_image (GtkWidget *editor, PikaContext *context, PikaImagefile *imagefile); static void documents_raise_display (PikaDisplay *display, RaiseClosure *closure); /* public functions */ void documents_open_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaContainerEditor *editor = PIKA_CONTAINER_EDITOR (data); PikaContext *context; PikaContainer *container; PikaImagefile *imagefile; context = pika_container_view_get_context (editor->view); container = pika_container_view_get_container (editor->view); imagefile = pika_context_get_imagefile (context); if (imagefile && pika_container_have (container, PIKA_OBJECT (imagefile))) { documents_open_image (GTK_WIDGET (editor), context, imagefile); } else { file_file_open_dialog (context->pika, NULL, GTK_WIDGET (editor)); } } void documents_raise_or_open_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaContainerEditor *editor = PIKA_CONTAINER_EDITOR (data); PikaContext *context; PikaContainer *container; PikaImagefile *imagefile; context = pika_container_view_get_context (editor->view); container = pika_container_view_get_container (editor->view); imagefile = pika_context_get_imagefile (context); if (imagefile && pika_container_have (container, PIKA_OBJECT (imagefile))) { RaiseClosure closure; closure.name = pika_object_get_name (imagefile); closure.found = FALSE; pika_container_foreach (PIKA_CONTAINER (context->pika->displays), (GFunc) documents_raise_display, &closure); if (! closure.found) documents_open_image (GTK_WIDGET (editor), context, imagefile); } } void documents_file_open_dialog_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaContainerEditor *editor = PIKA_CONTAINER_EDITOR (data); PikaContext *context; PikaContainer *container; PikaImagefile *imagefile; context = pika_container_view_get_context (editor->view); container = pika_container_view_get_container (editor->view); imagefile = pika_context_get_imagefile (context); if (imagefile && pika_container_have (container, PIKA_OBJECT (imagefile))) { file_file_open_dialog (context->pika, pika_imagefile_get_file (imagefile), GTK_WIDGET (editor)); } } void documents_copy_location_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaContainerEditor *editor = PIKA_CONTAINER_EDITOR (data); PikaContext *context; PikaImagefile *imagefile; context = pika_container_view_get_context (editor->view); imagefile = pika_context_get_imagefile (context); if (imagefile) pika_clipboard_set_text (context->pika, pika_object_get_name (imagefile)); } void documents_show_in_file_manager_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaContainerEditor *editor = PIKA_CONTAINER_EDITOR (data); PikaContext *context; PikaImagefile *imagefile; context = pika_container_view_get_context (editor->view); imagefile = pika_context_get_imagefile (context); if (imagefile) { GFile *file = g_file_new_for_uri (pika_object_get_name (imagefile)); GError *error = NULL; if (! pika_file_show_in_file_manager (file, &error)) { pika_message (context->pika, G_OBJECT (editor), PIKA_MESSAGE_ERROR, _("Can't show file in file manager: %s"), error->message); g_clear_error (&error); } g_object_unref (file); } } void documents_remove_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaContainerEditor *editor = PIKA_CONTAINER_EDITOR (data); PikaContext *context = pika_container_view_get_context (editor->view); PikaImagefile *imagefile = pika_context_get_imagefile (context); const gchar *uri; uri = pika_object_get_name (imagefile); gtk_recent_manager_remove_item (gtk_recent_manager_get_default (), uri, NULL); pika_container_view_remove_active (editor->view); } void documents_clear_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaContainerEditor *editor = PIKA_CONTAINER_EDITOR (data); PikaContext *context = pika_container_view_get_context (editor->view); Pika *pika = context->pika; GtkWidget *dialog; dialog = pika_message_dialog_new (_("Clear Document History"), PIKA_ICON_SHRED, GTK_WIDGET (editor), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, pika_standard_help_func, NULL, _("_Cancel"), GTK_RESPONSE_CANCEL, _("Cl_ear"), GTK_RESPONSE_OK, NULL); pika_dialog_set_alternative_button_order (GTK_DIALOG (dialog), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1); g_signal_connect_object (gtk_widget_get_toplevel (GTK_WIDGET (editor)), "unmap", G_CALLBACK (gtk_widget_destroy), dialog, G_CONNECT_SWAPPED); pika_message_box_set_primary_text (PIKA_MESSAGE_DIALOG (dialog)->box, _("Clear the Recent Documents list?")); pika_message_box_set_text (PIKA_MESSAGE_DIALOG (dialog)->box, _("Clearing the document history will " "permanently remove all images from " "the recent documents list.")); if (pika_dialog_run (PIKA_DIALOG (dialog)) == GTK_RESPONSE_OK) { GtkRecentManager *manager = gtk_recent_manager_get_default (); GList *items; GList *list; items = gtk_recent_manager_get_items (manager); for (list = items; list; list = list->next) { GtkRecentInfo *info = list->data; if (gtk_recent_info_has_application (info, "Photo and Image Kooker Application")) { gtk_recent_manager_remove_item (manager, gtk_recent_info_get_uri (info), NULL); } gtk_recent_info_unref (info); } g_list_free (items); pika_container_clear (pika->documents); } gtk_widget_destroy (dialog); } void documents_recreate_preview_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaContainerEditor *editor = PIKA_CONTAINER_EDITOR (data); PikaContext *context; PikaContainer *container; PikaImagefile *imagefile; context = pika_container_view_get_context (editor->view); container = pika_container_view_get_container (editor->view); imagefile = pika_context_get_imagefile (context); if (imagefile && pika_container_have (container, PIKA_OBJECT (imagefile))) { GError *error = NULL; if (! pika_imagefile_create_thumbnail (imagefile, context, NULL, context->pika->config->thumbnail_size, FALSE, &error)) { pika_message_literal (context->pika, NULL , PIKA_MESSAGE_ERROR, error->message); g_clear_error (&error); } } } void documents_reload_previews_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaContainerEditor *editor = PIKA_CONTAINER_EDITOR (data); PikaContainer *container; container = pika_container_view_get_container (editor->view); pika_container_foreach (container, (GFunc) pika_imagefile_update, editor->view); } static void documents_remove_dangling_foreach (PikaImagefile *imagefile, PikaContainer *container) { PikaThumbnail *thumbnail = pika_imagefile_get_thumbnail (imagefile); if (pika_thumbnail_peek_image (thumbnail) == PIKA_THUMB_STATE_NOT_FOUND) { const gchar *uri = pika_object_get_name (imagefile); gtk_recent_manager_remove_item (gtk_recent_manager_get_default (), uri, NULL); pika_container_remove (container, PIKA_OBJECT (imagefile)); } } void documents_remove_dangling_cmd_callback (PikaAction *action, GVariant *value, gpointer data) { PikaContainerEditor *editor = PIKA_CONTAINER_EDITOR (data); PikaContainer *container; container = pika_container_view_get_container (editor->view); pika_container_foreach (container, (GFunc) documents_remove_dangling_foreach, container); } /* private functions */ static void documents_open_image (GtkWidget *editor, PikaContext *context, PikaImagefile *imagefile) { GFile *file; PikaImage *image; PikaPDBStatusType status; GError *error = NULL; file = pika_imagefile_get_file (imagefile); image = file_open_with_display (context->pika, context, NULL, file, FALSE, G_OBJECT (pika_widget_get_monitor (editor)), &status, &error); if (! image && status != PIKA_PDB_CANCEL) { pika_message (context->pika, G_OBJECT (editor), PIKA_MESSAGE_ERROR, _("Opening '%s' failed:\n\n%s"), pika_file_get_utf8_name (file), error->message); g_clear_error (&error); } } static void documents_raise_display (PikaDisplay *display, RaiseClosure *closure) { PikaImage *image; GFile *file; gchar *uri = NULL; image = pika_display_get_image (display); file = pika_image_get_file (image); if (! file) file = pika_image_get_imported_file (image); if (file) uri = g_file_get_uri (file); if (! g_strcmp0 (closure->name, uri)) { closure->found = TRUE; pika_display_shell_present (pika_display_get_shell (display)); } g_free (uri); }