[evolution-data-server] Add ESourceLocal::writable extension property



commit 524ea74756d92529fdc856b2b4cd381a4f67958c
Author: Milan Crha <mcrha redhat com>
Date:   Fri May 31 08:49:03 2019 +0200

    Add ESourceLocal::writable extension property
    
    This is used for calendar backends referencing custom files and it allows
    to tell the backend whether the calendar should be opened in writable way.
    It doesn't force writable open for files which cannot be open in write mode.

 src/calendar/backends/file/e-cal-backend-file.c |  35 +++++---
 src/libedataserver/e-source-local.c             | 103 +++++++++++++++++++++++-
 src/libedataserver/e-source-local.h             |   4 +-
 3 files changed, 129 insertions(+), 13 deletions(-)
---
diff --git a/src/calendar/backends/file/e-cal-backend-file.c b/src/calendar/backends/file/e-cal-backend-file.c
index 63706095f..7acdd3378 100644
--- a/src/calendar/backends/file/e-cal-backend-file.c
+++ b/src/calendar/backends/file/e-cal-backend-file.c
@@ -1399,6 +1399,26 @@ get_uri_string (ECalBackend *backend)
        return full_uri;
 }
 
+static gboolean
+get_source_writable (EBackend *backend)
+{
+       ESource *source;
+       ESourceLocal *extension;
+
+       source = e_backend_get_source (backend);
+
+       if (!e_source_get_writable (source))
+               return FALSE;
+
+       if (!e_source_has_extension (source, E_SOURCE_EXTENSION_LOCAL_BACKEND))
+               return TRUE;
+
+       extension = e_source_get_extension (source, E_SOURCE_EXTENSION_LOCAL_BACKEND);
+
+       return !e_source_local_get_custom_file (extension) ||
+               e_source_local_get_writable (extension);
+}
+
 static void
 source_changed_cb (ESource *source,
                    ECalBackend *backend)
