Add g_file_query_default_handler utility to easily look up the GAppInfo
authorAlexander Larsson <alexl@redhat.com>
Tue, 29 Jan 2008 12:18:48 +0000 (12:18 +0000)
committerAlexander Larsson <alexl@src.gnome.org>
Tue, 29 Jan 2008 12:18:48 +0000 (12:18 +0000)
2008-01-29  Alexander Larsson  <alexl@redhat.com>

        * gfile.[ch]:
        Add g_file_query_default_handler utility to easily look up
the GAppInfo that handles a file.

        * gdesktopappinfo.[ch]:
        * giomodule.c:
Set up an extension point for g_app_info_get_default_for_uri_scheme()

        * gvfs.c:
Remove unused function

svn path=/trunk/; revision=6409

gio/ChangeLog
gio/gdesktopappinfo.c
gio/gdesktopappinfo.h
gio/gfile.c
gio/gfile.h
gio/giomodule.c
gio/gvfs.c

index c8143b7..6656947 100644 (file)
@@ -1,5 +1,18 @@
 2008-01-29  Alexander Larsson  <alexl@redhat.com>
 
+        * gfile.[ch]:
+        Add g_file_query_default_handler utility to easily look up
+       the GAppInfo that handles a file.
+       
+        * gdesktopappinfo.[ch]:
+        * giomodule.c:
+       Set up an extension point for g_app_info_get_default_for_uri_scheme()
+       
+        * gvfs.c:
+       Remove unused function
+
+2008-01-29  Alexander Larsson  <alexl@redhat.com>
+
         * gfileenumerator.c:
         Mention need to free returned value in
        g_file_enumerator_next_files_finish docs.
index 72ff00e..9f1c242 100644 (file)
@@ -1607,7 +1607,6 @@ g_app_info_get_default_for_type (const char *content_type,
   return info;
 }
 
-
 /**
  * g_app_info_get_default_for_uri_scheme:
  * @uri_scheme: a string containing a URI scheme.
@@ -1622,10 +1621,54 @@ g_app_info_get_default_for_type (const char *content_type,
 GAppInfo *
 g_app_info_get_default_for_uri_scheme (const char *uri_scheme)
 {
-  /* TODO: Implement this using giomodules, reading the gconf settings
-   * in /desktop/gnome/url-handlers
-   */
-  return NULL;
+  static gsize lookup = 0;
+  
+  if (g_once_init_enter (&lookup))
+    {
+      gsize setup_value = 1;
+      GDesktopAppInfoLookup *lookup_instance;
+      const char *use_this;
+      GIOExtensionPoint *ep;
+      GIOExtension *extension;
+      GList *l;
+
+      use_this = g_getenv ("GIO_USE_URI_ASSOCIATION");
+      
+      /* Ensure vfs in modules loaded */
+      _g_io_modules_ensure_loaded ();
+      
+      ep = g_io_extension_point_lookup (G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME);
+
+      lookup_instance = NULL;
+      if (use_this)
+       {
+         extension = g_io_extension_point_get_extension_by_name (ep, use_this);
+         if (extension)
+           lookup_instance = g_object_new (g_io_extension_get_type (extension), NULL);
+       }
+      
+      if (lookup_instance == NULL)
+       {
+         for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
+           {
+             extension = l->data;
+             lookup_instance = g_object_new (g_io_extension_get_type (extension), NULL);
+             if (lookup_instance != NULL)
+               break;
+           }
+       }
+
+      if (lookup_instance != NULL)
+       setup_value = (gsize)lookup_instance;
+      
+      g_once_init_leave (&lookup, setup_value);
+    }
+
+  if (lookup == 1)
+    return NULL;
+
+  return g_desktop_app_info_lookup_get_default_for_uri_scheme (G_DESKTOP_APP_INFO_LOOKUP (lookup),
+                                                              uri_scheme);
 }
 
 
@@ -2284,5 +2327,65 @@ get_all_desktop_entries_for_mime_type (const char *base_mime_type)
   return desktop_entries;
 }
 
