[gedit] selector: add sources and behaviours.



commit aa7c9af6865faade92a74b77813442d2420f277c
Author: Sebastien Lafargue <slafargue gnome org>
Date:   Mon Jan 5 21:53:01 2015 +0100

    selector: add sources and behaviours.
    
    Like in Gedit's quickopen plugin, in addition to recent files,
    some sources for searching files are added :
    
      - home's directory
      - desktop's directory
      - local bookmark directories
      - Gedit file browser directory
      - Gedit's active document directory
      - currently opened documents in the corresponding Gedit's window
    
    The file list shown is always sorted by
    he most recently used files at top.
    
    By default, ie with no text in the search entry,
    the recent files list is shown, limited in size by the Gedit's gsetting:
      path: org.gnome.gedit.preferences.ui and key: max-recents
    
    With text in the search entry, the filtering is done with no limit
    amongst all the sources ( ie the recent files's source is not limited )
    
    Searches are only done in local/native directories, except
    with the recent file list if you have opened distant files.
    
    The treeview is also limited in height by the same max-recents settings:
    the treeview show max-recents entries but no more than ten, the scrollbar
    taking the relay.
    
    You can directly hit enter to validate a file name / uri
    in the search entry. The recognized cases are:
    
      - an uri
      - a local file name:
        the prefix ~/ is replaced by your home's dir if present.
    
    All file's queries for lists's computation are done asynchronously.
    
    You can print debug and timing by setting #if 1 in place of #if 0
    in gedit-open-document-selector-helper.h, then rebuild.
    
    You can get more informations at the top of this file:
    gedit-open-document-selector-store.c
    
    https://bugzilla.gnome.org/show_bug.cgi?id=742280

 gedit/Makefile.am                                  |  170 ++--
 gedit/gedit-open-document-selector-helper.c        |   83 ++
 gedit/gedit-open-document-selector-helper.h        |   99 +++
 gedit/gedit-open-document-selector-store.c         |  792 ++++++++++++++++++
 gedit/gedit-open-document-selector-store.h         |   91 ++
 gedit/gedit-open-document-selector.c               |  885 +++++++++++++++-----
 gedit/gedit-open-document-selector.h               |   13 +-
 gedit/gedit-recent.c                               |    5 +-
 gedit/gedit-window.c                               |   11 +-
 gedit/resources/css/gedit.adwaita.css              |   22 +-
 gedit/resources/ui/gedit-open-document-selector.ui |   37 +-
 11 files changed, 1891 insertions(+), 317 deletions(-)
---
diff --git a/gedit/Makefile.am b/gedit/Makefile.am
index 32df810..d45f45a 100644
--- a/gedit/Makefile.am
+++ b/gedit/Makefile.am
@@ -98,36 +98,38 @@ gedit_built_sources =                       \
        gedit/gedit-marshal.c           \
        gedit/gedit-marshal.h
 
-gedit_NOINST_H_FILES =                         \
-       gedit/gedit-close-confirmation-dialog.h \
-       gedit/gedit-dirs.h                      \
-       gedit/gedit-documents-panel.h           \
-       gedit/gedit-encodings-dialog.h          \
-       gedit/gedit-encoding-items.h            \
-       gedit/gedit-open-document-selector.h    \
-       gedit/gedit-file-chooser-dialog.h       \
-       gedit/gedit-file-chooser-dialog-gtk.h   \
-       gedit/gedit-highlight-mode-dialog.h     \
-       gedit/gedit-highlight-mode-selector.h   \
-       gedit/gedit-history-entry.h             \
-       gedit/gedit-io-error-info-bar.h         \
-       gedit/gedit-menu-stack-switcher.h       \
-       gedit/gedit-multi-notebook.h            \
-       gedit/gedit-notebook.h                  \
-       gedit/gedit-notebook-popup-menu.h       \
-       gedit/gedit-notebook-stack-switcher.h   \
-       gedit/gedit-plugins-engine.h            \
-       gedit/gedit-preferences-dialog.h        \
-       gedit/gedit-print-job.h                 \
-       gedit/gedit-print-preview.h             \
-       gedit/gedit-recent.h                    \
-       gedit/gedit-replace-dialog.h            \
-       gedit/gedit-settings.h                  \
-       gedit/gedit-small-button.h              \
-       gedit/gedit-status-menu-button.h        \
-       gedit/gedit-tab-label.h                 \
-       gedit/gedit-view-frame.h                \
-       gedit/gedit-view-holder.h               \
+gedit_NOINST_H_FILES =                                 \
+       gedit/gedit-close-confirmation-dialog.h         \
+       gedit/gedit-dirs.h                              \
+       gedit/gedit-documents-panel.h                   \
+       gedit/gedit-encodings-dialog.h                  \
+       gedit/gedit-encoding-items.h                    \
+       gedit/gedit-open-document-selector.h            \
+       gedit/gedit-open-document-selector-helper.h     \
+       gedit/gedit-open-document-selector-store.h      \
+       gedit/gedit-file-chooser-dialog.h               \
+       gedit/gedit-file-chooser-dialog-gtk.h           \
+       gedit/gedit-highlight-mode-dialog.h             \
+       gedit/gedit-highlight-mode-selector.h           \
+       gedit/gedit-history-entry.h                     \
+       gedit/gedit-io-error-info-bar.h                 \
+       gedit/gedit-menu-stack-switcher.h               \
+       gedit/gedit-multi-notebook.h                    \
+       gedit/gedit-notebook.h                          \
+       gedit/gedit-notebook-popup-menu.h               \
+       gedit/gedit-notebook-stack-switcher.h           \
+       gedit/gedit-plugins-engine.h                    \
+       gedit/gedit-preferences-dialog.h                \
+       gedit/gedit-print-job.h                         \
+       gedit/gedit-print-preview.h                     \
+       gedit/gedit-recent.h                            \
+       gedit/gedit-replace-dialog.h                    \
+       gedit/gedit-settings.h                          \
+       gedit/gedit-small-button.h                      \
+       gedit/gedit-status-menu-button.h                \
+       gedit/gedit-tab-label.h                         \
+       gedit/gedit-view-frame.h                        \
+       gedit/gedit-view-holder.h                       \
        gedit/gedit-window-private.h
 
 gedit_INST_H_FILES =                           \
@@ -156,59 +158,61 @@ endif
 gedit_headerdir = $(prefix)/include/gedit-$(GEDIT_API_VERSION)/gedit
 gedit_header_HEADERS = $(gedit_INST_H_FILES)
 
-gedit_libgedit_c_files =                       \
-       gedit/gedit-app.c                       \
-       gedit/gedit-app-activatable.c           \
-       gedit/gedit-view-activatable.c          \
-       gedit/gedit-window-activatable.c        \
-       gedit/gedit-menu-extension.c            \
-       gedit/gedit-resources.c                 \
-       gedit/gedit-close-confirmation-dialog.c \
-       gedit/gedit-commands-documents.c        \
-       gedit/gedit-commands-edit.c             \
-       gedit/gedit-commands-file.c             \
-       gedit/gedit-commands-file-print.c       \
-       gedit/gedit-commands-help.c             \
-       gedit/gedit-commands-search.c           \
-       gedit/gedit-commands-view.c             \
-       gedit/gedit-debug.c                     \
-       gedit/gedit-dirs.c                      \
-       gedit/gedit-document.c                  \
-       gedit/gedit-documents-panel.c           \
-       gedit/gedit-encodings-combo-box.c       \
-       gedit/gedit-encodings-dialog.c          \
-       gedit/gedit-encoding-items.c            \
-       gedit/gedit-open-document-selector.c    \
-       gedit/gedit-file-chooser-dialog.c       \
-       gedit/gedit-file-chooser-dialog-gtk.c   \
-       gedit/gedit-highlight-mode-dialog.c     \
-       gedit/gedit-highlight-mode-selector.c   \
-       gedit/gedit-history-entry.c             \
-       gedit/gedit-io-error-info-bar.c         \
-       gedit/gedit-menu-stack-switcher.c       \
-       gedit/gedit-message-bus.c               \
-       gedit/gedit-message.c                   \
-       gedit/gedit-multi-notebook.c            \
-       gedit/gedit-notebook.c                  \
-       gedit/gedit-notebook-popup-menu.c       \
-       gedit/gedit-notebook-stack-switcher.c   \
-       gedit/gedit-plugins-engine.c            \
-       gedit/gedit-preferences-dialog.c        \
-       gedit/gedit-print-job.c                 \
-       gedit/gedit-print-preview.c             \
-       gedit/gedit-progress-info-bar.c         \
-       gedit/gedit-recent.c                    \
-       gedit/gedit-replace-dialog.c            \
-       gedit/gedit-settings.c                  \
-       gedit/gedit-small-button.c              \
-       gedit/gedit-statusbar.c                 \
-       gedit/gedit-status-menu-button.c        \
-       gedit/gedit-tab.c                       \
-       gedit/gedit-tab-label.c                 \
-       gedit/gedit-utils.c                     \
-       gedit/gedit-view.c                      \
-       gedit/gedit-view-frame.c                \
-       gedit/gedit-view-holder.c               \
+gedit_libgedit_c_files =                               \
+       gedit/gedit-app.c                               \
+       gedit/gedit-app-activatable.c                   \
+       gedit/gedit-view-activatable.c                  \
+       gedit/gedit-window-activatable.c                \
+       gedit/gedit-menu-extension.c                    \
+       gedit/gedit-resources.c                         \
+       gedit/gedit-close-confirmation-dialog.c         \
+       gedit/gedit-commands-documents.c                \
+       gedit/gedit-commands-edit.c                     \
+       gedit/gedit-commands-file.c                     \
+       gedit/gedit-commands-file-print.c               \
+       gedit/gedit-commands-help.c                     \
+       gedit/gedit-commands-search.c                   \
+       gedit/gedit-commands-view.c                     \
+       gedit/gedit-debug.c                             \
+       gedit/gedit-dirs.c                              \
+       gedit/gedit-document.c                          \
+       gedit/gedit-documents-panel.c                   \
+       gedit/gedit-encodings-combo-box.c               \
+       gedit/gedit-encodings-dialog.c                  \
+       gedit/gedit-encoding-items.c                    \
+       gedit/gedit-open-document-selector.c            \
+       gedit/gedit-open-document-selector-helper.c     \
+       gedit/gedit-open-document-selector-store.c      \
+       gedit/gedit-file-chooser-dialog.c               \
+       gedit/gedit-file-chooser-dialog-gtk.c           \
+       gedit/gedit-highlight-mode-dialog.c             \
+       gedit/gedit-highlight-mode-selector.c           \
+       gedit/gedit-history-entry.c                     \
+       gedit/gedit-io-error-info-bar.c                 \
+       gedit/gedit-menu-stack-switcher.c               \
+       gedit/gedit-message-bus.c                       \
+       gedit/gedit-message.c                           \
+       gedit/gedit-multi-notebook.c                    \
+       gedit/gedit-notebook.c                          \
+       gedit/gedit-notebook-popup-menu.c               \
+       gedit/gedit-notebook-stack-switcher.c           \
+       gedit/gedit-plugins-engine.c                    \
+       gedit/gedit-preferences-dialog.c                \
+       gedit/gedit-print-job.c                         \
+       gedit/gedit-print-preview.c                     \
+       gedit/gedit-progress-info-bar.c                 \
+       gedit/gedit-recent.c                            \
+       gedit/gedit-replace-dialog.c                    \
+       gedit/gedit-settings.c                          \
+       gedit/gedit-small-button.c                      \
+       gedit/gedit-statusbar.c                         \
+       gedit/gedit-status-menu-button.c                \
+       gedit/gedit-tab.c                               \
+       gedit/gedit-tab-label.c                         \
+       gedit/gedit-utils.c                             \
+       gedit/gedit-view.c                              \
+       gedit/gedit-view-frame.c                        \
+       gedit/gedit-view-holder.c                       \
        gedit/gedit-window.c
 
 gedit_libgedit_la_SOURCES =            \
diff --git a/gedit/gedit-open-document-selector-helper.c b/gedit/gedit-open-document-selector-helper.c
new file mode 100644
index 0000000..21b87ae
--- /dev/null
+++ b/gedit/gedit-open-document-selector-helper.c
@@ -0,0 +1,83 @@
+/*
+ * gedit-open-document-selector-helper.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gedit-open-document-selector-helper.h"
+
+void
+gedit_open_document_selector_debug_print_list (const gchar *title,
+                                               GList       *fileitem_list)
+{
+       FileItem *item;
+       GList *l;
+       gchar *uri;
+       glong time_sec;
+       glong time_usec;
+
+       g_print ("%s\n", title);
+
+       for (l = fileitem_list; l != NULL; l = l->next)
+       {
+               item = (FileItem *)l->data;
+               time_sec = item->access_time.tv_sec;
+               time_usec = item->access_time.tv_usec;
+               uri = item->uri;
+               g_print ("%ld:%ld%s\n", time_sec, time_usec, uri);
+       }
+}
+
+void
+gedit_open_document_selector_free_fileitem_item (FileItem *item)
+{
+       g_free (item->uri);
+       g_slice_free (FileItem, item);
+}
+
+FileItem *
+gedit_open_document_selector_copy_fileitem_item (FileItem *item)
+{
+       FileItem *new_item;
+
+       new_item = g_slice_new (FileItem);
+       new_item->uri = g_strdup (item->uri);
+       new_item->access_time = item->access_time;
+
+       return new_item;
+}
+
+inline GList *
+gedit_open_document_selector_copy_file_items_list (const GList *file_items_list)
+{
+       GList *new_file_items_list;
+
+       new_file_items_list = g_list_copy_deep ((GList *)file_items_list,
+                                               (GCopyFunc)gedit_open_document_selector_copy_fileitem_item,
+                                               NULL);
+
+       return new_file_items_list;
+}
+
+inline void
+gedit_open_document_selector_free_file_items_list (GList *file_items_list)
+{
+       g_list_free_full (file_items_list,
+                         (GDestroyNotify)gedit_open_document_selector_free_fileitem_item);
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector-helper.h b/gedit/gedit-open-document-selector-helper.h
new file mode 100644
index 0000000..61a9a90
--- /dev/null
+++ b/gedit/gedit-open-document-selector-helper.h
@@ -0,0 +1,99 @@
+/*
+ * gedit-open-document-selector-helper.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GEDIT_OPEN_DOCUMENT_SELECTOR_HELPER_H__
+#define __GEDIT_OPEN_DOCUMENT_SELECTOR_HELPER_H__
+
+#include "gedit-open-document-selector.h"
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+       gchar *uri;
+       GTimeVal access_time;
+} FileItem;
+
+typedef enum
+{
+       GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST = 0,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_HOME_DIR_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_DESKTOP_DIR_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_LOCAL_BOOKMARKS_DIR_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_FILE_BROWSER_ROOT_DIR_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_ACTIVE_DOC_DIR_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_CURRENT_DOCS_LIST,
+       GEDIT_OPEN_DOCUMENT_SELECTOR_LIST_TYPE_NUM_OF_LISTS
+} ListType;
+
+/* Use #if 1 and rebuild to activate selector debugging and timing */
+#if 0
+#define DEBUG_OPEN_DOCUMENT_SELECTOR
+#endif
+
+#ifdef DEBUG_OPEN_DOCUMENT_SELECTOR
+G_GNUC_UNUSED static const gchar *list_type_string[] =
+{
+       "RECENT_FILES_LIST",
+       "HOME_DIR_LIST",
+       "DESKTOP_DIR_LIST",
+       "LOCAL_BOOKMARKS_DIR_LIST",
+       "FILE_BROWSER_ROOT_DIR_LIST",
+       "ACTIVE_DOC_DIR_LIST",
+       "CURRENT_DOCS_LIST"
+};
+
+#define DEBUG_SELECTOR(x) do { x; } while (0)
+#define DEBUG_SELECTOR_TIMER_DECL G_GNUC_UNUSED GTimer *debug_timer;
+#define DEBUG_SELECTOR_TIMER_NEW debug_timer = g_timer_new ();
+#define DEBUG_SELECTOR_TIMER_DESTROY g_timer_destroy (debug_timer);
+#define DEBUG_SELECTOR_TIMER_GET g_timer_elapsed (debug_timer, NULL)
+#else
+#define DEBUG_SELECTOR(x)
+#define DEBUG_SELECTOR_TIMER_DECL
+#define DEBUG_SELECTOR_TIMER_NEW
+#define DEBUG_SELECTOR_TIMER_DESTROY
+#define DEBUG_SELECTOR_TIMER_GET
+#endif
+
+typedef struct
+{
+       GeditOpenDocumentSelector *selector;
+       ListType type;
+} PushMessage;
+
+void            gedit_open_document_selector_debug_print_list          (const gchar *title,
+                                                                         GList       *fileitem_list);
+
+GList          *gedit_open_document_selector_copy_file_items_list      (const GList *file_items_list);
+
+void            gedit_open_document_selector_free_file_items_list      (GList *file_items_list);
+
+void            gedit_open_document_selector_free_fileitem_item        (FileItem *item);
+
+FileItem       *gedit_open_document_selector_copy_fileitem_item        (FileItem *item);
+
+G_END_DECLS
+
+#endif /* __GEDIT_OPEN_DOCUMENT_SELECTOR_HELPER_H__ */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector-store.c b/gedit/gedit-open-document-selector-store.c
new file mode 100644
index 0000000..8bf92c3
--- /dev/null
+++ b/gedit/gedit-open-document-selector-store.c
@@ -0,0 +1,792 @@
+/*
+ * gedit-open-document-selector-store.c
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* You need to call gedit_open_document_selector_store_get_default()
+ * to get a singleton #GeditOpenDocumentSelectorStore object.
+ * #GeditOpenDocumentSelectorStore is responsible of managing
+ * the recent files list and computing others lists.
+ *
+ * The lists returned are lists of FileItem structs.
+ *
+ * #GeditOpenDocumentSelectorStore is destroyed automaticly at
+ * the end of your application.
+ *
+ * Call gedit_open_document_selector_store_update_list_async() with
+ * the corresponding ListType, then in your callback, call
+ * gedit_open_document_selector_store_update_list_finish() to get
+ * in return the list of FileItem structs.
+ *
+ * The recent files list can be filtered by calling
+ * gedit_open_document_selector_store_set_recent_filter()
+ * and you can get the actual filter by calling
+ * gedit_open_document_selector_store_get_recent_filter()
+ * ( this is in addition to the text mime type filter)
+ *
+ * The recent files list is not capped by Gedit settings like
+ * in gedit_recent_get_items() but you still can get the limit
+ * by calling gedit_open_document_selector_store_get_recent_limit().
+ *
+ * The original setting is stored in gsettings at :
+ * org.gnome.gedit.preferences.ui
+ * with the key : max-recents
+ */
+
+#include "gedit-open-document-selector-store.h"
+
+#include <time.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "gedit-recent.h"
+#include "gedit-utils.h"
+#include "gedit-window.h"
+#include "gedit-debug.h"
+
+struct _GeditOpenDocumentSelectorStorePrivate
+{
+       GeditRecentConfiguration recent_config;
+       GList *recent_items;
+       gint recent_config_limit;
+       gboolean recent_items_need_update;
+};
+
+G_LOCK_DEFINE_STATIC (recent_files_filter_lock);
+G_LOCK_DEFINE_STATIC (store_recent_items_lock);
+
+G_DEFINE_TYPE_WITH_PRIVATE (GeditOpenDocumentSelectorStore, gedit_open_document_selector_store, 
G_TYPE_OBJECT)
+
+G_DEFINE_QUARK (gedit-open-document-selector-store-error-quark,
+                gedit_open_document_selector_store_error)
+
+static GList *
+get_current_docs_list (GeditOpenDocumentSelectorStore *selector_store,
+                       GeditOpenDocumentSelector      *selector)
+{
+       GList *docs;
+       GList *l;
+       GFile *file;
+       GFileInfo *info;
+       FileItem *item;
+       GList *file_items_list = NULL;
+
+       docs = gedit_window_get_documents (selector->window);
+       for (l = docs; l != NULL; l = l->next)
+       {
+               file = gtk_source_file_get_location (gedit_document_get_file (l->data));
+               if (file == NULL)
+               {
+                       /* In case of not saved docs */
+                       continue;
+               }
+
+               info = g_file_query_info (file,
+                                         "time::access,time::access-usec",
+                                         G_FILE_QUERY_INFO_NONE,
+                                         NULL,
+                                         NULL);
+               if (info == NULL)
+               {
+                       continue;
+               }
+
+               item = (FileItem *)g_slice_new (FileItem);
+
+               item->access_time.tv_sec = g_file_info_get_attribute_uint64 (info, "time::access");
+               item->access_time.tv_usec = g_file_info_get_attribute_uint32 (info, "time::access-usec");
+               item->uri = g_file_get_uri (file);
+
+               file_items_list = g_list_prepend (file_items_list, item);
+
+               g_object_unref (info);
+       }
+
+       g_list_free (docs);
+       return file_items_list;
+}
+
+/* Notice that a content-type attribute must have been query to work */
+static gboolean
+check_mime_type (GFileInfo *info)
+{
+       const gchar *content_type;
+       G_GNUC_UNUSED gchar *mime_type;
+
+       content_type = g_file_info_get_attribute_string (info, "standard::fast-content-type");
+       if (content_type == NULL)
+       {
+               return FALSE;
+       }
+
+#ifdef G_OS_WIN32
+       if (g_content_type_is_a (content_type, "text"))
+       {
+               return TRUE:
+       }
+
+       mime_type = g_content_type_get_mime_type (content_type);
+       if (mime_type == NULL)
+       {
+               return FALSE;
+       }
+
+       if (g_strcmp0 (mime_type, "text/plain") == 0)
+       {
+               g_free (mime_type);
+               return TRUE;
+       }
+
+       g_free (mime_type);
+#else
+       if (g_content_type_is_a (content_type, "text/plain"))
+       {
+               return TRUE;
+       }
+#endif
+       return FALSE;
+}
+
+static GList *
+get_children_from_dir (GeditOpenDocumentSelectorStore *selector_store,
+                       GFile                          *dir)
+{
+       GList *file_items_list = NULL;
+       GFileEnumerator *file_enum;
+       GFileInfo *info;
+       GFileType filetype;
+       GFile *file;
+       gchar *uri;
+       FileItem *item;
+       gboolean is_text;
+       gboolean is_correct_type;
+
+       g_return_val_if_fail (G_IS_FILE (dir), NULL);
+
+       file_enum = g_file_enumerate_children (dir,
+                                              "standard::name,"
+                                              "standard::type,"
+                                              "standard::fast-content-type,"
+                                              "time::access,time::access-usec",
+                                              G_FILE_QUERY_INFO_NONE,
+                                              NULL,
+                                              NULL);
+       if (file_enum == NULL)
+       {
+               return NULL;
+       }
+
+       while ((info = g_file_enumerator_next_file (file_enum, NULL, NULL)))
+       {
+               filetype = g_file_info_get_file_type (info);
+               is_text = check_mime_type (info);
+               is_correct_type = (filetype == G_FILE_TYPE_REGULAR ||
+                                  filetype == G_FILE_TYPE_SYMBOLIC_LINK ||
+                                  filetype == G_FILE_TYPE_SHORTCUT);
+
+               if (is_text &&
+                   is_correct_type &&
+                   (file = g_file_enumerator_get_child (file_enum, info)) != NULL)
+               {
+                       item = (FileItem *)g_slice_new (FileItem);
+                       uri = g_file_get_uri (file);
+                       item->uri = uri;
+
+                       item->access_time.tv_sec = g_file_info_get_attribute_uint64 (info, "time::access");
+                       item->access_time.tv_usec = g_file_info_get_attribute_uint32 (info, 
"time::access-usec");
+
+                       file_items_list = g_list_prepend (file_items_list, item);
+                       g_object_unref (file);
+               }
+
+               g_object_unref (info);
+       }
+
+       g_file_enumerator_close (file_enum, NULL, NULL);
+       g_object_unref (file_enum);
+
+       return file_items_list;
+}
+
+static GList *
+get_active_doc_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+                         GeditOpenDocumentSelector      *selector)
+{
+       GeditDocument *active_doc;
+       GList *file_items_list = NULL;
+       GFile *file;
+       GFile *parent_dir;
+
+       active_doc = gedit_window_get_active_document (selector->window);
+       if (active_doc != NULL && gedit_document_is_local (active_doc))
+       {
+               file = gtk_source_file_get_location (gedit_document_get_file (active_doc));
+               parent_dir = g_file_get_parent (file);
+               if (parent_dir != NULL)
+               {
+                       file_items_list = get_children_from_dir (selector_store, parent_dir);
+                       g_object_unref (parent_dir);
+               }
+       }
+
+       return file_items_list;
+}
+
+static GFile *
+get_file_browser_root (GeditOpenDocumentSelectorStore *selector_store,
+                       GeditOpenDocumentSelector      *selector)
+{
+       GeditMessageBus *bus;
+       GeditMessage *msg;
+       GFile *root = NULL;
+
+       bus = gedit_window_get_message_bus (selector->window);
+       if (gedit_message_bus_is_registered (bus, "/plugins/filebrowser", "get_root"))
+       {
+               msg = gedit_message_bus_send_sync (bus, "/plugins/filebrowser", "get_root", NULL, NULL);
+               g_object_get (msg, "location", &root, NULL);
+               g_object_unref (msg);
+       }
+
+       return root;
+}
+
+static GList *
+get_file_browser_root_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+                                GeditOpenDocumentSelector      *selector)
+{
+       GFile *root;
+       GList *file_items_list = NULL;
+
+       root = get_file_browser_root (selector_store, selector);
+       if (root != NULL && g_file_is_native (root))
+       {
+               file_items_list = get_children_from_dir (selector_store, root);
+       }
+
+       g_clear_object (&root);
+       return file_items_list;
+}
+
+/* Taken and adapted from gtk+ gtkbookmarksmanager.c */
+static GList *
+read_bookmarks_file (GFile *file)
+{
+       gchar *contents;
+       gchar **lines, *space;
+       GList *uri_list = NULL;
+       gint i;
+
+       if (!g_file_load_contents (file, NULL, &contents, NULL, NULL, NULL))
+       {
+               return NULL;
+       }
+
+       lines = g_strsplit (contents, "\n", -1);
+
+       for (i = 0; lines[i]; i++)
+       {
+               if (*lines[i] == '\0')
+               {
+                       continue;
+               }
+
+               if (!g_utf8_validate (lines[i], -1, NULL))
+               {
+                       continue;
+               }
+
+               if ((space = strchr (lines[i], ' ')) != NULL)
+               {
+                       space[0] = '\0';
+               }
+
+               uri_list = g_list_prepend (uri_list, g_strdup (lines[i]));
+       }
+
+       g_strfreev (lines);
+       g_free (contents);
+
+       return uri_list;
+}
+
+static GList *
+get_local_bookmarks_list (GeditOpenDocumentSelectorStore *selector_store,
+                          GeditOpenDocumentSelector      *selector)
+{
+       GList *bookmarks_uri_list = NULL;
+       GList *file_items_list = NULL;
+       GList *new_file_items_list = NULL;
+       GFile *bookmarks_file;
+       GFile *file;
+       gchar *filename;
+       GList *l;
+
+       filename = g_build_filename (g_get_user_config_dir (), "gtk-3.0", "bookmarks", NULL);
+       bookmarks_file = g_file_new_for_path (filename);
+       g_free (filename);
+
+       bookmarks_uri_list = read_bookmarks_file (bookmarks_file);
+       g_object_unref (bookmarks_file);
+
+       for (l = bookmarks_uri_list; l != NULL; l = l->next)
+       {
+               file = g_file_new_for_uri (l->data);
+               if (g_file_is_native (file))
+               {
+                       new_file_items_list = get_children_from_dir (selector_store, file);
+                       file_items_list = g_list_concat (file_items_list, new_file_items_list);
+               }
+
+               g_object_unref (file);
+       }
+
+       g_list_free_full (bookmarks_uri_list, g_free);
+       return file_items_list;
+}
+
+/* Taken and adapted from gtk+ gtkplacessidebar.c */
+static gboolean
+path_is_home_dir (const gchar *path)
+{
+       GFile *home_dir;
+       GFile *location;
+       const gchar *home_path;
+       gboolean res;
+
+       home_path = g_get_home_dir ();
+       if (home_path == NULL)
+       {
+               return FALSE;
+       }
+
+       home_dir = g_file_new_for_path (home_path);
+       location = g_file_new_for_path (path);
+       res = g_file_equal (home_dir, location);
+
+       g_object_unref (home_dir);
+       g_object_unref (location);
+
+       return res;
+}
+
+static GList *
+get_desktop_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+                      GeditOpenDocumentSelector      *selector)
+{
+       GList *file_items_list = NULL;
+       const gchar *desktop_dir_name;
+       gchar *desktop_uri;
+       GFile *desktop_file;
+
+       desktop_dir_name = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
+
+       /* "To disable a directory, point it to the homedir."
+        * See http://freedesktop.org/wiki/Software/xdg-user-dirs
+        */
+       if (path_is_home_dir (desktop_dir_name))
+       {
+               return NULL;
+       }
+
+       desktop_uri = g_strconcat ("file://", desktop_dir_name, NULL);
+       desktop_file = g_file_new_for_uri (desktop_uri);
+       file_items_list = get_children_from_dir (selector_store, desktop_file);
+
+       g_free (desktop_uri);
+       g_object_unref (desktop_file);
+
+       return file_items_list;
+}
+
+static GList *
+get_home_dir_list (GeditOpenDocumentSelectorStore *selector_store,
+                   GeditOpenDocumentSelector      *selector)
+{
+       GList *file_items_list = NULL;
+       const gchar *home_name;
+       gchar *home_uri;
+       GFile *home_file;
+
+       home_name = g_get_home_dir ();
+       if (home_name == NULL)
+       {
+               return NULL;
+       }
+
+       home_uri = g_strconcat ("file://", home_name, NULL);
+       home_file = g_file_new_for_uri (home_uri);
+       file_items_list = get_children_from_dir (selector_store, home_file);
+
+       g_free (home_uri);
+       g_object_unref (home_file);
+
+       return file_items_list;
+}
+
+static GList *
+convert_recent_item_list_to_fileitem_list (GList *uri_list)
+{
+       GList *l;
+       GList *fileitem_list = NULL;
+
+       for (l = uri_list; l != NULL; l = l->next)
+       {
+               gchar *uri;
+               GFile *file;
+               GFileInfo *info;
+               FileItem *item;
+
+               uri = g_strdup (gtk_recent_info_get_uri (l->data));
+               file = g_file_new_for_uri (uri);
+               info = g_file_query_info (file, "time::access,time::access-usec", G_FILE_QUERY_INFO_NONE, 
NULL, NULL);
+               g_object_unref (file);
+
+               if (info == NULL)
+               {
+                       g_free (uri);
+                       continue;
+               }
+
+               item = g_slice_new (FileItem);
+               item->uri = uri;
+               /* We query access time because gtk_recent_info_get_modified() doesn't give us the usec part 
*/
+               item->access_time.tv_sec = g_file_info_get_attribute_uint64 (info, "time::access");
+               item->access_time.tv_usec = g_file_info_get_attribute_uint32 (info, "time::access-usec");
+
+               fileitem_list = g_list_prepend (fileitem_list, item);
+               g_object_unref (info);
+       }
+
+       fileitem_list = g_list_reverse (fileitem_list);
+       return fileitem_list;
+}
+
+static GList *
+get_recent_files_list (GeditOpenDocumentSelectorStore *selector_store,
+                       GeditOpenDocumentSelector      *selector)
+{
+       GeditOpenDocumentSelectorStorePrivate *priv = selector_store->priv;
+       GList *recent_items_list;
+       GList *file_items_list;
+
+       G_LOCK (recent_files_filter_lock);
+       recent_items_list = gedit_recent_get_items (&priv->recent_config);
+       G_UNLOCK (recent_files_filter_lock);
+
+       file_items_list = convert_recent_item_list_to_fileitem_list (recent_items_list);
+       g_list_free_full (recent_items_list, (GDestroyNotify)gtk_recent_info_unref);
+
+       return file_items_list;
+}
+
+static void
+update_list_cb (GeditOpenDocumentSelectorStore *selector_store,
+                GAsyncResult                   *res,
+                gpointer                        user_data)
+{
+       GList *list;
+       GError *error;
+       PushMessage *message;
+       ListType type;
+
+       list = gedit_open_document_selector_store_update_list_finish (selector_store, res, &error);
+
+       message = g_task_get_task_data (G_TASK (res));
+       type = message->type;
+
+       switch (type)
+       {
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST:
+                       G_LOCK (store_recent_items_lock);
+
+                       gedit_open_document_selector_free_file_items_list 
(selector_store->priv->recent_items);
+                       selector_store->priv->recent_items = list;
+
+                       DEBUG_SELECTOR (g_print ("\tStore(%p): update_list_cb: Thread:%p, type:%s, 
length:%i\n",
+                                                selector_store, g_thread_self (), list_type_string[type], 
g_list_length (list)););
+
+                       G_UNLOCK (store_recent_items_lock);
+                       break;
+               default:
+                       break;
+       }
+}
+
+static void
+on_recent_manager_changed (GtkRecentManager *manager,
+                           gpointer          user_data)
+{
+       GeditOpenDocumentSelectorStore *selector_store = GEDIT_OPEN_DOCUMENT_SELECTOR_STORE (user_data);
+
+       selector_store->priv->recent_items_need_update = TRUE;
+       gedit_open_document_selector_store_update_list_async (selector_store,
+                                                             NULL,
+                                                             NULL,
+                                                             (GAsyncReadyCallback)update_list_cb,
+                                                             GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST,
+                                                             NULL);
+}
+
+static void
+gedit_open_document_selector_store_dispose (GObject *object)
+{
+       GeditOpenDocumentSelectorStore *selector_store = GEDIT_OPEN_DOCUMENT_SELECTOR_STORE (object);
+       GeditOpenDocumentSelectorStorePrivate *priv = selector_store->priv;
+
+       gedit_recent_configuration_destroy (&priv->recent_config);
+
+       if (priv->recent_items)
+       {
+               gedit_open_document_selector_free_file_items_list (priv->recent_items);
+               priv->recent_items = NULL;
+       }
+
+       G_OBJECT_CLASS (gedit_open_document_selector_store_parent_class)->dispose (object);
+}
+
+static void
+gedit_open_document_selector_store_class_init (GeditOpenDocumentSelectorStoreClass *klass)
+{
+       GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+       gobject_class->dispose = gedit_open_document_selector_store_dispose;
+}
+
+/* The order of functions pointers must be the same as in
+ * ListType enum define in ./gedit-open-document-selector-helper.h
+ */
+static GList * (*list_func [])(GeditOpenDocumentSelectorStore *selector_store,
+                               GeditOpenDocumentSelector      *selector) =
+{
+       get_local_bookmarks_list,
+       get_home_dir_list,
+       get_desktop_dir_list,
+       get_file_browser_root_dir_list,
+       get_active_doc_dir_list,
+       get_recent_files_list,
+       get_current_docs_list
+};
+
+static void
+update_list_dispatcher (GTask        *task,
+                        gpointer      source_object,
+                        gpointer      task_data,
+                        GCancellable *cancellable)
+{
+       GeditOpenDocumentSelectorStore *selector_store = source_object;
+       GeditOpenDocumentSelectorStorePrivate *priv = selector_store->priv;
+       GeditOpenDocumentSelector *selector;
+       PushMessage *message;
+       ListType type;
+       GList *file_items_list;
+
+       message = task_data;
+       selector = message->selector;
+       type = message->type;
+
+       DEBUG_SELECTOR_TIMER_DECL
+       DEBUG_SELECTOR_TIMER_NEW
+       DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: Thread:%p, type:%s\n",
+                                selector, g_thread_self (), list_type_string[type]););
+
+       /* Update the recent list only when it changes, copy otherwise but keep it the first time */
+       if (type == GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST)
+       {
+               G_LOCK (store_recent_items_lock);
+
+               if (priv->recent_items != NULL && priv->recent_items_need_update == FALSE)
+               {
+                       file_items_list = gedit_open_document_selector_copy_file_items_list 
(priv->recent_items);
+
+                       DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: recent list copy\n", 
selector););
+               }
+               else
+               {
+                       priv->recent_items_need_update = FALSE;
+                       file_items_list = get_recent_files_list (selector_store, selector);
+
+                       DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: recent list compute\n", 
selector););
+
+                       if (priv->recent_items == NULL)
+                       {
+                               priv->recent_items = gedit_open_document_selector_copy_file_items_list 
(file_items_list);
+                       }
+               }
+
+               G_UNLOCK (store_recent_items_lock);
+
+               g_task_return_pointer (task,
+                                      file_items_list,
+                                      (GDestroyNotify)gedit_open_document_selector_free_file_items_list);
+
+               DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: Thread:%p, type:%s, time:%lf\n",
+                                        selector, g_thread_self (), list_type_string[type], 
DEBUG_SELECTOR_TIMER_GET););
+               DEBUG_SELECTOR_TIMER_DESTROY
+
+               return;
+       }
+
+       if (type >= GEDIT_OPEN_DOCUMENT_SELECTOR_LIST_TYPE_NUM_OF_LISTS)
+       {
+               g_task_return_new_error (task,
+                                        GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_ERROR, TYPE_OUT_OF_RANGE,
+                                        "List Type out of range");
+               g_object_unref (task);
+               return;
+       }
+
+       /* Here we call the corresponding list creator function */
+       file_items_list = (*list_func[type]) (selector_store, selector);
+
+       DEBUG_SELECTOR (g_print ("\tStore(%p): store dispatcher: Thread:%p, type:%s, time:%lf\n",
+                                selector, g_thread_self (), list_type_string[type], 
DEBUG_SELECTOR_TIMER_GET););
+       DEBUG_SELECTOR_TIMER_DESTROY
+
+       g_task_return_pointer (task,
+                              file_items_list,
+                              (GDestroyNotify)gedit_open_document_selector_free_file_items_list);
+}
+
+GList *
+gedit_open_document_selector_store_update_list_finish (GeditOpenDocumentSelectorStore  
*open_document_selector_store,
+                                                       GAsyncResult                    *result,
+                                                       GError                         **error)
+{
+       g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (open_document_selector_store), NULL);
+       g_return_val_if_fail (g_task_is_valid (result, open_document_selector_store), NULL);
+
+       return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+void
+gedit_open_document_selector_store_update_list_async (GeditOpenDocumentSelectorStore *selector_store,
+                                                      GeditOpenDocumentSelector      *selector,
+                                                      GCancellable                   *cancellable,
+                                                      GAsyncReadyCallback             callback,
+                                                      ListType                        type,
+                                                      gpointer                        user_data)
+{
+       GTask *task;
+       PushMessage *message;
+
+       g_return_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (selector_store));
+       g_return_if_fail (selector == NULL || GEDIT_IS_OPEN_DOCUMENT_SELECTOR (selector));
+
+       message = g_new (PushMessage, 1);
+       message->selector = selector;
+       message->type = type;
+
+       task = g_task_new (selector_store, cancellable, callback, user_data);
+       g_task_set_source_tag (task, gedit_open_document_selector_store_update_list_async);
+       g_task_set_priority (task, G_PRIORITY_DEFAULT);
+       g_task_set_task_data (task, message, (GDestroyNotify)g_free);
+
+       g_task_run_in_thread (task, update_list_dispatcher);
+       g_object_unref (task);
+}
+
+static void
+gedit_open_document_selector_store_init (GeditOpenDocumentSelectorStore *open_document_selector_store)
+{
+       GeditOpenDocumentSelectorStorePrivate *priv;
+
+       open_document_selector_store->priv = gedit_open_document_selector_store_get_instance_private 
(open_document_selector_store);
+       priv = open_document_selector_store->priv;
+
+       gedit_recent_configuration_init_default (&priv->recent_config);
+       /* We remove the recent files limit since we need the whole list but
+        * we back it up as gedit_open_document_selector_store_get_recent_limit
+        * use it
+        */
+       priv->recent_config_limit = priv->recent_config.limit;
+       priv->recent_config.limit = -1;
+
+       g_signal_connect_object (priv->recent_config.manager,
+                                "changed",
+                                G_CALLBACK (on_recent_manager_changed),
+                                open_document_selector_store,
+                                0);
+
+       priv->recent_items_need_update = TRUE;
+}
+
+gint
+gedit_open_document_selector_store_get_recent_limit (GeditOpenDocumentSelectorStore *store)
+{
+       g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (store), -1);
+
+       return store->priv->recent_config_limit;
+}
+
+void
+gedit_open_document_selector_store_set_recent_filter (GeditOpenDocumentSelectorStore *store,
+                                                      gchar                          *filter)
+{
+       gchar *old_filter;
+
+       g_return_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (store));
+       g_return_if_fail (filter != NULL);
+
+       G_LOCK (recent_files_filter_lock);
+
+       old_filter = store->priv->recent_config.substring_filter;
+       store->priv->recent_config.substring_filter = filter;
+
+       G_UNLOCK (recent_files_filter_lock);
+       g_free (old_filter);
+}
+
+gchar *
+gedit_open_document_selector_store_get_recent_filter (GeditOpenDocumentSelectorStore *store)
+{
+       gchar *recent_filter;
+
+       g_return_val_if_fail (GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE (store), NULL);
+
+       G_LOCK (recent_files_filter_lock);
+       recent_filter = g_strdup (store->priv->recent_config.substring_filter);
+       G_UNLOCK (recent_files_filter_lock);
+
+       return recent_filter;
+}
+
+/* Gets a unique instance of #GeditOpenDocumentSelectorStore
+ *
+ * Returns: (transfer none): A unique #GeditOpenDocumentSelectorStore.
+ * Do not ref or unref it, it will be destroyed at the end of the application.
+ */
+GeditOpenDocumentSelectorStore *
+gedit_open_document_selector_store_get_default (void)
+{
+       static GeditOpenDocumentSelectorStore *instance;
+
+       if (instance == NULL)
+       {
+               instance = g_object_new (GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE, NULL);
+               g_object_add_weak_pointer (G_OBJECT (instance), (gpointer) &instance);
+       }
+
+       return instance;
+}
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector-store.h b/gedit/gedit-open-document-selector-store.h
new file mode 100644
index 0000000..4413635
--- /dev/null
+++ b/gedit/gedit-open-document-selector-store.h
@@ -0,0 +1,91 @@
+/*
+ * gedit-open-document-selector-store.h
+ * This file is part of gedit
+ *
+ * Copyright (C) 2015 - Sébastien Lafargue
+ *
+ * gedit is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gedit 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gedit. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_H__
+#define __GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_H__
+
+#include "gedit-open-document-selector-helper.h"
+#include "gedit-open-document-selector.h"
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE                        
(gedit_open_document_selector_store_get_type ())
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_STORE(obj)                        (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE, GeditOpenDocumentSelectorStore))
+#define GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE))
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_CONST(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE, GeditOpenDocumentSelectorStore const))
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_CLASS(klass)                (G_TYPE_CHECK_CLASS_CAST ((klass), 
GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE, GeditOpenDocumentSelectorStoreClass))
+#define GEDIT_IS_OPEN_DOCUMENT_SELECTOR_STORE_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), 
GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE))
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR_STORE, GeditOpenDocumentSelectorStoreClass))
+
+typedef struct _GeditOpenDocumentSelectorStore                 GeditOpenDocumentSelectorStore;
+typedef struct _GeditOpenDocumentSelectorStoreClass            GeditOpenDocumentSelectorStoreClass;
+typedef struct _GeditOpenDocumentSelectorStorePrivate          GeditOpenDocumentSelectorStorePrivate;
+
+struct _GeditOpenDocumentSelectorStore
+{
+       GtkBox parent;
+
+       GeditOpenDocumentSelectorStorePrivate *priv;
+};
+
+struct _GeditOpenDocumentSelectorStoreClass
+{
+       GtkBoxClass  parent_class;
+};
+
+#define GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_ERROR gedit_open_document_selector_store_error_quark ()
+
+typedef enum
+{
+       TYPE_OUT_OF_RANGE
+} GeditOpenDocumentSelectorStoreError;
+
+GQuark                          gedit_open_document_selector_store_error_quark                         
(void);
+
+GType                           gedit_open_document_selector_store_get_type                            
(void) G_GNUC_CONST;
+
+gint                            gedit_open_document_selector_store_get_recent_limit                    
(GeditOpenDocumentSelectorStore *store);
+
+void                            gedit_open_document_selector_store_set_recent_filter                   
(GeditOpenDocumentSelectorStore *store,
+                                                                                                         
gchar                          *filter);
+
+gchar                          *gedit_open_document_selector_store_get_recent_filter                   
(GeditOpenDocumentSelectorStore *store);
+
+GList                          *gedit_open_document_selector_store_update_list_finish                  
(GeditOpenDocumentSelectorStore  *open_document_selector_store,
+                                                                                                         
GAsyncResult                    *res,
+                                                                                                         
GError                         **error);
+
+void                           gedit_open_document_selector_store_update_list_async                    
(GeditOpenDocumentSelectorStore *open_document_selector_store,
+                                                                                                         
GeditOpenDocumentSelector      *open_document_selector,
+                                                                                                         
GCancellable                   *cancellable,
+                                                                                                         
GAsyncReadyCallback             callback,
+                                                                                                         
ListType                        type,
+                                                                                                         
gpointer                        user_data);
+
+GeditOpenDocumentSelectorStore *gedit_open_document_selector_store_get_default                         
(void);
+
+G_END_DECLS
+
+#endif /* __GEDIT_OPEN_DOCUMENT_SELECTOR_STORE_H__ */
+
+/* ex:set ts=8 noet: */
diff --git a/gedit/gedit-open-document-selector.c b/gedit/gedit-open-document-selector.c
index 33c51aa..913f409 100644
--- a/gedit/gedit-open-document-selector.c
+++ b/gedit/gedit-open-document-selector.c
@@ -19,7 +19,12 @@
  */
 
 #include "gedit-open-document-selector.h"
