[gvfs] recent: Port from GtkRecentManager to GBookmarkFile



commit dff13283c943c8b10265bd3925d86f17cdc4be6f
Author: Ondrej Holy <oholy redhat com>
Date:   Tue Dec 13 08:43:48 2016 +0100

    recent: Port from GtkRecentManager to GBookmarkFile
    
    GVfs dependency on GTK+ causes various issues. It is only needed by the
    recent backend, which is based on GtkRecentManager. GtkRecentManager is
    just wrapper for GBookmarkFile. Let's port the backend to use GBookmarkFile
    and remove the unwanted GTK+ dependency.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=773300

 configure.ac               |   23 -----
 daemon/Makefile.am         |   17 +---
 daemon/gvfsbackendrecent.c |  192 +++++++++++++++++++++++++++++++++----------
 3 files changed, 152 insertions(+), 80 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 602c7b9..db13274 100644
--- a/configure.ac
+++ b/configure.ac
@@ -609,28 +609,6 @@ AC_SUBST(SAMBA_LIBS)
 dnl ==========================================================================
 
 dnl ****************************
-dnl *** Check for GTK        ***
-dnl ****************************
-
-AC_ARG_ENABLE([gtk], [AS_HELP_STRING([--disable-gtk],[build without GTK+])])
-msg_gtk=no
-GTK_REQUIRED=3.0
-
-if test "x$enable_gtk" != "xno"; then
-  PKG_CHECK_EXISTS([gtk+-3.0 >= $GTK_REQUIRED], [msg_gtk=yes])
-
-  if test "x$msg_gtk" = "xyes"; then
-    PKG_CHECK_MODULES([GTK],[gtk+-3.0 >= $GTK_REQUIRED])
-    AC_DEFINE([HAVE_GTK], 1, [Define to 1 if GTK+ is available])
-  fi
-fi
-
-AM_CONDITIONAL([USE_GTK], [test "$msg_gtk" = "yes"])
-
-AC_SUBST(GTK_CFLAGS)
-AC_SUBST(GTK_LIBS)
-
-dnl ****************************
 dnl *** Check for libarchive ***
 dnl ****************************
 
@@ -939,7 +917,6 @@ echo "
         Use libsystemd-login:         $msg_libsystemd_login
         Use GCR:                      $msg_gcr
        GNOME Keyring support:        $msg_keyring
