[Zope3-checkins] CVS: Zope3/src/zope/app/container/browser - __init__.py:1.1 add.pt:1.1 adding.py:1.1 commontasks.pt:1.1 configure.zcml:1.1 contents.pt:1.1 contents.py:1.1 find.pt:1.1 find.py:1.1 index.pt:1.1 meta.zcml:1.1 metaconfigure.py:1.1

Stephan Richter srichter at cosmos.phy.tufts.edu
Sat Mar 13 21:17:04 EST 2004


Update of /cvs-repository/Zope3/src/zope/app/container/browser
In directory cvs.zope.org:/tmp/cvs-serv8281/src/zope/app/container/browser

Added Files:
	__init__.py add.pt adding.py commontasks.pt configure.zcml 
	contents.pt contents.py find.pt find.py index.pt meta.zcml 
	metaconfigure.py 
Log Message:
Moved zope.app.browser.container to zope.app.container.browser.


=== Added File Zope3/src/zope/app/container/browser/__init__.py ===
#
# This file is necessary to make this directory a package.


=== Added File Zope3/src/zope/app/container/browser/add.pt ===
<html metal:use-macro="views/standard_macros/page">
<body>
<div metal:fill-slot="body">

  <form action="action.html" method="post" action="action.html">
    <table class="TypeListing" cellpadding="3">

      <caption tal:content="view/title | default">Add Content</caption>

      <tbody tal:define="infos view/addingInfo">

        <tr tal:repeat="info infos">

          <td class="Selector">
            <input type="radio" name="type_name"
                   tal:attributes="value   info/action;
                                   id      info/action;
                                   checked python:len(infos)==1" />
          </td>

          <td class="TypeName">
            <label style="font-weight: bold;"
                   tal:attributes="for info/action">
              <span tal:replace="info/title" >Folder</span>
            </label>
            <div class="TypeDescription" tal:content="info/description">
              Folders are generic containers for content, including other
              folders.
            </div>
          </td>
        </tr>

      <tr>
        <td><br /></td>
        <td><input type="text" name="id"
                   tal:condition="view/namesAccepted"
                   tal:attributes="value request/id | nothing" />
            <input type="submit" name="add" value=" Add "
                   i18n:attributes="value add-button" />
        </td>
      </tr>

      </tbody>

    </table>

  </form>

</div>
</body>
</html>


=== Added File Zope3/src/zope/app/container/browser/adding.py ===
##############################################################################
#
# Copyright (c) 2002 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.
#
##############################################################################
"""Adding View

The Adding View is used to add new objects to a container. It is sort of a
factory screen.

$Id: adding.py,v 1.1 2004/03/14 02:17:02 srichter Exp $
"""
__metaclass__ = type

import zope.security.checker
from zope.interface import implements
from zope.publisher.interfaces import IPublishTraverse
from zope.proxy import removeAllProxies
from zope.component.interfaces import IFactory

from zope.app.interfaces.exceptions import UserError
from zope.app.container.interfaces import IAdding
from zope.app.container.interfaces import IContainerNamesContainer
from zope.app.container.interfaces import INameChooser

from zope.app import zapi
from zope.app.event.objectevent import ObjectCreatedEvent
from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
from zope.app.event import publish
from zope.app.publisher.browser import BrowserView

from zope.app.i18n import ZopeMessageIDFactory as _
from zope.i18n import translate
from zope.app.location import LocationProxy
from zope.app.container.constraints import checkFactory


