[gimp] app: add file-remote.[ch] which implements uploading/downloading



commit 9680a28deb75e30c82bddcb64da8e12644981647
Author: Michael Natterer <mitch gimp org>
Date:   Fri Jul 11 00:49:56 2014 +0200

    app: add file-remote.[ch] which implements uploading/downloading
    
    and will make the file-uri plug-in obsolete.

 app/file/Makefile.am   |    2 +
 app/file/file-remote.c |  399 ++++++++++++++++++++++++++++++++++++++++++++++++
 app/file/file-remote.h |   46 ++++++
 po/POTFILES.in         |    1 +
 4 files changed, 448 insertions(+), 0 deletions(-)
---
diff --git a/app/file/Makefile.am b/app/file/Makefile.am
index 19db33b..2ce23af 100644
--- a/app/file/Makefile.am
+++ b/app/file/Makefile.am
@@ -17,6 +17,8 @@ libappfile_a_SOURCES = \
        file-open.h             \
        file-procedure.c        \
        file-procedure.h        \
+       file-remote.c           \
+       file-remote.h           \
        file-save.c             \
        file-save.h             \
        file-utils.c            \
diff --git a/app/file/file-remote.c b/app/file/file-remote.c
new file mode 100644
index 0000000..d7399a8
--- /dev/null
+++ b/app/file/file-remote.c
@@ -0,0 +1,399 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * file-remote.c
+ * Copyright (C) 2014  Michael Natterer <mitch gimp org>
+ *
+ * Based on: URI plug-in, GIO/GVfs backend
+ * Copyright (C) 2008  Sven Neumann <sven gimp org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "libgimpbase/gimpbase.h"
+
+#include "core/core-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpprogress.h"
+
+#include "file-remote.h"
+
+#include "gimp-intl.h"
+
+
+typedef enum
+{
+  DOWNLOAD,
+  UPLOAD
+} RemoteCopyMode;
+
+typedef struct
+{
+  RemoteCopyMode  mode;
+  GimpProgress   *progress;
+  GCancellable   *cancellable;
+  gboolean        cancel;
+  GTimeVal        last_time;
+} 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_progress_callback (goffset          current_num_bytes,
+                                                 goffset          total_num_bytes,
+                                                 gpointer         user_data);
+
+
+/*  public functions  */
+
+GFile *
+file_remote_download_image (Gimp          *gimp,
+                            GFile         *file,
+                            gboolean      *mounted,
+                            GimpProgress  *progress,
+                            GError       **error)
+{
+  GFile *local_file;
+
+  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);
+
+      if (! file_remote_copy_file (gimp, file, local_file, DOWNLOAD,
+                                   progress, error))
+        {
+          g_object_unref (local_file);
+          return NULL;
+        }
+    }
+
+  return local_file;
+}
+
+GFile *
+file_remote_upload_image_prepare (Gimp          *gimp,
+                                  GFile         *file,
+                                  gboolean      *mounted,
+                                  GimpProgress  *progress,
+                                  GError       **error)
+{
+  GFile *local_file;
+
+  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);
+    }
+
+  return local_file;
+}
+
+gboolean
+file_remote_upload_image_finish (Gimp          *gimp,
+                                 GFile         *file,
+                                 GFile         *local_file,
+                                 gboolean       mounted,
+                                 GimpProgress  *progress,
+                                 GError       **error)
+{
+  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 (G_IS_FILE (local_file), NULL);
+  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))
+        {
+          return FALSE;
+        }
+    }
+
+  return TRUE;
+}
+
+
+/*  private functions  */
+
+static GFile *
+file_remote_get_temp_file (Gimp  *gimp,
+                           GFile *file)
+{
+  gchar *basename;
+  GFile *temp_file = NULL;
+
+  basename = g_path_get_basename (gimp_file_get_utf8_name (file));
+
+  if (basename)
+    {
+      const gchar *ext = strchr (basename, '.');
+
+      if (ext && strlen (ext))
+        temp_file = gimp_get_temp_file (gimp, ext + 1);
+
+      g_free (basename);
+    }
+
+  if (! temp_file)
+    temp_file = gimp_get_temp_file (gimp, "xxx");
+
+  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,
+                       GFile           *dest_file,
+                       RemoteCopyMode   mode,
+                       GimpProgress    *progress,
+                       GError         **error)
+{
+  RemoteProgress  remote_progress = { 0, };
+  gboolean        success;
+  GError         *my_error = NULL;
+
+  remote_progress.mode     = mode;
+  remote_progress.progress = progress;
+
+  if (progress)
+    {
+      remote_progress.cancellable = g_cancellable_new ();
+
+      gimp_progress_start (progress, _("Connecting to server"), TRUE);
+
+      g_signal_connect (progress, "cancel",
+                        G_CALLBACK (file_remote_copy_file_cancel),
+                        &remote_progress);
+
+      success = g_file_copy (src_file, dest_file, G_FILE_COPY_OVERWRITE,
+                             remote_progress.cancellable,
+                             file_remote_progress_callback, &remote_progress,
+                             &my_error);
+
+      gimp_progress_set_value (progress, 1.0);
+    }
+  else
+    {
+      success = g_file_copy (src_file, dest_file, G_FILE_COPY_OVERWRITE,
+                             NULL, NULL, NULL,
+                             &my_error);
+    }
+
+  if (! success                      &&
+      ! gimp->no_interface           &&
+      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)
+    {
+      gimp_progress_end (progress);
+
+      g_object_unref (remote_progress.cancellable);
+    }
+
+  return success;
+}
+
+static void
+file_remote_copy_file_cancel (GimpProgress   *progress,
+                              RemoteProgress *remote_progress)
+{
+  remote_progress->cancel = TRUE;
+
+  g_cancellable_cancel (remote_progress->cancellable);
+}
+
+static void
+file_remote_progress_callback (goffset  current_num_bytes,
+                               goffset  total_num_bytes,
+                               gpointer user_data)
+{
+  RemoteProgress *progress = user_data;
+  GTimeVal        now;
+
+  /*  update the progress only up to 10 times a second  */
+  g_get_current_time (&now);
+
+  if (progress->last_time.tv_sec &&
+      ((now.tv_sec - progress->last_time.tv_sec) * 1000 +
+       (now.tv_usec - progress->last_time.tv_usec) / 1000) < 100)
+    return;
+
+  progress->last_time = now;
+
+  if (total_num_bytes > 0)
+    {
+      const gchar *format;
+      gchar       *done  = g_format_size (current_num_bytes);
+      gchar       *total = g_format_size (total_num_bytes);
+      gchar       *text;
+
+      switch (progress->mode)
+        {
+        case DOWNLOAD:
+          format = _("Downloading image (%s of %s)");
+          break;
+
+        case UPLOAD:
+          format = _("Uploading image (%s of %s)");
+          break;
+
+        default:
+          g_assert_not_reached ();
+        }
+
+      text = g_strdup_printf (format, done, total);
+      g_free (total);
+      g_free (done);
+
+      gimp_progress_set_text (progress->progress, text);
+      g_free (text);
+
+      gimp_progress_set_value (progress->progress,
+                               (gdouble) current_num_bytes /
+                               (gdouble) total_num_bytes);
+    }
+  else
+    {
+      const gchar *format;
+      gchar       *done = g_format_size (current_num_bytes);
+      gchar       *text;
+
+      switch (progress->mode)
+        {
+        case DOWNLOAD:
+          format = _("Downloaded %s of image data");
+          break;
+
+        case UPLOAD:
+          format = _("Uploaded %s of image data");
+          break;
+
+        default:
+          g_assert_not_reached ();
+        }
+
+      text = g_strdup_printf (format, done);
+      g_free (done);
+
+      gimp_progress_set_text (progress->progress, text);
+      g_free (text);
+
+      gimp_progress_pulse (progress->progress);
+    }
+
+  while (! progress->cancel && g_main_context_pending (NULL))
+    g_main_context_iteration (NULL, FALSE);
+
+}
diff --git a/app/file/file-remote.h b/app/file/file-remote.h
new file mode 100644
index 0000000..3edc1ae
--- /dev/null
+++ b/app/file/file-remote.h
@@ -0,0 +1,46 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
+ *
+ * file-remote.h
+ * Copyright (C) 2014  Michael Natterer <mitch gimp org>
+ *
+ * Based on: URI plug-in, GIO/GVfs backend
+ * Copyright (C) 2008  Sven Neumann <sven gimp org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __FILE_REMOTE_H__
+#define __FILE_REMOTE_H__
+
+
+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);
+
+#endif /* __FILE_REMOTE_H__ */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1087a54..0ae3fb9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -231,6 +231,7 @@ app/display/gimpstatusbar.c
 
 app/file/file-open.c
 app/file/file-procedure.c
+app/file/file-remote.c
 app/file/file-save.c
 app/file/file-utils.c
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]