[gnome-shell] Add sections to the all apps view



commit 3d60245b18ee0a988b15f569bccf15da5e827132
Author: Maxim Ermilov <zaspire rambler ru>
Date:   Sat Jun 5 02:01:32 2010 +0400

    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(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index 7b99875..f035f95 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 0000000..38ed805
--- /dev/null
+++ b/data/gs-applications.menu
@@ -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>
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index c34ae63..1f3dd03 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 0000000..c2a8bb9
Binary files /dev/null and b/data/theme/separator-white.png differ
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index deeeb6f..71243c3 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 8e689fd..2951cb2 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 2dfb4f3..07dceb4 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 faa960e..c0ebc7f 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 2f3dda7..696972b 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);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]