class BasicAdding(BrowserView):
    implements(IAdding, IPublishTraverse)

    def add(self, content):
        """See zope.app.container.interfaces.IAdding
        """
        container = self.context
        name = self.contentName
        chooser = INameChooser(container)

        if IContainerNamesContainer.providedBy(container):
            # The container pick's it's own names.
            # We need to ask it to pick one.
            name = chooser.chooseName(self.contentName or '', content)
        else:
            request = self.request
            name = request.get('add_input_name', name)

            if name is None:
                name = chooser.chooseName(self.contentName or '', content)
            elif name == '':
                name = chooser.chooseName('', content)
            chooser.checkName(name, container)

        container[name] = content
        self.contentName = name # Set the added object Name
        return container[name]

    contentName = None # usually set by Adding traverser

    def nextURL(self):
        """See zope.app.container.interfaces.IAdding"""
        return (str(zapi.getView(self.context, "absolute_url", self.request))
                + '/@@contents.html')

    request = None # set in BrowserView.__init__

    context = None # set in BrowserView.__init__


    def renderAddButton(self):
        """To Render Add button with or without Inputbox"""
        container = self.context
        add_button_value = _('add-button', 'Add')
        add_button_label = _('add-button-label','Object Name')
        
        add_button_value = translate(self.context, add_button_value,
                                     context=self.request)
        add_button_label = translate(self.context, add_button_label,
                                     context=self.request)
        if IContainerNamesContainer.providedBy(container):
            return " <input type='submit' name='UPDATE_SUBMIT' value='%s'>" \
                   % add_button_value
        else:
            contentName = self.contentName or ''
            return (
               "&nbsp;&nbsp;<input type='submit' name='UPDATE_SUBMIT' value='%s'>"
               "&nbsp;&nbsp;<b>%s:</b>&nbsp;"
               "<input type='text' name='add_input_name' value='%s'>"
                    % (add_button_value, add_button_label, contentName))

    def publishTraverse(self, request, name):
        """See zope.app.container.interfaces.IAdding"""
        if '=' in name:
            view_name, content_name = name.split("=", 1)
            self.contentName = content_name

            if view_name.startswith('@@'):
                view_name = view_name[2:]
            return zapi.getView(self, view_name, request)

        if name.startswith('@@'):
            view_name = name[2:]
        else:
            view_name = name

        view = zapi.queryView(self, view_name, request)
        if view is not None:
            return view

        factory = zapi.queryFactory(self.context, name)
        if factory is None:
            return super(BasicAdding, self).publishTraverse(request, name)

        return factory

    def action(self, type_name='', id=''):
        if not type_name:
            raise UserError(_(u"You must select the type of object to add."))

        if type_name.startswith('@@'):
            type_name = type_name[2:]

        if '/' in type_name:
            view_name  = type_name.split('/', 1)[0]
        else:
            view_name = type_name

        if zapi.queryView(self, view_name, self.request) is not None:
            url = "%s/%s=%s" % (
                zapi.getView(self, "absolute_url", self.request),
                type_name, id)
            self.request.response.redirect(url)
            return

        if not self.contentName:
            self.contentName = id

        # XXX: If the factory wrapped by LocationProxy is already a Proxy,
        #      then ProxyFactory does not the right thing and the original's
        #      checker info gets lost. No factory that was registered via ZCML
        #      and was used via addMenuItem worked here. (SR)
        factory = zapi.getUtility(self, IFactory, type_name)
        if not type(factory) is zope.security.checker.Proxy:
            factory = LocationProxy(factory, self, type_name)
            factory = zope.security.checker.ProxyFactory(factory)
        content = factory()

        # Can't store security proxies.
        # Note that it is important to do this here, rather than
        # in add, otherwise, someone might be able to trick add
        # into unproxying an existing object,
        content = removeAllProxies(content)

        publish(self.context, ObjectCreatedEvent(content))

        self.add(content)
        self.request.response.redirect(self.nextURL())

    def namesAccepted(self):
        return not IContainerNamesContainer.providedBy(self.context)

class Adding(BasicAdding):

    menu_id = None

    index = ViewPageTemplateFile("add.pt")

    def addingInfo(self):
        """Return menu data.

        This is sorted by title.
        """
        container = self.context
        menu_service = zapi.getService(container, "BrowserMenu")
        result = []
        for menu_id in (self.menu_id, 'zope.app.container.add'):
            if not menu_id:
                continue
            for item in menu_service.getMenu(menu_id, self, self.request):
                extra = item.get('extra')
                if extra:
                    factory = extra.get('factory')
                    if factory:
                        factory = zapi.getUtility(container, IFactory, factory)
                        if not checkFactory(container, None, factory):
                            continue
                        elif item['extra']['factory'] != item['action']:
                            item['has_custom_add_view']=True
                result.append(item)

        result.sort(lambda a, b: cmp(a['title'], b['title']))
        return result

    def isSingleMenuItem(self):
        "Return whether there is single menu item or not."
        return len(self.addingInfo()) == 1

    def hasCustomAddView(self):
       "This should be called only if there is singleMenuItem else return 0"
       if self.isSingleMenuItem():
           menu_item = self.addingInfo()[0]
           if 'has_custom_add_view' in menu_item:
               return True
       return False

