[gnome-utils] screenshot: move the filename builder to a separate file
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-utils] screenshot: move the filename builder to a separate file
- Date: Mon, 26 Sep 2011 20:56:24 +0000 (UTC)
commit 53763b161e3b4be7c0eeaacaa73bd867b6c1a669
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Mon Sep 26 12:01:56 2011 -0400
screenshot: move the filename builder to a separate file
Move the async function that builds a filename into a separate file.
gnome-screenshot/Makefile.am | 2 +
gnome-screenshot/gnome-screenshot.c | 367 ++++--------------------
gnome-screenshot/screenshot-filename-builder.c | 290 +++++++++++++++++++
gnome-screenshot/screenshot-filename-builder.h | 32 ++
4 files changed, 383 insertions(+), 308 deletions(-)
---
diff --git a/gnome-screenshot/Makefile.am b/gnome-screenshot/Makefile.am
index 203537a..e36f14d 100644
--- a/gnome-screenshot/Makefile.am
+++ b/gnome-screenshot/Makefile.am
@@ -17,6 +17,8 @@ gnome_screenshot_SOURCES = \
cheese-flash.h \
screenshot-dialog.c \
screenshot-dialog.h \
+ screenshot-filename-builder.c \
+ screenshot-filename-builder.h \
screenshot-shadow.c \
screenshot-shadow.h \
screenshot-utils.c \
diff --git a/gnome-screenshot/gnome-screenshot.c b/gnome-screenshot/gnome-screenshot.c
index e455088..559a0aa 100644
--- a/gnome-screenshot/gnome-screenshot.c
+++ b/gnome-screenshot/gnome-screenshot.c
@@ -41,6 +41,7 @@
#include <X11/Xutil.h>
#include <canberra-gtk.h>
+#include "screenshot-filename-builder.h"
#include "screenshot-shadow.h"
#include "screenshot-utils.h"
#include "screenshot-save.h"
@@ -72,28 +73,10 @@ typedef enum {
SCREENSHOT_EFFECT_BORDER
} ScreenshotEffectType;
-typedef enum
-{
- TEST_LAST_DIR = 0,
- TEST_DESKTOP = 1,
- TEST_TMP = 2,
-} TestType;
-
-typedef struct
-{
- char *base_uris[3];
- char *retval;
- int iteration;
- TestType type;
- GdkWindow *window;
- GdkRectangle *rectangle;
-} AsyncExistenceJob;
-
static GdkPixbuf *screenshot = NULL;
/* Global variables*/
static char *last_save_dir = NULL;
-static char *window_title = NULL;
static char *temporary_file = NULL;
static gboolean save_immediately = FALSE;
static GSettings *settings = NULL;
@@ -113,7 +96,6 @@ static guint delay = 0;
/* some local prototypes */
static void display_help (GtkWindow *parent);
static void save_done_notification (gpointer data);
-static char *get_screenshot_dir (void);
static void save_options (void);
static GtkWidget *border_check = NULL;
@@ -761,7 +743,6 @@ screenshot_dialog_response_cb (GtkDialog *d,
gtk_main_quit ();
}
}
-
static void
run_dialog (ScreenshotDialog *dialog)
@@ -777,6 +758,34 @@ run_dialog (ScreenshotDialog *dialog)
G_CALLBACK (screenshot_dialog_response_cb),
dialog);
}
+
+static void
+build_filename_ready_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ ScreenshotDialog *dialog;
+ GdkPixbuf *screenshot = user_data;
+ gchar *save_uri;
+ GError *error = NULL;
+
+ save_uri = screenshot_build_filename_finish (res, &error);
+
+ if (error != NULL)
+ {
+ g_critical ("Impossible to find a valid location to save the screenshot: %s",
+ error->message);
+ g_error_free (error);
+
+ exit(1);
+ }
+
+ dialog = screenshot_dialog_new (screenshot, save_uri, take_window_shot);
+ screenshot_save_start (screenshot, save_done_notification, dialog);
+ run_dialog (dialog);
+
+ g_free (save_uri);
+}
static void
play_sound_effect (GdkWindow *window)
@@ -820,7 +829,6 @@ play_sound_effect (GdkWindow *window)
static gchar *
get_profile_for_window (GdkWindow *window)
{
- gboolean ret = FALSE;
GError *error = NULL;
guint xid;
gchar *icc_profile = NULL;
@@ -863,8 +871,30 @@ out:
return icc_profile;
}
+static GdkWindow *
+find_current_window (void)
+{
+ GdkWindow *window = NULL;
+
+ if (!screenshot_grab_lock ())
+ exit (0);
+
+ if (take_window_shot)
+ {
+ window = screenshot_find_current_window ();
+
+ if (window == NULL)
+ take_window_shot = FALSE;
+ }
+
+ if (window == NULL)
+ window = gdk_get_default_root_window ();
+
+ return window;
+}
+
static void
-finish_prepare_screenshot (char *initial_uri, GdkWindow *window, GdkRectangle *rectangle)
+finish_prepare_screenshot (GdkRectangle *rectangle)
{
char *icc_profile_filename;
guchar *icc_profile;
@@ -873,8 +903,10 @@ finish_prepare_screenshot (char *initial_uri, GdkWindow *window, GdkRectangle *r
gboolean ret;
GError *error = NULL;
GdkRectangle rect;
- ScreenshotDialog *dialog;
gboolean include_mask = (!take_window_shot && !take_area_shot);
+ GdkWindow *window;
+
+ window = find_current_window ();
/* always disable window border for full-desktop or selected-area screenshots */
if (!take_window_shot)
@@ -958,246 +990,16 @@ finish_prepare_screenshot (char *initial_uri, GdkWindow *window, GdkRectangle *r
g_free (icc_profile_filename);
}
}
- dialog = screenshot_dialog_new (screenshot, initial_uri, take_window_shot);
- screenshot_save_start (screenshot, save_done_notification, dialog);
-
- run_dialog (dialog);
+ screenshot_build_filename_async (last_save_dir,
+ build_filename_ready_cb, screenshot);
}
-
- g_free (initial_uri);
-}
-
-static void
-async_existence_job_free (AsyncExistenceJob *job)
-{
- if (!job)
- return;
-
- g_free (job->base_uris[1]);
- g_free (job->base_uris[2]);
-
- if (job->rectangle != NULL)
- g_slice_free (GdkRectangle, job->rectangle);
-
- g_slice_free (AsyncExistenceJob, job);
-}
-
-static gboolean
-check_file_done (gpointer user_data)
-{
- AsyncExistenceJob *job = user_data;
-
- finish_prepare_screenshot (job->retval, job->window, job->rectangle);
-
- async_existence_job_free (job);
-
- return FALSE;
-}
-
-static char *
-build_uri (AsyncExistenceJob *job)
-{
- char *retval, *file_name;
- char *timestamp;
- GDateTime *d;
-
- d = g_date_time_new_now_local ();
- timestamp = g_date_time_format (d, "%Y-%m-%d %H:%M:%S");
- g_date_time_unref (d);
-
- 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 at %s.png"), timestamp);
- }
- 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 at %s - %d.png"), timestamp, job->iteration);
- }
-
- retval = g_build_filename (job->base_uris[job->type], file_name, NULL);
- g_free (file_name);
- g_free (timestamp);
-
- return retval;
-}
-
-static gboolean
-try_check_file (GIOSchedulerJob *io_job,
- GCancellable *cancellable,
- gpointer data)
-{
- AsyncExistenceJob *job = data;
- GFile *file;
- GFileInfo *info;
- GError *error;
- char *uri;
-
-retry:
- error = NULL;
- uri = build_uri (job);
- file = g_file_new_for_uri (uri);
-
- 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 (uri);
-
- (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))
- {
- (job->type)++;
- job->iteration = 0;
-
- g_object_unref (file);
- g_object_unref (parent);
- goto retry;
- }
- else
- {
- job->retval = uri;
-
- g_object_unref (parent);
- goto out;
- }
- }
- else
- {
- /* another kind of error, assume this location is not
- * accessible.
- */
- g_free (uri);
- if (job->type == TEST_TMP)
- {
- job->retval = NULL;
- goto out;
- }
- else
- {
- (job->type)++;
- job->iteration = 0;
-
- g_error_free (error);
- g_object_unref (file);
- goto retry;
- }
- }
- }
-
-out:
- g_error_free (error);
- g_object_unref (file);
-
- g_io_scheduler_job_send_to_mainloop_async (io_job,
- check_file_done,
- job,
- NULL);
- return FALSE;
-}
-
-static GdkWindow *
-find_current_window (char **window_title)
-{
- GdkWindow *window;
-
- if (!screenshot_grab_lock ())
- exit (0);
-
- if (take_window_shot)
- {
- window = screenshot_find_current_window ();
- if (!window)
- {
- take_window_shot = FALSE;
- window = gdk_get_default_root_window ();
- }
- else
- {
- gchar *tmp, *sanitized;
-
- tmp = screenshot_get_window_title (window);
- sanitized = screenshot_sanitize_filename (tmp);
- g_free (tmp);
- *window_title = sanitized;
- }
- }
- else
- {
- window = gdk_get_default_root_window ();
- }
-
- return window;
-}
-
-static void
-push_check_file_job (GdkRectangle *rectangle)
-{
- AsyncExistenceJob *job;
-
- job = g_slice_new0 (AsyncExistenceJob);
- job->base_uris[0] = last_save_dir;
- /* we'll have to free these two */
- job->base_uris[1] = get_screenshot_dir ();
- job->base_uris[2] = g_strconcat ("file://", g_get_tmp_dir (), NULL);
- job->iteration = 0;
- job->type = TEST_LAST_DIR;
- job->window = find_current_window (&window_title);
-
- if (rectangle != NULL)
- {
- job->rectangle = g_slice_new0 (GdkRectangle);
- job->rectangle->x = rectangle->x;
- job->rectangle->y = rectangle->y;
- job->rectangle->width = rectangle->width;
- job->rectangle->height = rectangle->height;
- }
-
- /* Check if the area selection was cancelled */
- if (job->rectangle &&
- (job->rectangle->width == 0 || job->rectangle->height == 0))
- {
- async_existence_job_free (job);
- gtk_main_quit ();
- return;
- }
-
- g_io_scheduler_push_job (try_check_file,
- job,
- NULL,
- 0, NULL);
}
static void
rectangle_found_cb (GdkRectangle *rectangle)
{
- push_check_file_job (rectangle);
+ finish_prepare_screenshot (rectangle);
}
static void
@@ -1206,7 +1008,7 @@ prepare_screenshot (void)
if (take_area_shot)
screenshot_select_area_async (rectangle_found_cb);
else
- push_check_file_job (NULL);
+ finish_prepare_screenshot (NULL);
}
static gboolean
@@ -1218,47 +1020,6 @@ prepare_screenshot_timeout (gpointer data)
return FALSE;
}
-
-static gchar *
-get_screenshot_dir (void)
-{
- gchar *shot_dir;
-
- shot_dir = g_strconcat ("file://", g_get_user_special_dir (G_USER_DIRECTORY_PICTURES), NULL);
-
- return shot_dir;
-}
-
-/* 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_strconcat (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);
-}
-
/* Load options */
static void
load_options (void)
@@ -1266,16 +1027,6 @@ load_options (void)
/* Find various dirs */
last_save_dir = g_settings_get_string (settings,
LAST_SAVE_DIRECTORY_KEY);
- if (!last_save_dir || !last_save_dir[0])
- {
- last_save_dir = get_screenshot_dir ();
- }
- else if (last_save_dir[0] == '~')
- {
- char *tmp = expand_initial_tilde (last_save_dir);
- g_free (last_save_dir);
- last_save_dir = tmp;
- }
include_border = g_settings_get_boolean (settings,
INCLUDE_BORDER_KEY);
diff --git a/gnome-screenshot/screenshot-filename-builder.c b/gnome-screenshot/screenshot-filename-builder.c
new file mode 100644
index 0000000..026be67
--- /dev/null
+++ b/gnome-screenshot/screenshot-filename-builder.c
@@ -0,0 +1,290 @@
+/* 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>
+
+typedef enum
+{
+ TEST_LAST_DIR = 0,
+ TEST_DESKTOP = 1,
+ TEST_TMP = 2,
+} TestType;
+
+typedef struct
+{
+ char *base_uris[3];
+ 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_strconcat (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_default_screenshot_dir (void)
+{
+ gchar *shot_dir;
+
+ shot_dir = g_strconcat ("file://", g_get_user_special_dir (G_USER_DIRECTORY_PICTURES), NULL);
+
+ return shot_dir;
+}
+
+static gchar *
+sanitize_save_directory (const gchar *save_dir)
+{
+ gchar *retval = g_strdup (save_dir);
+
+ if (save_dir[0] == '~')
+ {
+ char *tmp = expand_initial_tilde (save_dir);
+ g_free (retval);
+ retval = tmp;
+ }
+
+ return retval;
+}
+
+static char *
+build_uri (AsyncExistenceJob *job)
+{
+ const gchar *base_uri;
+ char *retval, *file_name;
+ char *timestamp;
+ GDateTime *d;
+
+ base_uri = job->base_uris[job->type];
+
+ if (base_uri == NULL ||
+ base_uri[0] == '\0')
+ return NULL;
+
+ d = g_date_time_new_now_local ();
+ timestamp = g_date_time_format (d, "%Y-%m-%d %H:%M:%S");
+ g_date_time_unref (d);
+
+ 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 at %s.png"), timestamp);
+ }
+ 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 at %s - %d.png"), timestamp, job->iteration);
+ }
+
+ retval = g_build_filename (base_uri, file_name, NULL);
+ g_free (file_name);
+ g_free (timestamp);
+
+ return retval;
+}
+
+static void
+async_existence_job_free (AsyncExistenceJob *job)
+{
+ gint idx;
+
+ for (idx = 0; idx < 3; idx++)
+ g_free (job->base_uris[idx]);
+
+ g_clear_object (&job->async_result);
+
+ g_slice_free (AsyncExistenceJob, job);
+}
+
+static gboolean
+try_check_file (GIOSchedulerJob *io_job,
+ GCancellable *cancellable,
+ gpointer data)
+{
+ AsyncExistenceJob *job = data;
+ GFile *file;
+ GFileInfo *info;
+ GError *error;
+ char *uri, *retval;
+
+retry:
+ error = NULL;
+ uri = build_uri (job);
+
+ if (uri == NULL)
+ {
+ (job->type)++;
+ goto retry;
+ }
+
+ file = g_file_new_for_uri (uri);
+ 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 (uri);
+
+ (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))
+ {
+ (job->type)++;
+ job->iteration = 0;
+
+ g_object_unref (file);
+ g_object_unref (parent);
+ goto retry;
+ }
+ else
+ {
+ retval = uri;
+
+ g_object_unref (parent);
+ goto out;
+ }
+ }
+ else
+ {
+ /* another kind of error, assume this location is not
+ * accessible.
+ */
+ g_free (uri);
+ if (job->type == TEST_TMP)
+ {
+ retval = NULL;
+ goto out;
+ }
+ else
+ {
+ (job->type)++;
+ job->iteration = 0;
+
+ g_error_free (error);
+ g_object_unref (file);
+ goto retry;
+ }
+ }
+ }
+
+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 gchar *save_dir,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ AsyncExistenceJob *job;
+
+ job = g_slice_new0 (AsyncExistenceJob);
+
+ job->base_uris[0] = sanitize_save_directory (save_dir);
+ job->base_uris[1] = get_default_screenshot_dir ();
+ job->base_uris[2] = g_strconcat ("file://", g_get_tmp_dir (), NULL);
+ job->iteration = 0;
+ job->type = TEST_LAST_DIR;
+
+ 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/gnome-screenshot/screenshot-filename-builder.h b/gnome-screenshot/screenshot-filename-builder.h
new file mode 100644
index 0000000..3c61499
--- /dev/null
+++ b/gnome-screenshot/screenshot-filename-builder.h
@@ -0,0 +1,32 @@
+/* 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 gchar *save_dir,
+ 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]