[nautilus/wip/csoriano/desktop-split-noconflicts: 1/2] directory: use gio extensions for directory dispatching



commit ca856bdd290835c66237553d81001454a6cf0803
Author: Carlos Soriano <csoriano gnome org>
Date:   Wed Apr 13 18:13:51 2016 +0200

    directory: use gio extensions for directory dispatching
    
    We needed to do some hackish code in order to allow types that are
    not included in nautilus-directory to dispatch the correct subclass.
    
    Instead of that, we can just create a "plugabble" system that allows
    directory types to be registered in the system, and implement a class
    vfunc that queries if the class handles a specific type of uri, falling
    back if none can handle it to the usual nautilus-directory.
    
    We can do this for the desktop directory and the search directory.

 libnautilus-private/nautilus-desktop-directory.c |   20 ++++-
 libnautilus-private/nautilus-desktop-directory.h |    2 +
 libnautilus-private/nautilus-directory.c         |   86 +++++++++++++---------
 libnautilus-private/nautilus-directory.h         |    8 ++-
 libnautilus-private/nautilus-file-utilities.c    |   22 ++++++
 libnautilus-private/nautilus-file-utilities.h    |    3 +
 libnautilus-private/nautilus-search-directory.c  |   19 ++++-
 libnautilus-private/nautilus-search-directory.h  |    2 +
 src/nautilus-application.c                       |    3 +
 src/nautilus-desktop-application.c               |   17 +++--
 10 files changed, 134 insertions(+), 48 deletions(-)
---
diff --git a/libnautilus-private/nautilus-desktop-directory.c 
b/libnautilus-private/nautilus-desktop-directory.c
index 2b610c2..9f97baa 100644
--- a/libnautilus-private/nautilus-desktop-directory.c
+++ b/libnautilus-private/nautilus-desktop-directory.c
@@ -60,9 +60,12 @@ typedef struct {
 
 static void desktop_directory_changed_callback (gpointer data);
 
-G_DEFINE_TYPE (NautilusDesktopDirectory, nautilus_desktop_directory,
-              NAUTILUS_TYPE_DIRECTORY);
-
+G_DEFINE_TYPE_WITH_CODE (NautilusDesktopDirectory, nautilus_desktop_directory, NAUTILUS_TYPE_DIRECTORY,
+                         nautilus_ensure_extension_points ();
+                         g_io_extension_point_implement (NAUTILUS_DIRECTORY_PROVIDER_EXTENSION_POINT_NAME,
+                                                         g_define_type_id,
+                                                         NAUTILUS_DESKTOP_DIRECTORY_PROVIDER_NAME,
+                                                         0));
 static gboolean
 desktop_contains_file (NautilusDirectory *directory,
                       NautilusFile *file)
@@ -509,6 +512,16 @@ real_new_file_from_filename (NautilusDirectory *directory,
        return file;
 }
 
+static gboolean
+real_handles_location (GFile *location)
+{
+        g_autofree gchar *uri;
+
+        uri = g_file_get_uri (location);
+
+        return eel_uri_is_desktop (uri);
+}
+
 static void
 desktop_directory_changed_callback (gpointer data)
 {
@@ -548,6 +561,7 @@ nautilus_desktop_directory_class_init (NautilusDesktopDirectoryClass *class)
        directory_class->are_all_files_seen = desktop_are_all_files_seen;
        directory_class->is_not_empty = desktop_is_not_empty;
        directory_class->new_file_from_filename = real_new_file_from_filename;
+       directory_class->handles_location = real_handles_location;
        /* Override get_file_list so that we can return the list of files
         * in NautilusDesktopDirectory->details->real_directory,
         * in addition to the list of standard desktop icons on the desktop.
diff --git a/libnautilus-private/nautilus-desktop-directory.h 
b/libnautilus-private/nautilus-desktop-directory.h
index bd7c173..9e9dc49 100644
--- a/libnautilus-private/nautilus-desktop-directory.h
+++ b/libnautilus-private/nautilus-desktop-directory.h
@@ -38,6 +38,8 @@
 #define NAUTILUS_DESKTOP_DIRECTORY_GET_CLASS(obj) \
   (G_TYPE_INSTANCE_GET_CLASS ((obj), NAUTILUS_TYPE_DESKTOP_DIRECTORY, NautilusDesktopDirectoryClass))
 
+#define NAUTILUS_DESKTOP_DIRECTORY_PROVIDER_NAME "desktop-directory-provider"
+
 typedef struct NautilusDesktopDirectoryDetails NautilusDesktopDirectoryDetails;
 
 typedef struct {
diff --git a/libnautilus-private/nautilus-directory.c b/libnautilus-private/nautilus-directory.c
index f28d713..8b4f63b 100644
--- a/libnautilus-private/nautilus-directory.c
+++ b/libnautilus-private/nautilus-directory.c
@@ -66,6 +66,7 @@ static void               set_directory_location              (NautilusDirectory
 static NautilusFile *     real_new_file_from_filename (NautilusDirectory *directory,
                                                        const char        *filename,
                                                        gboolean           self_owned);
+static gboolean           real_handles_location               (GFile                  *location);
 
 G_DEFINE_TYPE (NautilusDirectory, nautilus_directory, G_TYPE_OBJECT);
 
@@ -160,6 +161,7 @@ nautilus_directory_class_init (NautilusDirectoryClass *klass)
 
        klass->get_file_list = real_get_file_list;
        klass->is_editable = real_is_editable;
+       klass->handles_location = real_handles_location;
 
        g_type_class_add_private (klass, sizeof (NautilusDirectoryDetails));
        g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
@@ -453,25 +455,6 @@ nautilus_directory_get_for_file (NautilusFile *file)
        return directory;
 }
 
-void
-nautilus_directory_add_to_cache (NautilusDirectory *directory)
-{
-       NautilusDirectory *existing_directory;
-       GFile *location;
-
-       location = nautilus_directory_get_location (directory);
-       existing_directory = nautilus_directory_get_existing (location);
-       if (existing_directory == NULL) {
-               /* Put it in the hash table. */
-               g_hash_table_insert (directories,
-                                    directory->details->location,
-                                    directory);
-       } else {
-               nautilus_directory_unref (existing_directory);
-       }
-}
-
-
 /* Returns a reffed NautilusFile object for this directory.
  */
 NautilusFile *