class ContentAdding(Adding):

    menu_id = "add_content"


=== Added File Zope3/src/zope/app/container/browser/commontasks.pt ===
<tal:block define="addingInfo context/@@+/addingInfo|nothing"
           condition="addingInfo" i18n:domain="zope">

  <tal:block repeat="info addingInfo" 
	define="namesRequired context/@@+/namesAccepted">
    <div tal:define="oddrow repeat/info/odd; 
		     namesRequired context/@@+/namesAccepted;
        has_custom_add_view python:'has_custom_add_view' in info"
      	tal:attributes="class python:oddrow and 'content even' or 'content odd'"
	class="even">
      <a href="#"
        tal:define="baseurl python:request.getURL(1)"
        tal:condition="python: not info['action'].startswith('../')
                               and namesRequired and not has_custom_add_view"
        tal:attributes="
          href string:${baseurl}/@@contents.html?type_name=${info/action};
          class info/selected"
        tal:content="info/title" i18n:translate="">Folder
      </a>
      
      <a href="#"
        tal:define="baseurl python:request.getURL(1)"
        tal:condition="python: not info['action'].startswith('../') 
		               and (has_custom_add_view or not namesRequired)"
        tal:attributes="
          href string:${baseurl}/@@+/action.html?type_name=${info/action};
          class info/selected"
        tal:content="info/title" i18n:translate="">Folder
      </a>

      <a href="#"
        tal:define="baseurl python:request.getURL(1)"
        tal:condition="python: info['action'].startswith('../')"
        tal:attributes="
          href python: info['action'][3:];
          class info/selected"
        tal:content="info/title" i18n:translate="">Folder
      </a>
    </div>
  </tal:block>
</tal:block>


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

  <view
      for="zope.app.container.interfaces.IContentContainer"
      name="+"
      menu="zmi_actions" title="Add"
      class="zope.app.container.browser.adding.ContentAdding"
      permission="zope.ManageContent"
      allowed_attributes="addingInfo isSingleMenuItem hasCustomAddView"
      usage="addingdialog">

    <page name="index.html"  template="add.pt" />
    <page name="action.html" attribute="action" />

  </view>

  <page
      for="zope.app.container.interfaces.IReadContainer"
      name="find.html"
      permission="zope.ManageContent"
      class="zope.app.container.browser.find.Find"
      template="find.pt"
      menu="zmi_actions" title="Find" />

  <page
      for="zope.app.container.interfaces.IWriteContainer"
      permission="zope.ManageContent"
      name="commonTasks"
      class="zope.app.container.browser.contents.Contents"
      template="commontasks.pt" />



</zope:configure>