+#include "gedit-open-document-selector-store.h"
+#include "gedit-open-document-selector-helper.h"
 
+#include <time.h>
+
+#include <glib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
@@ -34,268 +39,558 @@
 struct _GeditOpenDocumentSelectorPrivate
 {
        GtkWidget *open_button;
-       GtkWidget *listbox;
+       GtkWidget *treeview;
+       GtkListStore *liststore;
+       GtkCellRenderer *name_renderer;
+       GtkCellRenderer *path_renderer;
+       GtkWidget *placeholder_box;
        GtkWidget *scrolled_window;
 
-       guint populate_listbox_id;
-
-       gint row_height;
+       GeditOpenDocumentSelectorStore *selector_store;
+       GList *recent_items;
+       GList *home_dir_items;
+       GList *desktop_dir_items;
+       GList *local_bookmarks_dir_items;
+       GList *file_browser_root_items;
+       GList *active_doc_dir_items;
+       GList *current_docs_items;
+       GList *all_items;
+
+       gint populate_liststore_is_idle : 1;
+       gint populate_scheduled : 1;
+};
 
-       GeditRecentConfiguration recent_config;
+enum
+{
+       NAME_COLUMN,
+       PATH_COLUMN,
+       URI_COLUMN,
+       N_COLUMNS
 };
 
 /* Signals */
 enum
 {
-       RECENT_FILE_ACTIVATED,
+       SELECTOR_FILE_ACTIVATED,
        LAST_SIGNAL
 };
 
