static void gimp_thumb_box_create_thumbnail (GimpThumbBox *box, const gchar *uri, GimpThumbnailSize size, gboolean force, GimpProgress *progress) { gchar *filename = file_utils_filename_from_uri (uri); GimpThumbnail *thumb; gchar *basename; if (filename) { gboolean regular = g_file_test (filename, G_FILE_TEST_IS_REGULAR); g_free (filename); if (! regular) return; } thumb = gimp_imagefile_get_thumbnail (box->imagefile); basename = file_utils_uri_display_basename (uri); gtk_label_set_text (GTK_LABEL (box->filename), basename); g_free (basename); gimp_object_set_name (GIMP_OBJECT (box->imagefile), uri); if (force || (gimp_thumbnail_peek_thumb (thumb, size) < GIMP_THUMB_STATE_FAILED && ! gimp_thumbnail_has_failed (thumb))) { GError *error = NULL; if (! gimp_imagefile_create_thumbnail (box->imagefile, box->context, progress, size, ! force, &error)) { gimp_message_literal (box->context->gimp, G_OBJECT (progress), GIMP_MESSAGE_ERROR, error->message); g_clear_error (&error); } } }
static void gimp_display_shell_close_name_changed (GimpImage *image, GimpMessageBox *box) { GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET (box)); gchar *name; name = file_utils_uri_display_basename (gimp_image_get_uri (image)); if (window) { gchar *title = g_strdup_printf (_("Close %s"), name); 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?"), name); g_free (name); }
static void gimp_display_shell_close_dialog (GimpDisplayShell *shell, GimpImage *image) { GtkWidget *dialog; GtkWidget *button; GimpMessageBox *box; GClosure *closure; GSource *source; gchar *name; gchar *title; if (shell->close_dialog) { gtk_window_present (GTK_WINDOW (shell->close_dialog)); return; } name = file_utils_uri_display_basename (gimp_image_get_uri (image)); title = g_strdup_printf (_("Close %s"), name); g_free (name); 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); button = gtk_dialog_add_button (GTK_DIALOG (dialog), _("Do_n't Save"), GTK_RESPONSE_CLOSE); gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_stock (GTK_STOCK_DELETE, GTK_ICON_SIZE_BUTTON)); gtk_dialog_add_buttons (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, 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 (10 * 1000); 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); }
GList * file_open_layers (Gimp *gimp, GimpContext *context, GimpProgress *progress, GimpImage *dest_image, gboolean merge_visible, const gchar *uri, GimpRunMode run_mode, GimpPlugInProcedure *file_proc, GimpPDBStatusType *status, GError **error) { GimpImage *new_image; GList *layers = NULL; const gchar *mime_type = NULL; g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); g_return_val_if_fail (GIMP_IS_IMAGE (dest_image), NULL); g_return_val_if_fail (uri != NULL, NULL); g_return_val_if_fail (status != NULL, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); new_image = file_open_image (gimp, context, progress, uri, uri, FALSE, file_proc, run_mode, status, &mime_type, error); if (new_image) { gint n_visible = 0; gimp_image_undo_disable (new_image); layers = file_open_get_layers (new_image, merge_visible, &n_visible); if (merge_visible && n_visible > 1) { GimpLayer *layer; g_list_free (layers); layer = gimp_image_merge_visible_layers (new_image, context, GIMP_CLIP_TO_IMAGE, FALSE, FALSE); layers = g_list_prepend (NULL, layer); } if (layers) { gchar *basename = file_utils_uri_display_basename (uri); file_open_convert_items (dest_image, basename, layers); g_free (basename); gimp_document_list_add_uri (GIMP_DOCUMENT_LIST (gimp->documents), uri, mime_type); } else { g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Image doesn't contain any layers")); *status = GIMP_PDB_EXECUTION_ERROR; } g_object_unref (new_image); } return g_list_reverse (layers); }
GimpImage * file_open_with_proc_and_display (Gimp *gimp, GimpContext *context, GimpProgress *progress, const gchar *uri, const gchar *entered_filename, gboolean as_new, GimpPlugInProcedure *file_proc, GimpPDBStatusType *status, GError **error) { GimpImage *image; const gchar *mime_type = NULL; g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL); g_return_val_if_fail (status != NULL, NULL); image = file_open_image (gimp, context, progress, uri, entered_filename, as_new, file_proc, GIMP_RUN_INTERACTIVE, status, &mime_type, error); if (image) { /* If the file was imported we want to set the layer name to the * file name. For now, assume that multi-layered imported images * have named the layers already, so only rename the layer of * single-layered imported files. Note that this will also * rename already named layers from e.g. single-layered PSD * files. To solve this properly, we would need new file plug-in * API. */ if (file_open_file_proc_is_import (file_proc) && gimp_image_get_n_layers (image) == 1) { GimpObject *layer = gimp_image_get_layer_iter (image)->data; gchar *basename = file_utils_uri_display_basename (uri); gimp_item_rename (GIMP_ITEM (layer), basename, NULL); gimp_image_undo_free (image); gimp_image_clean_all (image); g_free (basename); } gimp_create_display (image->gimp, image, GIMP_UNIT_PIXEL, 1.0); if (! as_new) { GimpDocumentList *documents = GIMP_DOCUMENT_LIST (gimp->documents); GimpImagefile *imagefile; imagefile = gimp_document_list_add_uri (documents, uri, mime_type); /* can only create a thumbnail if the passed uri and the * resulting image's uri match. */ if (strcmp (uri, gimp_image_get_uri_or_untitled (image)) == 0) { /* no need to save a thumbnail if there's a good one already */ if (! gimp_imagefile_check_thumbnail (imagefile)) { gimp_imagefile_save_thumbnail (imagefile, mime_type, image); } } } /* the display owns the image now */ g_object_unref (image); /* announce that we opened this image */ gimp_image_opened (image->gimp, uri); } return image; }
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 = display->image; uri = gimp_object_get_name (GIMP_OBJECT (image)); dialog = g_object_get_data (G_OBJECT (image), REVERT_DATA_KEY); if (! uri) { gimp_message (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 *basename; gchar *filename; dialog = gimp_message_dialog_new (_("Revert Image"), GTK_STOCK_REVERT_TO_SAVED, display->shell, 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); basename = file_utils_uri_display_basename (uri); filename = file_utils_uri_display_name (uri); gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box, _("Revert '%s' to '%s'?"), basename, filename); g_free (filename); g_free (basename); 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 gimp_display_shell_format_title (GimpDisplayShell *shell, gchar *title, gint title_len, const gchar *format) { Gimp *gimp; GimpImage *image; gint num, denom; gint i = 0; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); image = shell->display->image; gimp = image->gimp; 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': /* pruned filename */ { const gchar *uri = gimp_image_get_uri (image); gchar *basename; basename = file_utils_uri_display_basename (uri); i += print (title, title_len, i, "%s", basename); g_free (basename); } break; case 'F': /* full filename */ { gchar *filename; const gchar *uri = gimp_image_get_uri (image); filename = file_utils_uri_display_name (uri); i += print (title, title_len, i, "%s", filename); g_free (filename); } 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", shell->display->instance); break; case 't': /* type */ { const gchar *image_type_str = NULL; gboolean empty = gimp_image_is_empty (image); switch (gimp_image_base_type (image)) { case GIMP_RGB: image_type_str = empty ? _("RGB-empty") : _("RGB"); break; case GIMP_GRAY: image_type_str = empty ? _("grayscale-empty") : _("grayscale"); break; case GIMP_INDEXED: image_type_str = empty ? _("indexed-empty") : _("indexed"); break; default: g_assert_not_reached (); break; } i += print (title, title_len, i, "%s", image_type_str); } 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 (image->dirty) 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 (! image->dirty) title[i++] = format[1]; format++; break; case 'B': /* dirty flag (long) */ if (image->dirty) i += print (title, title_len, i, "%s", _("(modified)")); break; case 'A': /* clean flag (long) */ if (! image->dirty) i += print (title, title_len, i, "%s", _("(clean)")); break; case 'm': /* memory used by image */ { GimpObject *object = GIMP_OBJECT (image); gchar *str; str = gimp_memsize_to_string (gimp_object_get_memsize (object, NULL)); i += print (title, title_len, i, "%s", str); g_free (str); } break; case 'l': /* number of layers */ i += print (title, title_len, i, "%d", gimp_container_num_children (image->layers)); break; case 'L': /* number of layers (long) */ { gint num = gimp_container_num_children (image->layers); 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) i += print (title, title_len, i, "%s", gimp_object_get_name (GIMP_OBJECT (drawable))); 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) { gchar unit_format[8]; g_snprintf (unit_format, sizeof (unit_format), "%%.%df", _gimp_unit_get_digits (gimp, shell->unit) + 1); i += print (title, title_len, i, unit_format, (image->width * _gimp_unit_get_factor (gimp, shell->unit) / image->xresolution)); break; } /* else fallthru */ case 'w': /* width in pixels */ i += print (title, title_len, i, "%d", image->width); break; case 'H': /* height in real-world units */ if (shell->unit != GIMP_UNIT_PIXEL) { gchar unit_format[8]; g_snprintf (unit_format, sizeof (unit_format), "%%.%df", _gimp_unit_get_digits (gimp, shell->unit) + 1); i += print (title, title_len, i, unit_format, (image->height * _gimp_unit_get_factor (gimp, shell->unit) / image->yresolution)); break; } /* else fallthru */ case 'h': /* height in pixels */ i += print (title, title_len, i, "%d", image->height); break; case 'u': /* unit symbol */ i += print (title, title_len, i, "%s", _gimp_unit_get_symbol (gimp, shell->unit)); break; case 'U': /* unit abbreviation */ i += print (title, title_len, i, "%s", _gimp_unit_get_abbreviation (gimp, 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'; }
static void gimp_file_dialog_proc_changed (GimpFileProcView *view, GimpFileDialog *dialog) { GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog); gchar *name; dialog->file_proc = gimp_file_proc_view_get_proc (view, &name); if (name) { gchar *label = g_strdup_printf (_("Select File _Type (%s)"), name); gtk_expander_set_label (GTK_EXPANDER (dialog->proc_expander), label); g_free (label); g_free (name); } if (gtk_file_chooser_get_action (chooser) == GTK_FILE_CHOOSER_ACTION_SAVE) { GimpPlugInProcedure *proc = dialog->file_proc; if (proc && proc->extensions_list) { gchar *uri = gtk_file_chooser_get_uri (chooser); if (uri && strlen (uri)) { const gchar *last_dot = strrchr (uri, '.'); /* if the dot is before the last slash, ignore it */ if (last_dot && strrchr (uri, '/') > last_dot) last_dot = NULL; /* check if the uri has a "meta extension" (e.g. foo.bar.gz) * and try to truncate both extensions away. */ if (last_dot && last_dot != uri) { GList *list; for (list = view->meta_extensions; list; list = g_list_next (list)) { const gchar *ext = list->data; if (! strcmp (ext, last_dot + 1)) { const gchar *p = last_dot - 1; while (p > uri && *p != '.') p--; if (p != uri && *p == '.') { last_dot = p; break; } } } } if (last_dot != uri) { GString *s = g_string_new (uri); gchar *basename; if (last_dot) g_string_truncate (s, last_dot - uri); g_string_append (s, "."); g_string_append (s, (gchar *) proc->extensions_list->data); gtk_file_chooser_set_uri (chooser, s->str); basename = file_utils_uri_display_basename (s->str); gtk_file_chooser_set_current_name (chooser, basename); g_free (basename); g_string_free (s, TRUE); } } g_free (uri); } } }
void gimp_file_dialog_set_image (GimpFileDialog *dialog, GimpImage *image, gboolean save_a_copy, gboolean close_after_saving) { const gchar *uri = NULL; gchar *dirname; gchar *basename; g_return_if_fail (GIMP_IS_FILE_DIALOG (dialog)); g_return_if_fail (GIMP_IS_IMAGE (image)); dialog->image = image; dialog->save_a_copy = save_a_copy; dialog->close_after_saving = close_after_saving; if (save_a_copy) uri = g_object_get_data (G_OBJECT (image), "gimp-image-save-a-copy"); if (! uri) uri = gimp_image_get_uri (image); gimp_file_dialog_set_file_proc (dialog, NULL); #ifndef G_OS_WIN32 dirname = g_path_get_dirname (uri); #else /* g_path_get_dirname() is supposed to work on pathnames, not URIs. * * If uri points to a file on the root of a drive * "file:///d:/foo.png", g_path_get_dirname() would return * "file:///d:". (What we really would want is "file:///d:/".) When * this then is passed inside gtk+ to g_filename_from_uri() we get * "d:" which is not an absolute pathname. This currently causes an * assertion failure in gtk+. This scenario occurs if we have opened * an image from the root of a drive and then do Save As. * * Of course, gtk+ shouldn't assert even if we feed it slighly bogus * data, and that problem should be fixed, too. But to get the * correct default current folder in the filechooser combo box, we * need to pass it the proper URI for an absolute path anyway. So * don't use g_path_get_dirname() on file: URIs. */ if (g_str_has_prefix (uri, "file:///")) { gchar *filepath = g_filename_from_uri (uri, NULL, NULL); gchar *dirpath = NULL; if (filepath != NULL) { dirpath = g_path_get_dirname (filepath); g_free (filepath); } if (dirpath != NULL) { dirname = g_filename_to_uri (dirpath, NULL, NULL); g_free (dirpath); } else { dirname = NULL; } } else { dirname = g_path_get_dirname (uri); } #endif if (dirname && strlen (dirname) && strcmp (dirname, ".")) { gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dialog), dirname); } else { const gchar *folder; folder = g_object_get_data (G_OBJECT (image), "gimp-image-dirname"); if (folder) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), folder); } g_free (dirname); basename = file_utils_uri_display_basename (uri); gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), basename); g_free (basename); }