/* 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 * * pikaviewabledialog.c * Copyright (C) 2000 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 "libpikabase/pikabase.h" #include "libpikawidgets/pikawidgets.h" #include "widgets-types.h" #include "core/pikacontext.h" #include "core/pikaimage.h" #include "core/pikaitem.h" #include "pikaview.h" #include "pikaviewabledialog.h" #include "pikaviewrenderer.h" enum { PROP_0, PROP_VIEWABLES, PROP_CONTEXT, PROP_ICON_NAME, PROP_DESC }; static void pika_viewable_dialog_dispose (GObject *object); static void pika_viewable_dialog_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec); static void pika_viewable_dialog_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec); static void pika_viewable_dialog_name_changed (PikaObject *object, PikaViewableDialog *dialog); static void pika_viewable_dialog_close (PikaViewableDialog *dialog); G_DEFINE_TYPE (PikaViewableDialog, pika_viewable_dialog, PIKA_TYPE_DIALOG) #define parent_class pika_viewable_dialog_parent_class static void pika_viewable_dialog_class_init (PikaViewableDialogClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = pika_viewable_dialog_dispose; object_class->get_property = pika_viewable_dialog_get_property; object_class->set_property = pika_viewable_dialog_set_property; g_object_class_install_property (object_class, PROP_VIEWABLES, g_param_spec_pointer ("viewables", NULL, NULL, PIKA_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_CONTEXT, g_param_spec_object ("context", NULL, NULL, PIKA_TYPE_CONTEXT, PIKA_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_ICON_NAME, g_param_spec_string ("icon-name", NULL, NULL, NULL, PIKA_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_DESC, g_param_spec_string ("description", NULL, NULL, NULL, PIKA_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); } static void pika_viewable_dialog_init (PikaViewableDialog *dialog) { GtkWidget *content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); GtkWidget *frame; GtkWidget *hbox; GtkWidget *vbox; frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT); gtk_box_pack_start (GTK_BOX (content_area), frame, FALSE, FALSE, 0); gtk_widget_show (frame); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); gtk_container_set_border_width (GTK_CONTAINER (hbox), 2); gtk_container_add (GTK_CONTAINER (frame), hbox); gtk_widget_show (hbox); dialog->icon = gtk_image_new (); gtk_widget_set_valign (dialog->icon, GTK_ALIGN_CENTER); gtk_box_pack_start (GTK_BOX (hbox), dialog->icon, FALSE, FALSE, 0); gtk_widget_show (dialog->icon); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); gtk_widget_show (vbox); dialog->desc_label = gtk_label_new (NULL); gtk_label_set_xalign (GTK_LABEL (dialog->desc_label), 0.0); pika_label_set_attributes (GTK_LABEL (dialog->desc_label), PANGO_ATTR_SCALE, PANGO_SCALE_LARGE, PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1); gtk_box_pack_start (GTK_BOX (vbox), dialog->desc_label, FALSE, FALSE, 0); gtk_widget_show (dialog->desc_label); dialog->viewable_label = g_object_new (GTK_TYPE_LABEL, "xalign", 0.0, "ellipsize", PANGO_ELLIPSIZE_END, NULL); pika_label_set_attributes (GTK_LABEL (dialog->viewable_label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1); gtk_box_pack_start (GTK_BOX (vbox), dialog->viewable_label, FALSE, FALSE, 0); gtk_widget_show (dialog->viewable_label); } static void pika_viewable_dialog_dispose (GObject *object) { PikaViewableDialog *dialog = PIKA_VIEWABLE_DIALOG (object); if (dialog->view) pika_viewable_dialog_set_viewables (dialog, NULL, NULL); g_list_free (dialog->viewables); dialog->viewables = NULL; G_OBJECT_CLASS (parent_class)->dispose (object); } static void pika_viewable_dialog_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { PikaViewableDialog *dialog = PIKA_VIEWABLE_DIALOG (object); switch (property_id) { case PROP_VIEWABLES: pika_viewable_dialog_set_viewables (dialog, g_value_get_pointer (value), dialog->context); break; case PROP_CONTEXT: pika_viewable_dialog_set_viewables (dialog, g_list_copy (dialog->viewables), g_value_get_object (value)); break; case PROP_ICON_NAME: gtk_image_set_from_icon_name (GTK_IMAGE (dialog->icon), g_value_get_string (value), GTK_ICON_SIZE_LARGE_TOOLBAR); break; case PROP_DESC: gtk_label_set_text (GTK_LABEL (dialog->desc_label), g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void pika_viewable_dialog_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { PikaViewableDialog *dialog = PIKA_VIEWABLE_DIALOG (object); switch (property_id) { case PROP_VIEWABLES: g_value_set_pointer (value, dialog->viewables); break; case PROP_CONTEXT: g_value_set_object (value, dialog->context); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } GtkWidget * pika_viewable_dialog_new (GList *viewables, PikaContext *context, const gchar *title, const gchar *role, const gchar *icon_name, const gchar *desc, GtkWidget *parent, PikaHelpFunc help_func, const gchar *help_id, ...) { PikaViewableDialog *dialog; va_list args; gboolean use_header_bar; g_return_val_if_fail (context == NULL || PIKA_IS_CONTEXT (context), NULL); g_return_val_if_fail (title != NULL, NULL); g_return_val_if_fail (role != NULL, NULL); g_return_val_if_fail (parent == NULL || GTK_IS_WIDGET (parent), NULL); if (! viewables) g_warning ("Use of PikaViewableDialog with an empty viewable list is deprecated!"); g_object_get (gtk_settings_get_default (), "gtk-dialogs-use-header", &use_header_bar, NULL); dialog = g_object_new (PIKA_TYPE_VIEWABLE_DIALOG, "viewables", viewables, "context", context, "title", title, "role", role, "help-func", help_func, "help-id", help_id, "icon-name", icon_name, "description", desc, "parent", parent, "use-header-bar", use_header_bar, NULL); va_start (args, help_id); pika_dialog_add_buttons_valist (PIKA_DIALOG (dialog), args); va_end (args); return GTK_WIDGET (dialog); } /* * pika_viewable_dialog_set_viewables: * @dialog: * @viewables: * @context: * * Sets @dialog to display contents related to the list of #PikaViewable * @viewables. If this list contains a single viewable, a small preview * is also shown. * @dialog takes ownership of @viewables and will free the list upon * destruction. */ void pika_viewable_dialog_set_viewables (PikaViewableDialog *dialog, GList *viewables, PikaContext *context) { g_return_if_fail (PIKA_IS_VIEWABLE_DIALOG (dialog)); g_return_if_fail (context == NULL || PIKA_IS_CONTEXT (context)); dialog->context = context; g_list_free (dialog->viewables); dialog->viewables = viewables; if (dialog->view) { PikaViewable *old_viewable = PIKA_VIEW (dialog->view)->viewable; if (g_list_length (viewables) == 1 && viewables->data == old_viewable) { pika_view_renderer_set_context (PIKA_VIEW (dialog->view)->renderer, context); return; } gtk_widget_destroy (dialog->view); if (old_viewable) { g_signal_handlers_disconnect_by_func (old_viewable, pika_viewable_dialog_name_changed, dialog); g_signal_handlers_disconnect_by_func (old_viewable, pika_viewable_dialog_close, dialog); } } if (g_list_length (viewables) == 1 && viewables->data) { PikaViewable *viewable = viewables->data; GtkWidget *box; g_return_if_fail (PIKA_IS_VIEWABLE (viewable)); g_signal_connect_object (viewable, PIKA_VIEWABLE_GET_CLASS (viewable)->name_changed_signal, G_CALLBACK (pika_viewable_dialog_name_changed), dialog, 0); box = gtk_widget_get_parent (dialog->icon); g_set_weak_pointer (&dialog->view, pika_view_new (context, viewable, 32, 1, TRUE)); gtk_box_pack_end (GTK_BOX (box), dialog->view, FALSE, FALSE, 2); gtk_widget_show (dialog->view); pika_viewable_dialog_name_changed (PIKA_OBJECT (viewable), dialog); if (PIKA_IS_ITEM (viewable)) { g_signal_connect_object (viewable, "removed", G_CALLBACK (pika_viewable_dialog_close), dialog, G_CONNECT_SWAPPED); } else { g_signal_connect_object (viewable, "disconnect", G_CALLBACK (pika_viewable_dialog_close), dialog, G_CONNECT_SWAPPED); } } } /* private functions */ static void pika_viewable_dialog_name_changed (PikaObject *object, PikaViewableDialog *dialog) { gchar *name; name = pika_viewable_get_description (PIKA_VIEWABLE (object), NULL); if (PIKA_IS_ITEM (object)) { PikaImage *image = pika_item_get_image (PIKA_ITEM (object)); gchar *tmp; tmp = name; name = g_strdup_printf ("%s-%d (%s)", tmp, pika_item_get_id (PIKA_ITEM (object)), pika_image_get_display_name (image)); g_free (tmp); } gtk_label_set_text (GTK_LABEL (dialog->viewable_label), name); g_free (name); } static void pika_viewable_dialog_close (PikaViewableDialog *dialog) { g_signal_emit_by_name (dialog, "close"); }