-#define OPEN_DOCUMENT_SELECTOR_ROW_BOX_SPACING 4
-#define OPEN_DOCUMENT_SELECTOR_WIDTH 400
-#define OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS 10
-
 static guint signals[LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE_WITH_PRIVATE (GeditOpenDocumentSelector, gedit_open_document_selector, GTK_TYPE_BOX)
-
-
-static GtkWidget *
-create_row_layout (GeditOpenDocumentSelector *open_document_selector,
-                   const gchar               *name,
-                   const gchar               *path)
-{
-       GtkWidget *row;
-       GtkWidget *vbox;
-       GtkWidget *name_label;
-       GtkWidget *path_label;
-       GtkStyleContext *context;
-
-       row = gtk_list_box_row_new ();
-
-       context = gtk_widget_get_style_context (GTK_WIDGET (row));
-       gtk_style_context_add_class (context, "open-document-selector-listbox-row");
-
-       name_label = gtk_label_new (name);
-
-       context = gtk_widget_get_style_context (GTK_WIDGET (name_label));
-       gtk_style_context_add_class (context, "name-label");
-
-       gtk_label_set_ellipsize (GTK_LABEL (name_label), PANGO_ELLIPSIZE_END);
-       gtk_widget_set_halign (name_label, GTK_ALIGN_START);
-       gtk_widget_set_valign (name_label, GTK_ALIGN_CENTER);
-
-       path_label = gtk_label_new (path);
-
-       context = gtk_widget_get_style_context (GTK_WIDGET (path_label));
-       gtk_style_context_add_class (context, "path-label");
-       gtk_style_context_add_class (context, "dim-label");
-
-       gtk_label_set_ellipsize (GTK_LABEL (path_label), PANGO_ELLIPSIZE_START);
-       gtk_widget_set_halign (path_label, GTK_ALIGN_START);
-       gtk_widget_set_valign (path_label, GTK_ALIGN_CENTER);
-
-       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, OPEN_DOCUMENT_SELECTOR_ROW_BOX_SPACING);
-       gtk_container_add (GTK_CONTAINER (row), vbox);
-
-       gtk_box_pack_start (GTK_BOX (vbox), name_label, FALSE, FALSE, 0);
-       gtk_box_pack_start (GTK_BOX (vbox), path_label, FALSE, FALSE, 0);
-
-       gtk_widget_show_all (row);
-
-       return row;
-}
-
-static gint
-calculate_row_height (GeditOpenDocumentSelector *open_document_selector)
+enum
 {
-       GtkWidget *row;
-       gint minimum_height;
-       gint natural_height;
-
-       /* Creating a fake row to mesure its height */
-       row = create_row_layout (open_document_selector, "Fake name", "Fake Path");
+       PROP_0,
+       PROP_WINDOW
+};
 