-       GTK+ support:                 $msg_gtk
        Installed tests:              $msg_installed_tests
 "
 
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index ae9dafe..60b9da2 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -50,10 +50,10 @@ endif
 %.localmount: %.mount.in ../config.log
        $(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(abs_builddir)|" $< > $@
 
-libexec_PROGRAMS=gvfsd gvfsd-sftp gvfsd-trash gvfsd-computer gvfsd-burn gvfsd-localtest gvfsd-ftp 
gvfsd-network
+libexec_PROGRAMS=gvfsd gvfsd-sftp gvfsd-trash gvfsd-computer gvfsd-burn gvfsd-localtest gvfsd-ftp 
gvfsd-network gvfsd-recent
 
-mount_in_files = sftp.mount.in ftp.mount.in ftps.mount.in trash.mount.in computer.mount.in burn.mount.in 
localtest.mount.in network.mount.in
-mount_DATA =  sftp.mount ftp.mount ftps.mount trash.mount computer.mount burn.mount localtest.mount 
network.mount
+mount_in_files = sftp.mount.in ftp.mount.in ftps.mount.in trash.mount.in computer.mount.in burn.mount.in 
localtest.mount.in network.mount.in recent.mount.in
+mount_DATA =  sftp.mount ftp.mount ftps.mount trash.mount computer.mount burn.mount localtest.mount 
network.mount recent.mount
 
 mount_in_files += admin.mount.in
 if HAVE_ADMIN
@@ -67,12 +67,6 @@ mount_DATA += google.mount
 libexec_PROGRAMS += gvfsd-google
 endif
 
-mount_in_files +=recent.mount.in
-if USE_GTK
-mount_DATA += recent.mount
-libexec_PROGRAMS += gvfsd-recent
-endif
-
 mount_in_files += http.mount.in dav.mount.in dav+sd.mount.in
 if HAVE_HTTP
 mount_DATA += http.mount dav.mount
@@ -354,10 +348,9 @@ gvfsd_recent_CPPFLAGS = \
        -DDEFAULT_BACKEND_TYPE=recent \
        -DMAX_JOB_THREADS=10 \
        -DBACKEND_USES_GVFS=1 \
-       -DBACKEND_TYPES='"recent", G_VFS_TYPE_BACKEND_RECENT,' \
-       $(GTK_CFLAGS)
+       -DBACKEND_TYPES='"recent", G_VFS_TYPE_BACKEND_RECENT,'
 
-gvfsd_recent_LDADD = $(libraries) $(GTK_LIBS)
+gvfsd_recent_LDADD = $(libraries)
 
 gvfsd_computer_SOURCES = \
        gvfsbackendcomputer.c gvfsbackendcomputer.h \
diff --git a/daemon/gvfsbackendrecent.c b/daemon/gvfsbackendrecent.c
index 14706d4..f2b5ce2 100644
--- a/daemon/gvfsbackendrecent.c
+++ b/daemon/gvfsbackendrecent.c
@@ -12,7 +12,6 @@
 #include "gvfsbackendrecent.h"
 
 #include <glib/gi18n.h> /* _() */
-#include <gtk/gtk.h>
 #include <string.h>
 
 #include "gvfsjobcreatemonitor.h"
@@ -38,7 +37,9 @@ struct OPAQUE_TYPE__GVfsBackendRecent
 {
   GVfsBackend parent_instance;
 
-  GtkRecentManager *recent_manager;
+  GBookmarkFile *bookmarks;
+  gchar *filename;
+  GFileMonitor *monitor;
   GHashTable *uri_map;
   GHashTable *items;
 
@@ -48,6 +49,8 @@ struct OPAQUE_TYPE__GVfsBackendRecent
 
 G_DEFINE_TYPE (GVfsBackendRecent, g_vfs_backend_recent, G_VFS_TYPE_BACKEND);
 
+#define RECENTLY_USED_FILE "recently-used.xbel"
+
 static GVfsMonitor *
 recent_backend_get_file_monitor (GVfsBackendRecent *backend,
                                  gboolean           create)
@@ -274,9 +277,11 @@ recent_backend_delete (GVfsBackend   *vfs_backend,
       if (item)
         {
           gboolean res;
-          res = gtk_recent_manager_remove_item (backend->recent_manager,
-                                                item->uri,
-                                                &error);
+
+          res = g_bookmark_file_remove_item (backend->bookmarks, item->uri, &error);
+          if (res)
+            res = g_bookmark_file_to_file (backend->bookmarks, backend->filename, &error);
+
           if (res)
             {
               g_vfs_job_succeeded (G_VFS_JOB (job));
@@ -374,15 +379,13 @@ recent_item_free (RecentItem *item)
 }
 
 static gboolean
-recent_item_update (RecentItem    *item,
-                    GtkRecentInfo *info)
+recent_item_update (RecentItem  *item,
+                    const gchar *uri,
+                    const gchar *display_name,
+                    time_t       modified)
 {
   gboolean changed = FALSE;
-  const char *uri;
-  const char *display_name;
-  time_t modified;
 
-  uri = gtk_recent_info_get_uri (info);
   if (g_strcmp0 (item->uri, uri) != 0)
     {
       changed = TRUE;
@@ -393,7 +396,6 @@ recent_item_update (RecentItem    *item,
       item->file = g_file_new_for_uri (item->uri);
     }
 
-  display_name = gtk_recent_info_get_display_name (info);
   if (g_strcmp0 (item->display_name, display_name) != 0)
     {
       changed = TRUE;
@@ -401,7 +403,6 @@ recent_item_update (RecentItem    *item,
       item->display_name = g_strdup (display_name);
     }
 
-  modified = gtk_recent_info_get_modified (info);
   if (item->modified != modified)
     {
       changed = TRUE;
@@ -412,69 +413,130 @@ recent_item_update (RecentItem    *item,
 }
 
 static RecentItem *
-recent_item_new (GtkRecentInfo *info)
+recent_item_new (const gchar *uri,
+                 const gchar *display_name,
+                 time_t       modified)
 {
   RecentItem *item;
   item = g_new0 (RecentItem, 1);
   item->guid = g_dbus_generate_guid ();
 
-  recent_item_update (item, info);
+  recent_item_update (item, uri, display_name, modified);
 
   return item;
 }
 
+static gboolean
+should_include (GBookmarkFile *bookmarks,
+                const gchar   *uri)
+{
+  gchar *mimetype, *filename;
+
+  /* Is public */
+  if (g_bookmark_file_get_is_private (bookmarks, uri, NULL))
+    return FALSE;
+
+  /* Is local */
+  if (g_ascii_strncasecmp (uri, "file:/", 6) != 0)
+    return FALSE;
+
+  /* Is not dir */
+  mimetype = g_bookmark_file_get_mime_type (bookmarks, uri, NULL);
+  if (g_strcmp0 (mimetype, "inode/directory") == 0)
+    {
+      g_free (mimetype);
+      return FALSE;
+    }
+  g_free (mimetype);
+
+  /* Exists */
+  filename = g_filename_from_uri (uri, NULL, NULL);
+  if (!g_file_test (filename, G_FILE_TEST_EXISTS))
+    {
+      g_free (filename);
+      return FALSE;
+    }
+  g_free (filename);
+
+  return TRUE;
+}
+
+static char *
+get_display_name (GBookmarkFile *bookmarks,
+                  const gchar   *uri)
+{
+  gchar *filename, *display_name;
+
+  display_name = g_bookmark_file_get_title (bookmarks, uri, NULL);
+  if (display_name == NULL)
+    {
+      filename = g_filename_from_uri (uri, NULL, NULL);
+      display_name = g_filename_display_basename (filename);
+      g_free (filename);
+    }
+
+  return display_name;
+}
+
 static void
 reload_recent_items (GVfsBackendRecent *backend)
 {
   GVfsMonitor *monitor;
-  GList *items;
-  GList *node;
   GList *added = NULL;
   GList *changed = NULL;
   GList *not_seen_items = NULL;
   GList *l;
+  GError *error = NULL;
+  gchar **uris;
+  gsize uris_len, i;
+
+  g_debug ("reloading recent items\n");
+
+  g_bookmark_file_load_from_file (backend->bookmarks, backend->filename, &error);
+  if (error != NULL)
+    {
+      g_warning ("Unable to load %s: %s", backend->filename, error->message);
+      g_clear_error (&error);
+      g_bookmark_file_free (backend->bookmarks);
+      backend->bookmarks = g_bookmark_file_new ();
+    }
 
   not_seen_items = g_hash_table_get_values (backend->items);
-  items = gtk_recent_manager_get_items (backend->recent_manager);
-  for (node = items; node; node = node->next)
+  uris = g_bookmark_file_get_uris (backend->bookmarks, &uris_len);
+  for (i = 0; i < uris_len; i++)
     {
-      GtkRecentInfo *recent_info = node->data;
-      const char *uri;
+      const char *uri = uris[i];
       const char *guid;
+      char *display_name;
+      time_t modified;
 
-      if (!gtk_recent_info_is_local (recent_info)
-          || gtk_recent_info_get_private_hint (recent_info)
-          || g_strcmp0 (gtk_recent_info_get_mime_type (recent_info), "inode/directory") == 0)
-        {
-          gtk_recent_info_unref (recent_info);
-          continue;
-        }
-
-      uri = gtk_recent_info_get_uri (recent_info);
-      guid = g_hash_table_lookup (backend->uri_map, uri);
-      if (gtk_recent_info_exists (recent_info))
+      if (should_include (backend->bookmarks, uri))
         {
+          display_name = get_display_name (backend->bookmarks, uri);
+          modified = g_bookmark_file_get_modified (backend->bookmarks, uri, NULL);
+          guid = g_hash_table_lookup (backend->uri_map, uri);
           if (guid)
             {
               RecentItem *item;
               item = g_hash_table_lookup (backend->items, guid);
-              if (recent_item_update (item, recent_info))
+              if (recent_item_update (item, uri, display_name, modified))
                 changed = g_list_prepend (changed, item->guid);
               not_seen_items = g_list_remove (not_seen_items, item);
             }
           else
             {
               RecentItem *item;
-              item = recent_item_new (recent_info);
+              item = recent_item_new (uri, display_name, modified);
               added = g_list_prepend (added, item->guid);
               g_hash_table_insert (backend->items, item->guid, item);
               g_hash_table_insert (backend->uri_map, item->uri, item->guid);
             }
+
+          g_free (display_name);
         }
-      gtk_recent_info_unref (recent_info);
     }
 
-  g_list_free (items);
+  g_strfreev (uris);
 
   monitor = recent_backend_get_dir_monitor (backend, FALSE);
 
@@ -510,10 +572,33 @@ reload_recent_items (GVfsBackendRecent *backend)
 }
 
 static void
-on_recent_manager_changed (GtkRecentManager  *manager,
-                           GVfsBackendRecent *backend)
+bookmarks_changed (GFileMonitor      *monitor,
+                   GFile             *file,
+                   GFile             *other_file,
+                   GFileMonitorEvent  event_type,
+                   gpointer           user_data)
 {
-  reload_recent_items (backend);
+  GVfsBackendRecent *backend = G_VFS_BACKEND_RECENT (user_data);
+  gchar *filename;
+
+  switch (event_type)
+    {
+      case G_FILE_MONITOR_EVENT_CREATED:
+      case G_FILE_MONITOR_EVENT_DELETED:
+        filename = g_file_get_path (file);
+        if (g_strcmp0 (filename, backend->filename) != 0)
+          {
+            g_free (filename);
+            break;
+          }
+        g_free (filename);
+      case G_FILE_MONITOR_EVENT_CHANGED:
+        reload_recent_items (backend);
+        break;
+
+      default:
+        break;
+    }
 }
 
 static gboolean
@@ -524,12 +609,23 @@ recent_backend_mount (GVfsBackend  *vfs_backend,
                       gboolean      is_automount)
 {
   GVfsBackendRecent *backend = G_VFS_BACKEND_RECENT (vfs_backend);
+  GError *error = NULL;
+  GFile *file;
+
+  backend->bookmarks = g_bookmark_file_new ();
+  backend->filename = g_build_filename (g_get_user_data_dir (), RECENTLY_USED_FILE, NULL);
+
+  file = g_file_new_for_path (backend->filename);
+  backend->monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
+  g_object_unref (file);
+  if (error != NULL)
+    {
+      g_warning ("Unable to monitor %s: %s", backend->filename, error->message);
+      g_clear_error (&error);
+    }
+  else
+    g_signal_connect (backend->monitor, "changed", G_CALLBACK (bookmarks_changed), backend);
 
-  backend->recent_manager = gtk_recent_manager_get_default ();
-  g_signal_connect (backend->recent_manager,
-                    "changed",
-                    G_CALLBACK (on_recent_manager_changed),
-                    backend);
   reload_recent_items (backend);
 
   g_vfs_job_succeeded (G_VFS_JOB (job));
@@ -688,7 +784,13 @@ recent_backend_finalize (GObject *object)
   g_hash_table_destroy (backend->items);
   g_hash_table_destroy (backend->uri_map);
 
-  g_signal_handlers_disconnect_by_func (backend->recent_manager, on_recent_manager_changed, backend);
+  g_clear_pointer (&backend->filename, g_free);
+  g_clear_pointer (&backend->bookmarks, g_bookmark_file_free);
+  if (backend->monitor)
+    {
+      g_signal_handlers_disconnect_by_func (backend->monitor, reload_recent_items, backend);
+      g_clear_object (&backend->monitor);
+    }
 
   if (G_OBJECT_CLASS (g_vfs_backend_recent_parent_class)->finalize)
     (*G_OBJECT_CLASS (g_vfs_backend_recent_parent_class)->finalize) (object);


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