[totem] screenshot: Add filename builder helpers



commit b68db23aa20cf97447a1caee93e2cec01f1fc6a5
Author: Bastien Nocera <hadess hadess net>
Date:   Thu Jun 28 12:40:50 2012 +0100

    screenshot: Add filename builder helpers
    
    From gnome-screenshot
    
    https://bugzilla.gnome.org/show_bug.cgi?id=674640

 .../screenshot/screenshot-filename-builder.c       |  338 ++++++++++++++++++++
 .../screenshot/screenshot-filename-builder.h       |   33 ++
 2 files changed, 371 insertions(+), 0 deletions(-)
---
diff --git a/src/plugins/screenshot/screenshot-filename-builder.c b/src/plugins/screenshot/screenshot-filename-builder.c
new file mode 100644
index 0000000..1cc3d50
--- /dev/null
+++ b/src/plugins/screenshot/screenshot-filename-builder.c
@@ -0,0 +1,338 @@
+/* screenshot-filename-builder.c - Builds a filename suitable for a screenshot
+ *
+ * Copyright (C) 2008, 2011 Cosimo Cecchi <cosimoc gnome 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <config.h>
+#include <gio/gio.h>
+#include <glib/gi18n.h>
+#include <pwd.h>
+#include <string.h>
+
+#include "screenshot-filename-builder.h"
+
+typedef enum
+{
+  TEST_SAVED_DIR = 0,
+  TEST_DEFAULT,
+  TEST_FALLBACK,
+  NUM_TESTS
+} TestType;
+
+typedef struct 
+{
+  char *base_paths[NUM_TESTS];
+  char *screenshot_origin;
+  int iteration;
+  TestType type;
+
+  GSimpleAsyncResult *async_result;
+} AsyncExistenceJob;
+
+/* Taken from gnome-vfs-utils.c */
+static char *
+expand_initial_tilde (const char *path)
+{
+  char *slash_after_user_name, *user_name;
+  struct passwd *passwd_file_entry;
+
+  if (path[1] == '/' || path[1] == '\0') {
+    return g_build_filename (g_get_home_dir (), &path[1], NULL);
+  }
+  
+  slash_after_user_name = strchr (&path[1], '/');
+  if (slash_after_user_name == NULL) {
+    user_name = g_strdup (&path[1]);
+  } else {
+    user_name = g_strndup (&path[1],
+                           slash_after_user_name - &path[1]);
+  }
+  passwd_file_entry = getpwnam (user_name);
+  g_free (user_name);
+  
+  if (passwd_file_entry == NULL || passwd_file_entry->pw_dir == NULL) {
+    return g_strdup (path);
+  }
+  
+  return g_strconcat (passwd_file_entry->pw_dir,
+                      slash_after_user_name,
+                      NULL);
+}
+
+static gchar *
+get_fallback_screenshot_dir (void)
+{
+  return g_strdup (g_get_home_dir ());
+}
+
+static gchar *
+get_default_screenshot_dir (void)
+{
+  return g_strdup (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES));
+}
+
+static gchar *
+sanitize_save_directory (const gchar *save_dir)
+{
+  gchar *retval = g_strdup (save_dir);
+
+  if (save_dir == NULL)
+    return NULL;
+
+  if (save_dir[0] == '~')
+    {
+      char *tmp = expand_initial_tilde (save_dir);
+      g_free (retval);
+      retval = tmp;
+    }
+  else if (strstr (save_dir, "://") != NULL)
+    {
+      GFile *file;
+
+      g_free (retval);
+      file = g_file_new_for_uri (save_dir);
+      retval = g_file_get_path (file);
+      g_object_unref (file);
+    }
+
+  return retval;
+}
+
+static char *
+build_path (AsyncExistenceJob *job)
+{
+  const gchar *base_path;
+  char *retval, *file_name;
+  char *origin;
+
+  base_path = job->base_paths[job->type];
+
+  if (base_path == NULL ||
+      base_path[0] == '\0')
+    return NULL;
+
+  if (job->screenshot_origin == NULL)
+    {
+      GDateTime *d;
+
+      d = g_date_time_new_now_local ();
+      origin = g_date_time_format (d, "%Y-%m-%d %H:%M:%S");
+      g_date_time_unref (d);
+    }
+  else
+    origin = g_strdup (job->screenshot_origin);
+
+  if (job->iteration == 0)
+    {
+      /* translators: this is the name of the file that gets made up
+       * with the screenshot if the entire screen is taken */
+      file_name = g_strdup_printf (_("Screenshot from %s.png"), origin);
+    }
+  else
+    {
+      /* translators: this is the name of the file that gets
+       * made up with the screenshot if the entire screen is
+       * taken */
+      file_name = g_strdup_printf (_("Screenshot from %s - %d.png"), origin, job->iteration);
+    }
+
+  retval = g_build_filename (base_path, file_name, NULL);
+  g_free (file_name);
+  g_free (origin);
+
+  return retval;
+}
+
+static void
+async_existence_job_free (AsyncExistenceJob *job)
+{
+  gint idx;
+
+  for (idx = 0; idx < NUM_TESTS; idx++)
+    g_free (job->base_paths[idx]);
+
+  g_free (job->screenshot_origin);
+
+  g_clear_object (&job->async_result);
+
+  g_slice_free (AsyncExistenceJob, job);
+}
+
+static gboolean
+prepare_next_cycle (AsyncExistenceJob *job)
+{
+  gboolean res = FALSE;
+
+  if (job->type != (NUM_TESTS - 1))
+    {
+      (job->type)++;
+      job->iteration = 0;
+
+      res = TRUE;
+    }
+
+  return res;
+}
+
+static gboolean
+try_check_file (GIOSchedulerJob *io_job,
+                GCancellable *cancellable,
+                gpointer data)
+{
+  AsyncExistenceJob *job = data;
+  GFile *file;
+  GFileInfo *info;
+  GError *error;
+  char *path, *retval;
+
+retry:
+  error = NULL;
+  path = build_path (job);
+
+  if (path == NULL)
+    {
+      (job->type)++;
+      goto retry;
+    }
+
+  file = g_file_new_for_path (path);
+  info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE,
+			    G_FILE_QUERY_INFO_NONE, cancellable, &error);
+  if (info != NULL)
+    {
+      /* file already exists, iterate again */
+      g_object_unref (info);
+      g_object_unref (file);
+      g_free (path);
+
+      (job->iteration)++;
+
+      goto retry;
+    }
+  else
+    {
+      /* see the error to check whether the location is not accessible
+       * or the file does not exist.
+       */
+      if (error->code == G_IO_ERROR_NOT_FOUND)
+        {
+          GFile *parent;
+
+          /* if the parent directory doesn't exist as well, forget the saved
+           * directory and treat this as a generic error.
+           */
+
+          parent = g_file_get_parent (file);
+
+          if (!g_file_query_exists (parent, NULL))
+            {
+              if (!prepare_next_cycle (job))
+                {
+                  retval = NULL;
+
+                  g_object_unref (parent);
+                  goto out;
+                }
+
+              g_object_unref (file);
+              g_object_unref (parent);
+              goto retry;
+            }
+          else
+            {
+              retval = path;
+
+              g_object_unref (parent);
+              goto out;
+            }
+        }
+      else
+        {
+          /* another kind of error, assume this location is not
+           * accessible.
+           */
+          g_free (path);
+
+          if (prepare_next_cycle (job))
+            {
+              g_error_free (error);
+              g_object_unref (file);
+              goto retry;
+            }
+          else
+            {
+              retval = NULL;
+              goto out;
+            }
+        }
+    }
+
+out:
+  g_error_free (error);
+  g_object_unref (file);
+
+  g_simple_async_result_set_op_res_gpointer (job->async_result,
+                                             retval, NULL);
+  if (retval == NULL)
+    g_simple_async_result_set_error (job->async_result,
+                                     G_IO_ERROR,
+                                     G_IO_ERROR_FAILED,
+                                     "%s", "Failed to find a valid place to save");
+
+  g_simple_async_result_complete_in_idle (job->async_result);
+  async_existence_job_free (job);
+
+  return FALSE;
+}
+
+void
+screenshot_build_filename_async (const char *save_dir,
+				 const char *screenshot_origin,
+                                 GAsyncReadyCallback callback,
+                                 gpointer user_data)
+{
+  AsyncExistenceJob *job;
+
+  job = g_slice_new0 (AsyncExistenceJob);
+
+  job->base_paths[TEST_SAVED_DIR] = sanitize_save_directory (save_dir);
+  job->base_paths[TEST_DEFAULT] = get_default_screenshot_dir ();
+  job->base_paths[TEST_FALLBACK] = get_fallback_screenshot_dir ();
+  job->iteration = 0;
+  job->type = TEST_SAVED_DIR;
+
+  job->screenshot_origin = g_strdup (screenshot_origin);
+
+  job->async_result = g_simple_async_result_new (NULL,
+                                                 callback, user_data,
+                                                 screenshot_build_filename_async);
+
+  g_io_scheduler_push_job (try_check_file,
+                           job, NULL,
+                           G_PRIORITY_DEFAULT, NULL);
+}
+
+gchar *
+screenshot_build_filename_finish (GAsyncResult *result,
+                                  GError **error)
+{
+  if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+    return NULL;
+
+  return g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+}
diff --git a/src/plugins/screenshot/screenshot-filename-builder.h b/src/plugins/screenshot/screenshot-filename-builder.h
new file mode 100644
index 0000000..2b0868f
--- /dev/null
+++ b/src/plugins/screenshot/screenshot-filename-builder.h
@@ -0,0 +1,33 @@
+/* screenshot-filename-builder.c - Builds a filename suitable for a screenshot
+ *
+ * Copyright (C) 2008, 2011 Cosimo Cecchi <cosimoc gnome 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef __SCREENSHOT_FILENAME_BUILDER_H__
+#define __SCREENSHOT_FILENAME_BUILDER_H__
+
+#include <gio/gio.h>
+
+void screenshot_build_filename_async (const char *save_dir,
+                                      const char *screenshot_origin,
+                                      GAsyncReadyCallback callback,
+                                      gpointer user_data);
+gchar *screenshot_build_filename_finish (GAsyncResult *result,
+                                         GError **error);
+
+#endif /* __SCREENSHOT_FILENAME_BUILDER_H__ */



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