Add sections to the all apps view
Separate out the main app view into different sections based on the categories in the desktop file. The configuration is done via gmenu and the desktop menu specification, we set XDG_MENU_PREFIX="gs-" on startup, so that gmenu reads gs-applications.menu, which we install. There is no support for "submenus" - only the menus directly under Applications will be displayed as categories. https://bugzilla.gnome.org/show_bug.cgi?id=614131
This commit is contained in:
parent
ccbf247970
commit
3d60245b18
@ -40,6 +40,7 @@ dist_theme_DATA = \
|
||||
theme/section-back.svg \
|
||||
theme/section-more.svg \
|
||||
theme/section-more-open.svg \
|
||||
theme/separator-white.png \
|
||||
theme/single-view-active.svg \
|
||||
theme/single-view.svg \
|
||||
theme/ws-switch-arrow-left.svg \
|
||||
@ -49,12 +50,18 @@ dist_theme_DATA = \
|
||||
schemadir = @GCONF_SCHEMA_FILE_DIR@
|
||||
schema_DATA = gnome-shell.schemas
|
||||
|
||||
menudir = $(sysconfdir)/xdg/menus
|
||||
|
||||
menu_DATA = \
|
||||
gs-applications.menu
|
||||
|
||||
install-data-local:
|
||||
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$(schema_DATA)
|
||||
|
||||
EXTRA_DIST = \
|
||||
gnome-shell.desktop.in.in \
|
||||
gnome-shell-clock-preferences.desktop.in.in \
|
||||
$(menu_DATA) \
|
||||
$(schema_DATA)
|
||||
|
||||
CLEANFILES = \
|
||||
|
36
data/gs-applications.menu
Normal file
36
data/gs-applications.menu
Normal file
@ -0,0 +1,36 @@
|
||||
<Menu>
|
||||
<Name>Applications</Name>
|
||||
<DefaultAppDirs/>
|
||||
<Menu>
|
||||
<Name>Games</Name>
|
||||
<Include>
|
||||
<And>
|
||||
<Category>Game</Category>
|
||||
</And>
|
||||
</Include>
|
||||
</Menu>
|
||||
<Menu>
|
||||
<Name>Tools</Name>
|
||||
<Include>
|
||||
<Category>Development</Category>
|
||||
<And>
|
||||
<Category>System</Category>
|
||||
<Not>
|
||||
<Category>Settings</Category>
|
||||
</Not>
|
||||
</And>
|
||||
<Category>Utility</Category>
|
||||
</Include>
|
||||
</Menu>
|
||||
<Menu>
|
||||
<Name>Other</Name>
|
||||
<OnlyUnallocated/>
|
||||
<Include>
|
||||
<And>
|
||||
<Not><Category>Core</Category></Not>
|
||||
<Not><Category>Settings</Category></Not>
|
||||
<Not><Category>Screensaver</Category></Not>
|
||||
</And>
|
||||
</Include>
|
||||
</Menu>
|
||||
</Menu>
|
@ -520,6 +520,16 @@ StTooltip {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.app-section-divider-container {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.app-section-divider {
|
||||
height: 2px;
|
||||
background-image: url("separator-white.png");
|
||||
}
|
||||
|
||||
.all-app-controls-panel {
|
||||
height: 30px;
|
||||
}
|
||||
|
BIN
data/theme/separator-white.png
Normal file
BIN
data/theme/separator-white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 531 B |
@ -24,12 +24,12 @@ const APPICON_SIZE = 48;
|
||||
const WELL_MAX_COLUMNS = 8;
|
||||
const MENU_POPUP_TIMEOUT = 600;
|
||||
|
||||
function AllAppView() {
|
||||
function AlphabeticalView() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
AllAppView.prototype = {
|
||||
_init: function(apps) {
|
||||
AlphabeticalView.prototype = {
|
||||
_init: function() {
|
||||
this.actor = new St.BoxLayout({ vertical: true });
|
||||
this._grid = new WellGrid(true);
|
||||
this._appSystem = Shell.AppSystem.get_default();
|
||||
@ -71,7 +71,67 @@ AllAppView.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(AllAppView.prototype);
|
||||
Signals.addSignalMethods(AlphabeticalView.prototype);
|
||||
|
||||
function ViewByCategories() {
|
||||
this._init();
|
||||
}
|
||||
|
||||
ViewByCategories.prototype = {
|
||||
_init: function() {
|
||||
this._appSystem = Shell.AppSystem.get_default();
|
||||
this.actor = new St.BoxLayout({ vertical: true });
|
||||
this.actor._delegate = this;
|
||||
this._sections = [];
|
||||
},
|
||||
|
||||
_updateSections: function(apps) {
|
||||
this._removeAll();
|
||||
|
||||
let sections = this._appSystem.get_sections();
|
||||
if (!sections)
|
||||
return;
|
||||
for (let i = 0; i < sections.length; i++) {
|
||||
if (i) {
|
||||
let actor = new St.Bin({ style_class: 'app-section-divider' });
|
||||
let divider = new St.Bin({ style_class: 'app-section-divider-container',
|
||||
child: actor,
|
||||
x_fill: true });
|
||||
|
||||
this.actor.add(divider, { y_fill: false, expand: true });
|
||||
}
|
||||
let _apps = apps.filter(function(app) {
|
||||
return app.get_section() == sections[i];
|
||||
});
|
||||
this._sections[i] = { view: new AlphabeticalView(),
|
||||
apps: _apps,
|
||||
name: sections[i] };
|
||||
this._sections[i].view.connect('launching', Lang.bind(this, function() {
|
||||
this.emit('launching');
|
||||
}));
|
||||
this._sections[i].view.connect('drag-begin', Lang.bind(this, function() {
|
||||
this.emit('drag-begin');
|
||||
}));
|
||||
this.actor.add(this._sections[i].view.actor, { y_align: St.Align.START, expand: true });
|
||||
}
|
||||
},
|
||||
|
||||
_removeAll: function() {
|
||||
this.actor.destroy_children();
|
||||
this._sections.forEach(function (section) { section.view.disconnectAll(); });
|
||||
|
||||
this._sections = [];
|
||||
},
|
||||
|
||||
refresh: function(apps) {
|
||||
this._updateSections(apps);
|
||||
for (let i = 0; i < this._sections.length; i++) {
|
||||
this._sections[i].view.refresh(this._sections[i].apps);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Signals.addSignalMethods(ViewByCategories.prototype);
|
||||
|
||||
/* This class represents a display containing a collection of application items.
|
||||
* The applications are sorted based on their name.
|
||||
@ -100,7 +160,7 @@ AllAppDisplay.prototype = {
|
||||
this.actor.add(bin);
|
||||
this.actor.add(view, { expand: true, y_fill: false, y_align: St.Align.START });
|
||||
|
||||
this._appView = new AllAppView();
|
||||
this._appView = new ViewByCategories();
|
||||
this._appView.connect('launching', Lang.bind(this, this.close));
|
||||
this._appView.connect('drag-begin', Lang.bind(this, this.close));
|
||||
this._scrollView.add_actor(this._appView.actor);
|
||||
|
@ -149,6 +149,7 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
|
||||
static void
|
||||
gnome_shell_plugin_init (GnomeShellPlugin *shell_plugin)
|
||||
{
|
||||
g_setenv ("XDG_MENU_PREFIX", "gs-", TRUE);
|
||||
meta_prefs_override_preference_location ("/apps/metacity/general/button_layout",
|
||||
"/desktop/gnome/shell/windows/button_layout");
|
||||
}
|
||||
|
@ -156,6 +156,7 @@ def start_shell(perf_output=None):
|
||||
env = dict(os.environ)
|
||||
env.update({'GNOME_SHELL_JS' : '@GJS_JS_DIR@:@GJS_JS_NATIVE_DIR@:' + js_dir,
|
||||
'PATH' : '@MUTTER_BIN_DIR@:' + os.environ.get('PATH', ''),
|
||||
'XDG_CONFIG_DIRS' : '@sysconfdir@/xdg:' + os.environ.get('XDG_CONFIG_DIRS', ''),
|
||||
'GNOME_DISABLE_CRASH_DIALOG' : '1'})
|
||||
|
||||
if running_from_source_tree:
|
||||
|
@ -1109,10 +1109,84 @@ shell_app_info_get_icon (ShellAppInfo *info)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GSList *
|
||||
shell_app_info_get_categories (ShellAppInfo *info)
|
||||
/**
|
||||
* shell_app_system_get_sections:
|
||||
*
|
||||
* return names of sections in applications menu.
|
||||
*
|
||||
* Returns: (element-type utf8) (transfer full): List of Names
|
||||
*/
|
||||
GList *
|
||||
shell_app_system_get_sections (ShellAppSystem *system)
|
||||
{
|
||||
return NULL; /* TODO */
|
||||
GList *res = NULL;
|
||||
GSList *i, *contents;
|
||||
GMenuTreeDirectory *root;
|
||||
|
||||
root = gmenu_tree_get_root_directory (system->priv->apps_tree);
|
||||
|
||||
if (G_UNLIKELY (!root))
|
||||
g_error ("applications.menu not found.");
|
||||
|
||||
contents = gmenu_tree_directory_get_contents (root);
|
||||
|
||||
for (i = contents; i; i = i->next)
|
||||
{
|
||||
GMenuTreeItem *item = i->data;
|
||||
if (gmenu_tree_item_get_type (item) == GMENU_TREE_ITEM_DIRECTORY)
|
||||
{
|
||||
char *name = g_strdup (gmenu_tree_directory_get_name ((GMenuTreeDirectory*)item));
|
||||
|
||||
g_assert (name);
|
||||
|
||||
res = g_list_append (res, name);
|
||||
}
|
||||
gmenu_tree_item_unref (item);
|
||||
}
|
||||
|
||||
g_slist_free (contents);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* shell_app_info_get_section:
|
||||
*
|
||||
* return name of section, that contain this application.
|
||||
* Returns: (transfer full): section name
|
||||
*/
|
||||
char *
|
||||
shell_app_info_get_section (ShellAppInfo *info)
|
||||
{
|
||||
char *name;
|
||||
GMenuTreeDirectory *dir, *parent;
|
||||
|
||||
if (info->type != SHELL_APP_INFO_TYPE_ENTRY)
|
||||
return NULL;
|
||||
|
||||
dir = gmenu_tree_item_get_parent ((GMenuTreeItem*)info->entry);
|
||||
if (!dir)
|
||||
return NULL;
|
||||
|
||||
parent = gmenu_tree_item_get_parent ((GMenuTreeItem*)dir);
|
||||
if (!parent)
|
||||
return NULL;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GMenuTreeDirectory *pparent = gmenu_tree_item_get_parent ((GMenuTreeItem*)parent);
|
||||
if (!pparent)
|
||||
break;
|
||||
gmenu_tree_item_unref ((GMenuTreeItem*)dir);
|
||||
dir = parent;
|
||||
parent = pparent;
|
||||
}
|
||||
|
||||
name = g_strdup (gmenu_tree_directory_get_name (dir));
|
||||
|
||||
gmenu_tree_item_unref ((GMenuTreeItem*)dir);
|
||||
gmenu_tree_item_unref ((GMenuTreeItem*)parent);
|
||||
return name;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -52,7 +52,7 @@ char *shell_app_info_get_executable (ShellAppInfo *info);
|
||||
char *shell_app_info_get_desktop_file_path (ShellAppInfo *info);
|
||||
GIcon *shell_app_info_get_icon (ShellAppInfo *info);
|
||||
ClutterActor *shell_app_info_create_icon_texture (ShellAppInfo *info, float size);
|
||||
GSList *shell_app_info_get_categories (ShellAppInfo *info);
|
||||
char *shell_app_info_get_section (ShellAppInfo *info);
|
||||
gboolean shell_app_info_get_is_nodisplay (ShellAppInfo *info);
|
||||
gboolean shell_app_info_is_transient (ShellAppInfo *info);
|
||||
|
||||
@ -69,6 +69,7 @@ gboolean shell_app_info_launch (ShellAppInfo *info,
|
||||
|
||||
ShellAppInfo *shell_app_system_load_from_desktop_file (ShellAppSystem *system, const char *filename, GError **error);
|
||||
|
||||
GList *shell_app_system_get_sections (ShellAppSystem *system);
|
||||
ShellApp *shell_app_system_get_app (ShellAppSystem *system, const char *id);
|
||||
ShellApp *shell_app_system_get_app_for_path (ShellAppSystem *system, const char *desktop_path);
|
||||
ShellApp *shell_app_system_get_app_for_window (ShellAppSystem *self, MetaWindow *window);
|
||||
|
Loading…
Reference in New Issue
Block a user