=== Added File Zope3/src/zope/app/container/browser/contents.pt ===
<html metal:use-macro="views/standard_macros/page">
<body>
<div metal:fill-slot="body">
  <div metal:define-macro="contents">

    <form name="containerContentsForm" method="POST" action="."
          tal:attributes="action request/URL"
          tal:define="container_contents view/listContentInfo">

      <input type="hidden" name="type_name" value=""
             tal:attributes="value request/type_name"
             tal:condition="request/type_name|nothing"
             />
      <input type="hidden" name="retitle_id" value=""
             tal:attributes="value request/retitle_id"
             tal:condition="request/retitle_id|nothing"
             />

      <div class="page_error"
           tal:condition="view/error"
           tal:content="view/error"
           i18n:translate="">
        Error message
      </div>

      <table id="sortable" class="listing" summary="Content listing"
             i18n:attributes="summary">

        <thead>
          <tr>
            <th>&nbsp;</th>
            <th i18n:translate="">Name</th>
            <th i18n:translate="">Title</th>
            <th i18n:translate="">Size</th>
            <th i18n:translate="">Created</th>
            <th i18n:translate="">Modified</th>
          </tr>
        </thead>

        <tbody>

        <tr tal:define="names_required context/@@+/namesAccepted"
	    tal:condition="python:names_required and request.has_key('type_name')">
          <td></td>
          <td><input name="new_value" id="focusid" value="" /></td>
          <td></td>
          <td></td>
          <td></td>
        </tr>

        <metal:block tal:define="supportsRename view/supportsRename"
                     tal:repeat="item container_contents">
          <tr tal:define="oddrow repeat/item/odd; url item/url"
              tal:attributes="class python:oddrow and 'even' or 'odd'" >
            <td>
              <input type="checkbox" class="noborder" name="ids:list" id="#"
                     value="#"
                     tal:attributes="value item/id;
                                     id item/cb_id;
                                     checked request/ids_checked|nothing;"/>
            </td>
            <td><a href="#"
                 tal:attributes="href
                                 string:${url}/@@SelectedManagementView.html"
                 tal:content="structure item/icon|default">
                </a
                ><span tal:condition="item/rename"
                   ><input name="new_value:list"
                     tal:attributes="value item/id"
                     /><input type="hidden" name="rename_ids:list" value=""
                              tal:attributes="value item/rename"
                     /></span
                ><span tal:condition="not:item/rename">
                  <a href="#"
                     tal:attributes="href
                                 string:${url}/@@SelectedManagementView.html"
                     tal:content="item/id"
                     >foo</a
                  ><a href="#"
                     tal:attributes="href
                         string:${request/URL}?rename_ids:list=${item/id}"
                     tal:condition="supportsRename"
                     >&nbsp;&nbsp;</a
                ></span
               ></td>
            <td>
              <input name="new_value" id="focusid"
                     tal:attributes="value item/title|nothing"
                     tal:condition="item/retitle"
                     />
              <a href="#"
                 tal:attributes="href
                                 string:${request/URL}?retitle_id=${item/id}"
                 tal:condition="item/retitleable"
                 tal:content="item/title|default"
                 >&nbsp;&nbsp;&nbsp;&nbsp;</a>
              <span
                 tal:condition="item/plaintitle"
                 tal:content="item/title|default"
                 >&nbsp;&nbsp;&nbsp;&nbsp;</span>
            </td>

            <td><span tal:attributes="size item/size/sizeForSorting"
                      tal:content="item/size/sizeForDisplay"
                      >&nbsp;</span></td>
            <td><span tal:define="created item/created|default"
                      tal:content="created">&nbsp;</span></td>
            <td><span tal:define="modified item/modified|default"
                      tal:content="modified">&nbsp;</span></td>
          </tr>
        </metal:block>

        </tbody>
      </table>

      <div tal:condition="view/normalButtons" 
	   tal:define="addingInfo context/@@+/addingInfo|nothing">

        <input type="submit" name="container_rename_button" value="Rename"
               i18n:attributes="value container-rename-button"
               tal:condition="view/supportsRename"
               />
        <input type="submit" name="container_cut_button" value="Cut"
               i18n:attributes="value container-cut-button"
               tal:condition="view/supportsCut"
               />
        <input type="submit" name="container_copy_button" value="Copy"
               i18n:attributes="value container-copy-button"
               tal:condition="view/supportsCopy"
               />
        <input type="submit" name="container_paste_button" value="Paste"
               tal:condition="view/hasClipboardContents"
               i18n:attributes="value container-paste-button"
               />
        <input type="submit" name="container_delete_button" value="Delete"
               i18n:attributes="value container-delete-button"
			   tal:condition="container_contents"
               i18n:domain="zope"
               />


	<div tal:condition="context/@@+/isSingleMenuItem" tal:omit-tag="" 
	     tal:define="has_custom_add_view context/@@+/hasCustomAddView; 
			 names_required context/@@+/namesAccepted">
          <input type="submit" name="container_add_button" value="Add"
	         i18n:attributes="value add-button"
                 i18n:domain="zope"
               />
          <input type="text" name="single_new_value" id="focusid"
		 tal:condition="python:names_required and not has_custom_add_view"
                 i18n:domain="zope"
               />
          <input type="hidden" name="single_type_name"
               value=""
               tal:attributes="value python:addingInfo[0]['action']" 
               />
	</div>

      </div>

      <div tal:condition="view/specialButtons">
        <input type="submit" value="Apply"
               i18n:attributes="value container-apply-button"
               />
        <input type="submit" name="container_cancel_button" value="Cancel"
               i18n:attributes="value container-cancel-button"
               />
      </div>

    </form>

    <script ><!--
        prettydump('focus', LG_INFO);
        if (document.containerContentsForm.new_value)
	        document.containerContentsForm.new_value.focus();
        //-->
    </script>

  </div>