-       gtk_widget_get_preferred_height (row, &minimum_height, &natural_height);
-       gtk_widget_destroy (row);
+#define OPEN_DOCUMENT_SELECTOR_WIDTH 400
+#define OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS 10
 
-       return natural_height;
-}
+G_DEFINE_TYPE_WITH_PRIVATE (GeditOpenDocumentSelector, gedit_open_document_selector, GTK_TYPE_BOX)
 
-static GtkWidget *
-create_row (GeditOpenDocumentSelector *open_document_selector,
-            GtkRecentInfo             *info)
+static void
+create_row (GeditOpenDocumentSelector *selector,
+            const gchar               *uri)
 {
-       GtkWidget *row;
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
+       GtkTreeIter iter;
        gchar *name;
        gchar *path;
-       gchar *uri;
        GFile *location;
 
-       uri = g_strdup (gtk_recent_info_get_uri (info));
        location = g_file_new_for_uri (uri);
 
        name = gedit_utils_basename_for_display (location);
        path = gedit_utils_location_get_dirname_for_display (location);
 
-       row = create_row_layout (open_document_selector, (const gchar*)name, (const gchar*)path);
+       gtk_list_store_append (priv->liststore, &iter);
+       gtk_list_store_set (priv->liststore, &iter,
+                           URI_COLUMN, uri,
+                           NAME_COLUMN, name,
+                           PATH_COLUMN, path,
+                           -1);
 
-       g_object_set_data (G_OBJECT(row), "uri", uri);
        g_free (name);
        g_free (path);
        g_object_unref (location);
-
-       return row;
 }
 
