aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2009-11-07 02:33:55 +0800
committerMatthew Barnes <mbarnes@redhat.com>2009-11-08 03:01:46 +0800
commitaa66a17e401d73cbe394ed7f99bf73350e9b938b (patch)
tree305c80be39d688cf8386b5e123f3df631f2cfc84
parentb2dd9c153519d315f96bfd760e91a6f6b32affd6 (diff)
downloadgsoc2013-evolution-aa66a17e401d73cbe394ed7f99bf73350e9b938b.tar
gsoc2013-evolution-aa66a17e401d73cbe394ed7f99bf73350e9b938b.tar.gz
gsoc2013-evolution-aa66a17e401d73cbe394ed7f99bf73350e9b938b.tar.bz2
gsoc2013-evolution-aa66a17e401d73cbe394ed7f99bf73350e9b938b.tar.lz
gsoc2013-evolution-aa66a17e401d73cbe394ed7f99bf73350e9b938b.tar.xz
gsoc2013-evolution-aa66a17e401d73cbe394ed7f99bf73350e9b938b.tar.zst
gsoc2013-evolution-aa66a17e401d73cbe394ed7f99bf73350e9b938b.zip
Test drive EIOActivity with a simple asynchronous function.
Rename e-fsutils to e-file-utils. This is where we'll add asynchronous functions for common file I/O operations with EActivity integration. Start with e_file_replace_contents_async() (and corresponding finish() function). This is a simple wrapper for g_file_replace_contents_async() which also returns an EActivity. It replaces e_write_file_uri(). Also redesign EIOActivity to -contain- a GAsyncResult rather than implement the interface for itself. This is easier for now but I may change my mind again when I figure out how to tie centralized error reporting into the EActivity framework.
-rw-r--r--e-util/Makefile.am4
-rw-r--r--e-util/e-file-utils.c (renamed from e-util/e-fsutils.c)125
-rw-r--r--e-util/e-file-utils.h (renamed from e-util/e-fsutils.h)26
-rw-r--r--e-util/e-io-activity.c206
-rw-r--r--e-util/e-io-activity.h12
-rw-r--r--shell/e-shell-migrate.c2
6 files changed, 284 insertions, 91 deletions
diff --git a/e-util/Makefile.am b/e-util/Makefile.am
index bc5e7cd4fc..ecc3220f29 100644
--- a/e-util/Makefile.am
+++ b/e-util/Makefile.am
@@ -24,8 +24,8 @@ eutilinclude_HEADERS = \
e-dialog-widgets.h \
e-error.h \
e-event.h \
+ e-file-utils.h \
e-folder-map.h \
- e-fsutils.h \
e-html-utils.h \
e-icon-factory.h \
e-import.h \
@@ -98,8 +98,8 @@ libeutil_la_SOURCES = \
e-dialog-widgets.c \
e-error.c \
e-event.c \
+ e-file-utils.c \
e-folder-map.c \
- e-fsutils.c \
e-html-utils.c \
e-icon-factory.c \
e-import.c \
diff --git a/e-util/e-fsutils.c b/e-util/e-file-utils.c
index c5426f8c81..f8adcc7a60 100644
--- a/e-util/e-fsutils.c
+++ b/e-util/e-file-utils.c
@@ -48,8 +48,131 @@
#include <glib.h>
#include <glib/gstdio.h>
+#include <glib/gi18n-lib.h>
-#include "e-fsutils.h"
+#include "e-file-utils.h"
+#include "e-io-activity.h"
+
+static void
+file_replace_contents_cb (GFile *file,
+ GAsyncResult *result,
+ EActivity *activity)
+{
+ gchar *new_etag;
+ gboolean success;
+ GError *error = NULL;
+
+ success = g_file_replace_contents_finish (
+ file, result, &new_etag, &error);
+
+ result = e_io_activity_get_async_result (E_IO_ACTIVITY (activity));
+
+ g_object_set_data_full (
+ G_OBJECT (result),
+ "__new_etag__", new_etag,
+ (GDestroyNotify) g_free);
+
+ g_simple_async_result_set_op_res_gboolean (
+ G_SIMPLE_ASYNC_RESULT (result), success);
+
+ if (error != NULL) {
+ g_simple_async_result_set_from_error (
+ G_SIMPLE_ASYNC_RESULT (result), error);
+ g_error_free (error);
+ }
+
+ e_activity_complete (activity);
+
+ g_object_unref (activity);
+}
+
+EActivity *
+e_file_replace_contents_async (GFile *file,
+ const gchar *contents,
+ gsize length,
+ const gchar *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ EActivity *activity;
+ GSimpleAsyncResult *simple;
+ GCancellable *cancellable;
+ const gchar *format;
+ gchar *description;
+ gchar *basename;
+ gchar *filename;
+ gchar *hostname;
+ gchar *uri;
+
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+ g_return_val_if_fail (contents != NULL, NULL);
+
+ uri = g_file_get_uri (file);
+ filename = g_filename_from_uri (uri, &hostname, NULL);
+ basename = g_filename_display_basename (filename);
+
+ if (hostname != NULL) {
+ /* Translators: The string value is the basename of a file. */
+ format = _("Writing \"%s\"");
+ description = g_strdup_printf (format, basename);
+ } else {
+ /* Translators: The first string value is the basename of a
+ * remote file, the second string value is the hostname. */
+ format = _("Writing \"%s\" to %s");
+ description = g_strdup_printf (format, basename, hostname);
+ }
+
+ cancellable = g_cancellable_new ();
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (file), callback, user_data,
+ e_file_replace_contents_async);
+
+ activity = e_io_activity_new (
+ description, G_ASYNC_RESULT (simple), cancellable);
+
+ g_file_replace_contents_async (
+ file, contents, length, etag,
+ make_backup, flags, cancellable,
+ (GAsyncReadyCallback) file_replace_contents_cb,
+ activity);
+
+ g_object_unref (cancellable);
+ g_object_unref (simple);
+
+ g_free (description);
+ g_free (basename);
+ g_free (filename);
+ g_free (hostname);
+ g_free (uri);
+
+ return activity;
+}
+
+gboolean
+e_file_replace_contents_finish (GFile *file,
+ GAsyncResult *result,
+ gchar **new_etag,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ if (new_etag != NULL)
+ *new_etag = g_object_steal_data (
+ G_OBJECT (result), "__new_etag__");
+
+ return TRUE;
+}
/**
* e_fsutils_usage:
diff --git a/e-util/e-fsutils.h b/e-util/e-file-utils.h
index 6143e487ab..147b9b5b79 100644
--- a/e-util/e-fsutils.h
+++ b/e-util/e-file-utils.h
@@ -20,16 +20,30 @@
*
*/
-#ifndef E_FSUTILS_H
-#define E_FSUTILS_H
+#ifndef E_FILE_UTILS_H
+#define E_FILE_UTILS_H
-#include <glib.h>
+#include <gio/gio.h>
+#include <e-util/e-activity.h>
G_BEGIN_DECLS
-glong e_fsutils_usage(const gchar *path);
-glong e_fsutils_avail(const gchar *path);
+EActivity * e_file_replace_contents_async (GFile *file,
+ const gchar *contents,
+ gsize length,
+ const gchar *etag,
+ gboolean make_backup,
+ GFileCreateFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_file_replace_contents_finish (GFile *file,
+ GAsyncResult *result,
+ gchar **new_etag,
+ GError **error);
+
+glong e_fsutils_usage (const gchar *path);
+glong e_fsutils_avail (const gchar *path);
G_END_DECLS
-#endif /* !E_FOLDER_MAP_H */
+#endif /* E_FILE_UTILS_H */
diff --git a/e-util/e-io-activity.c b/e-util/e-io-activity.c
index 086ee10529..9569e42914 100644
--- a/e-util/e-io-activity.c
+++ b/e-util/e-io-activity.c
@@ -26,26 +26,54 @@
((obj), E_TYPE_IO_ACTIVITY, EIOActivityPrivate))
struct _EIOActivityPrivate {
- GObject *source_object;
+ GAsyncResult *async_result;
GCancellable *cancellable;
- GAsyncReadyCallback callback;
- gpointer user_data;
};
enum {
PROP_0,
+ PROP_ASYNC_RESULT,
PROP_CANCELLABLE
};
static gpointer parent_class;
static void
+io_activity_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_ASYNC_RESULT:
+ e_io_activity_set_async_result (
+ E_IO_ACTIVITY (object),
+ g_value_get_object (value));
+ return;
+
+ case PROP_CANCELLABLE:
+ e_io_activity_set_cancellable (
+ E_IO_ACTIVITY (object),
+ g_value_get_object (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
io_activity_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
switch (property_id) {
+ case PROP_ASYNC_RESULT:
+ g_value_set_object (
+ value, e_io_activity_get_async_result (
+ E_IO_ACTIVITY (object)));
+ return;
+
case PROP_CANCELLABLE:
g_value_set_object (
value, e_io_activity_get_cancellable (
@@ -63,9 +91,9 @@ io_activity_dispose (GObject *object)
priv = E_IO_ACTIVITY_GET_PRIVATE (object);
- if (priv->source_object != NULL) {
- g_object_unref (priv->source_object);
- priv->source_object = NULL;
+ if (priv->async_result != NULL) {
+ g_object_unref (priv->async_result);
+ priv->async_result = NULL;
}
if (priv->cancellable != NULL) {
@@ -80,55 +108,37 @@ io_activity_dispose (GObject *object)
static void
io_activity_cancelled (EActivity *activity)
{
- EIOActivityPrivate *priv;
-
- priv = E_IO_ACTIVITY_GET_PRIVATE (activity);
+ EIOActivity *io_activity;
+ GCancellable *cancellable;
/* Chain up to parent's cancelled() method. */
E_ACTIVITY_CLASS (parent_class)->cancelled (activity);
- g_cancellable_cancel (priv->cancellable);
+ io_activity = E_IO_ACTIVITY (activity);
+ cancellable = e_io_activity_get_cancellable (io_activity);
+
+ if (cancellable != NULL)
+ g_cancellable_cancel (cancellable);
}
static void
io_activity_completed (EActivity *activity)
{
- EIOActivityPrivate *priv;
-
- priv = E_IO_ACTIVITY_GET_PRIVATE (activity);
+ EIOActivity *io_activity;
+ GAsyncResult *async_result;
/* Chain up to parent's completed() method. */
E_ACTIVITY_CLASS (parent_class)->completed (activity);
- /* Clear the function pointer after invoking it
- * to guarantee it will not be invoked again. */
- if (priv->callback != NULL) {
- priv->callback (
- priv->source_object,
- G_ASYNC_RESULT (activity),
- priv->user_data);
- priv->callback = NULL;
- }
-}
-
-static gpointer
-io_activity_get_user_data (GAsyncResult *async_result)
-{
- EIOActivityPrivate *priv;
+ io_activity = E_IO_ACTIVITY (activity);
+ async_result = e_io_activity_get_async_result (io_activity);
- priv = E_IO_ACTIVITY_GET_PRIVATE (async_result);
-
- return priv->user_data;
-}
-
-static GObject *
-io_activity_get_source_object (GAsyncResult *async_result)
-{
- EIOActivityPrivate *priv;
-
- priv = E_IO_ACTIVITY_GET_PRIVATE (async_result);
-
- return priv->source_object;
+ /* We know how to invoke a GSimpleAsyncResult. For any other
+ * type of GAsyncResult the caller will have to take measures
+ * to invoke it himself. */
+ if (G_IS_SIMPLE_ASYNC_RESULT (async_result))
+ g_simple_async_result_complete (
+ G_SIMPLE_ASYNC_RESULT (async_result));
}
static void
@@ -141,6 +151,7 @@ io_activity_class_init (EIOActivityClass *class)
g_type_class_add_private (class, sizeof (EIOActivityPrivate));
object_class = G_OBJECT_CLASS (class);
+ object_class->set_property = io_activity_set_property;
object_class->get_property = io_activity_get_property;
object_class->dispose = io_activity_dispose;
@@ -150,28 +161,31 @@ io_activity_class_init (EIOActivityClass *class)
g_object_class_install_property (
object_class,
+ PROP_ASYNC_RESULT,
+ g_param_spec_object (
+ "async-result",
+ "Asynchronous Result",
+ NULL,
+ G_TYPE_ASYNC_RESULT,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
PROP_CANCELLABLE,
g_param_spec_object (
"cancellable",
"Cancellable",
NULL,
G_TYPE_CANCELLABLE,
- G_PARAM_READABLE));
-}
-
-static void
-io_activity_iface_init (GAsyncResultIface *iface)
-{
- iface->get_user_data = io_activity_get_user_data;
- iface->get_source_object = io_activity_get_source_object;
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
}
static void
io_activity_init (EIOActivity *io_activity)
{
io_activity->priv = E_IO_ACTIVITY_GET_PRIVATE (io_activity);
-
- io_activity->priv->cancellable = g_cancellable_new ();
}
GType
@@ -193,45 +207,57 @@ e_io_activity_get_type (void)
NULL /* value_table */
};
- static const GInterfaceInfo iface_info = {
- (GInterfaceInitFunc) io_activity_iface_init,
- (GInterfaceFinalizeFunc) NULL,
- NULL /* interface_data */
- };
-
type = g_type_register_static (
E_TYPE_ACTIVITY, "EIOActivity", &type_info, 0);
-
- g_type_add_interface_static (
- type, G_TYPE_ASYNC_RESULT, &iface_info);
}
return type;
}
EActivity *
-e_io_activity_new (GObject *source_object,
- const gchar *primary_text,
- GAsyncReadyCallback callback,
- gpointer user_data)
+e_io_activity_new (const gchar *primary_text,
+ GAsyncResult *async_result,
+ GCancellable *cancellable)
{
- EActivity *activity;
- EIOActivityPrivate *priv;
-
- g_return_val_if_fail (G_IS_OBJECT (source_object), NULL);
g_return_val_if_fail (primary_text != NULL, NULL);
- g_return_val_if_fail (callback != NULL, NULL);
- activity = g_object_new (
- E_TYPE_IO_ACTIVITY, "primary-text", primary_text, NULL);
+ if (async_result != NULL)
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (async_result), NULL);
- /* XXX Should these be construct properties? */
- priv = E_IO_ACTIVITY_GET_PRIVATE (activity);
- priv->source_object = g_object_ref (source_object);
- priv->callback = callback;
- priv->user_data = user_data;
+ if (cancellable != NULL)
+ g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), NULL);
- return activity;
+ return g_object_new (
+ E_TYPE_IO_ACTIVITY,
+ "async-result", async_result, "cancellable",
+ cancellable, "primary-text", primary_text, NULL);
+}
+
+GAsyncResult *
+e_io_activity_get_async_result (EIOActivity *io_activity)
+{
+ g_return_val_if_fail (E_IS_IO_ACTIVITY (io_activity), NULL);
+
+ return io_activity->priv->async_result;
+}
+
+void
+e_io_activity_set_async_result (EIOActivity *io_activity,
+ GAsyncResult *async_result)
+{
+ g_return_if_fail (E_IS_IO_ACTIVITY (io_activity));
+
+ if (async_result != NULL) {
+ g_return_if_fail (G_IS_ASYNC_RESULT (async_result));
+ g_object_ref (async_result);
+ }
+
+ if (io_activity->priv->async_result != NULL)
+ g_object_unref (io_activity->priv->async_result);
+
+ io_activity->priv->async_result = async_result;
+
+ g_object_notify (G_OBJECT (io_activity), "async-result");
}
GCancellable *
@@ -241,3 +267,29 @@ e_io_activity_get_cancellable (EIOActivity *io_activity)
return io_activity->priv->cancellable;
}
+
+void
+e_io_activity_set_cancellable (EIOActivity *io_activity,
+ GCancellable *cancellable)
+{
+ g_return_if_fail (E_IS_IO_ACTIVITY (io_activity));
+
+ if (cancellable != NULL) {
+ g_return_if_fail (G_IS_CANCELLABLE (cancellable));
+ g_object_ref (cancellable);
+ }
+
+ if (io_activity->priv->cancellable != NULL)
+ g_object_unref (io_activity->priv->cancellable);
+
+ io_activity->priv->cancellable = cancellable;
+
+ g_object_freeze_notify (G_OBJECT (io_activity));
+
+ e_activity_set_allow_cancel (
+ E_ACTIVITY (io_activity), (cancellable != NULL));
+
+ g_object_notify (G_OBJECT (io_activity), "cancellable");
+
+ g_object_thaw_notify (G_OBJECT (io_activity));
+}
diff --git a/e-util/e-io-activity.h b/e-util/e-io-activity.h
index c94953af3e..773417472d 100644
--- a/e-util/e-io-activity.h
+++ b/e-util/e-io-activity.h
@@ -60,11 +60,15 @@ struct _EIOActivityClass {
};
GType e_io_activity_get_type (void);
-EActivity * e_io_activity_new (GObject *source_object,
- const gchar *primary_text,
- GAsyncReadyCallback callback,
- gpointer user_data);
+EActivity * e_io_activity_new (const gchar *primary_text,
+ GAsyncResult *async_result,
+ GCancellable *cancellable);
+GAsyncResult * e_io_activity_get_async_result (EIOActivity *io_activity);
+void e_io_activity_set_async_result (EIOActivity *io_activity,
+ GAsyncResult *async_result);
GCancellable * e_io_activity_get_cancellable (EIOActivity *io_activity);
+void e_io_activity_set_cancellable (EIOActivity *io_activity,
+ GCancellable *cancellable);
G_END_DECLS
diff --git a/shell/e-shell-migrate.c b/shell/e-shell-migrate.c
index a330d9d1a5..d7c8312a86 100644
--- a/shell/e-shell-migrate.c
+++ b/shell/e-shell-migrate.c
@@ -29,7 +29,7 @@
#include "e-util/e-bconf-map.h"
#include "e-util/e-error.h"
-#include "e-util/e-fsutils.h"
+#include "e-util/e-file-utils.h"
#include "e-util/e-util.h"
#include "es-event.h"