ViewSelector: remove the places & devices search provider
Remove the PlacesManager, its search provider and all associated code. Places search is now provided by nautilus using the external search provider API. https://bugzilla.gnome.org/show_bug.cgi?id=683506
This commit is contained in:
parent
b203a95a78
commit
f39098a4f2
@ -69,7 +69,6 @@ nobase_dist_js_DATA = \
|
|||||||
ui/overview.js \
|
ui/overview.js \
|
||||||
ui/panel.js \
|
ui/panel.js \
|
||||||
ui/panelMenu.js \
|
ui/panelMenu.js \
|
||||||
ui/placeDisplay.js \
|
|
||||||
ui/pointerWatcher.js \
|
ui/pointerWatcher.js \
|
||||||
ui/popupMenu.js \
|
ui/popupMenu.js \
|
||||||
ui/remoteSearch.js \
|
ui/remoteSearch.js \
|
||||||
|
@ -20,7 +20,6 @@ const Keyboard = imports.ui.keyboard;
|
|||||||
const MessageTray = imports.ui.messageTray;
|
const MessageTray = imports.ui.messageTray;
|
||||||
const Overview = imports.ui.overview;
|
const Overview = imports.ui.overview;
|
||||||
const Panel = imports.ui.panel;
|
const Panel = imports.ui.panel;
|
||||||
const PlaceDisplay = imports.ui.placeDisplay;
|
|
||||||
const RunDialog = imports.ui.runDialog;
|
const RunDialog = imports.ui.runDialog;
|
||||||
const Layout = imports.ui.layout;
|
const Layout = imports.ui.layout;
|
||||||
const LookingGlass = imports.ui.lookingGlass;
|
const LookingGlass = imports.ui.lookingGlass;
|
||||||
|
@ -1,412 +0,0 @@
|
|||||||
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
||||||
|
|
||||||
const GLib = imports.gi.GLib;
|
|
||||||
const Gio = imports.gi.Gio;
|
|
||||||
const Shell = imports.gi.Shell;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
const Mainloop = imports.mainloop;
|
|
||||||
const Signals = imports.signals;
|
|
||||||
const St = imports.gi.St;
|
|
||||||
|
|
||||||
const DND = imports.ui.dnd;
|
|
||||||
const Main = imports.ui.main;
|
|
||||||
const Params = imports.misc.params;
|
|
||||||
const Search = imports.ui.search;
|
|
||||||
const Util = imports.misc.util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a place object, which is most normally a bookmark entry,
|
|
||||||
* a mount/volume, or a special place like the Home Folder, Computer, and Network.
|
|
||||||
*
|
|
||||||
* @name: String title
|
|
||||||
* @iconFactory: A JavaScript callback which will create an icon texture given a size parameter
|
|
||||||
* @launch: A JavaScript callback to launch the entry
|
|
||||||
*/
|
|
||||||
const PlaceInfo = new Lang.Class({
|
|
||||||
Name: 'PlaceInfo',
|
|
||||||
|
|
||||||
_init: function(id, name, iconFactory, launch) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this._lowerName = name.toLowerCase();
|
|
||||||
this.iconFactory = iconFactory;
|
|
||||||
this.launch = launch;
|
|
||||||
},
|
|
||||||
|
|
||||||
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;
|
|
||||||
},
|
|
||||||
|
|
||||||
isRemovable: function() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Helper function to translate launch parameters into a GAppLaunchContext
|
|
||||||
function _makeLaunchContext(params)
|
|
||||||
{
|
|
||||||
params = Params.parse(params, { workspace: -1,
|
|
||||||
timestamp: 0 });
|
|
||||||
|
|
||||||
let launchContext = global.create_app_launch_context();
|
|
||||||
if (params.workspace != -1)
|
|
||||||
launchContext.set_desktop(params.workspace);
|
|
||||||
if (params.timestamp != 0)
|
|
||||||
launchContext.set_timestamp(params.timestamp);
|
|
||||||
|
|
||||||
return launchContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
const PlaceDeviceInfo = new Lang.Class({
|
|
||||||
Name: 'PlaceDeviceInfo',
|
|
||||||
Extends: PlaceInfo,
|
|
||||||
|
|
||||||
_init: function(mount) {
|
|
||||||
this._mount = mount;
|
|
||||||
this.name = mount.get_name();
|
|
||||||
this._lowerName = this.name.toLowerCase();
|
|
||||||
this.id = 'mount:' + mount.get_root().get_uri();
|
|
||||||
},
|
|
||||||
|
|
||||||
iconFactory: function(size) {
|
|
||||||
let icon = this._mount.get_icon();
|
|
||||||
return St.TextureCache.get_default().load_gicon(null, icon, size);
|
|
||||||
},
|
|
||||||
|
|
||||||
launch: function(params) {
|
|
||||||
Gio.app_info_launch_default_for_uri(this._mount.get_root().get_uri(),
|
|
||||||
_makeLaunchContext(params));
|
|
||||||
},
|
|
||||||
|
|
||||||
isRemovable: function() {
|
|
||||||
return this._mount.can_unmount();
|
|
||||||
},
|
|
||||||
|
|
||||||
remove: function() {
|
|
||||||
if (!this.isRemovable())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (this._mount.can_eject())
|
|
||||||
this._mount.eject(0, null, Lang.bind(this, this._removeFinish));
|
|
||||||
else
|
|
||||||
this._mount.unmount(0, null, Lang.bind(this, this._removeFinish));
|
|
||||||
},
|
|
||||||
|
|
||||||
_removeFinish: function(o, res, data) {
|
|
||||||
try {
|
|
||||||
if (this._mount.can_eject())
|
|
||||||
this._mount.eject_finish(res);
|
|
||||||
else
|
|
||||||
this._mount.unmount_finish(res);
|
|
||||||
} catch (e) {
|
|
||||||
let message = _("Failed to unmount '%s'").format(o.get_name());
|
|
||||||
Main.overview.setMessage(message,
|
|
||||||
Lang.bind(this, this.remove),
|
|
||||||
_("Retry"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const PlacesManager = new Lang.Class({
|
|
||||||
Name: 'PlacesManager',
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this._defaultPlaces = [];
|
|
||||||
this._mounts = [];
|
|
||||||
this._bookmarks = [];
|
|
||||||
|
|
||||||
let homeFile = Gio.file_new_for_path (GLib.get_home_dir());
|
|
||||||
let homeUri = homeFile.get_uri();
|
|
||||||
let homeLabel = Shell.util_get_label_for_uri (homeUri);
|
|
||||||
let homeIcon = Shell.util_get_icon_for_uri (homeUri);
|
|
||||||
this._home = new PlaceInfo('special:home', homeLabel,
|
|
||||||
function(size) {
|
|
||||||
return St.TextureCache.get_default().load_gicon(null, homeIcon, size);
|
|
||||||
},
|
|
||||||
function(params) {
|
|
||||||
Gio.app_info_launch_default_for_uri(homeUri, _makeLaunchContext(params));
|
|
||||||
});
|
|
||||||
|
|
||||||
let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP);
|
|
||||||
let desktopFile = Gio.file_new_for_path (desktopPath);
|
|
||||||
let desktopUri = desktopFile.get_uri();
|
|
||||||
let desktopLabel = Shell.util_get_label_for_uri (desktopUri);
|
|
||||||
let desktopIcon = Shell.util_get_icon_for_uri (desktopUri);
|
|
||||||
this._desktopMenu = new PlaceInfo('special:desktop', desktopLabel,
|
|
||||||
function(size) {
|
|
||||||
return St.TextureCache.get_default().load_gicon(null, desktopIcon, size);
|
|
||||||
},
|
|
||||||
function(params) {
|
|
||||||
Gio.app_info_launch_default_for_uri(desktopUri, _makeLaunchContext(params));
|
|
||||||
});
|
|
||||||
|
|
||||||
this._defaultPlaces.push(this._home);
|
|
||||||
this._defaultPlaces.push(this._desktopMenu);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Show devices, code more or less ported from nautilus-places-sidebar.c
|
|
||||||
*/
|
|
||||||
this._volumeMonitor = Gio.VolumeMonitor.get();
|
|
||||||
this._volumeMonitor.connect('volume-added', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('volume-removed',Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('volume-changed', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('mount-added', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('mount-changed', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._updateDevices));
|
|
||||||
this._volumeMonitor.connect('drive-changed', Lang.bind(this, this._updateDevices));
|
|
||||||
this._updateDevices();
|
|
||||||
|
|
||||||
this._bookmarksPath = GLib.build_filenamev([GLib.get_user_config_dir(), 'gtk-3.0', 'bookmarks']);
|
|
||||||
this._bookmarksFile = Gio.file_new_for_path(this._bookmarksPath);
|
|
||||||
this._monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
|
|
||||||
this._bookmarkTimeoutId = 0;
|
|
||||||
this._monitor.connect('changed', Lang.bind(this, function () {
|
|
||||||
if (this._bookmarkTimeoutId > 0)
|
|
||||||
return;
|
|
||||||
/* Defensive event compression */
|
|
||||||
this._bookmarkTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function () {
|
|
||||||
this._bookmarkTimeoutId = 0;
|
|
||||||
this._reloadBookmarks();
|
|
||||||
return false;
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
|
|
||||||
this._reloadBookmarks();
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateDevices: function() {
|
|
||||||
this._mounts = [];
|
|
||||||
|
|
||||||
/* first go through all connected drives */
|
|
||||||
let drives = this._volumeMonitor.get_connected_drives();
|
|
||||||
for (let i = 0; i < drives.length; i++) {
|
|
||||||
let volumes = drives[i].get_volumes();
|
|
||||||
for(let j = 0; j < volumes.length; j++) {
|
|
||||||
let mount = volumes[j].get_mount();
|
|
||||||
if(mount != null) {
|
|
||||||
this._addMount(mount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add all volumes that is not associated with a drive */
|
|
||||||
let volumes = this._volumeMonitor.get_volumes();
|
|
||||||
for(let i = 0; i < volumes.length; i++) {
|
|
||||||
if(volumes[i].get_drive() != null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let mount = volumes[i].get_mount();
|
|
||||||
if(mount != null) {
|
|
||||||
this._addMount(mount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
|
|
||||||
let mounts = this._volumeMonitor.get_mounts();
|
|
||||||
for(let i = 0; i < mounts.length; i++) {
|
|
||||||
if(mounts[i].is_shadowed())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(mounts[i].get_volume())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
this._addMount(mounts[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We emit two signals, one for a generic 'all places' update
|
|
||||||
* and the other for one specific to mounts. We do this because
|
|
||||||
* clients like PlaceDisplay may only care about places in general
|
|
||||||
* being updated while clients like DashPlaceDisplay care which
|
|
||||||
* specific type of place got updated.
|
|
||||||
*/
|
|
||||||
this.emit('mounts-updated');
|
|
||||||
this.emit('places-updated');
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
_reloadBookmarks: function() {
|
|
||||||
|
|
||||||
this._bookmarks = [];
|
|
||||||
|
|
||||||
if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let bookmarksContent = Shell.get_file_contents_utf8_sync(this._bookmarksPath);
|
|
||||||
|
|
||||||
let bookmarks = bookmarksContent.split('\n');
|
|
||||||
|
|
||||||
let bookmarksToLabel = {};
|
|
||||||
let bookmarksOrder = [];
|
|
||||||
for (let i = 0; i < bookmarks.length; i++) {
|
|
||||||
let bookmarkLine = bookmarks[i];
|
|
||||||
let components = bookmarkLine.split(' ');
|
|
||||||
let bookmark = components[0];
|
|
||||||
if (bookmark in bookmarksToLabel)
|
|
||||||
continue;
|
|
||||||
let label = null;
|
|
||||||
if (components.length > 1)
|
|
||||||
label = components.slice(1).join(' ');
|
|
||||||
bookmarksToLabel[bookmark] = label;
|
|
||||||
bookmarksOrder.push(bookmark);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < bookmarksOrder.length; i++) {
|
|
||||||
let bookmark = bookmarksOrder[i];
|
|
||||||
let label = bookmarksToLabel[bookmark];
|
|
||||||
let file = Gio.file_new_for_uri(bookmark);
|
|
||||||
if (!file.query_exists(null))
|
|
||||||
continue;
|
|
||||||
if (label == null)
|
|
||||||
label = Shell.util_get_label_for_uri(bookmark);
|
|
||||||
if (label == null)
|
|
||||||
continue;
|
|
||||||
let icon = Shell.util_get_icon_for_uri(bookmark);
|
|
||||||
|
|
||||||
let item = new PlaceInfo('bookmark:' + bookmark, label,
|
|
||||||
function(size) {
|
|
||||||
return St.TextureCache.get_default().load_gicon(null, icon, size);
|
|
||||||
},
|
|
||||||
function(params) {
|
|
||||||
Gio.app_info_launch_default_for_uri(bookmark, _makeLaunchContext(params));
|
|
||||||
});
|
|
||||||
this._bookmarks.push(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See comment in _updateDevices for explanation why there are two signals. */
|
|
||||||
this.emit('bookmarks-updated');
|
|
||||||
this.emit('places-updated');
|
|
||||||
},
|
|
||||||
|
|
||||||
_addMount: function(mount) {
|
|
||||||
let devItem = new PlaceDeviceInfo(mount);
|
|
||||||
this._mounts.push(devItem);
|
|
||||||
},
|
|
||||||
|
|
||||||
getAllPlaces: function () {
|
|
||||||
return this.getDefaultPlaces().concat(this.getBookmarks(), this.getMounts());
|
|
||||||
},
|
|
||||||
|
|
||||||
getDefaultPlaces: function () {
|
|
||||||
return this._defaultPlaces;
|
|
||||||
},
|
|
||||||
|
|
||||||
getBookmarks: function () {
|
|
||||||
return this._bookmarks;
|
|
||||||
},
|
|
||||||
|
|
||||||
getMounts: function () {
|
|
||||||
return this._mounts;
|
|
||||||
},
|
|
||||||
|
|
||||||
_lookupIndexById: function(sourceArray, id) {
|
|
||||||
for (let i = 0; i < sourceArray.length; i++) {
|
|
||||||
let place = sourceArray[i];
|
|
||||||
if (place.id == id)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
lookupPlaceById: function(id) {
|
|
||||||
let colonIdx = id.indexOf(':');
|
|
||||||
let type = id.substring(0, colonIdx);
|
|
||||||
let sourceArray = null;
|
|
||||||
if (type == 'special')
|
|
||||||
sourceArray = this._defaultPlaces;
|
|
||||||
else if (type == 'mount')
|
|
||||||
sourceArray = this._mounts;
|
|
||||||
else if (type == 'bookmark')
|
|
||||||
sourceArray = this._bookmarks;
|
|
||||||
return sourceArray[this._lookupIndexById(sourceArray, id)];
|
|
||||||
},
|
|
||||||
|
|
||||||
_removeById: function(sourceArray, id) {
|
|
||||||
sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Signals.addSignalMethods(PlacesManager.prototype);
|
|
||||||
|
|
||||||
const PlaceSearchProvider = new Lang.Class({
|
|
||||||
Name: 'PlaceSearchProvider',
|
|
||||||
Extends: Search.SearchProvider,
|
|
||||||
|
|
||||||
_init: function() {
|
|
||||||
this.parent(_("PLACES & DEVICES"));
|
|
||||||
this.placesManager = new PlacesManager();
|
|
||||||
},
|
|
||||||
|
|
||||||
getResultMetas: function(resultIds, callback) {
|
|
||||||
let metas = [];
|
|
||||||
for (let i = 0; i < resultIds.length; i++) {
|
|
||||||
let placeInfo = this.placesManager.lookupPlaceById(resultIds[i]);
|
|
||||||
if (!placeInfo)
|
|
||||||
metas.push(null);
|
|
||||||
else
|
|
||||||
metas.push({ 'id': resultIds[i],
|
|
||||||
'name': placeInfo.name,
|
|
||||||
'createIcon': function(size) {
|
|
||||||
return placeInfo.iconFactory(size);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
callback(metas);
|
|
||||||
},
|
|
||||||
|
|
||||||
activateResult: function(id, params) {
|
|
||||||
let placeInfo = this.placesManager.lookupPlaceById(id);
|
|
||||||
placeInfo.launch(params);
|
|
||||||
},
|
|
||||||
|
|
||||||
_compareResultMeta: function (idA, idB) {
|
|
||||||
let infoA = this.placesManager.lookupPlaceById(idA);
|
|
||||||
let infoB = this.placesManager.lookupPlaceById(idB);
|
|
||||||
return infoA.name.localeCompare(infoB.name);
|
|
||||||
},
|
|
||||||
|
|
||||||
_searchPlaces: function(places, terms) {
|
|
||||||
let prefixResults = [];
|
|
||||||
let substringResults = [];
|
|
||||||
|
|
||||||
terms = terms.map(String.toLowerCase);
|
|
||||||
|
|
||||||
for (let i = 0; i < places.length; i++) {
|
|
||||||
let place = places[i];
|
|
||||||
let mtype = place.matchTerms(terms);
|
|
||||||
if (mtype == Search.MatchType.PREFIX)
|
|
||||||
prefixResults.push(place.id);
|
|
||||||
else if (mtype == Search.MatchType.SUBSTRING)
|
|
||||||
substringResults.push(place.id);
|
|
||||||
}
|
|
||||||
prefixResults.sort(Lang.bind(this, this._compareResultMeta));
|
|
||||||
substringResults.sort(Lang.bind(this, this._compareResultMeta));
|
|
||||||
|
|
||||||
this.searchSystem.pushResults(this, prefixResults.concat(substringResults));
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialResultSet: function(terms) {
|
|
||||||
let places = this.placesManager.getAllPlaces();
|
|
||||||
this._searchPlaces(places, terms);
|
|
||||||
},
|
|
||||||
|
|
||||||
getSubsearchResultSet: function(previousResults, terms) {
|
|
||||||
let places = previousResults.map(Lang.bind(this, function(id) {
|
|
||||||
return this.placesManager.lookupPlaceById(id);
|
|
||||||
}));
|
|
||||||
this._searchPlaces(places, terms);
|
|
||||||
}
|
|
||||||
});
|
|
@ -11,7 +11,6 @@ const St = imports.gi.St;
|
|||||||
|
|
||||||
const AppDisplay = imports.ui.appDisplay;
|
const AppDisplay = imports.ui.appDisplay;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const PlaceDisplay = imports.ui.placeDisplay;
|
|
||||||
const RemoteSearch = imports.ui.remoteSearch;
|
const RemoteSearch = imports.ui.remoteSearch;
|
||||||
const Search = imports.ui.search;
|
const Search = imports.ui.search;
|
||||||
const SearchDisplay = imports.ui.searchDisplay;
|
const SearchDisplay = imports.ui.searchDisplay;
|
||||||
@ -98,7 +97,6 @@ const ViewSelector = new Lang.Class({
|
|||||||
this.addSearchProvider(new Wanda.WandaSearchProvider());
|
this.addSearchProvider(new Wanda.WandaSearchProvider());
|
||||||
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());
|
|
||||||
|
|
||||||
// Load remote search providers provided by applications
|
// Load remote search providers provided by applications
|
||||||
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
|
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
|
||||||
|
365
src/shell-util.c
365
src/shell-util.c
@ -19,371 +19,6 @@
|
|||||||
#include <systemd/sd-login.h>
|
#include <systemd/sd-login.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Some code in this file adapted under the GPLv2+ from:
|
|
||||||
*
|
|
||||||
* GNOME panel utils: gnome-panel/gnome-panel/panel-util.c
|
|
||||||
* (C) 1997, 1998, 1999, 2000 The Free Software Foundation
|
|
||||||
* Copyright 2000 Helix Code, Inc.
|
|
||||||
* Copyright 2000,2001 Eazel, Inc.
|
|
||||||
* Copyright 2001 George Lebl
|
|
||||||
* Copyright 2002 Sun Microsystems Inc.
|
|
||||||
*
|
|
||||||
* Authors: George Lebl
|
|
||||||
* Jacob Berkman
|
|
||||||
* Mark McLoughlin
|
|
||||||
*/
|
|
||||||
|
|
||||||
static GFile *
|
|
||||||
shell_util_get_gfile_root (GFile *file)
|
|
||||||
{
|
|
||||||
GFile *parent;
|
|
||||||
GFile *parent_old;
|
|
||||||
|
|
||||||
/* search for the root on the URI */
|
|
||||||
parent_old = g_object_ref (file);
|
|
||||||
parent = g_file_get_parent (file);
|
|
||||||
while (parent != NULL)
|
|
||||||
{
|
|
||||||
g_object_unref (parent_old);
|
|
||||||
parent_old = parent;
|
|
||||||
parent = g_file_get_parent (parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent_old;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
shell_util_get_file_display_name_if_mount (GFile *file)
|
|
||||||
{
|
|
||||||
GFile *compare;
|
|
||||||
GVolumeMonitor *monitor;
|
|
||||||
GList *mounts, *l;
|
|
||||||
char *ret;
|
|
||||||
|
|
||||||
ret = NULL;
|
|
||||||
|
|
||||||
/* compare with all mounts */
|
|
||||||
monitor = g_volume_monitor_get ();
|
|
||||||
mounts = g_volume_monitor_get_mounts (monitor);
|
|
||||||
for (l = mounts; l != NULL; l = l->next)
|
|
||||||
{
|
|
||||||
GMount *mount;
|
|
||||||
mount = G_MOUNT(l->data);
|
|
||||||
compare = g_mount_get_root (mount);
|
|
||||||
if (!ret && g_file_equal (file, compare))
|
|
||||||
ret = g_mount_get_name (mount);
|
|
||||||
g_object_unref (mount);
|
|
||||||
}
|
|
||||||
g_list_free (mounts);
|
|
||||||
g_object_unref (monitor);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
shell_util_get_file_display_for_common_files (GFile *file)
|
|
||||||
{
|
|
||||||
GFile *compare;
|
|
||||||
|
|
||||||
compare = g_file_new_for_path (g_get_home_dir ());
|
|
||||||
if (g_file_equal (file, compare))
|
|
||||||
{
|
|
||||||
g_object_unref (compare);
|
|
||||||
/* Translators: this is the same string as the one found in
|
|
||||||
* nautilus */
|
|
||||||
return g_strdup (_("Home"));
|
|
||||||
}
|
|
||||||
g_object_unref (compare);
|
|
||||||
|
|
||||||
compare = g_file_new_for_path ("/");
|
|
||||||
if (g_file_equal (file, compare))
|
|
||||||
{
|
|
||||||
g_object_unref (compare);
|
|
||||||
/* Translators: this is the same string as the one found in
|
|
||||||
* nautilus */
|
|
||||||
return g_strdup (_("File System"));
|
|
||||||
}
|
|
||||||
g_object_unref (compare);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
shell_util_get_file_description (GFile *file)
|
|
||||||
{
|
|
||||||
GFileInfo *info;
|
|
||||||
char *ret;
|
|
||||||
|
|
||||||
ret = NULL;
|
|
||||||
|
|
||||||
info = g_file_query_info (file, "standard::description",
|
|
||||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
|
|
||||||
|
|
||||||
if (info)
|
|
||||||
{
|
|
||||||
ret = g_strdup (g_file_info_get_attribute_string(info,
|
|
||||||
G_FILE_ATTRIBUTE_STANDARD_DESCRIPTION));
|
|
||||||
g_object_unref (info);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
shell_util_get_file_display_name (GFile *file, gboolean use_fallback)
|
|
||||||
{
|
|
||||||
GFileInfo *info;
|
|
||||||
char *ret;
|
|
||||||
|
|
||||||
ret = NULL;
|
|
||||||
|
|
||||||
info = g_file_query_info (file, "standard::display-name",
|
|
||||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL);
|
|
||||||
|
|
||||||
if (info)
|
|
||||||
{
|
|
||||||
ret = g_strdup (g_file_info_get_display_name (info));
|
|
||||||
g_object_unref (info);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ret && use_fallback)
|
|
||||||
{
|
|
||||||
/* can happen with URI schemes non supported by gvfs */
|
|
||||||
char *basename;
|
|
||||||
|
|
||||||
basename = g_file_get_basename (file);
|
|
||||||
ret = g_filename_display_name (basename);
|
|
||||||
g_free (basename);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GIcon *
|
|
||||||
shell_util_get_file_icon_if_mount (GFile *file)
|
|
||||||
{
|
|
||||||
GFile *compare;
|
|
||||||
GVolumeMonitor *monitor;
|
|
||||||
GList *mounts, *l;
|
|
||||||
GIcon *ret;
|
|
||||||
|
|
||||||
ret = NULL;
|
|
||||||
|
|
||||||
/* compare with all mounts */
|
|
||||||
monitor = g_volume_monitor_get ();
|
|
||||||
mounts = g_volume_monitor_get_mounts (monitor);
|
|
||||||
for (l = mounts; l != NULL; l = l->next)
|
|
||||||
{
|
|
||||||
GMount *mount;
|
|
||||||
mount = G_MOUNT (l->data);
|
|
||||||
compare = g_mount_get_root (mount);
|
|
||||||
if (!ret && g_file_equal (file, compare))
|
|
||||||
{
|
|
||||||
ret = g_mount_get_icon (mount);
|
|
||||||
}
|
|
||||||
g_object_unref (mount);
|
|
||||||
}
|
|
||||||
g_list_free (mounts);
|
|
||||||
g_object_unref (monitor);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
shell_util_get_icon_for_uri_known_folders (const char *uri)
|
|
||||||
{
|
|
||||||
const char *icon;
|
|
||||||
char *path;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
icon = NULL;
|
|
||||||
|
|
||||||
if (!g_str_has_prefix (uri, "file:"))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
path = g_filename_from_uri (uri, NULL, NULL);
|
|
||||||
|
|
||||||
len = strlen (path);
|
|
||||||
if (path[len] == '/')
|
|
||||||
path[len] = '\0';
|
|
||||||
|
|
||||||
if (strcmp (path, "/") == 0)
|
|
||||||
icon = "drive-harddisk";
|
|
||||||
else if (strcmp (path, g_get_home_dir ()) == 0)
|
|
||||||
icon = "user-home";
|
|
||||||
else if (strcmp (path, g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP))
|
|
||||||
== 0)
|
|
||||||
icon = "user-desktop";
|
|
||||||
|
|
||||||
g_free (path);
|
|
||||||
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is based on nautilus_compute_title_for_uri() and
|
|
||||||
* nautilus_file_get_display_name_nocopy() */
|
|
||||||
char *
|
|
||||||
shell_util_get_label_for_uri (const char *text_uri)
|
|
||||||
{
|
|
||||||
GFile *file;
|
|
||||||
char *label;
|
|
||||||
GFile *root;
|
|
||||||
char *root_display;
|
|
||||||
|
|
||||||
/* Here's what we do:
|
|
||||||
* + x-nautilus-search: URI
|
|
||||||
* + check if the URI is a mount
|
|
||||||
* + if file: URI:
|
|
||||||
* - check for known file: URI
|
|
||||||
* - check for description of the GFile
|
|
||||||
* - use display name of the GFile
|
|
||||||
* + else:
|
|
||||||
* - check for description of the GFile
|
|
||||||
* - if the URI is a root: "root displayname"
|
|
||||||
* - else: "root displayname: displayname"
|
|
||||||
*/
|
|
||||||
|
|
||||||
label = NULL;
|
|
||||||
|
|
||||||
//FIXME: see nautilus_query_to_readable_string() to have a nice name
|
|
||||||
if (g_str_has_prefix (text_uri, "x-nautilus-search:"))
|
|
||||||
return g_strdup (_("Search"));
|
|
||||||
|
|
||||||
file = g_file_new_for_uri (text_uri);
|
|
||||||
|
|
||||||
label = shell_util_get_file_display_name_if_mount (file);
|
|
||||||
if (label)
|
|
||||||
{
|
|
||||||
g_object_unref (file);
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_str_has_prefix (text_uri, "file:"))
|
|
||||||
{
|
|
||||||
label = shell_util_get_file_display_for_common_files (file);
|
|
||||||
if (!label)
|
|
||||||
label = shell_util_get_file_description (file);
|
|
||||||
if (!label)
|
|
||||||
label = shell_util_get_file_display_name (file, TRUE);
|
|
||||||
g_object_unref (file);
|
|
||||||
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
label = shell_util_get_file_description (file);
|
|
||||||
if (label)
|
|
||||||
{
|
|
||||||
g_object_unref (file);
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
root = shell_util_get_gfile_root (file);
|
|
||||||
root_display = shell_util_get_file_description (root);
|
|
||||||
if (!root_display)
|
|
||||||
root_display = shell_util_get_file_display_name (root, FALSE);
|
|
||||||
if (!root_display)
|
|
||||||
/* can happen with URI schemes non supported by gvfs */
|
|
||||||
root_display = g_file_get_uri_scheme (root);
|
|
||||||
|
|
||||||
if (g_file_equal (file, root))
|
|
||||||
label = root_display;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *displayname;
|
|
||||||
|
|
||||||
displayname = shell_util_get_file_display_name (file, TRUE);
|
|
||||||
/* Translators: the first string is the name of a gvfs
|
|
||||||
* method, and the second string is a path. For
|
|
||||||
* example, "Trash: some-directory". It means that the
|
|
||||||
* directory called "some-directory" is in the trash.
|
|
||||||
*/
|
|
||||||
label = g_strdup_printf (_("%1$s: %2$s"),
|
|
||||||
root_display, displayname);
|
|
||||||
g_free (root_display);
|
|
||||||
g_free (displayname);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_unref (root);
|
|
||||||
g_object_unref (file);
|
|
||||||
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* shell_util_get_icon_for_uri:
|
|
||||||
* @text_uri: A URI
|
|
||||||
*
|
|
||||||
* Look up the icon that should be associated with a given URI. Handles
|
|
||||||
* various special GNOME-internal cases like x-nautilus-search, etc.
|
|
||||||
*
|
|
||||||
* Return Value: (transfer full): A new #GIcon
|
|
||||||
*/
|
|
||||||
GIcon *
|
|
||||||
shell_util_get_icon_for_uri (const char *text_uri)
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
GFile *file;
|
|
||||||
GFileInfo *info;
|
|
||||||
GIcon *retval;
|
|
||||||
|
|
||||||
/* Here's what we do:
|
|
||||||
* + check for known file: URI
|
|
||||||
* + x-nautilus-search: URI
|
|
||||||
* + override burn: URI icon
|
|
||||||
* + check if the URI is a mount
|
|
||||||
* + override trash: URI icon for subfolders
|
|
||||||
* + check for application/x-gnome-saved-search mime type and override
|
|
||||||
* icon of the GFile
|
|
||||||
* + use icon of the GFile
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* this only checks file: URI */
|
|
||||||
name = shell_util_get_icon_for_uri_known_folders (text_uri);
|
|
||||||
if (name)
|
|
||||||
return g_themed_icon_new (name);
|
|
||||||
|
|
||||||
if (g_str_has_prefix (text_uri, "x-nautilus-search:"))
|
|
||||||
return g_themed_icon_new ("folder-saved-search");
|
|
||||||
|
|
||||||
/* gvfs doesn't give us a nice icon, so overriding */
|
|
||||||
if (g_str_has_prefix (text_uri, "burn:"))
|
|
||||||
return g_themed_icon_new ("nautilus-cd-burner");
|
|
||||||
|
|
||||||
file = g_file_new_for_uri (text_uri);
|
|
||||||
|
|
||||||
retval = shell_util_get_file_icon_if_mount (file);
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
/* gvfs doesn't give us a nice icon for subfolders of the trash, so
|
|
||||||
* overriding */
|
|
||||||
if (g_str_has_prefix (text_uri, "trash:"))
|
|
||||||
{
|
|
||||||
GFile *root;
|
|
||||||
|
|
||||||
root = shell_util_get_gfile_root (file);
|
|
||||||
g_object_unref (file);
|
|
||||||
file = root;
|
|
||||||
}
|
|
||||||
|
|
||||||
info = g_file_query_info (file, "standard::icon", G_FILE_QUERY_INFO_NONE,
|
|
||||||
NULL, NULL);
|
|
||||||
g_object_unref (file);
|
|
||||||
|
|
||||||
if (!info)
|
|
||||||
return g_themed_icon_new ("gtk-file");
|
|
||||||
|
|
||||||
retval = g_file_info_get_icon (info);
|
|
||||||
if (retval)
|
|
||||||
g_object_ref (retval);
|
|
||||||
g_object_unref (info);
|
|
||||||
|
|
||||||
if (retval)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
return g_themed_icon_new ("gtk-file");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stop_pick (ClutterActor *actor,
|
stop_pick (ClutterActor *actor,
|
||||||
const ClutterColor *color)
|
const ClutterColor *color)
|
||||||
|
@ -10,9 +10,6 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
char *shell_util_get_label_for_uri (const char *text_uri);
|
|
||||||
GIcon *shell_util_get_icon_for_uri (const char *text_uri);
|
|
||||||
|
|
||||||
void shell_util_set_hidden_from_pick (ClutterActor *actor,
|
void shell_util_set_hidden_from_pick (ClutterActor *actor,
|
||||||
gboolean hidden);
|
gboolean hidden);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user