</div>
</body>
</html>


=== Added File Zope3/src/zope/app/container/browser/contents.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""View Class for the Container's Contents view.

$Id: contents.py,v 1.1 2004/03/14 02:17:02 srichter Exp $
"""

from zope.exceptions import NotFoundError

from zope.app import zapi
from zope.app.size.interfaces import ISized
from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
from zope.app.publisher.browser import BrowserView
from zope.app.i18n import ZopeMessageIDFactory as _
from zope.app.dublincore.interfaces import IZopeDublinCore
from zope.app.dublincore.interfaces import IDCDescriptiveProperties
from zope.app.copypastemove.interfaces import IPrincipalClipboard
from zope.app.copypastemove.interfaces import IObjectCopier
from zope.app.copypastemove.interfaces import IObjectMover
from zope.app.copypastemove import rename

from zope.app.container.browser.adding import BasicAdding
from zope.app.container.interfaces import IContainer
from zope.app.container.interfaces import IContainerNamesContainer

class Contents(BrowserView):

    __used_for__ = IContainer

    error = ''
    message = ''
    normalButtons = False
    specialButtons = False
    supportsRename = False

    def listContentInfo(self):
        request = self.request

        if  "container_cancel_button" in request:
            if "type_name" in request:
                del request.form['type_name']
            if "rename_ids" in request and "new_value" in request:
                del request.form['rename_ids']
            if "retitle_id" in request and "new_value" in request:
                del request.form['retitle_id']

            return self._normalListContentsInfo()

        elif "container_rename_button" in request and not request.get("ids"):
            self.error = _("You didn't specify any ids to rename.")
        elif "container_add_button" in request:
            if "single_type_name" in request \
                   and "single_new_value" in request:
                request.form['type_name'] = request['single_type_name']
                request.form['new_value'] = request['single_new_value']
                self.addObject()
            elif 'single_type_name' in request \
                     and 'single_new_value' not in request:
                request.form['type_name'] = request['single_type_name']
                request.form['new_value'] = ""
                self.addObject()
        elif "type_name" in request and "new_value" in request:
            self.addObject()
        elif "rename_ids" in request and "new_value" in request:
            self.renameObjects()
        elif "retitle_id" in request and "new_value" in request:
            self.changeTitle()
        elif "container_cut_button" in request:
            self.cutObjects()
        elif "container_copy_button" in request:
            self.copyObjects()
        elif "container_paste_button" in request:
            self.pasteObjects()
        elif "container_delete_button" in request:
            self.removeObjects()
        else:
            return self._normalListContentsInfo()

        if self.error:
            return self._normalListContentsInfo()

        status = request.response.getStatus()
        if status not in (302, 303):
            # Only redirect if nothing else has
            request.response.redirect(request.URL)
        return ()

    def normalListContentInfo(self):
        return self._normalListContentsInfo()

    def _normalListContentsInfo(self):
        request = self.request

        self.specialButtons = (
                 'type_name' in request or
                 'rename_ids' in request or
                 ('container_rename_button' in request
                  and request.get("ids")) or
                 'retitle_id' in request
                 )
        self.normalButtons = not self.specialButtons

        info = map(self._extractContentInfo, self.context.items())

        self.supportsCut = info
        self.supportsCopy = info
        self.supportsPaste = self.pasteable()
        self.supportsRename = (
            self.supportsCut and
            not IContainerNamesContainer.providedBy(self.context)
            )

        return info


    def _extractContentInfo(self, item):
        request = self.request


        rename_ids = {}
        if "container_rename_button" in request:
            for rename_id in request.get('ids', ()):
                rename_ids[rename_id] = rename_id
        elif "rename_ids" in request:
            for rename_id in request.get('rename_ids', ()):
                rename_ids[rename_id] = rename_id


        retitle_id = request.get('retitle_id')

        id, obj = item
        info = {}
        info['id'] = info['cb_id'] = id
        info['object'] = obj

        info['url'] = id
        info['rename'] = rename_ids.get(id)
        info['retitle'] = id == retitle_id


        zmi_icon = zapi.queryView(obj, 'zmi_icon', self.request)
        if zmi_icon is None:
            info['icon'] = None
        else:
            info['icon'] = zmi_icon()

        dc = IZopeDublinCore(obj, None)
        if dc is not None:
            info['retitleable'] = id != retitle_id
            info['plaintitle'] = 0

            title = dc.title
            if title:
                info['title'] = title

            formatter = self.request.locale.dates.getFormatter(
                'dateTime', 'short')

            created = dc.created
            if created is not None:
                info['created'] = formatter.format(created)

            modified = dc.modified
            if modified is not None:
                info['modified'] = formatter.format(modified)
        else:
            info['retitleable'] = 0
            info['plaintitle'] = 1


        sized_adapter = ISized(obj, None)
        if sized_adapter is not None:
            info['size'] = sized_adapter
        return info

    def renameObjects(self):
        """Given a sequence of tuples of old, new ids we rename"""
        request = self.request
        ids = request.get("rename_ids")
        newids = request.get("new_value")

        for oldid, newid in map(None, ids, newids):
            if newid != oldid:
                rename(self.context, oldid, newid)

    def changeTitle(self):
        """Given a sequence of tuples of old, new ids we rename"""
        request = self.request
        id = request.get("retitle_id")
        new = request.get("new_value")

        item = self.context[id]
        dc = IDCDescriptiveProperties(item)
        dc.title = new

    def addObject(self):
        request = self.request
        if IContainerNamesContainer.providedBy(self.context):
            new = ""
        else:
            new = request["new_value"]

        adding = zapi.queryView(self.context, "+", request)
        if adding is None:
            adding = BasicAdding(self.context, request)
        else:
            # Set up context so that the adding can build a url
            # if the type name names a view.
            # Note that we can't so this for the "adding is None" case
            # above, because there is no "+" view.
            adding.__parent__ = self.context
            adding.__name__ = '+'
             
        adding.action(request['type_name'], new)

    def removeObjects(self):
        """Remove objects specified in a list of object ids"""
        request = self.request
        ids = request.get('ids')
        if not ids:
            self.error = _("You didn't specify any ids to remove.")
            return

        container = self.context
        for id in ids:
            del container[id]

    def copyObjects(self):
        """Copy objects specified in a list of object ids"""
        request = self.request
        ids = request.get('ids')
        if not ids:
            self.error = _("You didn't specify any ids to copy.")
            return

        container_path = zapi.getPath(self.context)

        user = self.request.user
        annotationsvc = zapi.getService(self.context, 'PrincipalAnnotation')
        annotations = annotationsvc.getAnnotations(user)
        clipboard = IPrincipalClipboard(annotations)
        clipboard.clearContents()
        items = []
        for id in ids:
            items.append(zapi.joinPath(container_path, id))
        clipboard.addItems('copy', items)

    def cutObjects(self):
        """move objects specified in a list of object ids"""
        request = self.request
        ids = request.get('ids')
        if not ids:
            self.error = _("You didn't specify any ids to cut.")
            return

        container_path = zapi.getPath(self.context)

        user = self.request.user
        annotationsvc = zapi.getService(self.context, 'PrincipalAnnotation')
        annotations = annotationsvc.getAnnotations(user)
        clipboard = IPrincipalClipboard(annotations)
        clipboard.clearContents()
        items = []
        for id in ids:
            items.append(zapi.joinPath(container_path, id))
        clipboard.addItems('cut', items)


    def pasteable(self):
        """Decide if there is anything to paste
        """
        target = self.context
        user = self.request.user
        annotationsvc = zapi.getService(self.context, 'PrincipalAnnotation')
        annotations = annotationsvc.getAnnotations(user)
        clipboard = IPrincipalClipboard(annotations)
        items = clipboard.getContents()
        for item in items:
            try:
                obj = zapi.traverse(target, item['target'])
            except NotFoundError:
                pass
            else:
                if item['action'] == 'cut':
                    mover = IObjectMover(obj)
                    if not mover.moveableTo(target):
                        return False
                elif item['action'] == 'copy':
                    copier = IObjectCopier(obj)
                    if not copier.copyableTo(target):
                        return False
                else:
                    raise

        return True


    def pasteObjects(self):
        """Paste ojects in the user clipboard to the container
        """
        target = self.context
        user = self.request.user
        annotationsvc = zapi.getService(self.context, 'PrincipalAnnotation')
        annotations = annotationsvc.getAnnotations(user)
        clipboard = IPrincipalClipboard(annotations)
        items = clipboard.getContents()
        moved = False
        for item in items:
            try:
                obj = zapi.traverse(target, item['target'])
            except NotFoundError:
                pass
            else:
                if item['action'] == 'cut':
                    mover = IObjectMover(obj)
                    mover.moveTo(target)
                    moved = True
                elif item['action'] == 'copy':
                    copier = IObjectCopier(obj)
                    copier.copyTo(target)
                else:
                    raise

        if moved:
            # Clear the clipboard if we do a move, but not if we only do a copy
            clipboard.clearContents()


    def hasClipboardContents(self):
        """ interogates the PrinicipalAnnotation to see if
           clipboard contents exist """

        if not self.supportsPaste:
            return False

        user = self.request.user

        annotationsvc = zapi.getService(self.context, 'PrincipalAnnotation')
        annotations = annotationsvc.getAnnotations(user)

        # touch at least one item to in clipboard confirm contents
        clipboard = IPrincipalClipboard(annotations)
        items = clipboard.getContents()
        for item in items:
            try:
                zapi.traverse(self.context, item['target'])
            except NotFoundError:
                pass
            else:
                return True

        return False

    contents = ViewPageTemplateFile('contents.pt')
    contentsMacros = contents

    _index = ViewPageTemplateFile('index.pt')

    def index(self):
        if 'index.html' in self.context:
            self.request.response.redirect('index.html')
            return ''

        return self._index()

class JustContents(Contents):
    """Like Contents, but does't delegate to item named index.html"""

    def index(self):
        return self._index()


