glib r7554 - in trunk/gio: . tests



Author: matthiasc
Date: Fri Sep 26 19:57:36 2008
New Revision: 7554
URL: http://svn.gnome.org/viewvc/glib?rev=7554&view=rev

Log:
2008-09-26  Matthias Clasen  <mclasen redhat com>

        Bug 545350 â GAppInfo deletion
        Bug 545351 â Reset associations for content type

        * gio.symbols:
        * gappinfo.[hc]: New functions g_app_info_can_delete,
        g_app_info_delete and g_app_info_reset_type_associations.

        * gdesktopappinfo.c:
        * gwin32appinfo.c: Implementations of these.

        * tests/Makefile.am:
        * tests/desktop-app-info.c: Tests for GAppInfo functionality.



Added:
   trunk/gio/tests/desktop-app-info.c
Modified:
   trunk/gio/ChangeLog
   trunk/gio/gappinfo.c
   trunk/gio/gappinfo.h
   trunk/gio/gdesktopappinfo.c
   trunk/gio/gio.symbols
   trunk/gio/gwin32appinfo.c
   trunk/gio/tests/Makefile.am

Modified: trunk/gio/gappinfo.c
==============================================================================
--- trunk/gio/gappinfo.c	(original)
+++ trunk/gio/gappinfo.c	Fri Sep 26 19:57:36 2008
@@ -574,6 +574,62 @@
   return res;
 }
 
+/**
+ * g_app_info_can_delete:
+ * @appinfo: a #GAppInfo
+ *
+ * Obtains the information whether the GAppInfo can be deleted.
+ * See g_app_info_delete().
+ *
+ * Returns: %TRUE if @appinfo can be deleted
+ *
+ * Since: 2.20
+ */
+gboolean
+g_app_info_can_delete (GAppInfo *appinfo)
+{
+  GAppInfoIface *iface;
+  
+  g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
+
+  iface = G_APP_INFO_GET_IFACE (appinfo);
+
+  if (iface->can_delete)
+    return (* iface->can_delete) (appinfo);
+ 
+  return FALSE; 
+}
+
+
+/**
+ * g_app_info_delete:
+ * @appinfo: a #GAppInfo
+ *
+ * Tries to delete an #GAppInfo. 
+ *
+ * On some platforms, there may be a difference between user-defined
+ * #GAppInfo<!-- -->s which can be deleted, and system-wide ones which
+ * cannot. See g_app_info_can_delete().
+ * 
+ * Returns: %TRUE if @appinfo has been deleted
+ *
+ * Since: 2.20
+ */
+gboolean
+g_app_info_delete (GAppInfo *appinfo)
+{
+  GAppInfoIface *iface;
+  
+  g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE);
+
+  iface = G_APP_INFO_GET_IFACE (appinfo);
+
+  if (iface->do_delete)
+    return (* iface->do_delete) (appinfo);
+ 
+  return FALSE; 
+}
+
 
 G_DEFINE_TYPE (GAppLaunchContext, g_app_launch_context, G_TYPE_OBJECT);
 
@@ -690,5 +746,6 @@
     class->launch_failed (context, startup_notify_id);
 }
 
+
 #define __G_APP_INFO_C__
 #include "gioaliasdef.c"

Modified: trunk/gio/gappinfo.h
==============================================================================
--- trunk/gio/gappinfo.h	(original)
+++ trunk/gio/gappinfo.h	Fri Sep 26 19:57:36 2008
@@ -75,6 +75,8 @@
  * @add_supports_type: Adds to the #GAppInfo information about supported file types.
  * @can_remove_supports_type: Checks for support for removing supported file types from a #GAppInfo.
  * @remove_supports_type: Removes a supported application type from a #GAppInfo.
+ * @can_delete: Checks if a #GAppInfo can be deleted. Since 2.20
+ * @do_delete: Deletes a #GAppInfo. Since 2.20
  *
  * Application Information interface, for operating system portability.
  */
@@ -120,6 +122,8 @@
   gboolean     (* remove_supports_type)         (GAppInfo           *appinfo,
                                                  const char         *content_type,
                                                  GError            **error);
+  gboolean     (* can_delete)                   (GAppInfo           *appinfo);
+  gboolean     (* do_delete)                    (GAppInfo           *appinfo);
 };
 
 GType       g_app_info_get_type                     (void) G_GNUC_CONST;
@@ -160,9 +164,12 @@
 gboolean    g_app_info_remove_supports_type         (GAppInfo             *appinfo,
 						     const char           *content_type,
 						     GError              **error);
