app: separate the mount logic from uploading/downloading

We need to mount every non-native GFile's volume, regardless of
whether the file procedure uses GIO directly or needs file-remote to
download/upload the file. Move the entire mount logic to a new
file-remote function and change gimp-gui.c and gui-vtable.c to only
return a GMountOperation. Try to mount every non-native file in
file-open.c and file-save.c and bail out if mounting fails. Simplify
the uploading and downloading code accordingly.
This commit is contained in:
Michael Natterer 2014-07-22 20:29:52 +02:00
parent 57e6b22b9d
commit 7e7c22fc32
7 changed files with 187 additions and 205 deletions

View File

@ -64,7 +64,7 @@ gimp_gui_init (Gimp *gimp)
gimp->gui.pdb_dialog_close = NULL;
gimp->gui.recent_list_add_file = NULL;
gimp->gui.recent_list_load = NULL;
gimp->gui.mount_enclosing_volume = NULL;
gimp->gui.get_mount_operation = NULL;
}
void
@ -494,19 +494,15 @@ gimp_recent_list_load (Gimp *gimp)
gimp->gui.recent_list_load (gimp);
}
gboolean
gimp_mount_enclosing_volume (Gimp *gimp,
GFile *file,
GimpProgress *progress,
GError **error)
GMountOperation *
gimp_get_mount_operation (Gimp *gimp,
GimpProgress *progress)
{
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
g_return_val_if_fail (G_IS_FILE (file), FALSE);
g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (gimp->gui.mount_enclosing_volume)
return gimp->gui.mount_enclosing_volume (gimp, file, progress, error);
if (gimp->gui.get_mount_operation)
return gimp->gui.get_mount_operation (gimp, progress);
return FALSE;
return g_mount_operation_new ();
}

View File

@ -93,10 +93,8 @@ struct _GimpGui
const gchar *mime_type);
void (* recent_list_load) (Gimp *gimp);
gboolean (* mount_enclosing_volume) (Gimp *gimp,
GFile *file,
GimpProgress *progress,
GError **error);
GMountOperation * (* get_mount_operation) (Gimp *gimp,
GimpProgress *progress);
};
@ -175,10 +173,8 @@ gboolean gimp_recent_list_add_file (Gimp *gimp,
const gchar *mime_type);
void gimp_recent_list_load (Gimp *gimp);
gboolean gimp_mount_enclosing_volume (Gimp *gimp,
GFile *file,
GimpProgress *progress,
GError **error);
GMountOperation * gimp_get_mount_operation (Gimp *gimp,
GimpProgress *progress);
#endif /* __GIMP_GUI_H__ */

View File

