Split appDisplay and docDisplay into "model" and "view" parts
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.
This commit is contained in:
@ -7,14 +7,13 @@ const Lang = imports.lang;
|
||||
const Shell = imports.gi.Shell;
|
||||
const Signals = imports.signals;
|
||||
|
||||
const DocInfo = imports.misc.docInfo;
|
||||
const GenericDisplay = imports.ui.genericDisplay;
|
||||
const Main = imports.ui.main;
|
||||
|
||||
const ITEM_DISPLAY_ICON_MARGIN = 2;
|
||||
|
||||
/* This class represents a single display item containing information about a document.
|
||||
*
|
||||
* docInfo - GtkRecentInfo object containing information about the document
|
||||
* docInfo - DocInfo object containing information about the document
|
||||
* availableWidth - total width available for the item
|
||||
*/
|
||||
function DocDisplayItem(docInfo, availableWidth) {
|
||||
@ -28,107 +27,34 @@ DocDisplayItem.prototype = {
|
||||
GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth);
|
||||
this._docInfo = docInfo;
|
||||
|
||||
let name = docInfo.get_display_name();
|
||||
|
||||
// we can possibly display tags in the space for description in the future
|
||||
let description = "";
|
||||
|
||||
let icon = new Clutter.Texture();
|
||||
this._iconPixbuf = Shell.get_thumbnail(docInfo.get_uri(), docInfo.get_mime_type());
|
||||
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 use extra margin when positioning it.
|
||||
let scalingFactor = (GenericDisplay.ITEM_DISPLAY_ICON_SIZE - ITEM_DISPLAY_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);
|
||||
icon.x = GenericDisplay.ITEM_DISPLAY_PADDING + ITEM_DISPLAY_ICON_MARGIN;
|
||||
icon.y = GenericDisplay.ITEM_DISPLAY_PADDING + ITEM_DISPLAY_ICON_MARGIN;
|
||||
} else {
|
||||
Shell.clutter_texture_set_from_pixbuf(icon, docInfo.get_icon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE));
|
||||
icon.x = GenericDisplay.ITEM_DISPLAY_PADDING;
|
||||
icon.y = GenericDisplay.ITEM_DISPLAY_PADDING;
|
||||
}
|
||||
|
||||
this._setItemInfo(name, description, icon);
|
||||
this._setItemInfo(docInfo.name, "",
|
||||
docInfo.getIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE));
|
||||
},
|
||||
|
||||
//// Public methods ////
|
||||
|
||||
// Returns the document info associated with this display item.
|
||||
getDocInfo : function() {
|
||||
return this._docInfo;
|
||||
},
|
||||
|
||||
//// Public method overrides ////
|
||||
|
||||
// Opens a document represented by this display item.
|
||||
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 mimeType = this._docInfo.get_mime_type();
|
||||
let appInfo = Gio.app_info_get_default_for_type(mimeType, true);
|
||||
|
||||
if (appInfo != null) {
|
||||
appInfo.launch_uris([this._docInfo.get_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._docInfo.last_application();
|
||||
let [success, appExec, count, time] = this._docInfo.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._docInfo.get_uri());
|
||||
}
|
||||
}
|
||||
this._docInfo.launch();
|
||||
},
|
||||
|
||||
//// Protected method overrides ////
|
||||
|
||||
// Ensures the preview icon is created.
|
||||
_ensurePreviewIconCreated : function() {
|
||||
if (this._previewIcon)
|
||||
return;
|
||||
|
||||
this._previewIcon = new Clutter.Texture();
|
||||
if (this._iconPixbuf) {
|
||||
let scalingFactor = (GenericDisplay.PREVIEW_ICON_SIZE / Math.max(this._iconPixbuf.get_width(), this._iconPixbuf.get_height()));
|
||||
this._previewIcon.set_width(Math.ceil(this._iconPixbuf.get_width() * scalingFactor));
|
||||
this._previewIcon.set_height(Math.ceil(this._iconPixbuf.get_height() * scalingFactor));
|
||||
Shell.clutter_texture_set_from_pixbuf(this._previewIcon, this._iconPixbuf);
|
||||
} else {
|
||||
Shell.clutter_texture_set_from_pixbuf(this._previewIcon, this._docInfo.get_icon(GenericDisplay.PREVIEW_ICON_SIZE));
|
||||
}
|
||||
if (!this._previewIcon)
|
||||
this._previewIcon = this._docInfo.getIcon(GenericDisplay.PREVIEW_ICON_SIZE);
|
||||
},
|
||||
|
||||
// Creates and returns a large preview icon, but only if this._docInfo is an image file
|
||||
// and we were able to generate a pixbuf from it successfully.
|
||||
_createLargePreviewIcon : function(availableWidth, availableHeight) {
|
||||
if (this._docInfo.get_mime_type() == null || this._docInfo.get_mime_type().indexOf("image/") != 0)
|
||||
if (this._docInfo.mimeType == null || this._docInfo.mimeType.indexOf("image/") != 0)
|
||||
return null;
|
||||
|
||||
return Shell.TextureCache.get_default().load_uri_sync(this._docInfo.get_uri(), availableWidth, availableHeight);
|
||||
return Shell.TextureCache.get_default().load_uri_sync(this._docInfo.uri, availableWidth, availableHeight);
|
||||
}
|
||||
};
|
||||
|
||||
@ -170,10 +96,11 @@ DocDisplay.prototype = {
|
||||
this._allItems = {};
|
||||
let docs = this._recentManager.get_items();
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
let docInfo = docs[i];
|
||||
let docId = docInfo.get_uri();
|
||||
let recentInfo = docs[i];
|
||||
let docInfo = new DocInfo.DocInfo(recentInfo);
|
||||
|
||||
// we use GtkRecentInfo URI as an item Id
|
||||
this._allItems[docId] = docInfo;
|
||||
this._allItems[docInfo.uri] = docInfo;
|
||||
}
|
||||
this._docsStale = false;
|
||||
},
|
||||
@ -217,15 +144,8 @@ DocDisplay.prototype = {
|
||||
_compareItems : function(itemIdA, itemIdB) {
|
||||
let docA = this._allItems[itemIdA];
|
||||
let docB = this._allItems[itemIdB];
|
||||
// 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
|
||||
if (docA.get_modified() > docB.get_modified())
|
||||
return -1;
|
||||
else if (docA.get_modified() < docB.get_modified())
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
|
||||
return docB.lastVisited() - docA.lastVisited();
|
||||
},
|
||||
|
||||
// Checks if the item info can be a match for the search string by checking
|
||||
@ -238,7 +158,7 @@ DocDisplay.prototype = {
|
||||
if (search == null || search == '')
|
||||
return true;
|
||||
|
||||
let name = itemInfo.get_display_name().toLowerCase();
|
||||
let name = itemInfo.name.toLowerCase();
|
||||
if (name.indexOf(search) >= 0)
|
||||
return true;
|
||||
// TODO: we can also check doc URIs, so that
|
||||
@ -246,7 +166,7 @@ DocDisplay.prototype = {
|
||||
return false;
|
||||
},
|
||||
|
||||
// Creates a DocDisplayItem based on itemInfo, which is expected be a GtkRecentInfo object.
|
||||
// Creates a DocDisplayItem based on itemInfo, which is expected to be a DocInfo object.
|
||||
_createDisplayItem: function(itemInfo) {
|
||||
return new DocDisplayItem(itemInfo, this._columnWidth);
|
||||
}
|
||||
|
Reference in New Issue
Block a user