From 3d60245b18ee0a988b15f569bccf15da5e827132 Mon Sep 17 00:00:00 2001 From: Maxim Ermilov Date: Sat, 5 Jun 2010 02:01:32 +0400 Subject: [PATCH] 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 --- data/Makefile.am | 7 +++ data/gs-applications.menu | 36 +++++++++++++++ data/theme/gnome-shell.css | 10 +++++ data/theme/separator-white.png | Bin 0 -> 531 bytes js/ui/appDisplay.js | 70 ++++++++++++++++++++++++++--- src/gnome-shell-plugin.c | 1 + src/gnome-shell.in | 1 + src/shell-app-system.c | 80 +++++++++++++++++++++++++++++++-- src/shell-app-system.h | 3 +- 9 files changed, 199 insertions(+), 9 deletions(-) create mode 100644 data/gs-applications.menu create mode 100644 data/theme/separator-white.png diff --git a/data/Makefile.am b/data/Makefile.am index 7b9987522..f035f95a5 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -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 = \ diff --git a/data/gs-applications.menu b/data/gs-applications.menu new file mode 100644 index 000000000..38ed80514 --- /dev/null +++ b/data/gs-applications.menu @@ -0,0 +1,36 @@ + + Applications + + + Games + + + Game + + + + + Tools + + Development + + System + + Settings + + + Utility + + + + Other + + + + Core + Settings + Screensaver + + + + diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index c34ae630d..1f3dd03db 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -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; } diff --git a/data/theme/separator-white.png b/data/theme/separator-white.png new file mode 100644 index 0000000000000000000000000000000000000000..c2a8bb91ad4a62a5522054e3d54f219bb1b6695d GIT binary patch literal 531 zcmV+u0_^>XP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igN4 z3IsdoTLA_D000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004QNkltATtF+O#_bz+t zxc|40sTRnI{U;O7lX{(IN+ZPmoagx%UL2-8d=cyJkAYJ-3O8_aPS_bM`{FR@YUM*i z)nY!@hr2(96yp?*(n#rox^^5H=CoJUhw625I8TN+Hlo`2`I{P?>|1Nmc&wptqBinV zcr32ssCo_F6OO<3nmJe4okpxL)kmdK)XJO?XRUSI_x-hpK6taLmj`ZKm4m~eZt#pV zxvBHb-f_-xEFSAtvFbM);3}rl6R}uMSA$(3)&HRmJiMUt0TzCCfv5v3Z|-cn`{Na2 zW{q7tl literal 0 HcmV?d00001 diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index deeeb6ff5..71243c3f9 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -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); diff --git a/src/gnome-shell-plugin.c b/src/gnome-shell-plugin.c index 8e689fdb2..2951cb232 100644 --- a/src/gnome-shell-plugin.c +++ b/src/gnome-shell-plugin.c @@ -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"); } diff --git a/src/gnome-shell.in b/src/gnome-shell.in index 2dfb4f3a0..07dceb44b 100644 --- a/src/gnome-shell.in +++ b/src/gnome-shell.in @@ -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: diff --git a/src/shell-app-system.c b/src/shell-app-system.c index faa960e55..c0ebc7fce 100644 --- a/src/shell-app-system.c +++ b/src/shell-app-system.c @@ -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 diff --git a/src/shell-app-system.h b/src/shell-app-system.h index 2f3dda74f..696972b11 100644 --- a/src/shell-app-system.h +++ b/src/shell-app-system.h @@ -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);