@@ -1417,17 +1437,18 @@ source_changed_cb (ESource *source,
        if (e_source_local_get_custom_file (extension) == NULL)
                return;
 
-       source_writable = e_source_get_writable (source);
+       source_writable = get_source_writable (E_BACKEND (backend));
        backend_writable = e_cal_backend_get_writable (backend);
 
        if (source_writable != backend_writable) {
                backend_writable = source_writable;
-               if (e_source_get_writable (source)) {
+
+               if (source_writable) {
                        gchar *str_uri = get_uri_string (backend);
 
                        g_return_if_fail (str_uri != NULL);
 
-                       backend_writable = (g_access (str_uri, W_OK) != 0);
+                       backend_writable = (g_access (str_uri, W_OK) == 0);
 
                        g_free (str_uri);
                }
@@ -1488,7 +1509,7 @@ e_cal_backend_file_open (ECalBackendSync *backend,
                                source, "changed",
                                G_CALLBACK (source_changed_cb), backend);
 
-                       if (!e_source_get_writable (source))
+                       if (!get_source_writable (E_BACKEND (backend)))
                                writable = FALSE;
                }
        }
@@ -3931,11 +3952,7 @@ e_cal_backend_file_reload (ECalBackendFile *cbfile,
        g_free (str_uri);
 
        if (!err && writable) {
-               ESource *source;
-
-               source = e_backend_get_source (E_BACKEND (cbfile));
-
-               if (!e_source_get_writable (source))
+               if (!get_source_writable (E_BACKEND (cbfile)))
                        writable = FALSE;
        }
   done:
diff --git a/src/libedataserver/e-source-local.c b/src/libedataserver/e-source-local.c
index 1215e03f2..4d379cb15 100644
--- a/src/libedataserver/e-source-local.c
+++ b/src/libedataserver/e-source-local.c
@@ -25,11 +25,13 @@
 
 struct _ESourceLocalPrivate {
        GFile *custom_file;
+       gboolean writable;
 };
 
 enum {
        PROP_0,
-       PROP_CUSTOM_FILE
+       PROP_CUSTOM_FILE,
+       PROP_WRITABLE
 };
 
 G_DEFINE_TYPE (
@@ -49,6 +51,12 @@ source_local_set_property (GObject *object,
                                E_SOURCE_LOCAL (object),
                                g_value_get_object (value));
                        return;
+
+               case PROP_WRITABLE:
+                       e_source_local_set_writable (
+                               E_SOURCE_LOCAL (object),
+                               g_value_get_boolean (value));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -67,6 +75,13 @@ source_local_get_property (GObject *object,
                                e_source_local_dup_custom_file (
                                E_SOURCE_LOCAL (object)));
                        return;
+
+               case PROP_WRITABLE:
+                       g_value_set_boolean (
+                               value,
+                               e_source_local_get_writable (
+                               E_SOURCE_LOCAL (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -116,6 +131,19 @@ e_source_local_class_init (ESourceLocalClass *class)
                        G_PARAM_CONSTRUCT |
                        G_PARAM_EXPLICIT_NOTIFY |
                        E_SOURCE_PARAM_SETTING));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_WRITABLE,
+               g_param_spec_boolean (
+                       "writable",
+                       "Writable",
+                       "Whether the file can be opened in writable mode",
+                       TRUE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_EXPLICIT_NOTIFY |
+                       E_SOURCE_PARAM_SETTING));
 }
 
 static void
@@ -128,7 +156,12 @@ e_source_local_init (ESourceLocal *extension)
  * e_source_local_get_custom_file:
  * @extension: an #ESourceLocal
  *
- * Returns: (transfer none): the #GFile instance
+ * Get the custom file being set on the @extension.
+ * The returned #GFile is owned by the @extension.
+ *
+ * For thread safety use e_source_local_dup_custom_file().
+ *
+ * Returns: (transfer none) (nullable): the #GFile instance, or %NULL
  **/
 GFile *
 e_source_local_get_custom_file (ESourceLocal *extension)
@@ -142,7 +175,11 @@ e_source_local_get_custom_file (ESourceLocal *extension)
  * e_source_local_dup_custom_file:
  * @extension: an #ESourceLocal
  *
- * Returns: (transfer full): the #GFile instance
+ * A thread safe variant to get a custom file being set on the @extension.
+ * Free the returned #GFile, if not %NULL, with g_object_unref(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full) (nullable): the #GFile instance, or %NULL
  **/
 GFile *
 e_source_local_dup_custom_file (ESourceLocal *extension)
@@ -162,6 +199,13 @@ e_source_local_dup_custom_file (ESourceLocal *extension)
        return duplicate;
 }
 
+/**
+ * e_source_local_set_custom_file:
+ * @extension: an #ESourceLocal
+ * @custom_file: (nullable): a #GFile, or %NULL
+ *
+ * Set, or unset, when using %NULL, the custom file for the @extension.
+ **/
 void
 e_source_local_set_custom_file (ESourceLocal *extension,
                                 GFile *custom_file)
@@ -184,3 +228,56 @@ e_source_local_set_custom_file (ESourceLocal *extension,
 
        g_object_notify (G_OBJECT (extension), "custom-file");
 }
+
+/**
+ * e_source_local_get_writable:
+ * @extension: an #ESourceLocal
+ *
+ * Returns whether the backend should prefer to open the file
+ * in writable mode. The default is %TRUE. The file can be still
+ * opened for read-only, for example when the access to the file
+ * is read-only.
+ *
+ * Returns: whether prefer to pen the file in writable mode
+ *
+ * Since: 3.34
+ **/
+gboolean
+e_source_local_get_writable (ESourceLocal *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_LOCAL (extension), FALSE);
+
+       return extension->priv->writable;
+}
+
+/**
+ * e_source_local_set_writable:
+ * @extension: an #ESourceLocal
+ * @writable: value to set
+ *
+ * Set whether the custom file should be opened in writable mode.
+ * The default is %TRUE. The file can be still opened for read-only,
+ * for example when the access to the file is read-only.
+ *
+ * Since: 3.34
+ **/
+void
+e_source_local_set_writable (ESourceLocal *extension,
+                            gboolean writable)
+{
+       gboolean changed = FALSE;
+
+       g_return_if_fail (E_IS_SOURCE_LOCAL (extension));
+
+       e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
+
+       changed = (extension->priv->writable ? 1 : 0) != (writable ? 1 : 0);
+
+       if (changed)
+               extension->priv->writable = writable;
+
+       e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
+
+       if (changed)
+               g_object_notify (G_OBJECT (extension), "writable");
+}
diff --git a/src/libedataserver/e-source-local.h b/src/libedataserver/e-source-local.h
index a2ec01a50..65847ef61 100644
--- a/src/libedataserver/e-source-local.h
+++ b/src/libedataserver/e-source-local.h
@@ -74,7 +74,9 @@ GFile *               e_source_local_get_custom_file  (ESourceLocal *extension);
 GFile *                e_source_local_dup_custom_file  (ESourceLocal *extension);
 void           e_source_local_set_custom_file  (ESourceLocal *extension,
                                                 GFile *custom_file);
-
+gboolean       e_source_local_get_writable     (ESourceLocal *extension);
+void           e_source_local_set_writable     (ESourceLocal *extension,
+                                                gboolean writable);
 G_END_DECLS
 
 #endif /* E_SOURCE_LOCAL_H */


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