gboolean file_utils_save_thumbnail (GimpImage *image, const gchar *filename) { const gchar *image_uri; gboolean success = FALSE; g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE); g_return_val_if_fail (filename != NULL, FALSE); image_uri = gimp_image_get_uri (image); if (image_uri) { gchar *uri = g_filename_to_uri (filename, NULL, NULL); if (uri) { if ( ! strcmp (uri, image_uri)) { GimpImagefile *imagefile; imagefile = gimp_imagefile_new (image->gimp, uri); success = gimp_imagefile_save_thumbnail (imagefile, NULL, image); g_object_unref (imagefile); } g_free (uri); } } return success; }
GimpPDBStatusType file_save (Gimp *gimp, GimpImage *image, GimpProgress *progress, const gchar *uri, GimpPlugInProcedure *file_proc, GimpRunMode run_mode, gboolean change_saved_state, gboolean export_backward, gboolean export_forward, GError **error) { GimpDrawable *drawable; GimpValueArray *return_vals; GimpPDBStatusType status; gchar *filename; gint32 image_ID; gint32 drawable_ID; g_return_val_if_fail (GIMP_IS_GIMP (gimp), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (GIMP_IS_IMAGE (image), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (uri != NULL, GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (file_proc), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail ((export_backward && export_forward) == FALSE, GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (error == NULL || *error == NULL, GIMP_PDB_CALLING_ERROR); drawable = gimp_image_get_active_drawable (image); if (! drawable) return GIMP_PDB_EXECUTION_ERROR; filename = file_utils_filename_from_uri (uri); if (filename) { /* check if we are saving to a file */ if (g_file_test (filename, G_FILE_TEST_EXISTS)) { if (! g_file_test (filename, G_FILE_TEST_IS_REGULAR)) { g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Not a regular file")); status = GIMP_PDB_EXECUTION_ERROR; goto out; } if (g_access (filename, W_OK) != 0) { g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_ACCES, g_strerror (errno)); status = GIMP_PDB_EXECUTION_ERROR; goto out; } } if (file_proc->handles_uri) { g_free (filename); filename = g_strdup (uri); } } else { filename = g_strdup (uri); } /* ref the image, so it can't get deleted during save */ g_object_ref (image); image_ID = gimp_image_get_ID (image); drawable_ID = gimp_item_get_ID (GIMP_ITEM (drawable)); return_vals = gimp_pdb_execute_procedure_by_name (image->gimp->pdb, gimp_get_user_context (gimp), progress, error, gimp_object_get_name (file_proc), GIMP_TYPE_INT32, run_mode, GIMP_TYPE_IMAGE_ID, image_ID, GIMP_TYPE_DRAWABLE_ID, drawable_ID, G_TYPE_STRING, filename, G_TYPE_STRING, uri, G_TYPE_NONE); status = g_value_get_enum (gimp_value_array_index (return_vals, 0)); gimp_value_array_unref (return_vals); if (status == GIMP_PDB_SUCCESS) { GimpDocumentList *documents; GimpImagefile *imagefile; if (change_saved_state) { gimp_image_set_uri (image, uri); gimp_image_set_save_proc (image, file_proc); /* Forget the import source when we save. We interpret a * save as that the user is not interested in being able * to quickly export back to the original any longer */ gimp_image_set_imported_uri (image, NULL); gimp_image_clean_all (image); } else if (export_backward) { /* We exported the image back to its imported source, * change nothing about export/import flags, only set * the export state to clean */ gimp_image_export_clean_all (image); gimp_object_name_changed (GIMP_OBJECT (image)); } else if (export_forward) { /* Remember the last entered Export URI for the image. We * only need to do this explicitly when exporting. It * happens implicitly when saving since the GimpObject name * of a GimpImage is the last-save URI */ gimp_image_set_exported_uri (image, uri); /* An image can not be considered both exported and imported * at the same time, so stop consider it as imported now * that we consider it exported. */ gimp_image_set_imported_uri (image, NULL); gimp_image_export_clean_all (image); } if (export_backward || export_forward) gimp_image_exported (image, uri); else gimp_image_saved (image, uri); documents = GIMP_DOCUMENT_LIST (image->gimp->documents); imagefile = gimp_document_list_add_uri (documents, uri, file_proc->mime_type); /* only save a thumbnail if we are saving as XCF, see bug #25272 */ if (GIMP_PROCEDURE (file_proc)->proc_type == GIMP_INTERNAL) gimp_imagefile_save_thumbnail (imagefile, file_proc->mime_type, image); } else if (status != GIMP_PDB_CANCEL) { if (error && *error == NULL) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("%s plug-in could not save image"), gimp_plug_in_procedure_get_label (file_proc)); } } gimp_image_flush (image); g_object_unref (image); out: g_free (filename); return status; }
GimpImage * file_open_with_proc_and_display (Gimp *gimp, GimpContext *context, GimpProgress *progress, GFile *file, GFile *entered_file, gboolean as_new, GimpPlugInProcedure *file_proc, GObject *screen, gint monitor, 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 (G_IS_FILE (file), NULL); g_return_val_if_fail (G_IS_FILE (entered_file), NULL); g_return_val_if_fail (screen == NULL || G_IS_OBJECT (screen), NULL); g_return_val_if_fail (status != NULL, NULL); image = file_open_image (gimp, context, progress, file, entered_file, 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_proc) file_proc = gimp_image_get_load_proc (image); 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; basename = g_path_get_basename (gimp_file_get_utf8_name (file)); gimp_item_rename (GIMP_ITEM (layer), basename, NULL); gimp_image_undo_free (image); gimp_image_clean_all (image); g_free (basename); } if (gimp_create_display (image->gimp, image, GIMP_UNIT_PIXEL, 1.0, screen, monitor)) { /* the display owns the image now */ g_object_unref (image); } if (! as_new) { GimpDocumentList *documents = GIMP_DOCUMENT_LIST (gimp->documents); GimpImagefile *imagefile; GFile *any_file; imagefile = gimp_document_list_add_file (documents, file, mime_type); /* can only create a thumbnail if the passed file and the * resulting image's file match. Use any_file() here so we * create thumbnails for both XCF and imported images. */ any_file = gimp_image_get_any_file (image); if (any_file && g_file_equal (file, any_file)) { /* 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, NULL); } } } /* announce that we opened this image */ gimp_image_opened (image->gimp, file); } return image; }
GimpPDBStatusType file_save (Gimp *gimp, GimpImage *image, GimpProgress *progress, GFile *file, GimpPlugInProcedure *file_proc, GimpRunMode run_mode, gboolean change_saved_state, gboolean export_backward, gboolean export_forward, GError **error) { GimpDrawable *drawable; GimpValueArray *return_vals; GimpPDBStatusType status = GIMP_PDB_EXECUTION_ERROR; GFile *local_file = NULL; gchar *path = NULL; gchar *uri = NULL; gint32 image_ID; gint32 drawable_ID; GError *my_error = NULL; g_return_val_if_fail (GIMP_IS_GIMP (gimp), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (GIMP_IS_IMAGE (image), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (G_IS_FILE (file), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (file_proc), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail ((export_backward && export_forward) == FALSE, GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (error == NULL || *error == NULL, GIMP_PDB_CALLING_ERROR); /* ref image and file, so they can't get deleted during save */ g_object_ref (image); g_object_ref (file); drawable = gimp_image_get_active_drawable (image); if (! drawable) goto out; /* FIXME enable these tests for remote files again, needs testing */ if (g_file_is_native (file) && g_file_query_exists (file, NULL)) { GFileInfo *info; info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_QUERY_INFO_NONE, NULL, error); if (! info) goto out; if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR) { g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Not a regular file")); g_object_unref (info); goto out; } if (! g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) { g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Permission denied")); g_object_unref (info); goto out; } g_object_unref (info); } if (! g_file_is_native (file) && ! file_remote_mount_file (gimp, file, progress, &my_error)) { if (my_error) g_propagate_error (error, my_error); else status = GIMP_PDB_CANCEL; goto out; } if (! file_proc->handles_uri) { path = g_file_get_path (file); if (! path) { local_file = file_remote_upload_image_prepare (gimp, file, progress, &my_error); if (! local_file) { if (my_error) g_propagate_error (error, my_error); else status = GIMP_PDB_CANCEL; goto out; } path = g_file_get_path (local_file); } } if (! path) path = g_file_get_uri (file); uri = g_file_get_uri (file); image_ID = gimp_image_get_ID (image); drawable_ID = gimp_item_get_ID (GIMP_ITEM (drawable)); return_vals = gimp_pdb_execute_procedure_by_name (image->gimp->pdb, gimp_get_user_context (gimp), progress, error, gimp_object_get_name (file_proc), GIMP_TYPE_INT32, run_mode, GIMP_TYPE_IMAGE_ID, image_ID, GIMP_TYPE_DRAWABLE_ID, drawable_ID, G_TYPE_STRING, path, G_TYPE_STRING, uri, G_TYPE_NONE); status = g_value_get_enum (gimp_value_array_index (return_vals, 0)); gimp_value_array_unref (return_vals); if (local_file) { if (status == GIMP_PDB_SUCCESS) { GError *my_error = NULL; if (! file_remote_upload_image_finish (gimp, file, local_file, progress, &my_error)) { status = GIMP_PDB_EXECUTION_ERROR; if (my_error) g_propagate_error (error, my_error); else status = GIMP_PDB_CANCEL; } } g_file_delete (local_file, NULL, NULL); g_object_unref (local_file); } if (status == GIMP_PDB_SUCCESS) { GimpDocumentList *documents; GimpImagefile *imagefile; if (change_saved_state) { gimp_image_set_file (image, file); gimp_image_set_save_proc (image, file_proc); /* Forget the import source when we save. We interpret a * save as that the user is not interested in being able * to quickly export back to the original any longer */ gimp_image_set_imported_file (image, NULL); gimp_image_clean_all (image); } else if (export_backward) { /* We exported the image back to its imported source, * change nothing about export/import flags, only set * the export state to clean */ gimp_image_export_clean_all (image); gimp_object_name_changed (GIMP_OBJECT (image)); } else if (export_forward) { /* Remember the last entered Export URI for the image. We * only need to do this explicitly when exporting. It * happens implicitly when saving since the GimpObject name * of a GimpImage is the last-save URI */ gimp_image_set_exported_file (image, file); gimp_image_set_export_proc (image, file_proc); /* An image can not be considered both exported and imported * at the same time, so stop consider it as imported now * that we consider it exported. */ gimp_image_set_imported_file (image, NULL); gimp_image_export_clean_all (image); } if (export_backward || export_forward) gimp_image_exported (image, file); else gimp_image_saved (image, file); documents = GIMP_DOCUMENT_LIST (image->gimp->documents); imagefile = gimp_document_list_add_file (documents, file, file_proc->mime_type); /* only save a thumbnail if we are saving as XCF, see bug #25272 */ if (GIMP_PROCEDURE (file_proc)->proc_type == GIMP_INTERNAL) gimp_imagefile_save_thumbnail (imagefile, file_proc->mime_type, image, NULL); } else if (status != GIMP_PDB_CANCEL) { if (error && *error == NULL) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("%s plug-in could not save image"), gimp_plug_in_procedure_get_label (file_proc)); } } gimp_image_flush (image); out: g_object_unref (file); g_object_unref (image); g_free (path); g_free (uri); return status; }
GimpPDBStatusType file_save (GimpImage *image, GimpContext *context, GimpProgress *progress, const gchar *uri, GimpPlugInProcedure *file_proc, GimpRunMode run_mode, gboolean save_a_copy, GError **error) { GimpDrawable *drawable; GValueArray *return_vals; GimpPDBStatusType status; gchar *filename; gint32 image_ID; gint32 drawable_ID; g_return_val_if_fail (GIMP_IS_IMAGE (image), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (GIMP_IS_CONTEXT (context), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (uri != NULL, GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (file_proc), GIMP_PDB_CALLING_ERROR); g_return_val_if_fail (error == NULL || *error == NULL, GIMP_PDB_CALLING_ERROR); drawable = gimp_image_get_active_drawable (image); if (! drawable) return GIMP_PDB_EXECUTION_ERROR; filename = file_utils_filename_from_uri (uri); if (filename) { /* check if we are saving to a file */ if (g_file_test (filename, G_FILE_TEST_EXISTS)) { if (! g_file_test (filename, G_FILE_TEST_IS_REGULAR)) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "%s", _("Not a regular file")); status = GIMP_PDB_EXECUTION_ERROR; goto out; } if (g_access (filename, W_OK) != 0) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_ACCES, "%s", g_strerror (errno)); status = GIMP_PDB_EXECUTION_ERROR; goto out; } } } else { filename = g_strdup (uri); } /* ref the image, so it can't get deleted during save */ g_object_ref (image); image_ID = gimp_image_get_ID (image); drawable_ID = gimp_item_get_ID (GIMP_ITEM (drawable)); return_vals = gimp_pdb_execute_procedure_by_name (image->gimp->pdb, context, progress, error, GIMP_OBJECT (file_proc)->name, GIMP_TYPE_INT32, run_mode, GIMP_TYPE_IMAGE_ID, image_ID, GIMP_TYPE_DRAWABLE_ID, drawable_ID, G_TYPE_STRING, filename, G_TYPE_STRING, uri, G_TYPE_NONE); status = g_value_get_enum (&return_vals->values[0]); g_value_array_free (return_vals); if (status == GIMP_PDB_SUCCESS) { GimpDocumentList *documents; GimpImagefile *imagefile; if (save_a_copy) { /* remember the "save-a-copy" filename for the next invocation */ g_object_set_data_full (G_OBJECT (image), "gimp-image-save-a-copy", g_strdup (uri), (GDestroyNotify) g_free); } else { /* reset the "save-a-copy" filename when the image URI changes */ if (strcmp (uri, gimp_image_get_uri (image))) g_object_set_data (G_OBJECT (image), "gimp-image-save-a-copy", NULL); gimp_image_set_uri (image, uri); gimp_image_set_save_proc (image, file_proc); gimp_image_clean_all (image); } gimp_image_saved (image, uri); documents = GIMP_DOCUMENT_LIST (image->gimp->documents); imagefile = gimp_document_list_add_uri (documents, uri, file_proc->mime_type); /* only save a thumbnail if we are saving as XCF, see bug #25272 */ if (GIMP_PROCEDURE (file_proc)->proc_type == GIMP_INTERNAL) gimp_imagefile_save_thumbnail (imagefile, file_proc->mime_type, image); } else if (status != GIMP_PDB_CANCEL) { if (error && *error == NULL) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("%s plug-in could not save image"), gimp_plug_in_procedure_get_label (file_proc)); } } gimp_image_flush (image); g_object_unref (image); out: g_free (filename); return status; }