summaryrefslogtreecommitdiff
path: root/libebackend/e-source-registry-server.c
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2012-12-23 23:37:25 -0500
committerMatthew Barnes <mbarnes@redhat.com>2012-12-24 08:45:02 -0500
commitff97f680df9eaf24664dc24b43c397c6cae79d3a (patch)
tree6546c7ff4cb1356448910e60f043a02dba3dc61a /libebackend/e-source-registry-server.c
parentf48d53cb5e366de2870911a2c238e833f3f0a120 (diff)
downloadevolution-data-server-ff97f680df9eaf24664dc24b43c397c6cae79d3a.tar.gz
ESourceRegistryServer: Add a "tweak-key-file" signal.
This signal is emitted from e_source_registry_server_load_file() just prior to instantiating an EServerSideSource. Signal handlers can tweak the GKeyFile content as necessary and return TRUE to write the modified content back to disk. For the purposes of tweaking, it's easier to deal with a plain GKeyFile than an ESource instance. An ESource, for example, does not allow key file groups to be removed. The return value is cumulative. If any signal handler returns TRUE, the GKeyFile content is written back to disk. Unfortunately this breaks the libebackend ABI because I forgot to add a pool of reserved pointers to the ESourceRegistryServerClass. Do so now, since we have the opportunity.
Diffstat (limited to 'libebackend/e-source-registry-server.c')
-rw-r--r--libebackend/e-source-registry-server.c110
1 files changed, 107 insertions, 3 deletions
diff --git a/libebackend/e-source-registry-server.c b/libebackend/e-source-registry-server.c
index 202cfba73..6b1ec6994 100644
--- a/libebackend/e-source-registry-server.c
+++ b/libebackend/e-source-registry-server.c
@@ -105,6 +105,7 @@ enum {
FILES_LOADED,
SOURCE_ADDED,
SOURCE_REMOVED,
+ TWEAK_KEY_FILE,
LAST_SIGNAL
};
@@ -1233,6 +1234,18 @@ source_registry_server_source_removed (ESourceRegistryServer *server,
g_object_unref (dbus_object);
}
+static gboolean
+source_registry_server_any_true (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer unused)
+{
+ if (g_value_get_boolean (handler_return))
+ g_value_set_boolean (return_accu, TRUE);
+
+ return TRUE;
+}
+
static void
e_source_registry_server_class_init (ESourceRegistryServerClass *class)
{
@@ -1316,7 +1329,7 @@ e_source_registry_server_class_init (ESourceRegistryServerClass *class)
/**
* ESourceRegistryServer::source-removed:
- * @server: the #ESourceRegistryServer when emitted the signal
+ * @server: the #ESourceRegistryServer which emitted the signal
* @source: the #EServerSideSource that got removed
*
* Emitted when an #EServerSideSource is removed from @server.
@@ -1330,6 +1343,39 @@ e_source_registry_server_class_init (ESourceRegistryServerClass *class)
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
E_TYPE_SERVER_SIDE_SOURCE);
+
+ /**
+ * ESourceRegistryServer::tweak-key-file:
+ * @server: the #ESourceRegistryServer which emitted the signal
+ * @key_file: a #GKeyFile
+ * @uid: a unique identifier string for @key_file
+ *
+ * Emitted from e_source_registry_server_load_file() just prior
+ * to instantiating an #EServerSideSource. Signal handlers can
+ * tweak the @key_file content as necessary and return %TRUE to
+ * write the modified content back to disk.
+ *
+ * For the purposes of tweaking, it's easier to deal with a plain
+ * #GKeyFile than an #ESource instance. An #ESource, for example,
+ * does not allow key file groups to be removed.
+ *
+ * The return value is cumulative. If any signal handler returns
+ * %TRUE, the @key_file content is written back to disk.
+ *
+ * Returns: %TRUE if @key_file was modified, %FALSE otherwise
+ *
+ * Since: 3.8
+ **/
+ signals[TWEAK_KEY_FILE] = g_signal_new (
+ "tweak-key-file",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (ESourceRegistryServerClass, tweak_key_file),
+ source_registry_server_any_true, NULL,
+ NULL,
+ G_TYPE_BOOLEAN, 2,
+ G_TYPE_KEY_FILE,
+ G_TYPE_STRING);
}
static void
@@ -1749,6 +1795,57 @@ e_source_registry_server_load_directory (ESourceRegistryServer *server,
return TRUE;
}
+/* Helper for e_source_registry_server_load_file() */
+static gboolean
+source_registry_server_tweak_key_file (ESourceRegistryServer *server,
+ GFile *file,
+ const gchar *uid,
+ GError **error)
+{
+ GKeyFile *key_file;
+ gchar *contents = NULL;
+ gsize length;
+ gboolean handler_pending;
+ gboolean success = FALSE;
+ gboolean tweaked = FALSE;
+
+ /* Skip this if no one's listening. */
+ handler_pending = g_signal_has_handler_pending (
+ server, signals[TWEAK_KEY_FILE], 0, FALSE);
+ if (!handler_pending)
+ return TRUE;
+
+ key_file = g_key_file_new ();
+
+ g_file_load_contents (file, NULL, &contents, &length, NULL, error);
+
+ if (contents != NULL) {
+ success = g_key_file_load_from_data (
+ key_file, contents, length,
+ G_KEY_FILE_KEEP_COMMENTS |
+ G_KEY_FILE_KEEP_TRANSLATIONS,
+ error);
+ g_free (contents);
+ }
+
+ if (success)
+ g_signal_emit (
+ server, signals[TWEAK_KEY_FILE], 0,
+ key_file, uid, &tweaked);
+
+ if (tweaked) {
+ contents = g_key_file_to_data (key_file, &length, NULL);
+ success = g_file_replace_contents (
+ file, contents, length, NULL, FALSE,
+ G_FILE_CREATE_NONE, NULL, NULL, error);
+ g_free (contents);
+ }
+
+ g_key_file_free (key_file);
+
+ return success;
+}
+
/**
* e_source_registry_server_load_file:
* @server: an #ESourceRegistryServer
@@ -1775,6 +1872,7 @@ e_source_registry_server_load_file (ESourceRegistryServer *server,
ESource *source;
gboolean writable;
gboolean removable;
+ gboolean success = TRUE;
gchar *uid;
g_return_val_if_fail (E_IS_SOURCE_REGISTRY_SERVER (server), NULL);
@@ -1791,11 +1889,17 @@ e_source_registry_server_load_file (ESourceRegistryServer *server,
/* Check if we already have this file loaded. */
source = e_source_registry_server_ref_source (server, uid);
- g_free (uid);
+ /* If the source is to be removable then the key file can
+ * be written back to disk, and can therefore be tweaked. */
+ if (source == NULL && removable)
+ success = source_registry_server_tweak_key_file (
+ server, file, uid, error);
- if (source == NULL)
+ if (source == NULL && success)
source = e_server_side_source_new (server, file, error);
+ g_free (uid);
+
if (source == NULL)
return NULL;