+/* GDesktopAppInfoLookup interface: */
+
+static void g_desktop_app_info_lookup_base_init (gpointer g_class);
+static void g_desktop_app_info_lookup_class_init (gpointer g_class,
+                                                 gpointer class_data);
+
+GType
+g_desktop_app_info_lookup_get_type (void)
+{
+  static GType desktop_app_info_lookup_type = 0;
+
+  if (! desktop_app_info_lookup_type)
+    {
+      static const GTypeInfo desktop_app_info_lookup_info =
+      {
+        sizeof (GDesktopAppInfoLookupIface), /* class_size */
+       g_desktop_app_info_lookup_base_init,   /* base_init */
+       NULL,           /* base_finalize */
+       g_desktop_app_info_lookup_class_init,
+       NULL,           /* class_finalize */
+       NULL,           /* class_data */
+       0,
+       0,              /* n_preallocs */
+       NULL
+      };
+
+      desktop_app_info_lookup_type =
+       g_type_register_static (G_TYPE_INTERFACE, I_("GDesktopAppInfoLookup"),
+                               &desktop_app_info_lookup_info, 0);
+
+      g_type_interface_add_prerequisite (desktop_app_info_lookup_type, G_TYPE_OBJECT);
+    }
+
+  return desktop_app_info_lookup_type;
+}
+
+static void
+g_desktop_app_info_lookup_class_init (gpointer g_class,
+                                     gpointer class_data)
+{
+}
+
+static void
+g_desktop_app_info_lookup_base_init (gpointer g_class)
+{
+}
+
+GAppInfo *
+g_desktop_app_info_lookup_get_default_for_uri_scheme (GDesktopAppInfoLookup *lookup,
+                                                     const char  *uri_scheme)
+{
+  GDesktopAppInfoLookupIface *iface;
+  
+  g_return_val_if_fail (G_IS_DESKTOP_APP_INFO_LOOKUP (lookup), FALSE);
+
+  iface = G_DESKTOP_APP_INFO_LOOKUP_GET_IFACE (lookup);
+
+  return (* iface->get_default_for_uri_scheme) (lookup, uri_scheme);
+}
+
 #define __G_DESKTOP_APP_INFO_C__
 #include "gioaliasdef.c"
index e7fed43..d7a38e0 100644 (file)
@@ -24,6 +24,7 @@
 #define __G_DESKTOP_APP_INFO_H__
 
 #include <gio/gio.h>
+#include "giomodule-priv.h"
 
 G_BEGIN_DECLS
 
@@ -42,6 +43,7 @@ struct _GDesktopAppInfoClass
   GObjectClass parent_class;
 };
 
+
 GType g_desktop_app_info_get_type (void) G_GNUC_CONST;
   
 GDesktopAppInfo *g_desktop_app_info_new_from_filename (const char      *filename);
@@ -50,6 +52,29 @@ gboolean         g_desktop_app_info_get_is_hidden     (GDesktopAppInfo *info);
 
 void             g_desktop_app_info_set_desktop_env   (const char *desktop_env);
 
+
+#define G_TYPE_DESKTOP_APP_INFO_LOOKUP           (g_desktop_app_info_lookup_get_type ())
+#define G_DESKTOP_APP_INFO_LOOKUP(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_DESKTOP_APP_INFO_LOOKUP, GDesktopAppInfoLookup))
+#define G_IS_DESKTOP_APP_INFO_LOOKUP(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_DESKTOP_APP_INFO_LOOKUP))
+#define G_DESKTOP_APP_INFO_LOOKUP_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_DESKTOP_APP_INFO_LOOKUP, GDesktopAppInfoLookupIface))
+
+#define G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME "gio-desktop-app-info-lookup"
+
+typedef struct _GDesktopAppInfoLookup GDesktopAppInfoLookup;
+typedef struct _GDesktopAppInfoLookupIface GDesktopAppInfoLookupIface;
+
+struct _GDesktopAppInfoLookupIface
+{
+  GTypeInterface g_iface;
+
+  GAppInfo * (*get_default_for_uri_scheme) (GDesktopAppInfoLookup *lookup,
+                                           const char  *uri_scheme);
+};
+
+GType g_desktop_app_info_lookup_get_type (void) G_GNUC_CONST;
+GAppInfo * g_desktop_app_info_lookup_get_default_for_uri_scheme (GDesktopAppInfoLookup *lookup,
+                                                                const char  *uri_scheme);
+
 G_END_DECLS
 
 
