static gint gimp_plug_in_manager_file_proc_compare (gconstpointer a, gconstpointer b, gpointer data) { GimpPlugInProcedure *proc_a = GIMP_PLUG_IN_PROCEDURE (a); GimpPlugInProcedure *proc_b = GIMP_PLUG_IN_PROCEDURE (b); const gchar *label_a; const gchar *label_b; gint retval = 0; if (g_str_has_prefix (proc_a->prog, "gimp-xcf")) return -1; if (g_str_has_prefix (proc_b->prog, "gimp-xcf")) return 1; label_a = gimp_plug_in_procedure_get_label (proc_a); label_b = gimp_plug_in_procedure_get_label (proc_b); if (label_a && label_b) retval = g_utf8_collate (label_a, label_b); return retval; }
static void gimp_image_prop_view_label_set_filetype (GtkWidget *label, GimpImage *image) { GimpPlugInManager *manager = image->gimp->plug_in_manager; GimpPlugInProcedure *proc; proc = gimp_image_get_save_proc (image); if (! proc) proc = gimp_image_get_load_proc (image); if (! proc) { gchar *filename = gimp_image_get_filename (image); if (filename) { proc = file_procedure_find (manager->load_procs, filename, NULL); g_free (filename); } } gtk_label_set_text (GTK_LABEL (label), proc ? gimp_plug_in_procedure_get_label (proc) : NULL); }
void gimp_plug_in_procedure_handle_return_values (GimpPlugInProcedure *proc, Gimp *gimp, GimpProgress *progress, GimpValueArray *return_vals) { g_return_if_fail (GIMP_IS_PLUG_IN_PROCEDURE (proc)); g_return_if_fail (return_vals != NULL); if (! gimp_value_array_length (return_vals) > 0 || G_VALUE_TYPE (gimp_value_array_index (return_vals, 0)) != GIMP_TYPE_PDB_STATUS_TYPE) { return; } switch (g_value_get_enum (gimp_value_array_index (return_vals, 0))) { case GIMP_PDB_SUCCESS: break; case GIMP_PDB_CALLING_ERROR: if (gimp_value_array_length (return_vals) > 1 && G_VALUE_HOLDS_STRING (gimp_value_array_index (return_vals, 1))) { gimp_message (gimp, G_OBJECT (progress), GIMP_MESSAGE_ERROR, _("Calling error for '%s':\n" "%s"), gimp_plug_in_procedure_get_label (proc), g_value_get_string (gimp_value_array_index (return_vals, 1))); } break; case GIMP_PDB_EXECUTION_ERROR: if (gimp_value_array_length (return_vals) > 1 && G_VALUE_HOLDS_STRING (gimp_value_array_index (return_vals, 1))) { gimp_message (gimp, G_OBJECT (progress), GIMP_MESSAGE_ERROR, _("Execution error for '%s':\n" "%s"), gimp_plug_in_procedure_get_label (proc), g_value_get_string (gimp_value_array_index (return_vals, 1))); } break; } }
static void gimp_plug_in_cleanup_item (GimpPlugInProcFrame *proc_frame, GimpPlugInCleanupItem *cleanup) { GimpItem *item = cleanup->item; if (cleanup->shadow_buffer) { GimpProcedure *proc = proc_frame->procedure; GIMP_LOG (SHADOW_TILES, "Freeing shadow buffer of drawable '%s' on behalf of '%s'.", gimp_object_get_name (item), gimp_plug_in_procedure_get_label (GIMP_PLUG_IN_PROCEDURE (proc))); gimp_drawable_free_shadow_buffer (GIMP_DRAWABLE (item)); } }
void gimp_plug_in_cleanup (GimpPlugIn *plug_in, GimpPlugInProcFrame *proc_frame) { GList *list; g_return_if_fail (GIMP_IS_PLUG_IN (plug_in)); g_return_if_fail (proc_frame != NULL); for (list = proc_frame->cleanups; list; list = g_list_next (list)) { GimpPlugInCleanupImage *cleanup = list->data; GimpImage *image = cleanup->image; if (! gimp_container_have (plug_in->manager->gimp->images, (GimpObject *) image)) continue; if (image->pushing_undo_group == GIMP_UNDO_GROUP_NONE) continue; if (cleanup->undo_group_count != image->group_count) { GimpProcedure *proc = proc_frame->procedure; g_message ("Plug-In '%s' left image undo in inconsistent state, " "closing open undo groups.", gimp_plug_in_procedure_get_label (GIMP_PLUG_IN_PROCEDURE (proc))); while (image->pushing_undo_group != GIMP_UNDO_GROUP_NONE && cleanup->undo_group_count < image->group_count) { if (! gimp_image_undo_group_end (image)) break; } } g_slice_free (GimpPlugInCleanupImage, cleanup); } g_list_free (proc_frame->cleanups); proc_frame->cleanups = NULL; }
const gchar * gimp_plug_in_get_undo_desc (GimpPlugIn *plug_in) { GimpPlugInProcFrame *proc_frame; const gchar *undo_desc = NULL; g_return_val_if_fail (GIMP_IS_PLUG_IN (plug_in), NULL); proc_frame = gimp_plug_in_get_proc_frame (plug_in); if (proc_frame) { GimpPlugInProcedure *proc; proc = GIMP_PLUG_IN_PROCEDURE (proc_frame->procedure); if (proc) undo_desc = gimp_plug_in_procedure_get_label (proc); } return undo_desc ? undo_desc : gimp_object_get_name (plug_in); }
static void gimp_plug_in_cleanup_image (GimpPlugInProcFrame *proc_frame, GimpPlugInCleanupImage *cleanup) { GimpImage *image = cleanup->image; if (gimp_image_get_undo_group_count (image) == 0) return; if (cleanup->undo_group_count != gimp_image_get_undo_group_count (image)) { GimpProcedure *proc = proc_frame->procedure; g_message ("Plug-In '%s' left image undo in inconsistent state, " "closing open undo groups.", gimp_plug_in_procedure_get_label (GIMP_PLUG_IN_PROCEDURE (proc))); while (cleanup->undo_group_count < gimp_image_get_undo_group_count (image)) { if (! gimp_image_undo_group_end (image)) break; } } }
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; }
static void plug_in_actions_history_changed (GimpPlugInManager *manager, GimpActionGroup *group) { GimpPlugInProcedure *proc; gint i; proc = gimp_plug_in_manager_history_nth (manager, 0); if (proc) { GtkAction *actual_action; const gchar *label; gchar *repeat; gchar *reshow; gboolean sensitive = FALSE; /* copy the sensitivity of the plug-in procedure's actual action * instead of calling plug_in_actions_update() because doing the * latter would set the sensitivity of this image's action on * all images' actions. See bug #517683. */ actual_action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), GIMP_OBJECT (proc)->name); if (actual_action) sensitive = gtk_action_get_sensitive (actual_action); label = gimp_plug_in_procedure_get_label (proc); repeat = g_strdup_printf (_("Re_peat \"%s\""), label); reshow = g_strdup_printf (_("R_e-Show \"%s\""), label); gimp_action_group_set_action_label (group, "plug-in-repeat", repeat); gimp_action_group_set_action_label (group, "plug-in-reshow", reshow); gimp_action_group_set_action_sensitive (group, "plug-in-repeat", sensitive); gimp_action_group_set_action_sensitive (group, "plug-in-reshow", sensitive); g_free (repeat); g_free (reshow); } else { gimp_action_group_set_action_label (group, "plug-in-repeat", _("Repeat Last")); gimp_action_group_set_action_label (group, "plug-in-reshow", _("Re-Show Last")); gimp_action_group_set_action_sensitive (group, "plug-in-repeat", FALSE); gimp_action_group_set_action_sensitive (group, "plug-in-reshow", FALSE); } for (i = 0; i < gimp_plug_in_manager_history_length (manager); i++) { GtkAction *action; GtkAction *actual_action; gchar *name = g_strdup_printf ("plug-in-recent-%02d", i + 1); gboolean sensitive = FALSE; action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), name); g_free (name); proc = gimp_plug_in_manager_history_nth (manager, i); /* see comment above */ actual_action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), GIMP_OBJECT (proc)->name); if (actual_action) sensitive = gtk_action_get_sensitive (actual_action); g_object_set (action, "visible", TRUE, "sensitive", sensitive, "procedure", proc, "label", gimp_plug_in_procedure_get_label (proc), "stock-id", gimp_plug_in_procedure_get_stock_id (proc), "tooltip", gimp_plug_in_procedure_get_blurb (proc), NULL); } for (; i < gimp_plug_in_manager_history_size (manager); i++) { GtkAction *action; gchar *name = g_strdup_printf ("plug-in-recent-%02d", i + 1); action = gtk_action_group_get_action (GTK_ACTION_GROUP (group), name); g_free (name); g_object_set (action, "visible", FALSE, "procedure", NULL, NULL); } }
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; }
GimpImage * file_open_image (Gimp *gimp, GimpContext *context, GimpProgress *progress, GFile *file, GFile *entered_file, gboolean as_new, GimpPlugInProcedure *file_proc, GimpRunMode run_mode, GimpPDBStatusType *status, const gchar **mime_type, GError **error) { GimpValueArray *return_vals; GimpImage *image = NULL; GFile *local_file = NULL; gchar *path = NULL; gchar *entered_uri = NULL; GError *my_error = 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 (status != NULL, NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); *status = GIMP_PDB_EXECUTION_ERROR; /* 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_READ, G_FILE_QUERY_INFO_NONE, NULL, error); if (! info) return NULL; 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); return NULL; } if (! g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) { g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Permission denied")); g_object_unref (info); return NULL; } g_object_unref (info); } if (! file_proc) file_proc = file_procedure_find (gimp->plug_in_manager->load_procs, file, error); if (! file_proc) return NULL; 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; return NULL; } if (! file_proc->handles_uri) { path = g_file_get_path (file); if (! path) { local_file = file_remote_download_image (gimp, file, progress, &my_error); if (! local_file) { if (my_error) g_propagate_error (error, my_error); else *status = GIMP_PDB_CANCEL; return NULL; } path = g_file_get_path (local_file); } } if (! path) path = g_file_get_uri (file); entered_uri = g_file_get_uri (entered_file); if (! entered_uri) entered_uri = g_strdup (path); return_vals = gimp_pdb_execute_procedure_by_name (gimp->pdb, context, progress, error, gimp_object_get_name (file_proc), GIMP_TYPE_INT32, run_mode, G_TYPE_STRING, path, G_TYPE_STRING, entered_uri, G_TYPE_NONE); g_free (path); g_free (entered_uri); *status = g_value_get_enum (gimp_value_array_index (return_vals, 0)); if (*status == GIMP_PDB_SUCCESS) image = gimp_value_get_image (gimp_value_array_index (return_vals, 1), gimp); if (local_file) { if (image) gimp_image_set_file (image, file); g_file_delete (local_file, NULL, NULL); g_object_unref (local_file); } if (*status == GIMP_PDB_SUCCESS) { if (image) { file_open_sanitize_image (image, as_new); /* Only set the load procedure if it hasn't already been set. */ if (! gimp_image_get_load_proc (image)) gimp_image_set_load_proc (image, file_proc); file_proc = gimp_image_get_load_proc (image); if (mime_type) *mime_type = file_proc->mime_type; } else { if (error && ! *error) g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("%s plug-in returned SUCCESS but did not " "return an image"), gimp_plug_in_procedure_get_label (file_proc)); *status = GIMP_PDB_EXECUTION_ERROR; } } else if (*status != GIMP_PDB_CANCEL) { if (error && ! *error) g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("%s plug-In could not open image"), gimp_plug_in_procedure_get_label (file_proc)); } gimp_value_array_unref (return_vals); if (image) { file_open_handle_color_profile (image, context, progress, run_mode); if (file_open_file_proc_is_import (file_proc)) { /* Remember the import source */ gimp_image_set_imported_file (image, file); /* We shall treat this file as an Untitled file */ gimp_image_set_file (image, NULL); } } return image; }
GimpImage * file_open_image (Gimp *gimp, GimpContext *context, GimpProgress *progress, const gchar *uri, const gchar *entered_filename, gboolean as_new, GimpPlugInProcedure *file_proc, GimpRunMode run_mode, GimpPDBStatusType *status, const gchar **mime_type, GError **error) { GValueArray *return_vals; gchar *filename; GimpImage *image = 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); g_return_val_if_fail (error == NULL || *error == NULL, NULL); *status = GIMP_PDB_EXECUTION_ERROR; if (! file_proc) file_proc = file_procedure_find (gimp->plug_in_manager->load_procs, uri, error); if (! file_proc) return NULL; filename = file_utils_filename_from_uri (uri); if (filename) { /* check if we are opening a file */ if (g_file_test (filename, G_FILE_TEST_EXISTS)) { if (! g_file_test (filename, G_FILE_TEST_IS_REGULAR)) { g_free (filename); g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Not a regular file")); return NULL; } if (g_access (filename, R_OK) != 0) { g_free (filename); g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_ACCES, g_strerror (errno)); return NULL; } } } else { filename = g_strdup (uri); } return_vals = gimp_pdb_execute_procedure_by_name (gimp->pdb, context, progress, error, gimp_object_get_name (file_proc), GIMP_TYPE_INT32, run_mode, G_TYPE_STRING, filename, G_TYPE_STRING, entered_filename, G_TYPE_NONE); g_free (filename); *status = g_value_get_enum (&return_vals->values[0]); if (*status == GIMP_PDB_SUCCESS) { image = gimp_value_get_image (&return_vals->values[1], gimp); if (image) { file_open_sanitize_image (image, as_new); /* Only set the load procedure if it hasn't already been set. */ if (! gimp_image_get_load_proc (image)) gimp_image_set_load_proc (image, file_proc); file_proc = gimp_image_get_load_proc (image); if (mime_type) *mime_type = file_proc->mime_type; } else { if (error && ! *error) g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("%s plug-in returned SUCCESS but did not " "return an image"), gimp_plug_in_procedure_get_label (file_proc)); *status = GIMP_PDB_EXECUTION_ERROR; } } else if (*status != GIMP_PDB_CANCEL) { if (error && ! *error) g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("%s plug-In could not open image"), gimp_plug_in_procedure_get_label (file_proc)); } g_value_array_free (return_vals); if (image) { file_open_handle_color_profile (image, context, progress, run_mode); if (file_open_file_proc_is_import (file_proc)) { /* Remember the import source */ gimp_image_set_imported_uri (image, uri); /* We shall treat this file as an Untitled file */ gimp_image_set_uri (image, NULL); } } return image; }
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; }
GtkWidget * gimp_file_proc_view_new (Gimp *gimp, GSList *procedures, const gchar *automatic, const gchar *automatic_help_id) { GtkTreeView *view; GtkTreeViewColumn *column; GtkCellRenderer *cell; GtkListStore *store; GSList *list; GtkTreeIter iter; g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); store = gtk_list_store_new (NUM_COLUMNS, GIMP_TYPE_PLUG_IN_PROCEDURE, /* COLUMN_PROC */ G_TYPE_STRING, /* COLUMN_LABEL */ G_TYPE_STRING, /* COLUMN_EXTENSIONS */ G_TYPE_STRING); /* COLUMN_HELP_ID */ view = g_object_new (GIMP_TYPE_FILE_PROC_VIEW, "model", store, "rules-hint", TRUE, NULL); g_object_unref (store); for (list = procedures; list; list = g_slist_next (list)) { GimpPlugInProcedure *proc = list->data; if (! proc->prefixes_list) /* skip URL loaders */ { const gchar *label = gimp_plug_in_procedure_get_label (proc); gchar *help_id = gimp_plug_in_procedure_get_help_id (proc); GSList *list2; if (label) { gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, COLUMN_PROC, proc, COLUMN_LABEL, label, COLUMN_EXTENSIONS, proc->extensions, COLUMN_HELP_ID, help_id, -1); } g_free (help_id); for (list2 = proc->extensions_list; list2; list2 = g_slist_next (list2)) { GimpFileProcView *proc_view = GIMP_FILE_PROC_VIEW (view); const gchar *ext = list2->data; const gchar *dot = strchr (ext, '.'); if (dot && dot != ext) proc_view->meta_extensions = g_list_append (proc_view->meta_extensions, g_strdup (dot + 1)); } } } if (automatic) { gtk_list_store_prepend (store, &iter); gtk_list_store_set (store, &iter, COLUMN_PROC, NULL, COLUMN_LABEL, automatic, COLUMN_HELP_ID, automatic_help_id, -1); } column = gtk_tree_view_column_new (); gtk_tree_view_column_set_title (column, _("File Type")); gtk_tree_view_column_set_expand (column, TRUE); cell = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, cell, TRUE); gtk_tree_view_column_set_attributes (column, cell, "text", COLUMN_LABEL, NULL); gtk_tree_view_append_column (view, column); column = gtk_tree_view_column_new (); gtk_tree_view_column_set_title (column, _("Extensions")); cell = gtk_cell_renderer_text_new (); gtk_tree_view_column_pack_start (column, cell, TRUE); gtk_tree_view_column_set_attributes (column, cell, "text", COLUMN_EXTENSIONS, NULL); gtk_tree_view_append_column (view, column); g_signal_connect (gtk_tree_view_get_selection (view), "changed", G_CALLBACK (gimp_file_proc_view_selection_changed), view); return GTK_WIDGET (view); }
static void gimp_file_dialog_add_filters (GimpFileDialog *dialog, Gimp *gimp, GSList *file_procs) { GtkFileFilter *all; GSList *list; all = gtk_file_filter_new (); gtk_file_filter_set_name (all, _("All files")); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), all); gtk_file_filter_add_pattern (all, "*"); all = gtk_file_filter_new (); gtk_file_filter_set_name (all, _("All images")); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), all); for (list = file_procs; list; list = g_slist_next (list)) { GimpPlugInProcedure *file_proc = list->data; if (file_proc->extensions_list) { GtkFileFilter *filter = gtk_file_filter_new (); GString *str; GSList *ext; gint i; str = g_string_new (gimp_plug_in_procedure_get_label (file_proc)); /* an arbitrary limit to keep the file dialog from becoming too wide */ #define MAX_EXTENSIONS 4 for (ext = file_proc->extensions_list, i = 0; ext; ext = g_slist_next (ext), i++) { const gchar *extension = ext->data; gchar *pattern; pattern = gimp_file_dialog_pattern_from_extension (extension); gtk_file_filter_add_pattern (filter, pattern); gtk_file_filter_add_pattern (all, pattern); g_free (pattern); if (i == 0) { g_string_append (str, " ("); } else if (i <= MAX_EXTENSIONS) { g_string_append (str, ", "); } if (i < MAX_EXTENSIONS) { g_string_append (str, "*."); g_string_append (str, extension); } else if (i == MAX_EXTENSIONS) { g_string_append (str, "..."); } if (! ext->next) { g_string_append (str, ")"); } } gtk_file_filter_set_name (filter, str->str); g_string_free (str, TRUE); gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); } } gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), all); }