-static void
-dispose_row (GeditOpenDocumentSelector *open_document_selector,
-             GtkWidget                 *row)
+static gint
+sort_items_by_mru (FileItem *a,
+                   FileItem *b,
+                   gpointer  unused)
 {
-       gchar *uri;
+       glong diff;
+
+       g_assert (a != NULL && b != NULL);
+       diff = b->access_time.tv_sec - a->access_time.tv_sec;
 
-       uri = g_object_get_data (G_OBJECT(row), "uri");
-       gtk_widget_destroy (GTK_WIDGET (row));
-       g_free (uri);
+       if (diff == 0)
+       {
+               return b->access_time.tv_usec - a->access_time.tv_usec;
+       }
+       else
+       {
+               return diff;
+       }
 }
 
-static gboolean
-real_populate_listbox (gpointer data)
+static GList *
+compute_all_items_list (GeditOpenDocumentSelector *selector)
 {
-       GeditOpenDocumentSelector *open_document_selector = GEDIT_OPEN_DOCUMENT_SELECTOR (data);
-       GeditOpenDocumentSelectorPrivate *priv = open_document_selector->priv;
-       GtkWidget *row = NULL;
-       GtkRecentInfo *info;
-       GList *children, *l, *items;
-
-       g_assert (priv->recent_config.manager != NULL);
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
+       GList *recent_items;
+       GList *home_dir_items;
+       GList *desktop_dir_items;
+       GList *local_bookmarks_dir_items;
+       GList *file_browser_root_items;
+       GList *active_doc_dir_items;
+       GList *current_docs_items;
+       GList *all_items = NULL;
+
+       /* Copy/concat the whole list */
+       recent_items = gedit_open_document_selector_copy_file_items_list ((const GList *)priv->recent_items);
+       home_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)priv->home_dir_items);
+       desktop_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)priv->desktop_dir_items);
+       local_bookmarks_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)priv->local_bookmarks_dir_items);
+       file_browser_root_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)priv->file_browser_root_items);
+       active_doc_dir_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)priv->active_doc_dir_items);
+       current_docs_items = gedit_open_document_selector_copy_file_items_list ((const GList 
*)priv->current_docs_items);
+
+       all_items = g_list_concat (all_items, recent_items);
+       all_items = g_list_concat (all_items, home_dir_items);
+       all_items = g_list_concat (all_items, desktop_dir_items);
+       all_items = g_list_concat (all_items, local_bookmarks_dir_items);
+       all_items = g_list_concat (all_items, file_browser_root_items);
+       all_items = g_list_concat (all_items, active_doc_dir_items);
+       all_items = g_list_concat (all_items, current_docs_items);
+
+       return all_items;
+}
 
-       /* Clear the listbox */
-       children = gtk_container_get_children (GTK_CONTAINER (priv->listbox));
+static GList *
+clamp_recent_items_list (GList *recent_items,
+                         gint   limit)
+{
+       GList *recent_items_capped = NULL;
+       GList *l;
+       FileItem *item;
 
-       for (l = children; l != NULL; l = l->next)
+       l = recent_items;
+       while (limit > 0 && l != NULL)
        {
-               row = l->data;
-               dispose_row (open_document_selector, row);
+               item = gedit_open_document_selector_copy_fileitem_item (l->data);
+               recent_items_capped = g_list_prepend (recent_items_capped, item);
+               l = l->next;
+               limit -= 1;
        }
 
-       g_list_free (children);
+       recent_items_capped = g_list_reverse (recent_items_capped);
+       return recent_items_capped;
+}
+
+static gboolean
+real_populate_liststore (gpointer data)
+{
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (data);
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
+       GeditOpenDocumentSelectorStore *selector_store = priv->selector_store;
+       GList *l;
+       GList *filter_items = NULL;
+       gchar *filter;
+       priv->populate_liststore_is_idle = FALSE;
+
+       DEBUG_SELECTOR_TIMER_DECL
+       DEBUG_SELECTOR_TIMER_NEW
 
-       items = gedit_recent_get_items (&priv->recent_config);
+       gtk_list_store_clear (priv->liststore);
 
-       for (l = items; l != NULL; l = l->next)
+       filter = gedit_open_document_selector_store_get_recent_filter (selector_store);
+       if (filter && *filter != '\0')
        {
-               info = l->data;
-               row = create_row (open_document_selector, info);
-               gtk_recent_info_unref(info);
+               DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: all lists\n", selector););
 
-               /* add a class until gtk implements :last-child */
-               /* see https://bugzilla.gnome.org/show_bug.cgi?id=732050 */
-               if (l->next == NULL)
+               for (l = priv->all_items; l != NULL; l = l->next)
                {
-                       GtkStyleContext *context;
+                       FileItem *item;
+                       gchar *uri_lower;
+                       gchar *scheme;
+                       gint end_of_scheme_pos = 0;
+
+                       item = l->data;
+                       uri_lower = g_utf8_strdown (item->uri, -1);
+                       scheme = g_uri_parse_scheme (uri_lower);
+                       if (scheme)
+                       {
+                               end_of_scheme_pos = strlen (scheme) + 1;
+                               g_free (scheme);
+                       }
+
+                       if (strstr (uri_lower + end_of_scheme_pos, filter))
+                       {
+                               filter_items = g_list_prepend (filter_items,
+                                                              
gedit_open_document_selector_copy_fileitem_item (item));
+                       }
+
+                       g_free (uri_lower);
+               }
 
-                       context = gtk_widget_get_style_context (row);
-                       gtk_style_context_add_class (context, "last-child");
+               filter_items = g_list_sort_with_data (filter_items, (GCompareDataFunc)sort_items_by_mru, 
NULL);
+               /* Remove doubles, the HEAD of the list never change */
+               l = filter_items;
+               while (l != NULL)
+               {
+                       gchar *l_uri, *l1_uri;
+                       GList *l1;
+
+                       if ((l1 = l->next) == NULL)
+                       {
+                               break;
+                       }
+
+                       l_uri = ((FileItem *)l->data)->uri;
+                       l1_uri = ((FileItem *)l1->data)->uri;
+                       if (g_strcmp0 (l_uri, l1_uri) == 0)
+                       {
+                               gedit_open_document_selector_free_fileitem_item ((FileItem *)l1->data);
+                               filter_items = g_list_delete_link (filter_items, l1);
+                       }
+                       else
+                       {
+                               l = l->next;
+                       }
                }
+       }
+       else
+       {
+               gint recent_limit;
+
+               DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: recent files list\n", selector););
 
-               gtk_list_box_insert (GTK_LIST_BOX (priv->listbox), row, -1);
+               recent_limit = gedit_open_document_selector_store_get_recent_limit (selector_store);
+
+               if (recent_limit > 0 )
+               {
+                       filter_items = clamp_recent_items_list (priv->recent_items, recent_limit);
+               }
+               else
+               {
+                       filter_items = gedit_open_document_selector_copy_file_items_list (priv->recent_items);
+               }
        }
 
-       g_list_free (items);
-       priv->populate_listbox_id = 0;
+       g_free (filter);
+
+       DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: length:%i\n",
+                                selector, g_list_length (filter_items)););
+
+       /* Show the placeholder if no results, show the treeview otherwise */
+       gtk_widget_set_visible (priv->scrolled_window, (filter_items != NULL));
+       gtk_widget_set_visible (priv->placeholder_box, (filter_items == NULL));
 