index 4eedbbb..0dec35a 100644 (file)
@@ -4572,6 +4572,57 @@ g_file_mount_enclosing_volume_finish (GFile         *location,
  *   Utility functions                      *
  ********************************************/
 
+GAppInfo *
+g_file_query_default_handler (GFile                  *file,
+                             GCancellable           *cancellable,
+                             GError                **error)
+{
+  char *uri_scheme;
+  const char *content_type;
+  GAppInfo *appinfo;
+  GFileInfo *info;
+  char *path;
+  
+  uri_scheme = g_file_get_uri_scheme (file);
+  appinfo = g_app_info_get_default_for_uri_scheme (uri_scheme);
+  g_free (uri_scheme);
+
+  if (appinfo != NULL)
+    return appinfo;
+
+  info = g_file_query_info (file,
+                           G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+                           0,
+                           cancellable,
+                           error);
+  if (info == NULL)
+    return NULL;
+
+  appinfo = NULL;
+
+  content_type = g_file_info_get_content_type (info);
+  if (content_type)
+    {
+      /* Don't use is_native(), as we want to support fuse paths if availible */
+      path = g_file_get_path (file);
+      appinfo = g_app_info_get_default_for_type (content_type,
+                                                path == NULL);
+      g_free (path);
+    }
+  
+  g_object_unref (info);
+
+  if (appinfo != NULL)
+    return appinfo;
+
+  g_set_error (error, G_IO_ERROR,
+              G_IO_ERROR_NOT_SUPPORTED,
+              _("No application is registered as handling this file"));
+  return NULL;
+  
+}
+
+
 #define GET_CONTENT_BLOCK_SIZE 8192
 
 /**
index 196d040..0072224 100644 (file)
@@ -33,6 +33,7 @@
 #include <gio/gfileinputstream.h>
 #include <gio/gfileoutputstream.h>
 #include <gio/gmountoperation.h>
+#include <gio/gappinfo.h>
 
 G_BEGIN_DECLS
 
@@ -838,6 +839,9 @@ GFileMonitor*           g_file_monitor_file               (GFile
 
 /* Utilities */
 
+GAppInfo *g_file_query_default_handler       (GFile                  *file,
+                                             GCancellable           *cancellable,
+                                             GError                **error);
 gboolean g_file_load_contents                (GFile                  *file,
                                              GCancellable           *cancellable,
                                              char                  **contents,
index cee23d6..9ec12ff 100644 (file)
@@ -30,7 +30,9 @@
 #include "glocaldirectorymonitor.h"
 #include "gnativevolumemonitor.h"
 #include "gvfs.h"
-
+#ifdef G_OS_UNIX
+#include "gdesktopappinfo.h"
+#endif
 #include "gioalias.h"
 
 /**
@@ -257,6 +259,11 @@ _g_io_modules_ensure_loaded (void)
     {
       loaded_dirs = TRUE;
 
+#ifdef G_OS_UNIX
+      ep = g_io_extension_point_register (G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME);
+      g_io_extension_point_set_required_type (ep, G_TYPE_DESKTOP_APP_INFO_LOOKUP);
+#endif
+      
       ep = g_io_extension_point_register (G_LOCAL_DIRECTORY_MONITOR_EXTENSION_POINT_NAME);
       g_io_extension_point_set_required_type (ep, G_TYPE_LOCAL_DIRECTORY_MONITOR);
       
index 67f0d38..7488c31 100644 (file)
@@ -167,46 +167,6 @@ g_vfs_parse_name (GVfs       *vfs,
   return (* class->parse_name) (vfs, parse_name);
 }
 
-/* Note: This compares in reverse order.
-   Higher prio -> sort first
- */
-static gint
-compare_vfs_type (gconstpointer  a,
-                 gconstpointer  b,
-                 gpointer       user_data)
-{
-  GType a_type, b_type;
-  char *a_name, *b_name;
-  int a_prio, b_prio;
-  gint res;
-  const char *use_this_monitor;
-  GQuark private_q, name_q;
-
-  private_q = g_quark_from_static_string ("gio-prio");
-  name_q = g_quark_from_static_string ("gio-name");
-  
-  use_this_monitor = user_data;
-  a_type = *(GType *)a;
-  b_type = *(GType *)b;
-  a_prio = GPOINTER_TO_INT (g_type_get_qdata (a_type, private_q));
-  a_name = g_type_get_qdata (a_type, name_q);
-  b_prio = GPOINTER_TO_INT (g_type_get_qdata (b_type, private_q));
-  b_name = g_type_get_qdata (b_type, name_q);
-
-  if (a_type == b_type)
-    res = 0;
-  else if (use_this_monitor != NULL &&
-          strcmp (a_name, use_this_monitor) == 0)
-    res = -1;
-  else if (use_this_monitor != NULL &&
-          strcmp (b_name, use_this_monitor) == 0)
-    res = 1;
-  else 
-    res = b_prio - a_prio;
-  
-  return res;
-}
-
 static gpointer
 get_default_vfs (gpointer arg)
 {