diff --git a/js/Makefile.am b/js/Makefile.am index 67806178e..7850460b1 100644 --- a/js/Makefile.am +++ b/js/Makefile.am @@ -24,7 +24,6 @@ nobase_dist_js_DATA = \ gdm/systemd.js \ extensionPrefs/main.js \ misc/config.js \ - misc/docInfo.js \ misc/extensionUtils.js \ misc/fileUtils.js \ misc/format.js \ @@ -49,7 +48,6 @@ nobase_dist_js_DATA = \ ui/dash.js \ ui/dateMenu.js \ ui/dnd.js \ - ui/docDisplay.js \ ui/endSessionDialog.js \ ui/environment.js \ ui/extensionSystem.js \ diff --git a/js/misc/docInfo.js b/js/misc/docInfo.js deleted file mode 100644 index 1c7db19fe..000000000 --- a/js/misc/docInfo.js +++ /dev/null @@ -1,136 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -const St = imports.gi.St; -const Shell = imports.gi.Shell; -const Lang = imports.lang; -const Signals = imports.signals; -const Search = imports.ui.search; - -const THUMBNAIL_ICON_MARGIN = 2; - -const DocInfo = new Lang.Class({ - Name: 'DocInfo', - - _init : function(recentInfo) { - this.recentInfo = recentInfo; - // We actually used get_modified() instead of get_visited() - // here, as GtkRecentInfo doesn't updated get_visited() - // correctly. See http://bugzilla.gnome.org/show_bug.cgi?id=567094 - this.timestamp = recentInfo.get_modified(); - this.name = recentInfo.get_display_name(); - this._lowerName = this.name.toLowerCase(); - this.uri = recentInfo.get_uri(); - this.mimeType = recentInfo.get_mime_type(); - }, - - createIcon : function(size) { - return St.TextureCache.get_default().load_recent_thumbnail(size, this.recentInfo); - }, - - launch : function(workspaceIndex) { - Shell.DocSystem.get_default().open(this.recentInfo, workspaceIndex); - }, - - matchTerms: function(terms) { - let mtype = Search.MatchType.NONE; - for (let i = 0; i < terms.length; i++) { - let term = terms[i]; - let idx = this._lowerName.indexOf(term); - if (idx == 0) { - mtype = Search.MatchType.PREFIX; - } else if (idx > 0) { - if (mtype == Search.MatchType.NONE) - mtype = Search.MatchType.SUBSTRING; - } else { - return Search.MatchType.NONE; - } - } - return mtype; - } -}); - -var docManagerInstance = null; - -function getDocManager() { - if (docManagerInstance == null) - docManagerInstance = new DocManager(); - return docManagerInstance; -} - -/** - * DocManager wraps the DocSystem, primarily to expose DocInfo objects. - */ -const DocManager = new Lang.Class({ - Name: 'DocManager', - - _init: function() { - this._docSystem = Shell.DocSystem.get_default(); - this._infosByTimestamp = []; - this._infosByUri = {}; - this._docSystem.connect('changed', Lang.bind(this, this._reload)); - this._reload(); - }, - - _reload: function() { - let docs = this._docSystem.get_all(); - this._infosByTimestamp = []; - this._infosByUri = {}; - for (let i = 0; i < docs.length; i++) { - let recentInfo = docs[i]; - - let docInfo = new DocInfo(recentInfo); - this._infosByTimestamp.push(docInfo); - this._infosByUri[docInfo.uri] = docInfo; - } - this.emit('changed'); - }, - - getTimestampOrderedInfos: function() { - return this._infosByTimestamp; - }, - - getInfosByUri: function() { - return this._infosByUri; - }, - - lookupByUri: function(uri) { - return this._infosByUri[uri]; - }, - - queueExistenceCheck: function(count) { - return this._docSystem.queue_existence_check(count); - }, - - _searchDocs: function(items, terms) { - let multiplePrefixMatches = []; - let prefixMatches = []; - let multipleSubtringMatches = []; - let substringMatches = []; - for (let i = 0; i < items.length; i++) { - let item = items[i]; - let mtype = item.matchTerms(terms); - if (mtype == Search.MatchType.MULTIPLE_PREFIX) - multiplePrefixMatches.push(item.uri); - else if (mtype == Search.MatchType.PREFIX) - prefixMatches.push(item.uri); - else if (mtype == Search.MatchType.MULTIPLE_SUBSTRING) - multipleSubtringMatches.push(item.uri); - else if (mtype == Search.MatchType.SUBSTRING) - substringMatches.push(item.uri); - } - return multiplePrefixMatches.concat(prefixMatches.concat(multipleSubtringMatches.concat(substringMatches))); - }, - - initialSearch: function(terms) { - return this._searchDocs(this._infosByTimestamp, terms); - }, - - subsearch: function(previousResults, terms) { - return this._searchDocs(previousResults.map(Lang.bind(this, - function(url) { - return this._infosByUri[url]; - })), terms); - } -}); - -Signals.addSignalMethods(DocManager.prototype); diff --git a/js/ui/docDisplay.js b/js/ui/docDisplay.js deleted file mode 100644 index dc840dafe..000000000 --- a/js/ui/docDisplay.js +++ /dev/null @@ -1,49 +0,0 @@ -// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- - -const DocInfo = imports.misc.docInfo; -const Lang = imports.lang; -const Params = imports.misc.params; -const Search = imports.ui.search; - -const DocSearchProvider = new Lang.Class({ - Name: 'DocSearchProvider', - Extends: Search.SearchProvider, - - _init: function(name) { - this.parent(_("RECENT ITEMS")); - this._docManager = DocInfo.getDocManager(); - }, - - getResultMetas: function(resultIds) { - let metas = []; - for (let i = 0; i < resultIds.length; i++) { - let docInfo = this._docManager.lookupByUri(resultIds[i]); - if (!docInfo) - metas.push(null); - else - metas.push({ 'id': resultIds[i], - 'name': docInfo.name, - 'createIcon': function(size) { - return docInfo.createIcon(size); - } - }); - } - return metas; - }, - - activateResult: function(id, params) { - params = Params.parse(params, { workspace: -1, - timestamp: 0 }); - - let docInfo = this._docManager.lookupByUri(id); - docInfo.launch(params.workspace); - }, - - getInitialResultSet: function(terms) { - return this._docManager.initialSearch(terms); - }, - - getSubsearchResultSet: function(previousResults, terms) { - return this._docManager.subsearch(previousResults, terms); - } -}); diff --git a/js/ui/overview.js b/js/ui/overview.js index 9db4c3d1d..b274a8c8b 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -14,7 +14,6 @@ const AppDisplay = imports.ui.appDisplay; const ContactDisplay = imports.ui.contactDisplay; const Dash = imports.ui.dash; const DND = imports.ui.dnd; -const DocDisplay = imports.ui.docDisplay; const Lightbox = imports.ui.lightbox; const Main = imports.ui.main; const MessageTray = imports.ui.messageTray; @@ -208,7 +207,6 @@ const Overview = new Lang.Class({ this.addSearchProvider(new AppDisplay.AppSearchProvider()); this.addSearchProvider(new AppDisplay.SettingsSearchProvider()); this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider()); - this.addSearchProvider(new DocDisplay.DocSearchProvider()); this.addSearchProvider(new ContactDisplay.ContactSearchProvider()); // Load remote search providers provided by applications diff --git a/src/Makefile.am b/src/Makefile.am index b512b41bd..d67f4fa19 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -105,7 +105,6 @@ shell_public_headers_h = \ shell-app-system.h \ shell-app-usage.h \ shell-contact-system.h \ - shell-doc-system.h \ shell-embedded-window.h \ shell-generic-container.h \ shell-gtk-embed.h \ @@ -152,7 +151,6 @@ libgnome_shell_la_SOURCES = \ shell-app-system.c \ shell-app-usage.c \ shell-contact-system.c \ - shell-doc-system.c \ shell-embedded-window.c \ shell-generic-container.c \ shell-gtk-embed.c \ diff --git a/src/shell-doc-system.c b/src/shell-doc-system.c deleted file mode 100644 index adb2dd162..000000000 --- a/src/shell-doc-system.c +++ /dev/null @@ -1,368 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#include "config.h" - -#include "shell-doc-system.h" - -#include "shell-global.h" - - -/** - * SECTION:shell-doc-system - * @short_description: Track recently used documents - * - * Wraps #GtkRecentManager, caching recently used document information, and adds - * APIs for asynchronous queries. - */ -enum { - CHANGED, - DELETED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -struct _ShellDocSystemPrivate { - GtkRecentManager *manager; - GHashTable *infos_by_uri; - GSList *infos_by_timestamp; - - guint idle_recent_changed_id; - - GHashTable *deleted_infos; - guint idle_emit_deleted_id; -}; - -G_DEFINE_TYPE(ShellDocSystem, shell_doc_system, G_TYPE_OBJECT); - -/** - * shell_doc_system_get_all: - * @system: A #ShellDocSystem - * - * Returns the currently cached set of recent files. Recent files are read initially - * from the underlying #GtkRecentManager, and updated when it changes. - * This function does not perform I/O. - * - * Returns: (transfer none) (element-type GtkRecentInfo): Cached recent file infos - */ -GSList * -shell_doc_system_get_all (ShellDocSystem *self) -{ - return self->priv->infos_by_timestamp; -} - -/** - * shell_doc_system_lookup_by_uri: - * @system: A #ShellDocSystem - * @uri: URI - * - * Returns: (transfer none): Recent file info corresponding to given @uri - */ -GtkRecentInfo * -shell_doc_system_lookup_by_uri (ShellDocSystem *system, - const char *uri) -{ - return g_hash_table_lookup (system->priv->infos_by_uri, uri); -} - -static gboolean -shell_doc_system_idle_emit_deleted (gpointer data) -{ - ShellDocSystem *self = SHELL_DOC_SYSTEM (data); - GHashTableIter iter; - gpointer key, value; - - self->priv->idle_emit_deleted_id = 0; - - g_hash_table_iter_init (&iter, self->priv->deleted_infos); - - while (g_hash_table_iter_next (&iter, &key, &value)) - { - GtkRecentInfo *info = key; - g_signal_emit (self, signals[DELETED], 0, info); - } - - g_signal_emit (self, signals[CHANGED], 0); - - return FALSE; -} - -typedef struct { - ShellDocSystem *self; - GtkRecentInfo *info; -} ShellDocSystemRecentQueryData; - -static void -on_recent_file_query_result (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - ShellDocSystemRecentQueryData *data = user_data; - ShellDocSystem *self = data->self; - GError *error = NULL; - GFileInfo *fileinfo; - - fileinfo = g_file_query_info_finish (G_FILE (source), result, &error); - if (fileinfo) - g_object_unref (fileinfo); - /* This is a strict error check; we don't want to cause recent files to - * vanish for anything potentially transient. - */ - if (error != NULL && error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_FOUND) - { - self->priv->infos_by_timestamp = g_slist_remove (self->priv->infos_by_timestamp, data->info); - g_hash_table_remove (self->priv->infos_by_uri, gtk_recent_info_get_uri (data->info)); - - g_hash_table_insert (self->priv->deleted_infos, gtk_recent_info_ref (data->info), NULL); - - if (self->priv->idle_emit_deleted_id == 0) - self->priv->idle_emit_deleted_id = g_timeout_add (0, shell_doc_system_idle_emit_deleted, self); - } - g_clear_error (&error); - - gtk_recent_info_unref (data->info); - g_free (data); -} - -/** - * shell_doc_system_queue_existence_check: - * @system: A #ShellDocSystem - * @n_items: Count of items to check for existence, starting from most recent - * - * Asynchronously start a check of a number of recent file for existence; - * any deleted files will be emitted from the #ShellDocSystem::deleted - * signal. Note that this function ignores non-local files; they - * will simply always appear to exist (until they are removed from - * the recent file list manually). - * - * The intent of this function is to be called after a #ShellDocSystem::changed - * signal has been emitted, and a display has shown a subset of those files. - */ -void -shell_doc_system_queue_existence_check (ShellDocSystem *self, - guint n_items) -{ - GSList *iter; - guint i; - - for (i = 0, iter = self->priv->infos_by_timestamp; i < n_items && iter; i++, iter = iter->next) - { - GtkRecentInfo *info = iter->data; - const char *uri; - GFile *file; - ShellDocSystemRecentQueryData *data; - - if (!gtk_recent_info_is_local (info)) - continue; - - data = g_new0 (ShellDocSystemRecentQueryData, 1); - data->self = self; - data->info = gtk_recent_info_ref (info); - - uri = gtk_recent_info_get_uri (info); - file = g_file_new_for_uri (uri); - - g_file_query_info_async (file, "standard::type", G_FILE_QUERY_INFO_NONE, - G_PRIORITY_DEFAULT, NULL, on_recent_file_query_result, data); - g_object_unref (file); - } -} - -static int -sort_infos_by_timestamp_descending (gconstpointer a, - gconstpointer b) -{ - GtkRecentInfo *info_a = (GtkRecentInfo*)a; - GtkRecentInfo *info_b = (GtkRecentInfo*)b; - time_t modified_a, modified_b; - - modified_a = gtk_recent_info_get_modified (info_a); - modified_b = gtk_recent_info_get_modified (info_b); - - return modified_b - modified_a; -} - -static gboolean -idle_handle_recent_changed (gpointer data) -{ - ShellDocSystem *self = SHELL_DOC_SYSTEM (data); - GList *items, *iter; - - self->priv->idle_recent_changed_id = 0; - - g_hash_table_remove_all (self->priv->deleted_infos); - g_hash_table_remove_all (self->priv->infos_by_uri); - g_slist_free (self->priv->infos_by_timestamp); - self->priv->infos_by_timestamp = NULL; - - items = gtk_recent_manager_get_items (self->priv->manager); - for (iter = items; iter; iter = iter->next) - { - GtkRecentInfo *info = iter->data; - const char *uri = gtk_recent_info_get_uri (info); - - /* uri is owned by the info */ - g_hash_table_insert (self->priv->infos_by_uri, (char*) uri, info); - - self->priv->infos_by_timestamp = g_slist_prepend (self->priv->infos_by_timestamp, info); - } - g_list_free (items); - - self->priv->infos_by_timestamp = g_slist_sort (self->priv->infos_by_timestamp, sort_infos_by_timestamp_descending); - - g_signal_emit (self, signals[CHANGED], 0); - - return FALSE; -} - -static void -shell_doc_system_on_recent_changed (GtkRecentManager *manager, - ShellDocSystem *self) -{ - if (self->priv->idle_recent_changed_id != 0) - return; - self->priv->idle_recent_changed_id = g_timeout_add (0, idle_handle_recent_changed, self); -} - -/** - * shell_doc_system_open: - * @system: A #ShellDocSystem - * @info: A #GtkRecentInfo - * @workspace: Open on this workspace, or -1 for default - * - * Launch the default application associated with the mime type of - * @info, using its uri. - */ -void -shell_doc_system_open (ShellDocSystem *system, - GtkRecentInfo *info, - int workspace) -{ - GFile *file; - GAppInfo *app_info; - gboolean needs_uri; - GAppLaunchContext *context; - - context = shell_global_create_app_launch_context (shell_global_get ()); - if (workspace != -1) - gdk_app_launch_context_set_desktop ((GdkAppLaunchContext *)context, workspace); - - file = g_file_new_for_uri (gtk_recent_info_get_uri (info)); - needs_uri = g_file_get_path (file) == NULL; - g_object_unref (file); - - app_info = g_app_info_get_default_for_type (gtk_recent_info_get_mime_type (info), needs_uri); - if (app_info != NULL) - { - GList *uris; - uris = g_list_prepend (NULL, (gpointer)gtk_recent_info_get_uri (info)); - g_app_info_launch_uris (app_info, uris, context, NULL); - g_list_free (uris); - } - else - { - char *app_name; - const char *app_exec; - char *app_exec_quoted; - guint count; - time_t time; - - app_name = gtk_recent_info_last_application (info); - if (gtk_recent_info_get_application_info (info, app_name, &app_exec, &count, &time)) - { - GRegex *regex; - - /* TODO: Change this once better support for creating - GAppInfo is added to GtkRecentInfo, as right now - this relies on the fact that the file uri is - already a part of appExec, so we don't supply any - files to app_info.launch(). - - The 'command line' passed to - create_from_command_line is allowed to contain - '%' macros that are expanded to file - name / icon name, etc, so we need to escape % as %% - */ - - regex = g_regex_new ("%", 0, 0, NULL); - app_exec_quoted = g_regex_replace (regex, app_exec, -1, 0, "%%", 0, NULL); - g_regex_unref (regex); - - app_info = g_app_info_create_from_commandline (app_exec_quoted, NULL, 0, NULL); - g_free (app_exec_quoted); - - /* The point of passing an app launch context to - launch() is mostly to get startup notification and - associated benefits like the app appearing on the - right desktop; but it doesn't really work for now - because with the way we create the appInfo we - aren't reading the application's desktop file, and - thus don't find the StartupNotify=true in it. So, - despite passing the app launch context, no startup - notification occurs. - */ - g_app_info_launch (app_info, NULL, context, NULL); - } - - g_free (app_name); - } - - g_object_unref (context); -} - -static void -shell_doc_system_class_init(ShellDocSystemClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *)klass; - - signals[CHANGED] = - g_signal_new ("changed", - SHELL_TYPE_DOC_SYSTEM, - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[DELETED] = - g_signal_new ("deleted", - SHELL_TYPE_DOC_SYSTEM, - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, GTK_TYPE_RECENT_INFO); - - g_type_class_add_private (gobject_class, sizeof (ShellDocSystemPrivate)); -} - -static void -shell_doc_system_init (ShellDocSystem *self) -{ - ShellDocSystemPrivate *priv; - - self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - SHELL_TYPE_DOC_SYSTEM, - ShellDocSystemPrivate); - self->priv->manager = gtk_recent_manager_get_default (); - - self->priv->deleted_infos = g_hash_table_new_full (NULL, NULL, (GDestroyNotify)gtk_recent_info_unref, NULL); - self->priv->infos_by_uri = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify)gtk_recent_info_unref); - - g_signal_connect (self->priv->manager, "changed", G_CALLBACK(shell_doc_system_on_recent_changed), self); - shell_doc_system_on_recent_changed (self->priv->manager, self); -} - -/** - * shell_doc_system_get_default: - * - * Return Value: (transfer none): The global #ShellDocSystem singleton - */ -ShellDocSystem * -shell_doc_system_get_default () -{ - static ShellDocSystem *instance = NULL; - - if (instance == NULL) - instance = g_object_new (SHELL_TYPE_DOC_SYSTEM, NULL); - - return instance; -} diff --git a/src/shell-doc-system.h b/src/shell-doc-system.h deleted file mode 100644 index 077bc1a6c..000000000 --- a/src/shell-doc-system.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -#ifndef __SHELL_DOC_SYSTEM_H__ -#define __SHELL_DOC_SYSTEM_H__ - -#include -#include - -#define SHELL_TYPE_DOC_SYSTEM (shell_doc_system_get_type ()) -#define SHELL_DOC_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_DOC_SYSTEM, ShellDocSystem)) -#define SHELL_DOC_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_DOC_SYSTEM, ShellDocSystemClass)) -#define SHELL_IS_DOC_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_DOC_SYSTEM)) -#define SHELL_IS_DOC_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_DOC_SYSTEM)) -#define SHELL_DOC_SYSTEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_DOC_SYSTEM, ShellDocSystemClass)) - -typedef struct _ShellDocSystem ShellDocSystem; -typedef struct _ShellDocSystemClass ShellDocSystemClass; -typedef struct _ShellDocSystemPrivate ShellDocSystemPrivate; - -struct _ShellDocSystem -{ - GObject parent; - - ShellDocSystemPrivate *priv; -}; - -struct _ShellDocSystemClass -{ - GObjectClass parent_class; -}; - -GType shell_doc_system_get_type (void) G_GNUC_CONST; - -ShellDocSystem* shell_doc_system_get_default (void); - -GSList *shell_doc_system_get_all (ShellDocSystem *system); - -GtkRecentInfo *shell_doc_system_lookup_by_uri (ShellDocSystem *system, - const char *uri); - -void shell_doc_system_queue_existence_check (ShellDocSystem *system, - guint n_items); - -void shell_doc_system_open (ShellDocSystem *system, - GtkRecentInfo *info, - int workspace); - -#endif /* __SHELL_DOC_SYSTEM_H__ */