-       return FALSE;
+       for (l = filter_items; l != NULL; l = l->next)
+       {
+               FileItem *item;
+
+               item = l->data;
+               create_row (selector, (const gchar *)item->uri);
+       }
+
+       gedit_open_document_selector_free_file_items_list (filter_items);
+
+       DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: time:%lf\n\n",
+                                 selector, DEBUG_SELECTOR_TIMER_GET););
+       DEBUG_SELECTOR_TIMER_DESTROY
+
+       if (priv->populate_scheduled == TRUE)
+       {
+               priv->populate_scheduled = FALSE;
+               return TRUE;
+       }
+       else
+       {
+               return FALSE;
+       }
 }
 
 static void
-populate_listbox (GeditOpenDocumentSelector *open_document_selector)
+populate_liststore (GeditOpenDocumentSelector *selector)
 {
-       GeditOpenDocumentSelectorPrivate *priv = open_document_selector->priv;
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
 
-       if (priv->populate_listbox_id)
+       /* Populate requests are compressed */
+       if (priv->populate_liststore_is_idle)
        {
+               DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: idle\n", selector););
+
+               priv->populate_scheduled = TRUE;
                return;
        }
 
-       priv->populate_listbox_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
-                                                              real_populate_listbox,
-                                                              open_document_selector,
-                                                              NULL);
+       DEBUG_SELECTOR (g_print ("Selector(%p): populate liststore: scheduled\n", selector););
+
+       priv->populate_liststore_is_idle = TRUE;
+       gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30, real_populate_liststore, selector, NULL);
 }
 
 static void
 on_entry_changed (GtkEntry                  *entry,
-                  GeditOpenDocumentSelector *open_document_selector)
+                  GeditOpenDocumentSelector *selector)
 {
-       GeditOpenDocumentSelectorPrivate *priv = open_document_selector->priv;
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
        const gchar *entry_text;
 
        entry_text = gtk_entry_get_text (entry);
+       gedit_open_document_selector_store_set_recent_filter (priv->selector_store,
+                                                             g_utf8_strdown (entry_text, -1));
 
-       g_free (priv->recent_config.substring_filter);
-       priv->recent_config.substring_filter = g_utf8_strdown (entry_text, -1);
-
-       populate_listbox (open_document_selector);
+       if (gtk_widget_get_mapped ( GTK_WIDGET (selector)))
+       {
+               populate_liststore (selector);
+       }
 }
 
 static void
-on_recent_manager_changed (GtkRecentManager *manager,
-                           gpointer          user_data)
+on_entry_activated (GtkEntry                  *entry,
+                    GeditOpenDocumentSelector *selector)
 {
-       GeditOpenDocumentSelector  *open_document_selector = GEDIT_OPEN_DOCUMENT_SELECTOR (user_data);
+       const gchar *entry_text;
+       GtkTreeSelection *selection;
+       gchar *uri;
+       GFile *file;
+       gchar *scheme;
+
+       entry_text = gtk_entry_get_text (entry);
+       scheme = g_uri_parse_scheme (entry_text);
+       if (!scheme)
+       {
+               const gchar *home_dir = g_get_home_dir ();
 
-       populate_listbox (open_document_selector);
+               if ( home_dir != NULL && g_str_has_prefix (entry_text, "~/"))
+               {
+                       uri = g_strconcat ("file://", home_dir, "/", entry_text + 2, NULL);
+               }
+               else
+               {
+                       uri = g_strconcat ("file://", entry_text, NULL);
+               }
+       }
+       else
+       {
+               g_free (scheme);
+               uri = g_strdup (entry_text);
+       }
+
+       file = g_file_new_for_uri (uri);
+       if (g_file_query_exists (file, NULL))
+       {
+               DEBUG_SELECTOR (g_print ("Selector(%p): search entry activated : loading '%s'\n",
+                                        selector, uri););
+
+               gtk_entry_set_text (entry, "");
+               selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (selector->priv->treeview));
+               gtk_tree_selection_unselect_all (selection);
+
+               g_signal_emit (G_OBJECT (selector), signals[SELECTOR_FILE_ACTIVATED], 0, uri);
+       }
+
+       g_object_unref (file);
 }
 
 static void
 gedit_open_document_selector_dispose (GObject *object)
 {
-       GeditOpenDocumentSelector *open_document_selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
-       GeditOpenDocumentSelectorPrivate *priv = open_document_selector->priv;
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
 
-       if (priv->populate_listbox_id)
+       while (TRUE)
        {
-               g_source_remove (priv->populate_listbox_id);
-               priv->populate_listbox_id = 0;
+               if (!g_idle_remove_by_data (selector))
+               {
+                       break;
+               }
+       }
+
+       if (priv->recent_items)
+       {
+               gedit_open_document_selector_free_file_items_list (priv->recent_items);
+               priv->recent_items = NULL;
        }
 
-       gedit_recent_configuration_destroy (&priv->recent_config);
+       if (priv->home_dir_items)
+       {
+               gedit_open_document_selector_free_file_items_list (priv->home_dir_items);
+               priv->home_dir_items = NULL;
+       }
+
+       if (priv->desktop_dir_items)
+       {
+               gedit_open_document_selector_free_file_items_list (priv->desktop_dir_items);
+               priv->desktop_dir_items = NULL;
+       }
+
+       if (priv->local_bookmarks_dir_items)
+       {
+               gedit_open_document_selector_free_file_items_list (priv->local_bookmarks_dir_items);
+               priv->local_bookmarks_dir_items = NULL;
+       }
+
+       if (priv->file_browser_root_items)
+       {
+               gedit_open_document_selector_free_file_items_list (priv->file_browser_root_items);
+               priv->file_browser_root_items = NULL;
+       }
+
+       if (priv->active_doc_dir_items)
+       {
+               gedit_open_document_selector_free_file_items_list (priv->active_doc_dir_items);
+               priv->active_doc_dir_items = NULL;
+       }
+
+       if (priv->current_docs_items)
+       {
+               gedit_open_document_selector_free_file_items_list (priv->current_docs_items);
+               priv->current_docs_items = NULL;
+       }
+
+       if (priv->all_items)
+       {
+               gedit_open_document_selector_free_file_items_list (priv->all_items);
+               priv->all_items = NULL;
+       }
 
        G_OBJECT_CLASS (gedit_open_document_selector_parent_class)->dispose (object);
 }
 
 static void
-gedit_open_document_selector_finalize (GObject *object)
+on_row_activated (GtkTreeView               *treeview,
+                  GtkTreePath               *path,
+                  GtkTreeViewColumn         *column,
+                  GeditOpenDocumentSelector *selector)
 {
-       G_OBJECT_CLASS (gedit_open_document_selector_parent_class)->finalize (object);
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
+       GtkTreeSelection *selection;
+       GtkTreeIter iter;
+       gchar *uri;
+
+       gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->liststore), &iter, path);
+       gtk_tree_model_get (GTK_TREE_MODEL (priv->liststore),
+                           &iter,
+                           URI_COLUMN, &uri,
+                           -1);
+
+       selection = gtk_tree_view_get_selection (treeview);
+       gtk_tree_selection_unselect_all (selection);
+
+       /* Leak of uri */
+       g_signal_emit (G_OBJECT (selector), signals[SELECTOR_FILE_ACTIVATED], 0, uri);
 }
 
 static void
-on_row_activated (GtkWidget                 *listbox,
-                  GtkListBoxRow             *row,
-                  GeditOpenDocumentSelector *open_document_selector)
+update_list_cb (GeditOpenDocumentSelectorStore *selector_store,
+                GAsyncResult                   *res,
+                gpointer                        user_data)
 {
-       gchar *uri;
+       GList *list;
+       GError *error;
+       PushMessage *message;
+       ListType type;
+       GeditOpenDocumentSelector *selector;
+       GeditOpenDocumentSelectorPrivate *priv;
 
-       uri = g_object_get_data (G_OBJECT (row), "uri");
+       list = gedit_open_document_selector_store_update_list_finish (selector_store, res, &error);
+       message = g_task_get_task_data (G_TASK (res));
+       selector = message->selector;
+       priv = selector->priv;
+       type = message->type;
 
-       gtk_list_box_unselect_all (GTK_LIST_BOX (listbox));
+       DEBUG_SELECTOR (g_print ("Selector(%p): update_list_cb - type:%s, length:%i\n",
+                                selector, list_type_string[type], g_list_length (list)););
+
+       switch (type)
+       {
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST:
+                       gedit_open_document_selector_free_file_items_list (priv->recent_items);
+                       priv->recent_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_HOME_DIR_LIST:
+                       gedit_open_document_selector_free_file_items_list (priv->home_dir_items);
+                       priv->home_dir_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_DESKTOP_DIR_LIST:
+                       gedit_open_document_selector_free_file_items_list (priv->desktop_dir_items);
+                       priv->desktop_dir_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_LOCAL_BOOKMARKS_DIR_LIST:
+                       gedit_open_document_selector_free_file_items_list (priv->local_bookmarks_dir_items);
+                       priv->local_bookmarks_dir_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_FILE_BROWSER_ROOT_DIR_LIST:
+                       gedit_open_document_selector_free_file_items_list (priv->file_browser_root_items);
+                       priv->file_browser_root_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_ACTIVE_DOC_DIR_LIST:
+                       gedit_open_document_selector_free_file_items_list (priv->active_doc_dir_items);
+                       priv->active_doc_dir_items = list;
+                       break;
+
+               case GEDIT_OPEN_DOCUMENT_SELECTOR_CURRENT_DOCS_LIST:
+                       gedit_open_document_selector_free_file_items_list (priv->current_docs_items);
+                       priv->current_docs_items = list;
+                       break;
+
+               default:
+                       g_return_if_reached ();
+       }
 
-       g_signal_emit (G_OBJECT (open_document_selector), signals[RECENT_FILE_ACTIVATED], 0, uri);
+       priv->all_items = compute_all_items_list (selector);
+       populate_liststore (selector);
 }
 
 static void
 gedit_open_document_selector_constructed (GObject *object)
 {
-       GeditOpenDocumentSelector *open_document_selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
-       GeditOpenDocumentSelectorPrivate *priv = open_document_selector->priv;
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
 
        G_OBJECT_CLASS (gedit_open_document_selector_parent_class)->constructed (object);
 
-       g_assert (priv->recent_config.manager);
+       DEBUG_SELECTOR (g_print ("Selector(%p): constructed - ask recent file list\n", selector););
 
-       populate_listbox (open_document_selector);
+       gedit_open_document_selector_store_update_list_async (priv->selector_store,
+                                                             selector,
+                                                             NULL,
+                                                             (GAsyncReadyCallback)update_list_cb,
+                                                             GEDIT_OPEN_DOCUMENT_SELECTOR_RECENT_FILES_LIST,
+                                                             selector);
+}
+
+static void
+gedit_open_document_selector_mapped (GtkWidget *widget)
+{
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (widget);
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
+       ListType list_number;
+
+       /* We update all the lists */
+       DEBUG_SELECTOR (g_print ("Selector(%p): mapped - ask all lists\n", selector););
+
+       for (list_number = 0; list_number < GEDIT_OPEN_DOCUMENT_SELECTOR_LIST_TYPE_NUM_OF_LISTS; 
list_number++)
+       {
+               gedit_open_document_selector_store_update_list_async (priv->selector_store,
+                                                                     selector,
+                                                                     NULL,
+                                                                     (GAsyncReadyCallback)update_list_cb,
+                                                                     list_number,
+                                                                     selector);
+       }
+
+       GTK_WIDGET_CLASS (gedit_open_document_selector_parent_class)->map (widget);
 }
 
 static GtkSizeRequestMode