=== Added File Zope3/src/zope/app/container/browser/find.pt ===
<html metal:use-macro="views/standard_macros/page">
<body>
<div metal:fill-slot="body" >

  <form action="@@find.html" method="get">
    <input type="text" name="ids" value="" /><br />
    <input type="submit" name="find_submit" value=" Find " 
           i18n:attributes="value find-button"/>
  </form>

  <table tal:condition="request/ids|nothing">
    <tr tal:repeat="item python:view.findByIds(request['ids'])">
      <td>
        <a href="" tal:attributes="href item/url" tal:content="item/id">id</a>
      </td>
    </tr>
  </table>

</div>
</body>
</html>


=== Added File Zope3/src/zope/app/container/browser/find.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################
"""Find View Class

$Id: find.py,v 1.1 2004/03/14 02:17:02 srichter Exp $
"""
# XXX this needs to be looked up in a registry
from zope.app.container.find import SimpleIdFindFilter
from zope.app.container.interfaces import IFind
from zope.app.traversing import getName
from zope.component import getView
from zope.app.publisher.browser import BrowserView

# XXX very simple implementation right now
class Find(BrowserView):

    def findByIds(self, ids):
        """Do a find for the ids listed in ids, which is a string."""
        finder = IFind(self.context)
        ids = ids.split()
        # if we don't have any ids listed, don't search at all
        if not ids:
            return []
        request = self.request
        result = []
        for object in finder.find([SimpleIdFindFilter(ids)]):
            url = str(getView(object, 'absolute_url', request))
            result.append({ 'id': getName(object), 'url': url})
        return result