@@ -564,6 +547,13 @@ nautilus_directory_get_location (NautilusDirectory  *directory)
        return g_object_ref (directory->details->location);
 }
 
+static gboolean
+real_handles_location (GFile *location)
+{
+        /* This class is the fallback on handling any location */
+        return TRUE;
+}
+
 NautilusFile *
 nautilus_directory_new_file_from_filename (NautilusDirectory *directory,
                                            const char        *filename,
@@ -601,26 +591,52 @@ real_new_file_from_filename (NautilusDirectory *directory,
        return file;
 }
 
+static GList*
+nautilus_directory_provider_get_all (void)
+{
+  GIOExtensionPoint *extension_point;
+  GList *extensions;
+
+  extension_point = g_io_extension_point_lookup (NAUTILUS_DIRECTORY_PROVIDER_EXTENSION_POINT_NAME);
+  extensions = g_io_extension_point_get_extensions (extension_point);
+
+  return extensions;
+}
+
 static NautilusDirectory *
 nautilus_directory_new (GFile *location)
 {
-       NautilusDirectory *directory;
-       GType type;
-       char *uri;
-
-       uri = g_file_get_uri (location);
+        GList *extensions;
+        GList *l;
+        GIOExtension *gio_extension;
+        GType handling_provider_type;
+        gboolean handled = FALSE;
+        NautilusDirectoryClass *current_provider_class;
+        NautilusDirectory *handling_instance;
+
+        extensions = nautilus_directory_provider_get_all ();
+
+        for (l = extensions; l != NULL; l = l->next) {
+                gio_extension = l->data;
+                current_provider_class = NAUTILUS_DIRECTORY_CLASS (g_io_extension_ref_class (gio_extension));
+                if (current_provider_class->handles_location (location)) {
+                        handling_provider_type = g_io_extension_get_type (gio_extension);
+                        handled = TRUE;
+                        break;
+                }
+        }
 
-       if (eel_uri_is_search (uri)) {
-               type = NAUTILUS_TYPE_SEARCH_DIRECTORY;
-       } else {
-               type = NAUTILUS_TYPE_VFS_DIRECTORY;
-       }
+        if (!handled) {
+                /* This class is the fallback for any location */
+                handling_provider_type = NAUTILUS_TYPE_VFS_DIRECTORY;
+        }
 
-       g_free (uri);
+        handling_instance = g_object_new (handling_provider_type,
+                                          "location", location,
+                                          NULL);
 
-       directory = g_object_new (type, "location", location, NULL);
 
-       return directory;
+        return handling_instance;
 }
 
 gboolean
diff --git a/libnautilus-private/nautilus-directory.h b/libnautilus-private/nautilus-directory.h
index 3fa92f2..ef5d00c 100644
--- a/libnautilus-private/nautilus-directory.h
+++ b/libnautilus-private/nautilus-directory.h
@@ -38,6 +38,8 @@
           operations on files.
 */
 
+#define NAUTILUS_DIRECTORY_PROVIDER_EXTENSION_POINT_NAME "nautilus-directory-provider"
+
 #define NAUTILUS_TYPE_DIRECTORY nautilus_directory_get_type()
 #define NAUTILUS_DIRECTORY(obj) \
   (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_DIRECTORY, NautilusDirectory))