@@ -313,23 +608,66 @@ gedit_open_document_selector_get_preferred_width (GtkWidget *widget,
 }
 
 static void
+gedit_open_document_selector_set_property (GObject      *object,
+                                           guint         prop_id,
+                                           const GValue *value,
+                                           GParamSpec   *pspec)
+{
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+
+       switch (prop_id)
+       {
+               case PROP_WINDOW:
+                       selector->window = g_value_get_object (value);
+                       break;
+
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                       break;
+       }
+}
+
+static void
+gedit_open_document_selector_get_property (GObject    *object,
+                                           guint       prop_id,
+                                           GValue     *value,
+                                           GParamSpec *pspec)
+{
+       GeditOpenDocumentSelector *selector = GEDIT_OPEN_DOCUMENT_SELECTOR (object);
+
+       switch (prop_id)
+       {
+               case PROP_WINDOW:
+                       g_value_set_object (value, selector->window);
+                       break;
+
+               default:
+                       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                       break;
+       }
+}
+
+static void
 gedit_open_document_selector_class_init (GeditOpenDocumentSelectorClass *klass)
 {
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
        gobject_class->constructed = gedit_open_document_selector_constructed;
-       gobject_class->finalize = gedit_open_document_selector_finalize;
        gobject_class->dispose = gedit_open_document_selector_dispose;
 
+       gobject_class->get_property = gedit_open_document_selector_get_property;
+       gobject_class->set_property = gedit_open_document_selector_set_property;
+
        widget_class->get_request_mode = gedit_open_document_selector_get_request_mode;
        widget_class->get_preferred_width = gedit_open_document_selector_get_preferred_width;
+       widget_class->map = gedit_open_document_selector_mapped;
 
-       signals[RECENT_FILE_ACTIVATED] =
-               g_signal_new ("recent-file-activated",
+       signals[SELECTOR_FILE_ACTIVATED] =
+               g_signal_new ("file-activated",
                              G_TYPE_FROM_CLASS (klass),
                              G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
-                             G_STRUCT_OFFSET (GeditOpenDocumentSelectorClass, recent_file_activated),
+                             G_STRUCT_OFFSET (GeditOpenDocumentSelectorClass, selector_file_activated),
                              NULL, NULL,
                              g_cclosure_marshal_VOID__STRING,
                              G_TYPE_NONE, 1,
@@ -339,99 +677,218 @@ gedit_open_document_selector_class_init (GeditOpenDocumentSelectorClass *klass)
                                                     "/org/gnome/gedit/ui/gedit-open-document-selector.ui");
 
        gtk_widget_class_bind_template_child_private (widget_class, GeditOpenDocumentSelector, open_button);
-       gtk_widget_class_bind_template_child_private (widget_class, GeditOpenDocumentSelector, listbox);
+       gtk_widget_class_bind_template_child_private (widget_class, GeditOpenDocumentSelector, treeview);
+       gtk_widget_class_bind_template_child_private (widget_class, GeditOpenDocumentSelector, 
placeholder_box);
        gtk_widget_class_bind_template_child_private (widget_class, GeditOpenDocumentSelector, 
scrolled_window);
        gtk_widget_class_bind_template_child (widget_class, GeditOpenDocumentSelector, recent_search_entry);
+
+       g_object_class_install_property (gobject_class,
+                                        PROP_WINDOW,
+                                        g_param_spec_object ("window",
+                                                             "Window",
+                                                             "The GeditWindow this GeditOpenDocumentSelector 
is associated with",
+                                                             GEDIT_TYPE_WINDOW,
+                                                             G_PARAM_READWRITE |
+                                                             G_PARAM_CONSTRUCT_ONLY |
+                                                             G_PARAM_STATIC_STRINGS));
 }
 
 static void
-on_listbox_allocate (GtkWidget                 *widget,
-                     GdkRectangle              *allocation,
-                     GeditOpenDocumentSelector *open_document_selector)
+on_treeview_allocate (GtkWidget                 *widget,
+                      GdkRectangle              *allocation,
+                      GeditOpenDocumentSelector *selector)
 {
-       GeditOpenDocumentSelectorPrivate *priv = open_document_selector->priv;
-       gint row_height;
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
+       GeditOpenDocumentSelectorStore *selector_store = priv->selector_store;
+       GtkStyleContext *context;
+       gint name_renderer_natural_size;
+       gint path_renderer_natural_size;
+       GtkBorder padding;
+       gint ypad;
        gint limit_capped;
-       gint listbox_height;
+       gint treeview_height;
+       gint grid_line_width;
+       gint row_height;
+       gint recent_limit;
+
+       context = gtk_widget_get_style_context (priv->treeview);
+
+       /* Treeview height computation */
+       gtk_cell_renderer_get_preferred_height (priv->name_renderer,
+                                               priv->treeview,
+                                               NULL,
+                                               &name_renderer_natural_size);
+
+       gtk_cell_renderer_get_preferred_height (priv->path_renderer,
+                                               priv->treeview,
+                                               NULL,
+                                               &path_renderer_natural_size);
+
+       gtk_style_context_get_padding (context, GTK_STATE_NORMAL, &padding);
+       gtk_cell_renderer_get_padding (priv->name_renderer, NULL, &ypad);
+       gtk_widget_style_get (priv->treeview, "grid-line-width", &grid_line_width, NULL);
 
-       row_height = calculate_row_height (open_document_selector);
-       limit_capped = MIN (priv->recent_config.limit, OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS);
-       listbox_height = row_height * limit_capped;
+       recent_limit = gedit_open_document_selector_store_get_recent_limit (selector_store);
 
+       limit_capped = (recent_limit > 0 ) ? MIN (recent_limit, OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS) :
+                                            OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS;
+
+       row_height = name_renderer_natural_size +
+                    path_renderer_natural_size +
+                    2 * (padding.top + padding.bottom) +
+                    ypad +
+                    grid_line_width;
+
+       treeview_height = row_height * limit_capped;
        gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (priv->scrolled_window),
-                                                   listbox_height - 2);
+                                                   treeview_height);
+
+       gtk_widget_set_size_request (priv->placeholder_box, -1, treeview_height);
 }
 
 static void
-gedit_open_document_selector_init (GeditOpenDocumentSelector *open_document_selector)
+name_renderer_datafunc (GtkTreeViewColumn         *column,
+                        GtkCellRenderer           *name_renderer,
+                        GtkTreeModel              *liststore,
+                        GtkTreeIter               *iter,
+                        GeditOpenDocumentSelector *selector)
 {
-       GeditOpenDocumentSelectorPrivate *priv;
-       GtkWidget *placeholder_label;
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
        GtkStyleContext *context;
-       gint row_height;
-       gint limit_capped;
-       gint listbox_height;
+       GdkRGBA label_color;
+       gdouble font_size;
 
-       gedit_debug (DEBUG_WINDOW);
+       context = gtk_widget_get_style_context (priv->treeview);
 
-       open_document_selector->priv = gedit_open_document_selector_get_instance_private 
(open_document_selector);
-       priv = open_document_selector->priv;
+       /* Name label foreground and font size styling */
+       gtk_style_context_add_class (context, "open-document-selector-name-label");
 
-       gtk_widget_init_template (GTK_WIDGET (open_document_selector));
+       gtk_style_context_get_color (context, GTK_STATE_NORMAL, &label_color);
+       g_object_set (priv->name_renderer, "foreground-rgba", &label_color, NULL);
 
-       /* gedit-open-document-selector initial state */
-       gedit_recent_configuration_init_default (&priv->recent_config);
+       gtk_style_context_get (context, GTK_STATE_NORMAL, "font-size", &font_size, NULL);
+       g_object_set (priv->name_renderer, "size-points", font_size, NULL);
 
-       g_signal_connect_object (priv->recent_config.manager,
-                                "changed",
-                                G_CALLBACK (on_recent_manager_changed),
-                                open_document_selector,
-                                0);
+       gtk_style_context_remove_class (context, "open-document-selector-name-label");
+}
 
-       priv->populate_listbox_id = 0;
+static void
+path_renderer_datafunc (GtkTreeViewColumn         *column,
+                        GtkCellRenderer           *path_renderer,
+                        GtkTreeModel              *liststore,
+                        GtkTreeIter               *iter,
+                        GeditOpenDocumentSelector *selector)
+{
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
+       GtkStyleContext *context;
+       GdkRGBA label_color;
+       gdouble font_size;
 
-       g_signal_connect (open_document_selector->recent_search_entry,
-                         "changed",
-                         G_CALLBACK (on_entry_changed),
-                         open_document_selector);
+       context = gtk_widget_get_style_context (priv->treeview);
 
-       g_signal_connect (priv->listbox,
-                         "row-activated",
-                         G_CALLBACK (on_row_activated),
-                         open_document_selector);
+       /* Path label foreground and font size styling */
+       gtk_style_context_add_class (context, "open-document-selector-path-label");
 
-       placeholder_label = gtk_label_new (_("No results"));
-       context = gtk_widget_get_style_context (GTK_WIDGET (placeholder_label));
-       gtk_style_context_add_class (context, "dim-label");
+       gtk_style_context_get_color (context, GTK_STATE_NORMAL, &label_color);
+       g_object_set (priv->path_renderer, "foreground-rgba", &label_color, NULL);
 
-       gtk_widget_set_halign (placeholder_label, GTK_ALIGN_CENTER);
-       gtk_widget_set_valign (placeholder_label, GTK_ALIGN_CENTER);
+       gtk_style_context_get (context, GTK_STATE_NORMAL, "font-size", &font_size, NULL);
+       g_object_set (priv->path_renderer, "size-points", font_size, NULL);
 
-       gtk_widget_show (placeholder_label);
-       gtk_list_box_set_placeholder (GTK_LIST_BOX (priv->listbox), placeholder_label);
+       gtk_style_context_remove_class (context, "open-document-selector-path-label");
+}
 
-       row_height = calculate_row_height (open_document_selector);
+static void
+setup_treeview (GeditOpenDocumentSelector *selector)
+{
+       GeditOpenDocumentSelectorPrivate *priv = selector->priv;
+       GtkTreeViewColumn *column;
+       GtkCellArea *cell_area;
+       GtkStyleContext *context;
 
-       limit_capped = MIN (priv->recent_config.limit, OPEN_DOCUMENT_SELECTOR_MAX_VISIBLE_ROWS);
-       listbox_height = row_height * limit_capped;
+       gtk_tree_view_set_model (GTK_TREE_VIEW (priv->treeview), GTK_TREE_MODEL (priv->liststore));
+       g_object_unref(GTK_TREE_MODEL (priv->liststore));
 
-       /* We substract 2px, no idea where they come from */
-       gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (priv->scrolled_window),
-                                                   listbox_height - 2);
+       priv->name_renderer = gtk_cell_renderer_text_new ();
+       priv->path_renderer = gtk_cell_renderer_text_new ();
 
