static void palette_import_image_changed (GimpContext *context, GimpImage *image, ImportDialog *dialog) { if (dialog->image) { g_signal_handlers_disconnect_by_func (dialog->image, palette_import_layer_changed, dialog); g_signal_handlers_disconnect_by_func (dialog->image, palette_import_mask_changed, dialog); } dialog->image = image; if (dialog->import_type == IMAGE_IMPORT) { gboolean sensitive = FALSE; if (image) { gchar *label; label = g_strdup_printf ("%s-%d", gimp_image_get_display_name (image), gimp_image_get_ID (image)); gtk_entry_set_text (GTK_ENTRY (dialog->entry), label); g_free (label); palette_import_make_palette (dialog); if (gimp_image_get_base_type (image) != GIMP_INDEXED) sensitive = TRUE; } gtk_widget_set_sensitive (dialog->sample_merged_toggle, sensitive); gtk_widget_set_sensitive (dialog->selection_only_toggle, sensitive); gimp_scale_entry_set_sensitive (GTK_OBJECT (dialog->threshold), sensitive); gimp_scale_entry_set_sensitive (GTK_OBJECT (dialog->num_colors), sensitive); } if (dialog->image) { g_signal_connect (dialog->image, "active-layer-changed", G_CALLBACK (palette_import_layer_changed), dialog); g_signal_connect (dialog->image, "mask-changed", G_CALLBACK (palette_import_mask_changed), dialog); } }
static gboolean debug_show_image_graph (GimpImage *source_image) { Gimp *gimp = source_image->gimp; GimpProjectable *projectable = GIMP_PROJECTABLE (source_image); GeglNode *image_graph = gimp_projectable_get_graph (projectable); GeglNode *output_node = gegl_node_get_output_proxy (image_graph, "output"); GimpImage *new_image = NULL; GimpLayer *layer = NULL; GeglNode *introspect = NULL; GeglNode *sink = NULL; GeglBuffer *buffer = NULL; gchar *new_name = NULL; /* Setup and process the introspection graph */ introspect = gegl_node_new_child (NULL, "operation", "gegl:introspect", "node", output_node, NULL); sink = gegl_node_new_child (NULL, "operation", "gegl:buffer-sink", "buffer", &buffer, NULL); gegl_node_link_many (introspect, sink, NULL); gegl_node_process (sink); /* Create a new image of the result */ new_name = g_strdup_printf ("%s GEGL graph", gimp_image_get_display_name (source_image)); new_image = gimp_create_image (gimp, gegl_buffer_get_width (buffer), gegl_buffer_get_height (buffer), GIMP_RGB, GIMP_PRECISION_U8, FALSE); gimp_image_set_uri (new_image, new_name); layer = gimp_layer_new_from_buffer (buffer, new_image, gimp_image_get_layer_format (new_image, TRUE), new_name, 1.0, GIMP_NORMAL_MODE); gimp_image_add_layer (new_image, layer, NULL, 0, FALSE); gimp_create_display (gimp, new_image, GIMP_UNIT_PIXEL, 1.0); /* Cleanup */ g_object_unref (new_image); g_free (new_name); g_object_unref (buffer); g_object_unref (sink); g_object_unref (introspect); g_object_unref (source_image); return FALSE; }
static void gimp_display_shell_close_name_changed (GimpImage *image, GimpMessageBox *box) { GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET (box)); if (GTK_IS_WINDOW (window)) { gchar *title = g_strdup_printf (_("Close %s"), gimp_image_get_display_name (image)); gtk_window_set_title (GTK_WINDOW (window), title); g_free (title); } gimp_message_box_set_primary_text (box, _("Save the changes to image '%s' " "before closing?"), gimp_image_get_display_name (image)); }
gboolean gimp_pdb_image_is_not_precision (GimpImage *image, GimpPrecision precision, GError **error) { g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); if (gimp_image_get_precision (image) != precision) return TRUE; g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT, _("Image '%s' (%d) must not be of precision '%s'"), gimp_image_get_display_name (image), gimp_image_get_ID (image), gimp_pdb_enum_value_get_nick (GIMP_TYPE_PRECISION, precision)); return FALSE; }
gboolean gimp_pdb_image_is_not_base_type (GimpImage *image, GimpImageBaseType type, GError **error) { g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); if (gimp_image_get_base_type (image) != type) return TRUE; g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT, _("Image '%s' (%d) must not be of type '%s'"), gimp_image_get_display_name (image), gimp_image_get_ID (image), gimp_pdb_enum_value_get_nick (GIMP_TYPE_IMAGE_BASE_TYPE, type)); return FALSE; }
static GimpValueArray * image_find_next_sample_point_invoker (GimpProcedure *procedure, Gimp *gimp, GimpContext *context, GimpProgress *progress, const GimpValueArray *args, GError **error) { gboolean success = TRUE; GimpValueArray *return_vals; GimpImage *image; gint32 sample_point; gint32 next_sample_point = 0; image = gimp_value_get_image (gimp_value_array_index (args, 0), gimp); sample_point = g_value_get_uint (gimp_value_array_index (args, 1)); if (success) { GimpSamplePoint *sp = gimp_image_get_next_sample_point (image, sample_point, &success); if (sp) next_sample_point = gimp_sample_point_get_ID (sp); if (! success) g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT, _("Image '%s' (%d) does not contain sample point with ID %d"), gimp_image_get_display_name (image), gimp_image_get_ID (image), sample_point); } return_vals = gimp_procedure_get_return_values (procedure, success, error ? *error : NULL); if (success) g_value_set_uint (gimp_value_array_index (return_vals, 1), next_sample_point); return return_vals; }
GimpGuide * gimp_pdb_image_get_guide (GimpImage *image, gint guide_ID, GError **error) { GimpGuide *guide; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); guide = gimp_image_get_guide (image, guide_ID); if (guide) return guide; g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT, _("Image '%s' (%d) does not contain guide with ID %d"), gimp_image_get_display_name (image), gimp_image_get_ID (image), guide_ID); return NULL; }
GimpSamplePoint * gimp_pdb_image_get_sample_point (GimpImage *image, gint sample_point_ID, GError **error) { GimpSamplePoint *sample_point; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); sample_point = gimp_image_get_sample_point (image, sample_point_ID); if (sample_point) return sample_point; g_set_error (error, GIMP_PDB_ERROR, GIMP_PDB_ERROR_INVALID_ARGUMENT, _("Image '%s' (%d) does not contain sample point with ID %d"), gimp_image_get_display_name (image), gimp_image_get_ID (image), sample_point_ID); return NULL; }
static void gimp_viewable_dialog_name_changed (GimpObject *object, GimpViewableDialog *dialog) { gchar *name; name = gimp_viewable_get_description (GIMP_VIEWABLE (object), NULL); if (GIMP_IS_ITEM (object)) { GimpImage *image = gimp_item_get_image (GIMP_ITEM (object)); gchar *tmp; tmp = name; name = g_strdup_printf ("%s-%d (%s)", tmp, gimp_item_get_ID (GIMP_ITEM (object)), gimp_image_get_display_name (image)); g_free (tmp); } gtk_label_set_text (GTK_LABEL (dialog->viewable_label), name); g_free (name); }
void file_revert_cmd_callback (GtkAction *action, gpointer data) { GimpDisplay *display; GimpImage *image; GtkWidget *dialog; const gchar *uri; return_if_no_display (display, data); image = gimp_display_get_image (display); uri = gimp_image_get_uri (image); if (! uri) uri = gimp_image_get_imported_uri (image); dialog = g_object_get_data (G_OBJECT (image), REVERT_DATA_KEY); if (! uri) { gimp_message_literal (image->gimp, G_OBJECT (display), GIMP_MESSAGE_ERROR, _("Revert failed. " "No file name associated with this image.")); } else if (dialog) { gtk_window_present (GTK_WINDOW (dialog)); } else { gchar *filename; dialog = gimp_message_dialog_new (_("Revert Image"), GTK_STOCK_REVERT_TO_SAVED, GTK_WIDGET (gimp_display_get_shell (display)), 0, gimp_standard_help_func, GIMP_HELP_FILE_REVERT, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_REVERT_TO_SAVED, GTK_RESPONSE_OK, NULL); gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1); g_signal_connect_object (display, "disconnect", G_CALLBACK (gtk_widget_destroy), dialog, G_CONNECT_SWAPPED); g_signal_connect (dialog, "response", G_CALLBACK (file_revert_confirm_response), display); filename = file_utils_uri_display_name (uri); gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box, _("Revert '%s' to '%s'?"), gimp_image_get_display_name (image), filename); g_free (filename); gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box, _("By reverting the image to the state saved " "on disk, you will lose all changes, " "including all undo information.")); g_object_set_data (G_OBJECT (image), REVERT_DATA_KEY, dialog); gtk_widget_show (dialog); } }
static void windows_actions_image_notify (GimpDisplay *display, const GParamSpec *unused, GimpActionGroup *group) { GimpImage *image = gimp_display_get_image (display); if (image) { GtkAction *action; gchar *action_name = gimp_display_get_action_name (display); action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), action_name); if (! action) { GimpActionEntry entry; entry.name = action_name; entry.stock_id = GIMP_STOCK_IMAGE; entry.label = ""; entry.accelerator = NULL; entry.tooltip = NULL; entry.callback = G_CALLBACK (windows_show_display_cmd_callback); entry.help_id = NULL; gimp_action_group_add_actions (group, NULL, &entry, 1); gimp_action_group_set_action_always_show_image (group, action_name, TRUE); action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), action_name); g_object_set_data (G_OBJECT (action), "display", display); } { const gchar *display_name; gchar *escaped; gchar *title; display_name = gimp_image_get_display_name (image); escaped = gimp_escape_uline (display_name); title = g_strdup_printf ("%s-%d.%d", escaped, gimp_image_get_ID (image), gimp_display_get_instance (display)); g_free (escaped); g_object_set (action, "label", title, "tooltip", gimp_image_get_display_path (image), "viewable", image, "context", gimp_get_user_context (group->gimp), NULL); g_free (title); } g_free (action_name); windows_actions_update_display_accels (group); } else { windows_actions_display_remove (group->gimp->displays, display, group); } }
static void gimp_display_shell_close_dialog (GimpDisplayShell *shell, GimpImage *image) { GtkWidget *dialog; GimpMessageBox *box; GClosure *closure; GSource *source; gchar *title; const gchar *uri; if (shell->close_dialog) { gtk_window_present (GTK_WINDOW (shell->close_dialog)); return; } uri = gimp_image_get_uri (image); title = g_strdup_printf (_("Close %s"), gimp_image_get_display_name (image)); shell->close_dialog = dialog = gimp_message_dialog_new (title, GTK_STOCK_SAVE, GTK_WIDGET (shell), GTK_DIALOG_DESTROY_WITH_PARENT, gimp_standard_help_func, NULL, NULL); g_free (title); gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("Close _without Saving"), GTK_RESPONSE_CLOSE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, (uri ? GTK_STOCK_SAVE : GTK_STOCK_SAVE_AS), RESPONSE_SAVE, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL); gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), RESPONSE_SAVE, GTK_RESPONSE_CLOSE, GTK_RESPONSE_CANCEL, -1); g_signal_connect (dialog, "destroy", G_CALLBACK (gtk_widget_destroyed), &shell->close_dialog); g_signal_connect (dialog, "response", G_CALLBACK (gimp_display_shell_close_response), shell); box = GIMP_MESSAGE_DIALOG (dialog)->box; g_signal_connect_object (image, "name-changed", G_CALLBACK (gimp_display_shell_close_name_changed), box, 0); gimp_display_shell_close_name_changed (image, box); closure = g_cclosure_new_object (G_CALLBACK (gimp_display_shell_close_time_changed), G_OBJECT (box)); /* update every 10 seconds */ source = g_timeout_source_new_seconds (10); g_source_set_closure (source, closure); g_source_attach (source, NULL); g_source_unref (source); /* The dialog is destroyed with the shell, so it should be safe * to hold an image pointer for the lifetime of the dialog. */ g_object_set_data (G_OBJECT (box), "gimp-image", image); gimp_display_shell_close_time_changed (box); gtk_widget_show (dialog); }
static gint gimp_display_shell_format_title (GimpDisplayShell *shell, gchar *title, gint title_len, const gchar *format) { GimpImage *image; gint num, denom; gint i = 0; g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), 0); image = gimp_display_get_image (shell->display); if (! image) { title[0] = '\n'; return 0; } gimp_zoom_model_get_fraction (shell->zoom, &num, &denom); while (i < title_len && *format) { switch (*format) { case '%': format++; switch (*format) { case 0: /* format string ends within %-sequence, print literal '%' */ case '%': title[i++] = '%'; break; case 'f': /* base filename */ i += print (title, title_len, i, "%s", gimp_image_get_display_name (image)); break; case 'F': /* full filename */ i += print (title, title_len, i, "%s", gimp_image_get_display_path (image)); break; case 'p': /* PDB id */ i += print (title, title_len, i, "%d", gimp_image_get_ID (image)); break; case 'i': /* instance */ i += print (title, title_len, i, "%d", gimp_display_get_instance (shell->display)); break; case 't': /* image type */ i += print (title, title_len, i, "%s %s", gimp_display_shell_title_image_type (image), gimp_display_shell_title_image_precision (image)); break; case 'T': /* drawable type */ { GimpDrawable *drawable = gimp_image_get_active_drawable (image); const Babl *format = gimp_drawable_get_format (drawable); if (drawable) i += print (title, title_len, i, "%s", gimp_babl_get_description (format)); } break; case 's': /* user source zoom factor */ i += print (title, title_len, i, "%d", denom); break; case 'd': /* user destination zoom factor */ i += print (title, title_len, i, "%d", num); break; case 'z': /* user zoom factor (percentage) */ { gdouble scale = gimp_zoom_model_get_factor (shell->zoom); i += print (title, title_len, i, scale >= 0.15 ? "%.0f" : "%.2f", 100.0 * scale); } break; case 'D': /* dirty flag */ if (format[1] == 0) { /* format string ends within %D-sequence, print literal '%D' */ i += print (title, title_len, i, "%%D"); break; } if (gimp_image_is_dirty (image)) title[i++] = format[1]; format++; break; case 'C': /* clean flag */ if (format[1] == 0) { /* format string ends within %C-sequence, print literal '%C' */ i += print (title, title_len, i, "%%C"); break; } if (! gimp_image_is_dirty (image)) title[i++] = format[1]; format++; break; case 'B': /* dirty flag (long) */ if (gimp_image_is_dirty (image)) i += print (title, title_len, i, "%s", _("(modified)")); break; case 'A': /* clean flag (long) */ if (! gimp_image_is_dirty (image)) i += print (title, title_len, i, "%s", _("(clean)")); break; case 'm': /* memory used by image */ { GimpObject *object = GIMP_OBJECT (image); gchar *str; str = g_format_size (gimp_object_get_memsize (object, NULL)); i += print (title, title_len, i, "%s", str); g_free (str); } break; case 'M': /* image size in megapixels */ i += print (title, title_len, i, "%.1f", (gdouble) gimp_image_get_width (image) * (gdouble) gimp_image_get_height (image) / 1000000.0); break; case 'l': /* number of layers */ i += print (title, title_len, i, "%d", gimp_image_get_n_layers (image)); break; case 'L': /* number of layers (long) */ { gint num = gimp_image_get_n_layers (image); i += print (title, title_len, i, ngettext ("%d layer", "%d layers", num), num); } break; case 'n': /* active drawable name */ { GimpDrawable *drawable = gimp_image_get_active_drawable (image); if (drawable) { gchar *desc; desc = gimp_viewable_get_description (GIMP_VIEWABLE (drawable), NULL); i += print (title, title_len, i, "%s", desc); g_free (desc); } else { i += print (title, title_len, i, "%s", _("(none)")); } } break; case 'P': /* active drawable PDB id */ { GimpDrawable *drawable = gimp_image_get_active_drawable (image); if (drawable) i += print (title, title_len, i, "%d", gimp_item_get_ID (GIMP_ITEM (drawable))); else i += print (title, title_len, i, "%s", _("(none)")); } break; case 'W': /* width in real-world units */ if (shell->unit != GIMP_UNIT_PIXEL) { gdouble xres; gdouble yres; gchar unit_format[8]; gimp_image_get_resolution (image, &xres, &yres); g_snprintf (unit_format, sizeof (unit_format), "%%.%df", gimp_unit_get_digits (shell->unit) + 1); i += print (title, title_len, i, unit_format, gimp_pixels_to_units (gimp_image_get_width (image), shell->unit, xres)); break; } /* else fallthru */ case 'w': /* width in pixels */ i += print (title, title_len, i, "%d", gimp_image_get_width (image)); break; case 'H': /* height in real-world units */ if (shell->unit != GIMP_UNIT_PIXEL) { gdouble xres; gdouble yres; gchar unit_format[8]; gimp_image_get_resolution (image, &xres, &yres); g_snprintf (unit_format, sizeof (unit_format), "%%.%df", gimp_unit_get_digits (shell->unit) + 1); i += print (title, title_len, i, unit_format, gimp_pixels_to_units (gimp_image_get_height (image), shell->unit, yres)); break; } /* else fallthru */ case 'h': /* height in pixels */ i += print (title, title_len, i, "%d", gimp_image_get_height (image)); break; case 'u': /* unit symbol */ i += print (title, title_len, i, "%s", gimp_unit_get_symbol (shell->unit)); break; case 'U': /* unit abbreviation */ i += print (title, title_len, i, "%s", gimp_unit_get_abbreviation (shell->unit)); break; /* Other cool things to be added: * %r = xresolution * %R = yresolution * %ø = image's fractal dimension * %þ = the answer to everything */ default: /* format string contains unknown %-sequence, print it literally */ i += print (title, title_len, i, "%%%c", *format); break; } break; default: title[i++] = *format; break; } format++; } title[MIN (i, title_len - 1)] = '\0'; return i; }
GimpColorProfilePolicy color_profile_import_dialog_run (GimpImage *image, GimpContext *context, GtkWidget *parent, GimpColorProfile **dest_profile, gboolean *dont_ask) { GtkWidget *dialog; GtkWidget *main_vbox; GtkWidget *frame; GtkWidget *label; GtkWidget *toggle; GimpColorProfile *src_profile; GimpColorProfilePolicy policy; const gchar *title; const gchar *frame_title; gchar *text; g_return_val_if_fail (GIMP_IS_IMAGE (image), GIMP_COLOR_PROFILE_POLICY_KEEP); g_return_val_if_fail (GIMP_IS_CONTEXT (context), GIMP_COLOR_PROFILE_POLICY_KEEP); g_return_val_if_fail (parent == NULL || GTK_IS_WIDGET (parent), GIMP_COLOR_PROFILE_POLICY_KEEP); g_return_val_if_fail (dest_profile != NULL, GIMP_COLOR_PROFILE_POLICY_KEEP); src_profile = gimp_image_get_color_profile (image); *dest_profile = gimp_image_get_builtin_color_profile (image); if (gimp_image_get_base_type (image) == GIMP_GRAY) { title = _("Convert to Grayscale Working Space?"); frame_title = _("Convert the image to the grayscale working space?"); } else { title = _("Convert to RGB Working Space?"); frame_title = _("Convert the image to the RGB working space?"); } dialog = gimp_viewable_dialog_new (GIMP_VIEWABLE (image), context, title, "gimp-image-color-profile-import", NULL, _("Import the image from a color profile"), parent, gimp_standard_help_func, GIMP_HELP_IMAGE_COLOR_PROFILE_IMPORT, _("Keep"), GTK_RESPONSE_CANCEL, _("Convert"), GTK_RESPONSE_OK, NULL); gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1); gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE); main_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12); gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), main_vbox, TRUE, TRUE, 0); gtk_widget_show (main_vbox); text = g_strdup_printf (_("The image '%s' has an embedded color profile"), gimp_image_get_display_name (image)); frame = gimp_frame_new (text); g_free (text); gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); label = gimp_color_profile_label_new (src_profile); gtk_container_add (GTK_CONTAINER (frame), label); gtk_widget_show (label); frame = gimp_frame_new (frame_title); gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); label = gimp_color_profile_label_new (*dest_profile); gtk_container_add (GTK_CONTAINER (frame), label); gtk_widget_show (label); if (dont_ask) { toggle = gtk_check_button_new_with_mnemonic (_("_Don't ask me again")); gtk_box_pack_end (GTK_BOX (main_vbox), toggle, FALSE, FALSE, 0); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), FALSE); gtk_widget_show (toggle); } switch (gtk_dialog_run (GTK_DIALOG (dialog))) { case GTK_RESPONSE_OK: policy = GIMP_COLOR_PROFILE_POLICY_CONVERT; g_object_ref (*dest_profile); break; default: policy = GIMP_COLOR_PROFILE_POLICY_KEEP; break; } if (dont_ask) { *dont_ask = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle)); } gtk_widget_destroy (dialog); return policy; }
static void gimp_display_shell_close_dialog (GimpDisplayShell *shell, GimpImage *image) { GtkWidget *dialog; GimpMessageBox *box; GtkWidget *label; GtkAccelGroup *accel_group; GClosure *closure; GSource *source; guint accel_key; GdkModifierType accel_mods; gchar *title; gchar *accel_string; gchar *hint; gchar *markup; GFile *file; if (shell->close_dialog) { gtk_window_present (GTK_WINDOW (shell->close_dialog)); return; } file = gimp_image_get_file (image); title = g_strdup_printf (_("Close %s"), gimp_image_get_display_name (image)); shell->close_dialog = dialog = gimp_message_dialog_new (title, "document-save", GTK_WIDGET (shell), GTK_DIALOG_DESTROY_WITH_PARENT, gimp_standard_help_func, NULL, NULL); g_free (title); gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("_Discard Changes"), GTK_RESPONSE_CLOSE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, (file ? GTK_STOCK_SAVE : GTK_STOCK_SAVE_AS), RESPONSE_SAVE, NULL); gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL); gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog), RESPONSE_SAVE, GTK_RESPONSE_CLOSE, GTK_RESPONSE_CANCEL, -1); g_signal_connect (dialog, "destroy", G_CALLBACK (gtk_widget_destroyed), &shell->close_dialog); g_signal_connect (dialog, "response", G_CALLBACK (gimp_display_shell_close_response), shell); /* connect <Primary>D to the quit/close button */ accel_group = gtk_accel_group_new (); gtk_window_add_accel_group (GTK_WINDOW (shell->close_dialog), accel_group); g_object_unref (accel_group); closure = g_closure_new_object (sizeof (GClosure), G_OBJECT (shell->close_dialog)); g_closure_set_marshal (closure, gimp_display_shell_close_accel_marshal); gtk_accelerator_parse ("<Primary>D", &accel_key, &accel_mods); gtk_accel_group_connect (accel_group, accel_key, accel_mods, 0, closure); box = GIMP_MESSAGE_DIALOG (dialog)->box; accel_string = gtk_accelerator_get_label (accel_key, accel_mods); hint = g_strdup_printf (_("Press %s to discard all changes and close the image."), accel_string); markup = g_strdup_printf ("<i><small>%s</small></i>", hint); label = gtk_label_new (NULL); gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); gtk_label_set_markup (GTK_LABEL (label), markup); gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0); gtk_widget_show (label); g_free (markup); g_free (hint); g_free (accel_string); g_signal_connect_object (image, "name-changed", G_CALLBACK (gimp_display_shell_close_name_changed), box, 0); g_signal_connect_object (image, "exported", G_CALLBACK (gimp_display_shell_close_exported), box, 0); gimp_display_shell_close_name_changed (image, box); closure = g_cclosure_new_object (G_CALLBACK (gimp_display_shell_close_time_changed), G_OBJECT (box)); /* update every 10 seconds */ source = g_timeout_source_new_seconds (10); g_source_set_closure (source, closure); g_source_attach (source, NULL); g_source_unref (source); /* The dialog is destroyed with the shell, so it should be safe * to hold an image pointer for the lifetime of the dialog. */ g_object_set_data (G_OBJECT (box), "gimp-image", image); gimp_display_shell_close_time_changed (box); gtk_widget_show (dialog); }