=== Added File Zope3/src/zope/app/container/browser/index.pt ===
<html metal:use-macro="views/standard_macros/page">
<head>
  <style metal:fill-slot="headers" type="text/css">
    <!--
    .ContentIcon {
      width: 20px;
    }

    .ContentTitle {
      text-align: left;
    }
    -->
  </style>
</head>
<body>
<div metal:fill-slot="body">

  <table  
      id="sortable" class="listing" summary="Content listing"
      cellpadding="2" cellspacing="0"
      i18n:attributes="summary">

    <thead> 
      <tr>
        <th>&nbsp;</th>
        <th i18n:translate="">Name</th>
        <th i18n:translate="">Title</th>
        <th i18n:translate="">Created</th>
        <th i18n:translate="">Modified</th>
      </tr>
    </thead>
  
    <tbody>
  
      <tr tal:repeat="info view/listContentInfo">
        <td> 
          <a 
              href="#" 
              tal:attributes="href info/url"
              tal:content="structure info/icon|default" />
        </td>
  
        <td class="ContentTitle">
          <a href="subfolder_id"
             tal:attributes="href info/url"
             tal:content="info/id"
          >ID here</a>
        </td>

        <td><span tal:content="info/title|default">&nbsp;</span></td>
        <td><span tal:content="info/created|default">&nbsp;</span></td>
        <td><span tal:content="info/modified|default">&nbsp;</span></td>
  
      </tr>
  
      <tr tal:condition="nothing">
  
        <td class="ContentIcon">
          <img alt="Document" src="../../ZMI/www/document_icon.gif" />
        </td>
  
        <td class="ContentTitle">
           <a href="document_id">Document Title or ID here</a>
        </td>
  
      </tr>
    </tbody>
  
  </table>