-       context = gtk_widget_get_style_context (GTK_WIDGET (priv->listbox));
-       gtk_style_context_add_class (context, "gedit-open-document-selector-listbox");
+       g_object_set (priv->name_renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+       g_object_set (priv->path_renderer, "ellipsize", PANGO_ELLIPSIZE_START, NULL);
 
-       g_signal_connect (priv->listbox,
+       column = gtk_tree_view_column_new ();
+       gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+
+       gtk_tree_view_column_pack_start (column, priv->name_renderer, TRUE);
+       gtk_tree_view_column_pack_start (column, priv->path_renderer, TRUE);
+
+       gtk_tree_view_column_set_attributes (column, priv->name_renderer, "text", NAME_COLUMN, NULL);
+       gtk_tree_view_column_set_attributes (column, priv->path_renderer, "text", PATH_COLUMN, NULL);
+
+       gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview), column);
+       cell_area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (column));
+       gtk_orientable_set_orientation (GTK_ORIENTABLE (cell_area), GTK_ORIENTATION_VERTICAL);
+
+       context = gtk_widget_get_style_context (priv->treeview);
+       gtk_style_context_add_class (context, "open-document-selector-treeview");
+
+       gtk_tree_view_column_set_cell_data_func (column,
+                                                priv->name_renderer,
+                                                (GtkTreeCellDataFunc)name_renderer_datafunc,
+                                                selector,
+                                                NULL);
+
+       gtk_tree_view_column_set_cell_data_func (column,
+                                                priv->path_renderer,
+                                                (GtkTreeCellDataFunc)path_renderer_datafunc,
+                                                selector,
+                                                NULL);
+}
+
+static void
+gedit_open_document_selector_init (GeditOpenDocumentSelector *selector)
+{
+       GeditOpenDocumentSelectorPrivate *priv;
+
+       gedit_debug (DEBUG_WINDOW);
+
+       selector->priv = gedit_open_document_selector_get_instance_private (selector);
+       priv = selector->priv;
+
+       gtk_widget_init_template (GTK_WIDGET (selector));
+
+       priv->selector_store = gedit_open_document_selector_store_get_default ();
+
+       priv->liststore = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
+       setup_treeview (selector);
+
+       g_signal_connect (selector->recent_search_entry,
+                         "changed",
+                         G_CALLBACK (on_entry_changed),
+                         selector);
+
+       g_signal_connect (selector->recent_search_entry,
+                         "activate",
+                         G_CALLBACK (on_entry_activated),
+                         selector);
+
+       g_signal_connect (priv->treeview,
+                         "row-activated",
+                         G_CALLBACK (on_row_activated),
+                         selector);
+
+       g_signal_connect (priv->treeview,
                          "size-allocate",
-                         G_CALLBACK (on_listbox_allocate),
-                         open_document_selector);
+                         G_CALLBACK (on_treeview_allocate),
+                         selector);
 }
 
 GeditOpenDocumentSelector *
-gedit_open_document_selector_new (void)
+gedit_open_document_selector_new (GeditWindow *window)
 {
+       g_return_val_if_fail (GEDIT_IS_WINDOW (window), NULL);
+
        return g_object_new (GEDIT_TYPE_OPEN_DOCUMENT_SELECTOR,
+                            "window", window,
                             NULL);
 }
 
diff --git a/gedit/gedit-open-document-selector.h b/gedit/gedit-open-document-selector.h
index 1445456..680d9b7 100644
--- a/gedit/gedit-open-document-selector.h
+++ b/gedit/gedit-open-document-selector.h
@@ -39,27 +39,34 @@ G_BEGIN_DECLS
 typedef struct _GeditOpenDocumentSelector              GeditOpenDocumentSelector;
 typedef struct _GeditOpenDocumentSelectorClass         GeditOpenDocumentSelectorClass;
 typedef struct _GeditOpenDocumentSelectorPrivate       GeditOpenDocumentSelectorPrivate;
+typedef struct _GeditOpenDocumentSelectorClassPrivate  GeditOpenDocumentSelectorClassPrivate;
 
 struct _GeditOpenDocumentSelector
 {
        GtkBox parent;
 
+       GeditWindow *window;
        GtkWidget *recent_search_entry;
 
        GeditOpenDocumentSelectorPrivate *priv;
 };
 
+enum ListType;
+
 struct _GeditOpenDocumentSelectorClass
 {
        GtkBoxClass  parent_class;
 
        /* Signals */
-       void (* recent_file_activated)  (GeditOpenDocumentSelector *open_document_selector, gchar *uri);
+       void (* selector_file_activated)        (GeditOpenDocumentSelector *selector,
+                                                gchar                     *uri);
+
+       GeditOpenDocumentSelectorClassPrivate *priv;
 };
 
-GType gedit_open_document_selector_get_type            (void) G_GNUC_CONST;
+GType                           gedit_open_document_selector_get_type          (void) G_GNUC_CONST;
 
-GeditOpenDocumentSelector * gedit_open_document_selector_new                   (void);
+GeditOpenDocumentSelector      *gedit_open_document_selector_new               (GeditWindow *window);
 
 G_END_DECLS
 
diff --git a/gedit/gedit-recent.c b/gedit/gedit-recent.c
index 4dd783a..bcae0ac 100644
--- a/gedit/gedit-recent.c
+++ b/gedit/gedit-recent.c
@@ -173,6 +173,7 @@ gedit_recent_configuration_init_default (GeditRecentConfiguration *config)
 
        config->filter = gtk_recent_filter_new ();
        gtk_recent_filter_add_application (config->filter, g_get_application_name ());
+       gtk_recent_filter_add_mime_type (config->filter, "text/plain");
        g_object_ref_sink (config->filter);
 
        settings = g_settings_new ("org.gnome.gedit.preferences.ui");
@@ -208,6 +209,7 @@ gedit_recent_get_items (GeditRecentConfiguration *config)
        GList *items;
        GList *retitems = NULL;
        gint length;
+       gboolean has_substring_filter;
 
        if (config->limit == 0)
        {
@@ -222,6 +224,7 @@ gedit_recent_get_items (GeditRecentConfiguration *config)
        }
 
        needed = gtk_recent_filter_get_needed (config->filter);
+       has_substring_filter = (config->substring_filter && *config->substring_filter != '\0');
 
        while (items)
        {
@@ -246,7 +249,7 @@ gedit_recent_get_items (GeditRecentConfiguration *config)
                }
                else
                {
-                       if (config->substring_filter && *config->substring_filter != '\0')
+                       if (has_substring_filter)
                        {
                                gchar *uri_lower;
 
diff --git a/gedit/gedit-window.c b/gedit/gedit-window.c
index fd6f128..1f07e4a 100644
--- a/gedit/gedit-window.c
+++ b/gedit/gedit-window.c
@@ -802,7 +802,8 @@ on_recent_chooser_item_activated (GeditOpenDocumentSelector *open_document_selec
                locations = g_slist_prepend (locations, (gpointer) location);
                loaded = gedit_commands_load_locations (window, locations, NULL, 0, 0);
 
-               if (!loaded || loaded->next) /* if it doesn't contain just 1 element */
+               /* if it doesn't contain just 1 element */
+               if (!loaded || loaded->next)
                {
                        gedit_recent_remove_if_local (location);
                }
@@ -1832,7 +1833,7 @@ fullscreen_controls_setup (GeditWindow *window)
        gtk_menu_button_set_popover (GTK_MENU_BUTTON (priv->fullscreen_open_button),
                                     priv->fullscreen_open_document_popover);
 
-       window->priv->fullscreen_open_document_selector = gedit_open_document_selector_new ();
+       window->priv->fullscreen_open_document_selector = gedit_open_document_selector_new (window);
 
        gtk_container_add (GTK_CONTAINER (priv->fullscreen_open_document_popover),
                           GTK_WIDGET (priv->fullscreen_open_document_selector));
@@ -1840,7 +1841,7 @@ fullscreen_controls_setup (GeditWindow *window)
        gtk_widget_show_all (GTK_WIDGET (priv->fullscreen_open_document_selector));
 
        g_signal_connect (window->priv->fullscreen_open_document_selector,
-                         "recent-file-activated",
+                         "file-activated",
                          G_CALLBACK (on_recent_chooser_item_activated),
                          window);
 }
@@ -2773,7 +2774,7 @@ gedit_window_init (GeditWindow *window)
        gtk_menu_button_set_popover (GTK_MENU_BUTTON (window->priv->open_button),
                                     window->priv->open_document_popover);
 
-       window->priv->open_document_selector = gedit_open_document_selector_new ();
+       window->priv->open_document_selector = gedit_open_document_selector_new (window);
 
        gtk_container_add (GTK_CONTAINER (window->priv->open_document_popover),
                           GTK_WIDGET (window->priv->open_document_selector));
@@ -2781,7 +2782,7 @@ gedit_window_init (GeditWindow *window)
        gtk_widget_show_all (GTK_WIDGET (window->priv->open_document_selector));
 
        g_signal_connect (window->priv->open_document_selector,
-                         "recent-file-activated",
+                         "file-activated",
                          G_CALLBACK (on_recent_chooser_item_activated),
                          window);
 
diff --git a/gedit/resources/css/gedit.adwaita.css b/gedit/resources/css/gedit.adwaita.css
index d7d8862..f4f2129 100644
--- a/gedit/resources/css/gedit.adwaita.css
+++ b/gedit/resources/css/gedit.adwaita.css
@@ -7,20 +7,26 @@ GeditWindow .pane-separator:hover {
     color: @borders;
 }
 
-.open-document-selector-listbox-row {
-    border-bottom: 1px solid shade(@theme_bg_color, 0.95);
-    padding: 6px 6px 6px 12px;
+.open-document-selector-treeview {
+    padding: 3px 6px 3px 6px;
 }
 
-.open-document-selector-listbox-row .name-label {
-    color: @theme_fg_color;
+.open-document-selector-treeview:prelight {
+    background-color: #fafafa;
 }
 
-.open-document-selector-listbox-row .path-label {
-    font-size: smaller;
+.open-document-selector-treeview:selected:prelight {
+    background-color: @theme_selected_bg_color;
 }
 
-.open-document-selector-listbox-row:selected .path-label {
+/* Only normal state is handle */
+.open-document-selector-name-label {
+    color: @theme_fg_color;
+}
+
+/* Only normal state is handle */
+.open-document-selector-path-label {
+    color: @theme_unfocused_fg_color;
     font-size: smaller;
 }
 
diff --git a/gedit/resources/ui/gedit-open-document-selector.ui 
b/gedit/resources/ui/gedit-open-document-selector.ui
index a9c403c..1963e6f 100644
--- a/gedit/resources/ui/gedit-open-document-selector.ui
+++ b/gedit/resources/ui/gedit-open-document-selector.ui
@@ -22,6 +22,33 @@
       </packing>
     </child>
     <child>
+      <object class="GtkFrame" id="placeholder_box">
+        <property name="visible">False</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="shadow_type">in</property>
+        <child>
+          <object class="GtkLabel" id="placeholder_label">
+            <property name="visible">True</property>
+            <property name="sensitive">False</property>
+            <property name="can_focus">False</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <property name="label" translatable="yes">No results</property>
+            <style>
+              <class name="dim-label"/>
+            </style>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+    <child>
       <object class="GtkScrolledWindow" id="scrolled_window">
         <property name="visible">True</property>
         <property name="hexpand">True</property>
@@ -29,18 +56,22 @@
         <property name="hscrollbar_policy">never</property>
         <property name="shadow_type">in</property>
         <child>
-          <object class="GtkListBox" id="listbox">
+          <object class="GtkTreeView" id="treeview">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="hexpand">True</property>
             <property name="vexpand">True</property>
+            <property name="headers_visible">False</property>
+            <property name="fixed_height_mode">True</property>
+            <property name="enable_grid_lines">horizontal</property>
+            <property name="activate_on_single_click">True</property>
           </object>
         </child>
       </object>
       <packing>
         <property name="expand">True</property>
         <property name="fill">True</property>
-        <property name="position">1</property>
+        <property name="position">2</property>
       </packing>
     </child>
     <child>
@@ -59,7 +90,7 @@
       <packing>
         <property name="expand">False</property>
         <property name="fill">True</property>
-        <property name="position">2</property>
+        <property name="position">3</property>
       </packing>
     </child>
   </template>



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