a3d35af444
This lets us share the recent-app-tracking, recent-file-tracking, and icon-drawing code between the overlay and the sidebar, without the sidebar having to poke into AppDisplayItem and DocDisplayItem's guts.
113 lines
4.6 KiB
JavaScript
113 lines
4.6 KiB
JavaScript
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
|
const Clutter = imports.gi.Clutter;
|
|
const Gio = imports.gi.Gio;
|
|
const Gtk = imports.gi.Gtk;
|
|
const Shell = imports.gi.Shell;
|
|
|
|
const Main = imports.ui.main;
|
|
|
|
const THUMBNAIL_ICON_MARGIN = 2;
|
|
|
|
function DocInfo(recentInfo) {
|
|
this._init(recentInfo);
|
|
}
|
|
|
|
DocInfo.prototype = {
|
|
_init : function(recentInfo) {
|
|
this._recentInfo = recentInfo;
|
|
this.name = recentInfo.get_display_name();
|
|
this.uri = recentInfo.get_uri();
|
|
this.mimeType = recentInfo.get_mime_type();
|
|
|
|
this._iconPixbuf = Shell.get_thumbnail(this.uri, this.mimeType);
|
|
},
|
|
|
|
getIcon : function(size) {
|
|
let icon = new Clutter.Texture();
|
|
|
|
if (this._iconPixbuf) {
|
|
// We calculate the width and height of the texture so as
|
|
// to preserve the aspect ratio of the thumbnail. Because
|
|
// the images generated based on thumbnails don't have an
|
|
// internal padding like system icons do, we create a
|
|
// slightly smaller texture and then create a group around
|
|
// it for padding purposes
|
|
|
|
let scalingFactor = (size - THUMBNAIL_ICON_MARGIN * 2) / Math.max(this._iconPixbuf.get_width(), this._iconPixbuf.get_height());
|
|
icon.set_width(Math.ceil(this._iconPixbuf.get_width() * scalingFactor));
|
|
icon.set_height(Math.ceil(this._iconPixbuf.get_height() * scalingFactor));
|
|
Shell.clutter_texture_set_from_pixbuf(icon, this._iconPixbuf);
|
|
|
|
let group = new Clutter.Group({ width: size,
|
|
height: size });
|
|
group.add_actor(icon);
|
|
icon.set_position(THUMBNAIL_ICON_MARGIN, THUMBNAIL_ICON_MARGIN);
|
|
return group;
|
|
} else {
|
|
Shell.clutter_texture_set_from_pixbuf(icon, this._recentInfo.get_icon(size));
|
|
return icon;
|
|
}
|
|
},
|
|
|
|
launch : function() {
|
|
// While using Gio.app_info_launch_default_for_uri() would be
|
|
// shorter in terms of lines of code, we are not doing so
|
|
// because that would duplicate the work of retrieving the
|
|
// mime type.
|
|
|
|
let appInfo = Gio.app_info_get_default_for_type(this.mimeType, true);
|
|
|
|
if (appInfo != null) {
|
|
appInfo.launch_uris([this.uri], Main.createAppLaunchContext());
|
|
} else {
|
|
log("Failed to get default application info for mime type " + mimeType +
|
|
". Will try to use the last application that registered the document.");
|
|
let appName = this._recentInfo.last_application();
|
|
let [success, appExec, count, time] = this._recentInfo.get_application_info(appName);
|
|
if (success) {
|
|
log("Will open a document with the following command: " + appExec);
|
|
// 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 appInfo.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 %%
|
|
appExec = appExec.replace(/%/g, "%%");
|
|
|
|
let appInfo = Gio.app_info_create_from_commandline(appExec, null, 0, null);
|
|
|
|
// 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.
|
|
appInfo.launch([], Main.createAppLaunchContext());
|
|
} else {
|
|
log("Failed to get application info for " + this.uri);
|
|
}
|
|
}
|
|
},
|
|
|
|
exists : function() {
|
|
return this._recentInfo.exists();
|
|
},
|
|
|
|
lastVisited : function() {
|
|
// 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
|
|
|
|
return this._recentInfo.get_modified();
|
|
}
|
|
};
|