@ -93,9 +93,9 @@ file_open_image (Gimp *gimp,
GimpValueArray *return_vals;
GimpImage *image = NULL;
GFile *local_file = NULL;
gboolean mounted = TRUE;
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);
@ -144,16 +144,25 @@ file_open_image (Gimp *gimp,
}
}
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)
{
GError *my_error = NULL;
local_file = file_remote_download_image (gimp, file, &mounted,
progress, &my_error);
local_file = file_remote_download_image (gimp, file, progress,
&my_error);
if (! local_file)
{
@ -200,9 +209,7 @@ file_open_image (Gimp *gimp,
if (image)
gimp_image_set_file (image, file);
if (! mounted)
g_file_delete (local_file, NULL, NULL);
g_file_delete (local_file, NULL, NULL);
g_object_unref (local_file);
}

View File

@ -46,6 +46,15 @@ typedef enum
UPLOAD
} RemoteCopyMode;
typedef struct
{
GimpProgress *progress;
GCancellable *cancellable;
gboolean cancel;
GMainLoop *main_loop;
GError *error;
} RemoteMount;
typedef struct
{
RemoteCopyMode mode;
@ -56,31 +65,101 @@ typedef struct
} RemoteProgress;
static GFile * file_remote_get_temp_file (Gimp *gimp,
GFile *file);
static GFile * file_remote_mount_file (Gimp *gimp,
GFile *file,
GimpProgress *progress);
static gboolean file_remote_copy_file (Gimp *gimp,
GFile *src_file,
GFile *dest_file,
RemoteCopyMode mode,
GimpProgress *progress,
GError **error);
static void file_remote_copy_file_cancel (GimpProgress *progress,
RemoteProgress *remote_progress);
static void file_remote_mount_volume_ready (GFile *file,
GAsyncResult *result,
RemoteMount *mount);
static void file_remote_mount_file_cancel (GimpProgress *progress,
RemoteMount *mount);
static void file_remote_progress_callback (goffset current_num_bytes,
goffset total_num_bytes,
gpointer user_data);
static GFile * file_remote_get_temp_file (Gimp *gimp,
GFile *file);
static gboolean file_remote_copy_file (Gimp *gimp,
GFile *src_file,
GFile *dest_file,
RemoteCopyMode mode,
GimpProgress *progress,
GError **error);
static void file_remote_copy_file_cancel (GimpProgress *progress,
RemoteProgress *remote_progress);
static void file_remote_progress_callback (goffset current_num_bytes,
goffset total_num_bytes,
gpointer user_data);
/* public functions */
gboolean
file_remote_mount_file (Gimp *gimp,
GFile *file,
GimpProgress *progress,
GError **error)
{
GMountOperation *operation;
RemoteMount mount = { 0, };
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
g_return_val_if_fail (G_IS_FILE (file), FALSE);
g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
mount.progress = progress;
mount.main_loop = g_main_loop_new (NULL, FALSE);
operation = gimp_get_mount_operation (gimp, progress);
if (progress)
{
gimp_progress_start (progress, TRUE, _("Mounting remote volume"));
mount.cancellable = g_cancellable_new ();
g_signal_connect (progress, "cancel",
G_CALLBACK (file_remote_mount_file_cancel),
&mount);
}
g_file_mount_enclosing_volume (file, G_MOUNT_MOUNT_NONE,
operation, mount.cancellable,
(GAsyncReadyCallback) file_remote_mount_volume_ready,
&mount);
g_main_loop_run (mount.main_loop);
g_main_loop_unref (mount.main_loop);
if (progress)
{
g_signal_handlers_disconnect_by_func (progress,
file_remote_mount_file_cancel,
&mount);
g_object_unref (mount.cancellable);
gimp_progress_end (progress);
}
g_object_unref (operation);
if (mount.error)
{
if (mount.error->domain != G_IO_ERROR ||
mount.error->code != G_IO_ERROR_ALREADY_MOUNTED)
{
g_propagate_error (error, mount.error);
return FALSE;
}
else
{
g_clear_error (&mount.error);
}
}
return TRUE;
}
GFile *
file_remote_download_image (Gimp *gimp,
GFile *file,
gboolean *mounted,
GimpProgress *progress,
GError **error)
{
@ -88,28 +167,16 @@ file_remote_download_image (Gimp *gimp,
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
g_return_val_if_fail (G_IS_FILE (file), NULL);
g_return_val_if_fail (mounted != NULL, NULL);
g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
local_file = file_remote_mount_file (gimp, file, progress);
local_file = file_remote_get_temp_file (gimp, file);
if (local_file)
if (! file_remote_copy_file (gimp, file, local_file, DOWNLOAD,
progress, error))
{
*mounted = TRUE;
}
else
{
*mounted = FALSE;
local_file = file_remote_get_temp_file (gimp, file);
if (! file_remote_copy_file (gimp, file, local_file, DOWNLOAD,
progress, error))
{
g_object_unref (local_file);
return NULL;
}
g_object_unref (local_file);
return NULL;
}
return local_file;
@ -118,7 +185,6 @@ file_remote_download_image (Gimp *gimp,
GFile *
file_remote_upload_image_prepare (Gimp *gimp,
GFile *file,
gboolean *mounted,
GimpProgress *progress,
GError **error)
{
@ -126,22 +192,10 @@ file_remote_upload_image_prepare (Gimp *gimp,
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
g_return_val_if_fail (G_IS_FILE (file), NULL);
g_return_val_if_fail (mounted != NULL, NULL);
g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
local_file = file_remote_mount_file (gimp, file, progress);
if (local_file)
{
*mounted = TRUE;
}
else
{
*mounted = FALSE;
local_file = file_remote_get_temp_file (gimp, file);
}
local_file = file_remote_get_temp_file (gimp, file);
return local_file;
}
@ -150,7 +204,6 @@ gboolean
file_remote_upload_image_finish (Gimp *gimp,
GFile *file,
GFile *local_file,
gboolean mounted,
GimpProgress *progress,
GError **error)
{
@ -160,13 +213,10 @@ file_remote_upload_image_finish (Gimp *gimp,
g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (! mounted)
if (! file_remote_copy_file (gimp, local_file, file, UPLOAD,
progress, error))
{
if (! file_remote_copy_file (gimp, local_file, file, UPLOAD,
progress, error))
{
return FALSE;
}
return FALSE;
}
return TRUE;
@ -175,6 +225,25 @@ file_remote_upload_image_finish (Gimp *gimp,
/* private functions */
static void
file_remote_mount_volume_ready (GFile *file,
GAsyncResult *result,
RemoteMount *mount)
{
g_file_mount_enclosing_volume_finish (file, result, &mount->error);
g_main_loop_quit (mount->main_loop);
}
static void
file_remote_mount_file_cancel (GimpProgress *progress,
RemoteMount *mount)
{
mount->cancel = TRUE;
g_cancellable_cancel (mount->cancellable);
}
static GFile *
file_remote_get_temp_file (Gimp *gimp,
GFile *file)
@ -200,33 +269,6 @@ file_remote_get_temp_file (Gimp *gimp,
return temp_file;
}
static GFile *
file_remote_mount_file (Gimp *gimp,
GFile *file,
GimpProgress *progress)
{
gboolean success = TRUE;
if (! gimp->no_interface)
{
GError *error = NULL;
if (! gimp_mount_enclosing_volume (gimp, file, progress, &error))
{
if (error->domain != G_IO_ERROR ||
error->code != G_IO_ERROR_ALREADY_MOUNTED)
success = FALSE;
g_clear_error (&error);
}
}
if (success && g_file_is_native (file))
return g_object_ref (file);
return NULL;
}
static gboolean
file_remote_copy_file (Gimp *gimp,
GFile *src_file,
@ -244,9 +286,9 @@ file_remote_copy_file (Gimp *gimp,
if (progress)
{
remote_progress.cancellable = g_cancellable_new ();
gimp_progress_start (progress, TRUE, _("Opening remote file"));
gimp_progress_start (progress, TRUE, _("Connecting to server"));
remote_progress.cancellable = g_cancellable_new ();
g_signal_connect (progress, "cancel",
G_CALLBACK (file_remote_copy_file_cancel),
@ -257,7 +299,14 @@ file_remote_copy_file (Gimp *gimp,
file_remote_progress_callback, &remote_progress,
&my_error);
g_signal_handlers_disconnect_by_func (progress,
file_remote_copy_file_cancel,
&remote_progress);
g_object_unref (remote_progress.cancellable);
gimp_progress_set_value (progress, 1.0);
gimp_progress_end (progress);
}
else
{
@ -266,47 +315,6 @@ file_remote_copy_file (Gimp *gimp,
&my_error);
}
if (! success &&
! gimp->no_interface &&
my_error &&
my_error->domain == G_IO_ERROR &&
my_error->code == G_IO_ERROR_NOT_MOUNTED)
{
g_clear_error (&my_error);
if (gimp_mount_enclosing_volume (gimp,
mode == DOWNLOAD ? src_file : dest_file,
progress,
error))
{
if (progress)
{
success = g_file_copy (src_file, dest_file, 0,
remote_progress.cancellable,
file_remote_progress_callback,
&remote_progress,
error);
}
else
{
success = g_file_copy (src_file, dest_file, 0,
NULL, NULL, NULL,
error);
}
}
}
if (progress)
{
g_signal_handlers_disconnect_by_func (progress,
file_remote_copy_file_cancel,
&remote_progress);
gimp_progress_end (progress);
g_object_unref (remote_progress.cancellable);
}
return success;
}

View File

@ -25,21 +25,23 @@
#define __FILE_REMOTE_H__
gboolean file_remote_mount_file (Gimp *gimp,
GFile *file,
GimpProgress *progress,
GError **error);
GFile * file_remote_download_image (Gimp *gimp,
GFile *file,
gboolean *mounted,
GimpProgress *progress,
GError **error);
GFile * file_remote_upload_image_prepare (Gimp *gimp,
GFile *file,
gboolean *mounted,
GimpProgress *progress,
GError **error);
gboolean file_remote_upload_image_finish (Gimp *gimp,
GFile *file,
GFile *local_file,
gboolean mounted,
GimpProgress *progress,
GError **error);

View File

@ -68,11 +68,11 @@ file_save (Gimp *gimp,
GimpValueArray *return_vals;
GimpPDBStatusType status = GIMP_PDB_EXECUTION_ERROR;
GFile *local_file = NULL;
gboolean mounted = TRUE;
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);
@ -125,16 +125,25 @@ file_save (Gimp *gimp,
}
}
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)
{
GError *my_error = NULL;
local_file = file_remote_upload_image_prepare (gimp, file, &mounted,
progress, &my_error);
local_file = file_remote_upload_image_prepare (gimp, file, progress,
&my_error);
if (! local_file)
{
@ -181,7 +190,6 @@ file_save (Gimp *gimp,
GError *my_error = NULL;
if (! file_remote_upload_image_finish (gimp, file, local_file,
mounted,
progress, &my_error))
{
status = GIMP_PDB_EXECUTION_ERROR;
@ -193,9 +201,7 @@ file_save (Gimp *gimp,
}
}
if (! mounted)
g_file_delete (local_file, NULL, NULL);
g_file_delete (local_file, NULL, NULL);
g_object_unref (local_file);
}

View File

@ -144,10 +144,8 @@ static gboolean gui_recent_list_add_file (Gimp *gimp,
const gchar *mime_type);
static void gui_recent_list_load (Gimp *gimp);
static gboolean gui_mount_enclosing_volume (Gimp *gimp,
GFile *file,
GimpProgress *progress,
GError **error);
static GMountOperation * gui_get_mount_operation (Gimp *gimp,
GimpProgress *progress);
/* public functions */
@ -183,7 +181,7 @@ gui_vtable_init (Gimp *gimp)
gimp->gui.pdb_dialog_close = gui_pdb_dialog_close;
gimp->gui.recent_list_add_file = gui_recent_list_add_file;
gimp->gui.recent_list_load = gui_recent_list_load;
gimp->gui.mount_enclosing_volume = gui_mount_enclosing_volume;
gimp->gui.get_mount_operation = gui_get_mount_operation;
}
@ -741,45 +739,14 @@ gui_recent_list_load (Gimp *gimp)
gimp_container_thaw (gimp->documents);
}
static void
mount_volume_ready (GFile *file,
GAsyncResult *res,
GError **error)
static GMountOperation *
gui_get_mount_operation (Gimp *gimp,
GimpProgress *progress)
{
g_file_mount_enclosing_volume_finish (file, res, error);
gtk_main_quit ();
}
static gboolean
gui_mount_enclosing_volume (Gimp *gimp,
GFile *file,
GimpProgress *progress,
GError **error)
{
GMountOperation *operation;
GtkWidget *toplevel = NULL;
GError *my_error = NULL;
GtkWidget *toplevel = NULL;
if (GTK_IS_WIDGET (progress))
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (progress));
operation = gtk_mount_operation_new (GTK_WINDOW (toplevel));
g_file_mount_enclosing_volume (file, G_MOUNT_MOUNT_NONE,
operation,
NULL,
(GAsyncReadyCallback) mount_volume_ready,
&my_error);
gtk_main ();
g_object_unref (operation);
if (my_error)
{
g_propagate_error (error, my_error);
return FALSE;
}
return TRUE;
return gtk_mount_operation_new (GTK_WINDOW (toplevel));
}