From ca856bdd290835c66237553d81001454a6cf0803 Mon Sep 17 00:00:00 2001 From: Carlos Soriano Date: Wed, 13 Apr 2016 18:13:51 +0200 Subject: 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 | 80 ++++++++++++++---------- 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, 131 insertions(+), 45 deletions(-) diff --git a/libnautilus-private/nautilus-desktop-directory.c b/libnautilus-private/nautilus-desktop-directory.c index 2b610c20e..9f97baaa9 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 bd7c173f7..9e9dc4949 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 f28d713b0..8b4f63b7e 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 3fa92f25e..ef5d00c4a 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 80303b6ac..df4aa534e 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 d93c40e57..ee5f62498 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 01d07ce9b..ed03ec03d 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 dd67f2d04..48f53cc18 100644 --- a/libnautilus-private/nautilus-search-directory.h +++ b/libnautilus-private/nautilus-search-directory.h @@ -25,6 +25,8 @@ #include #include +#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 c9f4213f4..a84052c85 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 47af210a9..31ff6e603 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 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 * -- cgit v1.2.1