[glib/glib-2-44] app info: tweak default application algorithm



commit 16c8a34aa2707366287424131db9dc51362095bb
Author: Ryan Lortie <desrt desrt ca>
Date:   Thu Apr 2 17:17:35 2015 -0400

    app info: tweak default application algorithm
    
    Always run the full algorithm for a given mime type before considering
    fallback types.
    
    This includes considering installed applications capable of handling a
    particular mimetype, even if such an app is not explicitly marked as
    default, and there is a default app for a less-specific type.
    
    Specifically, this often helps with cases of installing apps that can
    handle a particular subtype of text/plain.  We want to take those apps
    in preference to a generic text editor, even if that editor is listed as
    the default for text/plain and there is no default listed for the more
    specific type.
    
    Because of the more holistic approach taken by the algorithm, it is now
    more complicated, but it also means that we can do more work while
    holding the lock.  In turn, that lets us avoid duplicating some strings,
    which is nice.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=744282

 gio/gdesktopappinfo.c |  103 +++++++++++++++++++++---------------------------
 1 files changed, 45 insertions(+), 58 deletions(-)
---
diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
index 786ce0f..1cc6caf 100644
--- a/gio/gdesktopappinfo.c
+++ b/gio/gdesktopappinfo.c
@@ -1163,7 +1163,7 @@ desktop_file_dir_unindexed_mime_lookup (DesktopFileDir *dir,
 
           if (!desktop_file_dir_app_name_is_masked (dir, app_name) &&
               !array_contains (blacklist, app_name) && !array_contains (hits, app_name))
-            g_ptr_array_add (hits, g_strdup (app_name));
+            g_ptr_array_add (hits, app_name);
         }
     }
 
@@ -1198,7 +1198,7 @@ desktop_file_dir_unindexed_default_lookup (DesktopFileDir *dir,
       gchar *app_name = tweaks->defaults[i];
 
       if (!array_contains (results, app_name))
-        g_ptr_array_add (results, g_strdup (app_name));
+        g_ptr_array_add (results, app_name);
     }
 }
 
@@ -3844,6 +3844,10 @@ g_desktop_app_info_get_desktop_ids_for_content_type (const gchar *content_type,
     for (j = 0; j < n_desktop_file_dirs; j++)
       desktop_file_dir_mime_lookup (&desktop_file_dirs[j], types[i], hits, blacklist);
 
+  /* We will keep the hits past unlocking, so we must dup them */
+  for (i = 0; i < hits->len; i++)
+    hits->pdata[i] = g_strdup (hits->pdata[i]);
+
   desktop_file_dirs_unlock ();
 
   g_ptr_array_add (hits, NULL);
@@ -3854,30 +3858,6 @@ g_desktop_app_info_get_desktop_ids_for_content_type (const gchar *content_type,
   return (gchar **) g_ptr_array_free (hits, FALSE);
 }
 
-static gchar **
-g_desktop_app_info_get_defaults_for_content_type (const gchar *content_type)
-{
-  GPtrArray *results;
-  gchar **types;
-  gint i, j;
-
-  types = get_list_of_mimetypes (content_type, TRUE);
-  results = g_ptr_array_new ();
-
-  desktop_file_dirs_lock ();
-
-  for (i = 0; types[i]; i++)
-    for (j = 0; j < n_desktop_file_dirs; j++)
-      desktop_file_dir_default_lookup (&desktop_file_dirs[j], types[i], results);
-
-  desktop_file_dirs_unlock ();
-
-  g_ptr_array_add (results, NULL);
-  g_strfreev (types);
-
-  return (gchar **) g_ptr_array_free (results, FALSE);
-}
-
 /**
  * g_app_info_get_recommended_for_type:
  * @content_type: the content type to find a #GAppInfo for
@@ -4045,57 +4025,64 @@ GAppInfo *
 g_app_info_get_default_for_type (const char *content_type,
                                  gboolean    must_support_uris)
 {
-  gchar **desktop_ids;
+  GPtrArray *blacklist;
+  GPtrArray *results;
   GAppInfo *info;
-  gint i;
+  gchar **types;
+  gint i, j, k;
 
   g_return_val_if_fail (content_type != NULL, NULL);
 
-  desktop_ids = g_desktop_app_info_get_defaults_for_content_type (content_type);
+  types = get_list_of_mimetypes (content_type, TRUE);
 
+  blacklist = g_ptr_array_new ();
+  results = g_ptr_array_new ();
   info = NULL;
-  for (i = 0; desktop_ids[i]; i++)
-    {
-      info = (GAppInfo *) g_desktop_app_info_new (desktop_ids[i]);
-
-      if (info)
-        {
-          if (!must_support_uris || g_app_info_supports_uris (info))
-            break;
-
-          g_object_unref (info);
-          info = NULL;
-        }
-    }
 
-  g_strfreev (desktop_ids);
+  desktop_file_dirs_lock ();
 
-  /* If we can't find a default app for this content type, pick one from
-   * the list of all supported apps.  This will be ordered by the user's
-   * preference and by "recommended" apps first, so the first one we
-   * find is probably the best fallback.
-   */
-  if (info == NULL)
+  for (i = 0; types[i]; i++)
     {
-      desktop_ids = g_desktop_app_info_get_desktop_ids_for_content_type (content_type, TRUE);
+      /* Collect all the default apps for this type */
+      for (j = 0; j < n_desktop_file_dirs; j++)
+        desktop_file_dir_default_lookup (&desktop_file_dirs[j], types[i], results);
 
-      for (i = 0; desktop_ids[i]; i++)
+      /* Consider the associations as well... */
+      for (j = 0; j < n_desktop_file_dirs; j++)
+        desktop_file_dir_mime_lookup (&desktop_file_dirs[j], types[i], results, blacklist);
+
+      /* (If any), see if one of those apps is installed... */
+      for (j = 0; j < results->len; j++)
         {
-          info = (GAppInfo *) g_desktop_app_info_new (desktop_ids[i]);
+          const gchar *desktop_id = g_ptr_array_index (results, j);
 
-          if (info)
+          for (k = 0; k < n_desktop_file_dirs; k++)
             {
-              if (!must_support_uris || g_app_info_supports_uris (info))
-                break;
+              info = (GAppInfo *) desktop_file_dir_get_app (&desktop_file_dirs[k], desktop_id);
+
+              if (info)
+                {
+                  if (!must_support_uris || g_app_info_supports_uris (info))
+                    goto out;
 
-              g_object_unref (info);
-              info = NULL;
+                  g_clear_object (&info);
+                }
             }
         }
 
-      g_strfreev (desktop_ids);
+      /* Reset the list, ready to try again with the next (parent)
+       * mimetype, but keep the blacklist in place.
+       */
+      g_ptr_array_set_size (results, 0);
     }
 
+out:
+  desktop_file_dirs_unlock ();
+
+  g_ptr_array_unref (blacklist);
+  g_ptr_array_unref (results);
+  g_strfreev (types);
+
   return info;
 }
 


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