docDisplay: Remove "Recent Items" search provider
Although not all "Finding and reminding" applications are ready yet, the integration with gnome-documents' search results overlaps enough with the "Recent Items" provider to justify its removal. https://bugzilla.gnome.org/show_bug.cgi?id=670150
This commit is contained in:
parent
34c6ff9645
commit
ac78a1e1c0
@ -24,7 +24,6 @@ nobase_dist_js_DATA = \
|
|||||||
gdm/systemd.js \
|
gdm/systemd.js \
|
||||||
extensionPrefs/main.js \
|
extensionPrefs/main.js \
|
||||||
misc/config.js \
|
misc/config.js \
|
||||||
misc/docInfo.js \
|
|
||||||
misc/extensionUtils.js \
|
misc/extensionUtils.js \
|
||||||
misc/fileUtils.js \
|
misc/fileUtils.js \
|
||||||
misc/format.js \
|
misc/format.js \
|
||||||
@ -49,7 +48,6 @@ nobase_dist_js_DATA = \
|
|||||||
ui/dash.js \
|
ui/dash.js \
|
||||||
ui/dateMenu.js \
|
ui/dateMenu.js \
|
||||||
ui/dnd.js \
|
ui/dnd.js \
|
||||||
ui/docDisplay.js \
|
|
||||||
ui/endSessionDialog.js \
|
ui/endSessionDialog.js \
|
||||||
ui/environment.js \
|
ui/environment.js \
|
||||||
ui/extensionSystem.js \
|
ui/extensionSystem.js \
|
||||||
|
@ -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);
|
|
@ -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);
|
|
||||||
}
|
|
||||||
});
|
|
@ -14,7 +14,6 @@ const AppDisplay = imports.ui.appDisplay;
|
|||||||
const ContactDisplay = imports.ui.contactDisplay;
|
const ContactDisplay = imports.ui.contactDisplay;
|
||||||
const Dash = imports.ui.dash;
|
const Dash = imports.ui.dash;
|
||||||
const DND = imports.ui.dnd;
|
const DND = imports.ui.dnd;
|
||||||
const DocDisplay = imports.ui.docDisplay;
|
|
||||||
const Lightbox = imports.ui.lightbox;
|
const Lightbox = imports.ui.lightbox;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const MessageTray = imports.ui.messageTray;
|
const MessageTray = imports.ui.messageTray;
|
||||||
@ -208,7 +207,6 @@ const Overview = new Lang.Class({
|
|||||||
this.addSearchProvider(new AppDisplay.AppSearchProvider());
|
this.addSearchProvider(new AppDisplay.AppSearchProvider());
|
||||||
this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
|
this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
|
||||||
this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
|
this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
|
||||||
this.addSearchProvider(new DocDisplay.DocSearchProvider());
|
|
||||||
this.addSearchProvider(new ContactDisplay.ContactSearchProvider());
|
this.addSearchProvider(new ContactDisplay.ContactSearchProvider());
|
||||||
|
|
||||||
// Load remote search providers provided by applications
|
// Load remote search providers provided by applications
|
||||||
|
@ -105,7 +105,6 @@ shell_public_headers_h = \
|
|||||||
shell-app-system.h \
|
shell-app-system.h \
|
||||||
shell-app-usage.h \
|
shell-app-usage.h \
|
||||||
shell-contact-system.h \
|
shell-contact-system.h \
|
||||||
shell-doc-system.h \
|
|
||||||
shell-embedded-window.h \
|
shell-embedded-window.h \
|
||||||
shell-generic-container.h \
|
shell-generic-container.h \
|
||||||
shell-gtk-embed.h \
|
shell-gtk-embed.h \
|
||||||
@ -152,7 +151,6 @@ libgnome_shell_la_SOURCES = \
|
|||||||
shell-app-system.c \
|
shell-app-system.c \
|
||||||
shell-app-usage.c \
|
shell-app-usage.c \
|
||||||
shell-contact-system.c \
|
shell-contact-system.c \
|
||||||
shell-doc-system.c \
|
|
||||||
shell-embedded-window.c \
|
shell-embedded-window.c \
|
||||||
shell-generic-container.c \
|
shell-generic-container.c \
|
||||||
shell-gtk-embed.c \
|
shell-gtk-embed.c \
|
||||||
|
@ -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
|
|
||||||
'%<something>' 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;
|
|
||||||
}
|
|
@ -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 <gio/gio.h>
|
|
||||||
#include <gtk/gtk.h>
|
|
||||||
|
|
||||||
#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__ */
|
|
Loading…
Reference in New Issue
Block a user