[Zope3-checkins] CVS: Zope3/src/zope/app/services - menu.py:1.1.2.1 menu.pyc:1.1.2.1 menu.zcml:1.1.2.1 configure.zcml:1.51.2.1

Stephan Richter srichter at cosmos.phy.tufts.edu
Thu Aug 14 14:58:15 EDT 2003


Update of /cvs-repository/Zope3/src/zope/app/services
In directory cvs.zope.org:/tmp/cvs-serv10819/app/services

Modified Files:
      Tag: dreamcatcher-ttwschema-branch
	configure.zcml 
Added Files:
      Tag: dreamcatcher-ttwschema-branch
	menu.py menu.pyc menu.zcml 
Log Message:
Checkpoint check-in for people following the branch:

Got Local Browser Menu Service to work. I used a similar model to the 
interface service, where the service uses registered Browser Menu utilities
to get its menu entries.

There are also a bunch of policy-type decisions that come with local menus.
One is whether a local menu should overwrite or complement existing menus.
Currently I have an 'inherit' flag that can be set. If true, the local menu
will add to the existing entries, otherwise it will overwrite them. Note 
that this does not solve all use cases, such as if you want to take over
just a few entries, but I called YAGNI on it (someone else can do it, if it
is necessary).

I added and extended interfaces for all of this to work. I tried really 
hard to avoid rewriting the getMenu() methof for the local menu service 
version and I think I got it. ;-)

I also have a nice Overview screen for the Local Menu Service, which shows
you all available menus.

To Do:

  - Flesh out the interfaces and implement missing methods.

  - Clean up the code.

  - Fix tests.

  - Write a bunch of new tests.




=== Added File Zope3/src/zope/app/services/menu.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Local Menu Service

