Switch to side-by-side view

--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -1,4 +1,5 @@
 import logging
+from collections import Counter, OrderedDict
 from datetime import datetime
 
 from tg import config
@@ -418,7 +419,8 @@
             if app.is_visible_to(c.user):
                 for sm in app.main_menu():
                     entry = sm.bind_app(app)
-                    entry.ui_icon='tool-%s' % ac.tool_name.lower()
+                    entry.tool_name = ac.tool_name
+                    entry.ui_icon = 'tool-%s' % entry.tool_name.lower()
                     ordinal = int(ac.options.get('ordinal', 0)) + delta_ordinal
                     if ordinal > max_ordinal:
                         max_ordinal = ordinal
@@ -430,6 +432,39 @@
 
         entries = sorted(entries, key=lambda e: e['ordinal'])
         return [e['entry'] for e in entries]
+
+    def grouped_navbar_entries(self):
+        """Return a ``allura.app.SitemapEntry`` list suitable for rendering
+        the project navbar with tools grouped together by tool type.
+        """
+        # get orginal (non-grouped) navbar entries
+        sitemap = self.sitemap()
+        # ordered dict to preserve the orginal ordering of tools
+        grouped_nav = OrderedDict()
+        # count how many tools of each type we have
+        counts = Counter([e.tool_name.lower() for e in sitemap if e.tool_name])
+        for e in sitemap:
+            # if it's not a tool, add to navbar and continue
+            if not e.tool_name:
+                grouped_nav[id(e)] = e
+                continue
+            tool_name = e.tool_name.lower()
+            # tool of a type we don't have in the navbar yet
+            if tool_name not in grouped_nav:
+                # there's more than one tool of this type
+                if counts.get(tool_name, 1) > 1:
+                    # change label to be the tool name (type)
+                    e.label = tool_name.capitalize()
+                    # add tool url to list of urls that will match this nav entry
+                    e.matching_urls.append(e.url)
+                    # change url to point to tool list page
+                    e.url = self.url() + '_list/' + tool_name
+                grouped_nav[tool_name] = e
+            else:
+                # already have a tool of this type in the nav; add this tool's
+                # url to the list of urls that match this nav entry
+                grouped_nav[tool_name].matching_urls.append(e.url)
+        return grouped_nav.values()
 
     def parent_iter(self):
         yield self