@@ -143,6 +145,10 @@ typedef struct
         NautilusFile * (* new_file_from_filename) (NautilusDirectory *directory,
                                                    const char        *filename,
                                                    gboolean           self_owned);
+        /* Subclasses can say if they handle the location provided or should the
+         * nautilus file class handle it.
+         */
+        gboolean       (* handles_location)       (GFile             *location);
 } NautilusDirectoryClass;
 
 /* Basic GObject requirements. */
@@ -238,8 +244,6 @@ gboolean           nautilus_directory_is_editable              (NautilusDirector
 
 void               nautilus_directory_dump                     (NautilusDirectory         *directory);
 
-void               nautilus_directory_add_to_cache             (NautilusDirectory         *directory);
-
 NautilusFile *     nautilus_directory_new_file_from_filename   (NautilusDirectory *directory,
                                                                 const char        *filename,
                                                                 gboolean           self_owned);
diff --git a/libnautilus-private/nautilus-file-utilities.c b/libnautilus-private/nautilus-file-utilities.c
index 80303b6..df4aa53 100644
--- a/libnautilus-private/nautilus-file-utilities.c
+++ b/libnautilus-private/nautilus-file-utilities.c
@@ -1147,4 +1147,26 @@ nautilus_self_check_file_utilities (void)
 {
 }
 
+void
+nautilus_ensure_extension_builtins (void)
+{
+      g_type_ensure (NAUTILUS_TYPE_SEARCH_DIRECTORY);
+}
+
+void
+nautilus_ensure_extension_points (void)
+{
+  static gsize once_init_value = 0;
+
+  if (g_once_init_enter (&once_init_value))
+    {
+      GIOExtensionPoint *extension_point;
+
+      extension_point = g_io_extension_point_register (NAUTILUS_DIRECTORY_PROVIDER_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (extension_point, NAUTILUS_TYPE_DIRECTORY);
+
+      g_once_init_leave (&once_init_value, 1);
+    }
+}
+
 #endif /* !NAUTILUS_OMIT_SELF_CHECK */
diff --git a/libnautilus-private/nautilus-file-utilities.h b/libnautilus-private/nautilus-file-utilities.h
index d93c40e..ee5f624 100644
--- a/libnautilus-private/nautilus-file-utilities.h
+++ b/libnautilus-private/nautilus-file-utilities.h
@@ -95,4 +95,7 @@ gboolean should_handle_content_types (const char * const *content_type);
 
 gboolean nautilus_file_selection_equal (GList *selection_a, GList *selection_b);
 
+void nautilus_ensure_extension_points (void);
+void nautilus_ensure_extension_builtins (void);
+
 #endif /* NAUTILUS_FILE_UTILITIES_H */
diff --git a/libnautilus-private/nautilus-search-directory.c b/libnautilus-private/nautilus-search-directory.c
index 01d07ce..ed03ec0 100644
--- a/libnautilus-private/nautilus-search-directory.c
+++ b/libnautilus-private/nautilus-search-directory.c
@@ -95,8 +95,12 @@ enum {
        NUM_PROPERTIES
 };
 
-G_DEFINE_TYPE (NautilusSearchDirectory, nautilus_search_directory,
-              NAUTILUS_TYPE_DIRECTORY);
+G_DEFINE_TYPE_WITH_CODE (NautilusSearchDirectory, nautilus_search_directory, NAUTILUS_TYPE_DIRECTORY,
+                         nautilus_ensure_extension_points ();
+                         g_io_extension_point_implement (NAUTILUS_DIRECTORY_PROVIDER_EXTENSION_POINT_NAME,
+                                                         g_define_type_id,
+                                                         NAUTILUS_SEARCH_DIRECTORY_PROVIDER_NAME,
+                                                         0));
 
 static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
 
@@ -687,6 +691,16 @@ search_is_editable (NautilusDirectory *directory)
        return FALSE;
 }
 
+static gboolean
+real_handles_location (GFile *location)
+{
+        g_autofree gchar *uri;
+
+        uri = g_file_get_uri (location);
+
+        return eel_uri_is_search (uri);
+}
+
 static void
 search_set_property (GObject *object,
                     guint property_id,
@@ -859,6 +873,7 @@ nautilus_search_directory_class_init (NautilusSearchDirectoryClass *class)
        
        directory_class->get_file_list = search_get_file_list;
        directory_class->is_editable = search_is_editable;
+       directory_class->handles_location = real_handles_location;
 
        properties[PROP_BASE_MODEL] =
                g_param_spec_object ("base-model",
diff --git a/libnautilus-private/nautilus-search-directory.h b/libnautilus-private/nautilus-search-directory.h
index dd67f2d..48f53cc 100644
--- a/libnautilus-private/nautilus-search-directory.h
+++ b/libnautilus-private/nautilus-search-directory.h
@@ -25,6 +25,8 @@
 #include <libnautilus-private/nautilus-directory.h>
 #include <libnautilus-private/nautilus-query.h>
 
+#define NAUTILUS_SEARCH_DIRECTORY_PROVIDER_NAME "search-directory-provider"
+
 #define NAUTILUS_TYPE_SEARCH_DIRECTORY nautilus_search_directory_get_type()
 #define NAUTILUS_SEARCH_DIRECTORY(obj) \
   (G_TYPE_CHECK_INSTANCE_CAST ((obj), NAUTILUS_TYPE_SEARCH_DIRECTORY, NautilusSearchDirectory))
diff --git a/src/nautilus-application.c b/src/nautilus-application.c
index c9f4213..a84052c 100644
--- a/src/nautilus-application.c
+++ b/src/nautilus-application.c
@@ -946,6 +946,9 @@ nautilus_application_init (NautilusApplication *self)
                                                      NULL);
 
        g_application_add_main_option_entries (G_APPLICATION (self), options);
+
+        nautilus_ensure_extension_points ();
+        nautilus_ensure_extension_builtins ();
 }
 
 static void
diff --git a/src/nautilus-desktop-application.c b/src/nautilus-desktop-application.c
index 47af210..31ff6e6 100644
--- a/src/nautilus-desktop-application.c
+++ b/src/nautilus-desktop-application.c
@@ -21,6 +21,7 @@
 #include "nautilus-desktop-application.h"
 #include "nautilus-desktop-window.h"
 #include "nautilus-desktop-directory.h"
+#include "nautilus-file-utilities.h"
 
 #include "nautilus-freedesktop-generated.h"
 
@@ -29,7 +30,6 @@
 #include <gdk/gdkx.h>
 
 static NautilusFreedesktopFileManager1 *freedesktop_proxy = NULL;
-static NautilusDirectory *desktop_directory = NULL;
 
 struct _NautilusDesktopApplication
 {
@@ -219,13 +219,18 @@ nautilus_desktop_application_class_init (NautilusDesktopApplicationClass *klass)
 }
 
 static void
-nautilus_desktop_application_init (NautilusDesktopApplication *self)
+nautilus_desktop_ensure_builtins (void)
 {
-  g_autoptr (GFile) desktop_location;
+  /* Ensure the type so it can be registered early as a directory extension provider*/
+  g_type_ensure (NAUTILUS_TYPE_DESKTOP_DIRECTORY);
+}
 
-  desktop_location = g_file_new_for_uri (EEL_DESKTOP_URI);
-  desktop_directory = g_object_new (NAUTILUS_TYPE_DESKTOP_DIRECTORY, "location", desktop_location, NULL);
-  nautilus_directory_add_to_cache (NAUTILUS_DIRECTORY (desktop_directory));
+static void
+nautilus_desktop_application_init (NautilusDesktopApplication *self)
+{
+  nautilus_ensure_extension_points ();
+  nautilus_ensure_extension_builtins ();
+  nautilus_desktop_ensure_builtins ();
 }
 
 NautilusDesktopApplication *


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