$Id: menu.py,v 1.1.2.1 2003/08/14 17:58:08 srichter Exp $
"""
from persistence import Persistent
from zope.app import zapi
from zope.app.component.nextservice import queryNextService
from zope.app.container.ordered import OrderedContainer
from zope.app.interfaces.services.menu import ILocalBrowserMenu
from zope.app.interfaces.publisher.browser import IBrowserMenuItem
from zope.app.interfaces.services.service import ISimpleService
from zope.app.publisher.browser.globalbrowsermenuservice import \
     Menu, BaseBrowserMenuService
from zope.app.services.servicenames import Utilities
from zope.interface import implements
from zope.context import ContextMethod
from zope.interface import providedBy
from zope.security.proxy import trustedRemoveSecurityProxy


class LocalBrowserMenuItem(Persistent):
    """A persistent browser menu item."""

    implements(IBrowserMenuItem)

    # See zope.app.interfaces.publisher.browser.IMenuItem
    interface = None

    # See zope.app.interfaces.publisher.browser.IMenuItem
    action = u''

    # See zope.app.interfaces.publisher.browser.IMenuItem
    title = u''

    # See zope.app.interfaces.publisher.browser.IMenuItem
    description = u''

    # See zope.app.interfaces.publisher.browser.IMenuItem
    permission = None

    # See zope.app.interfaces.publisher.browser.IMenuItem
    filter_string = u''
    

class LocalBrowserMenu(OrderedContainer):
    """A persistent browser menu that can store menu item objects."""
    
    implements(ILocalBrowserMenu)

    # See zope.app.interfaces.publisher.browser.IMenuItem
    title = u''

    # See zope.app.interfaces.publisher.browser.IMenuItem
    description = u''

    # See zope.app.interfaces.publisher.browser.IMenuItem
    usage = u''

    # See zope.app.interfaces.publisher.browser.IMenuItem
    inherit = True

    def __init__(self):
        super(LocalBrowserMenu, self).__init__()
        self._next = 0

    def getMenuItems(self, object=None):
        """See zope.app.interfaces.publisher.browser.IMenuItem"""
        result = []
        interfaces = providedBy(object).flattened()
        for menuitem in self.values():
            if menuitem.interface in interfaces or object is None:
                result.append(
                    (menuitem.action,
                     menuitem.title,
                     menuitem.description,
                     menuitem.filter_string or None,
                     menuitem.permission))

        return result


    def setObject(self, key, object):
        self._next += 1
        key = str(self._next)
        while key in self:
            self._next += 1
            key = str(self._next)
        super(LocalBrowserMenu, self).setObject(key, object)
        return key


class BrowserMenuService(BaseBrowserMenuService, Persistent):
    """This implementation strongly depends on the semantics of
    GlobalBrowserMenuService."""
    
    implements(ISimpleService)

    def __init__(self):
        super(BrowserMenuService, self).__init__()

    def getAllLocalMenus(self):
        utilities = zapi.getService(self, Utilities)
        matching = utilities.getRegisteredMatching(ILocalBrowserMenu)
        return matching

    def getLocalMenu(self, menu_id):
        menu = self.queryLocalMenu(menu_id)
        if menu is None:
            raise ComponentLookupError(menu_id)
        return menu
    getLocalMenu = ContextMethod(getLocalMenu)

    def queryLocalMenu(self, menu_id, default=None):
        utilities = zapi.getService(self, Utilities)
        matching = utilities.getRegisteredMatching(ILocalBrowserMenu, menu_id)
        if matching and matching[0][2].active():
            return matching[0][2].active().getComponent()
        return default
    queryLocalMenu = ContextMethod(queryLocalMenu)

    def getAllMenuItems(self, menu_id, object):
        """Get the menu entries of the local menu and all the ones higher up
        the tree."""
        result = []
    
        # Find the local items, if available 
        menu = self.queryLocalMenu(menu_id)
        if menu is not None:
            result += menu.getMenuItems()
            # We might not want to inherit menu entries from higher up
            if not menu.inherit:
                return result
    
        # Try to find the next service and get its items. The next service is
        # also responsible for finding items higher up.
        next = queryNextService(self, "BrowserMenu")
        if next is not None:
            result += next.getAllMenuItems(menu_id, object)

        return tuple(result)
    getAllMenuItems = ContextMethod(getAllMenuItems)


    def getMenu(self, menu_id, object, request, max=999999):
        return super(BrowserMenuService,
                     self).getMenu(menu_id, object, request, max)
    getMenu = ContextMethod(getMenu)


=== Added File Zope3/src/zope/app/services/menu.pyc ===
  <Binary-ish file>

=== Added File Zope3/src/zope/app/services/menu.zcml ===
<configure
    xmlns="http://namespaces.zope.org/zope">

<!-- Browser Menu Service -->
  <content class="zope.app.services.menu.BrowserMenuService">
    <factory
        id="zope.app.services.MenuService"
        permission="zope.ManageServices"
        title="Browser Menu Service"
        description="A Persistent Browser Menu Service" />
        />
    <require
        permission="zope.ManageServices"
        interface="zope.app.interfaces.services.registration.IRegistry"
        attributes="menu menuItem"
        />
  </content>

<!-- Browser Menu -->
  <content class=".menu.LocalBrowserMenu">

    <factory
      id="zope.app.services.menu.LocalBrowserMenu"
      permission="zope.ManageServices"
      title="Browser Menu"
      description="A Persistent Browser Menu" />

    <allow
        interface="zope.app.interfaces.container.IReadContainer" />

    <require
        permission="zope.ManageServices"
        interface="zope.app.interfaces.container.IWriteContainer" />

    <implements
      interface="zope.app.interfaces.services.utility.ILocalUtility" />

    <implements
      interface="zope.app.interfaces.annotation.IAttributeAnnotatable" />

    <require
      permission="zope.ManageServices"
      interface="zope.app.interfaces.services.menu.ILocalBrowserMenu"
      set_schema="zope.app.interfaces.services.menu.ILocalBrowserMenu" />

  </content>

<!-- Browser Menu Item -->
  <content class=".menu.LocalBrowserMenuItem">

    <factory
      id="utility.LocalBrowserMenuItem"
      permission="zope.ManageServices"
      title="Browser Menu Item"
      description="A Persistent Browser Menu Item" />

    <implements
      interface="zope.app.interfaces.annotation.IAttributeAnnotatable" />

    <require
      permission="zope.ManageServices"
      interface="zope.app.interfaces.publisher.browser.IBrowserMenuItem"
      set_schema="zope.app.interfaces.publisher.browser.IBrowserMenuItem" />

  </content>


</configure>



=== Zope3/src/zope/app/services/configure.zcml 1.51 => 1.51.2.1 ===
--- Zope3/src/zope/app/services/configure.zcml:1.51	Thu Aug  7 11:32:41 2003
+++ Zope3/src/zope/app/services/configure.zcml	Thu Aug 14 13:58:07 2003
@@ -103,6 +103,10 @@
    />
 
 
+<!-- Menu Service -->
+<include file="menu.zcml"/>
+
+
 <!-- Page Templates -->
 
 <content class="zope.app.services.zpt.ZPTTemplate">




More information about the Zope3-Checkins mailing list