</div>
</body>
</html>






=== Added File Zope3/src/zope/app/container/browser/meta.zcml ===
<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:meta="http://namespaces.zope.org/meta">

  <meta:directives namespace="http://namespaces.zope.org/browser">

  <!-- browser cotainer views -->
  <meta:directive
        name="containerViews"
        schema=".metaconfigure.IContainerViews"
        handler=".metaconfigure.containerViews"
        />

  </meta:directives>

</configure>

=== Added File Zope3/src/zope/app/container/browser/metaconfigure.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 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.
#
##############################################################################

from zope.interface import Interface
from zope.configuration.fields import GlobalObject
from zope.schema import Id
from zope.app.publisher.browser.viewmeta import page, view
from zope.app.container.browser.contents import Contents
from zope.app.container.browser.adding import Adding
from zope.app.i18n import ZopeMessageIDFactory as _

class IContainerViews(Interface):
    """Define a container views"""

    for_ = GlobalObject(
        title=u"The interface this containerViews are for.",
        description=u"""
        The containerViews will be for all objects that implement this
        interface.""",
        required=True
        )
     
    contents = Id(
        title=u"The permission needed for content page.",
        required=False,
        )

    index = Id(
        title=u"The permission needed for index page.",
        required=False,
        )

    add = Id(
        title=u"The permission needed for add page.",
        required=False,
        )


def containerViews(_context, for_, contents=None, add=None, index=None):
    """Create an container view for a given content type"""

    if for_ is None:
            raise ValueError("A for interface must be specified.")

    if contents is not None:
        page(_context, name='contents.html', permission=contents,
            for_=for_, class_=Contents, attribute='contents', menu='zmi_views',
            title=_('Contents'))
            
    if index is not None:
        page(_context, name='index.html', permission=index, for_=for_, 
            class_=Contents, attribute='contents')

    if add is not None:
        viewObj = view(_context, name='+', menu='zmi_actions',
                       title=_('Add'), for_=for_, permission=add, class_=Adding)
        viewObj.page(_context, name='index.html', attribute='index')
        viewObj.page(_context, name='action.html', attribute='action')
        viewObj()


        





More information about the Zope3-Checkins mailing list