+gboolean    g_app_info_can_delete                   (GAppInfo   *appinfo);
+gboolean    g_app_info_delete                       (GAppInfo   *appinfo);
 
 GList *   g_app_info_get_all                     (void);
 GList *   g_app_info_get_all_for_type            (const char  *content_type);
+void      g_app_info_reset_type_associations     (const char  *content_type);
 GAppInfo *g_app_info_get_default_for_type        (const char  *content_type,
 						  gboolean     must_support_uris);
 GAppInfo *g_app_info_get_default_for_uri_scheme  (const char  *uri_scheme);

Modified: trunk/gio/gdesktopappinfo.c
==============================================================================
--- trunk/gio/gdesktopappinfo.c	(original)
+++ trunk/gio/gdesktopappinfo.c	Fri Sep 26 19:57:36 2008
@@ -1171,7 +1171,8 @@
   char **list;
   gsize length, data_size;
   char *data;
-  int i, j;
+  int i, j, k;
+  char **content_types;
 
   /* Don't add both at start and end */
   g_assert (!(add_at_start && add_at_end));
@@ -1191,75 +1192,109 @@
       key_file = g_key_file_new ();
     }
 
-  /* Add to the right place in the list */
+  if (content_type)
+    {
+      content_types = g_new (char *, 2);
+      content_types[0] = g_strdup (content_type);
+      content_types[1] = NULL;
+    }
+  else
+    {
+      content_types = g_key_file_get_keys (key_file, ADDED_ASSOCIATIONS_GROUP, NULL, NULL);
+    }
+
+  for (k = 0; content_types && content_types[k]; k++)
+    { 
+      /* Add to the right place in the list */
   
-  length = 0;
-  old_list = g_key_file_get_string_list (key_file, ADDED_ASSOCIATIONS_GROUP,
-					 content_type, &length, NULL);
+      length = 0;
+      old_list = g_key_file_get_string_list (key_file, ADDED_ASSOCIATIONS_GROUP,
+					     content_types[k], &length, NULL);
 
-  list = g_new (char *, 1 + length + 1);
+      list = g_new (char *, 1 + length + 1);
 
-  i = 0;
-  if (add_at_start)
-    list[i++] = g_strdup (desktop_id);
-  if (old_list)
-    {
-      for (j = 0; old_list[j] != NULL; j++)
-	{
-	  if (strcmp (old_list[j], desktop_id) != 0)
-	    list[i++] = g_strdup (old_list[j]);
-	}
+      i = 0;
+      if (add_at_start)
+        list[i++] = g_strdup (desktop_id);
+      if (old_list)
+        {
+          for (j = 0; old_list[j] != NULL; j++)
+	    {
+	      if (g_strcmp0 (old_list[j], desktop_id) != 0)
+	        list[i++] = g_strdup (old_list[j]);
+	    }
+        }
+      if (add_at_end)
+        list[i++] = g_strdup (desktop_id);
+      list[i] = NULL;
+  
+      g_strfreev (old_list);
+
+      if (list[0] == NULL || desktop_id == NULL)
+        g_key_file_remove_key (key_file,
+			       ADDED_ASSOCIATIONS_GROUP,
+			       content_types[k],
+			       NULL);
+      else
+        g_key_file_set_string_list (key_file,
+			            ADDED_ASSOCIATIONS_GROUP,
+			            content_types[k],
+			            (const char * const *)list, i);
+   
+      g_strfreev (list);
     }
-  if (add_at_end)
-    list[i++] = g_strdup (desktop_id);
-  list[i] = NULL;
   
-  g_strfreev (old_list);
+  if (content_type)
+    {
+      /* reuse the list from above */
+    }
+  else
+    {
+      g_strfreev (content_types);
+      content_types = g_key_file_get_keys (key_file, REMOVED_ASSOCIATIONS_GROUP, NULL, NULL);
+    }
 
-  g_key_file_set_string_list (key_file,
-			      ADDED_ASSOCIATIONS_GROUP,
-			      content_type,
-			      (const char * const *)list, i);
+  for (k = 0; content_types && content_types[k]; k++) 
+    {
+      /* Remove from removed associations group (unless remove) */
+  
+      length = 0;
+      old_list = g_key_file_get_string_list (key_file, REMOVED_ASSOCIATIONS_GROUP,
+					     content_types[k], &length, NULL);
 
-  g_strfreev (list);
+      list = g_new (char *, 1 + length + 1);
 
-  /* Remove from removed associations group (unless remove) */
+      i = 0;
+      if (remove)
+        list[i++] = g_strdup (desktop_id);
+      if (old_list)
+        {
+          for (j = 0; old_list[j] != NULL; j++)
+	    {
+	      if (g_strcmp0 (old_list[j], desktop_id) != 0)
+	        list[i++] = g_strdup (old_list[j]);
+	    }
+        }
+      list[i] = NULL;
   
-  length = 0;
-  old_list = g_key_file_get_string_list (key_file, REMOVED_ASSOCIATIONS_GROUP,
-					 content_type, &length, NULL);
+      g_strfreev (old_list);
 
-  list = g_new (char *, 1 + length + 1);
+      if (list[0] == NULL || desktop_id == NULL)
+        g_key_file_remove_key (key_file,
+			       REMOVED_ASSOCIATIONS_GROUP,
+			       content_types[k],
+			       NULL);
+      else
+        g_key_file_set_string_list (key_file,
+				    REMOVED_ASSOCIATIONS_GROUP,
+				    content_types[k],
+				    (const char * const *)list, i);
 
-  i = 0;
-  if (remove)
-    list[i++] = g_strdup (desktop_id);
-  if (old_list)
-    {
-      for (j = 0; old_list[j] != NULL; j++)
-	{
-	  if (strcmp (old_list[j], desktop_id) != 0)
-	    list[i++] = g_strdup (old_list[j]);
-	}
+      g_strfreev (list);
     }
-  list[i] = NULL;
   
-  g_strfreev (old_list);
-
-  if (list[0] == NULL)
-    g_key_file_remove_key (key_file,
-			   REMOVED_ASSOCIATIONS_GROUP,
-			   content_type,
-			   NULL);
-  else
-    g_key_file_set_string_list (key_file,
-				REMOVED_ASSOCIATIONS_GROUP,
-				content_type,
-				(const char * const *)list, i);
+  g_strfreev (content_types);  
 
-  g_strfreev (list);
-
-  
   data = g_key_file_to_data (key_file, &data_size, error);
   g_key_file_free (key_file);
   
@@ -1513,6 +1548,40 @@
   return TRUE;
 }
 
+static gboolean
+g_desktop_app_info_can_delete (GAppInfo *appinfo)
+{
+  GDesktopAppInfo *info = G_DESKTOP_APP_INFO (appinfo);
+
+  if (info->filename)
+    return g_access (info->filename, W_OK) == 0;
+
+  return FALSE;
+}
+
+static gboolean
+g_desktop_app_info_delete (GAppInfo *appinfo)
+{
+  GDesktopAppInfo *info = G_DESKTOP_APP_INFO (appinfo);
+  
+  if (info->filename)
+    { 
+      if (g_remove (info->filename) == 0)
+        {
+          update_mimeapps_list (info->desktop_id, NULL, FALSE, FALSE, FALSE, NULL);
+
+          g_free (info->filename);
+          info->filename = NULL;
+          g_free (info->desktop_id);
+          info->desktop_id = NULL;
+
+          return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
 /**
  * g_app_info_create_from_commandline:
  * @commandline: the commandline to use
@@ -1586,6 +1655,8 @@
   iface->add_supports_type = g_desktop_app_info_add_supports_type;
   iface->can_remove_supports_type = g_desktop_app_info_can_remove_supports_type;
   iface->remove_supports_type = g_desktop_app_info_remove_supports_type;
+  iface->can_delete = g_desktop_app_info_can_delete;
+  iface->do_delete = g_desktop_app_info_delete;
 }
 
 static gboolean
@@ -1643,6 +1714,22 @@
   return g_list_reverse (infos);
 }
 
+/**
+ * g_app_info_reset_type_associations:
+ * content_type: a content type 
+ *
+ * Removes all changes to the type associations done by
+ * g_app_info_set_as_default_for_type(), 
+ * g_app_info_set_as_default_for_extension(), 
+ * g_app_info_add_supports_type() of g_app_info_remove_supports_type().
+ *
+ * Since: 2.20
+ */
+void
+g_app_info_reset_type_associations (const char *content_type)
+{
+  update_mimeapps_list (NULL, content_type, FALSE, FALSE, FALSE, NULL);
+}
 
 /**
  * g_app_info_get_default_for_type:

Modified: trunk/gio/gio.symbols
==============================================================================
--- trunk/gio/gio.symbols	(original)
+++ trunk/gio/gio.symbols	Fri Sep 26 19:57:36 2008
@@ -48,6 +48,8 @@
 g_app_info_can_remove_supports_type
 g_app_info_remove_supports_type
 g_app_info_launch_default_for_uri
+g_app_info_can_delete
+g_app_info_delete
 g_app_launch_context_new
 g_app_launch_context_get_display
 g_app_launch_context_get_startup_notify_id
@@ -60,6 +62,7 @@
 g_app_info_get_all_for_type
 g_app_info_get_default_for_type
 g_app_info_get_default_for_uri_scheme
+g_app_info_reset_type_associations
 #endif
 #endif
 

Modified: trunk/gio/gwin32appinfo.c
==============================================================================
--- trunk/gio/gwin32appinfo.c	(original)
+++ trunk/gio/gwin32appinfo.c	Fri Sep 26 19:57:36 2008
@@ -661,3 +661,9 @@
 
   return g_list_reverse (infos);
 }
+
+void
+g_app_info_reset_type_associations (const char *content_type)
+{
+  /* nothing to do */
+}

Modified: trunk/gio/tests/Makefile.am
==============================================================================
--- trunk/gio/tests/Makefile.am	(original)
+++ trunk/gio/tests/Makefile.am	Fri Sep 26 19:57:36 2008
@@ -22,7 +22,8 @@
 	g-file 			\
 	g-file-info 		\
 	data-input-stream 	\
-	data-output-stream
+	data-output-stream 	\
+	desktop-app-info
 
 if OS_UNIX
 TEST_PROGS += live-g-file unix-streams
@@ -49,7 +50,9 @@
 live_g_file_SOURCES	  = live-g-file.c
 live_g_file_LDADD	  = $(progs_ldadd)
 
+desktop_app_info_SOURCES  = desktop-app-info.c
+desktop_app_info_LDADD	  = $(progs_ldadd)
+
 unix_streams_SOURCES	  = unix-streams.c
 unix_streams_LDADD	  = $(progs_ldadd) \
 	$(top_builddir)/gthread/libgthread-2.0.la
-

Added: trunk/gio/tests/desktop-app-info.c
==============================================================================
--- (empty file)
+++ trunk/gio/tests/desktop-app-info.c	Fri Sep 26 19:57:36 2008
@@ -0,0 +1,253 @@
+/* 
+ * Copyright (C) 2008 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ * Author: Matthias Clasen
+ */
+
+#include <glib/glib.h>
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *basedir;
+
+static GAppInfo * 
+create_app_info (const char *name)
+{
+  GError *error;
+  GAppInfo *info;
+
+  error = NULL;
+  info = g_app_info_create_from_commandline ("/usr/bin/true blah",
+                                             name,
+                                             G_APP_INFO_CREATE_NONE,
+                                             &error);
+  g_assert (error == NULL);
+
+  /* this is necessary to ensure that the info is saved */
+  g_app_info_set_as_default_for_type (info, "application/x-blah", &error);
+  g_assert (error == NULL);
+  g_app_info_remove_supports_type (info, "application/x-blah", &error);
+  g_assert (error == NULL);
+  g_app_info_reset_type_associations ("application/x-blah");
+  
+  return info;
+}
+
+static void
+test_delete (void)
+{
+  GAppInfo *info;
+
+  const char *id;
+  char *filename;
+  gboolean res;
+
+  info = create_app_info ("Blah");
+ 
+  id = g_app_info_get_id (info);
+  g_assert (id != NULL);
+
+  filename = g_build_filename (basedir, "applications", id, NULL);
+
+  res = g_file_test (filename, G_FILE_TEST_EXISTS);
+  g_assert (res);
+
+  res = g_app_info_can_delete (info);
+  g_assert (res);
+
+  res = g_app_info_delete (info);
+  g_assert (res);
+
+  res = g_file_test (filename, G_FILE_TEST_EXISTS);
+  g_assert (!res);
+
+  g_object_unref (info);
+
+  if (g_file_test ("/usr/share/applications/gedit.desktop", G_FILE_TEST_EXISTS))
+    {
+      info = (GAppInfo*)g_desktop_app_info_new ("gedit.desktop");
+      g_assert (info);
+     
+      res = g_app_info_can_delete (info);
+      g_assert (!res);
+ 
+      res = g_app_info_delete (info);
+      g_assert (!res);
+    }
+}
+
+static void
+test_default (void)
+{
+  GAppInfo *info, *info1, *info2, *info3;
+  GList *list;
+  GError *error = NULL;  
+
+  info1 = create_app_info ("Blah1");
+  info2 = create_app_info ("Blah2");
+  info3 = create_app_info ("Blah3");
+
+  g_app_info_set_as_default_for_type (info1, "application/x-test", &error);
+  g_assert (error == NULL);
+
+  g_app_info_set_as_default_for_type (info2, "application/x-test", &error);
+  g_assert (error == NULL);
+
+  list = g_app_info_get_all_for_type ("application/x-test");
+  g_assert (g_list_length (list) == 2);
+  
+  /* check that both are in the list, info2 before info1 */
+  info = (GAppInfo *)list->data;
+  g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info2)) == 0);
+
+  info = (GAppInfo *)list->next->data;
+  g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info1)) == 0);
+
+  g_list_foreach (list, (GFunc)g_object_unref, NULL);
+  g_list_free (list);
+
+  /* now try adding something at the end */
+  g_app_info_add_supports_type (info3, "application/x-test", &error);
+  g_assert (error == NULL);
+
+  list = g_app_info_get_all_for_type ("application/x-test");
+  g_assert (g_list_length (list) == 3);
+  
+  /* check that all are in the list, info2, info1, info3 */
+  info = (GAppInfo *)list->data;
+  g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info2)) == 0);
+
+  info = (GAppInfo *)list->next->data;
+  g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info1)) == 0);
+
+  info = (GAppInfo *)list->next->next->data;
+  g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info3)) == 0);
+
+  g_list_foreach (list, (GFunc)g_object_unref, NULL);
+  g_list_free (list);
+
+  /* now remove info1 again */
+  g_app_info_remove_supports_type (info1, "application/x-test", &error);
+  g_assert (error == NULL);
+
+  list = g_app_info_get_all_for_type ("application/x-test");
+  g_assert (g_list_length (list) == 2);
+  
+  /* check that both are in the list, info2 before info3 */
+  info = (GAppInfo *)list->data;
+  g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info2)) == 0);
+
+  info = (GAppInfo *)list->next->data;
+  g_assert (g_strcmp0 (g_app_info_get_id (info), g_app_info_get_id (info3)) == 0);
+
+  g_list_foreach (list, (GFunc)g_object_unref, NULL);
+  g_list_free (list);
+
+  /* now clean it all up */
+  g_app_info_reset_type_associations ("application/x-test");
+
+  list = g_app_info_get_all_for_type ("application/x-test");
+  g_assert (list == NULL);
+  
+  g_app_info_delete (info1);
+  g_app_info_delete (info2);
+  g_app_info_delete (info3);
+
+  g_object_unref (info1);
+  g_object_unref (info2);
+}
+
+static void
+cleanup_dir_recurse (GFile *parent, GFile *root)
+{
+  gboolean res;
+  GError *error;
+  GFileEnumerator *enumerator;
+  GFileInfo *info;
+  GFile *descend;
+  char *relative_path;
+
+  g_assert (root != NULL);
+
+  error = NULL;
+  enumerator =
+    g_file_enumerate_children (parent, "*",
+                               G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL,
+                               &error);
+  if (! enumerator)
+          return;
+  error = NULL;
+  info = g_file_enumerator_next_file (enumerator, NULL, &error);
+  while ((info) && (!error))
+    {
+      descend = g_file_get_child (parent, g_file_info_get_name (info));
+      g_assert (descend != NULL);
+      relative_path = g_file_get_relative_path (root, descend);
+      g_assert (relative_path != NULL);
+
+      if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
+          cleanup_dir_recurse (descend, root);
+
+      error = NULL;
+      res = g_file_delete (descend, NULL, &error);
+      g_assert_cmpint (res, ==, TRUE);
+
+      g_object_unref (descend);
+      error = NULL;
+      info = g_file_enumerator_next_file (enumerator, NULL, &error);
+    }
+  g_assert (error == NULL);
+
+  error = NULL;
+  res = g_file_enumerator_close (enumerator, NULL, &error);
+  g_assert_cmpint (res, ==, TRUE);
+  g_assert (error == NULL);
+}
+
+static void
+cleanup_subdirs (const char *basedir)
+{
+  GFile *base, *file;
+ 
+  base = g_file_new_for_path (basedir);  
+  file = g_file_get_child (base, "applications");
+  cleanup_dir_recurse (file, file);
+  g_object_unref (file);
+  file = g_file_get_child (base, "mime");
+  cleanup_dir_recurse (file, file);
+  g_object_unref (file);
+}
+
+int
+main (int   argc,
+      char *argv[])
+{
+  g_type_init ();
+  g_test_init (&argc, &argv, NULL);
+  
+  basedir = g_get_current_dir ();
+  g_setenv ("XDG_DATA_HOME", basedir, TRUE);
+  cleanup_subdirs (basedir);
+  
+  g_test_add_func ("/desktop-app-info/delete", test_delete);
+  g_test_add_func ("/desktop-app-info/default", test_default);
+
+  return g_test_run();
+}



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