Commit fb57a04a authored by 's avatar

Merged yuppie-ordersupport-branch:

- Added OrderSupport and OrderedFolder.
- Added optional 'id' argument to Folder constructor.
- Modified main.dtml to play well with Folder and OrderedFolder.
parent 8ac0a607
......@@ -8,6 +8,14 @@ Zope Changes
Features added
- OFS: OrderSupport and OrderedFolder added. OrderSupport is a mixin class
that adds the IOrderedContainer interface to ObjectManagers.
OrderedFolder - meta_type 'Folder (Ordered)' - is a new Folder class
using OrderSupport.
(thanks to Stephan Richter for inspiration and some code)
- Folder: Constructor now takes an optional 'id' argument.
- Show known medusa servers in Control_Panel.
- New startup and installation regime (./configure; make; make install
......
......@@ -12,7 +12,7 @@
##############################################################################
"""Constant definitions for built-in Zope permissions"""
__version__='$Revision: 1.6 $'[11:-2]
__version__='$Revision: 1.7 $'[11:-2]
access_contents_information='Access contents information'
......@@ -21,6 +21,7 @@ add_documents_images_and_files='Add Documents, Images, and Files'
add_external_methods='Add External Methods'
add_folders='Add Folders'
add_mailhost_objects='Add MailHost objects'
add_page_templates='Add Page Templates'
add_python_scripts='Add Python Scripts'
add_user_folders='Add User Folders'
add_versions='Add Versions'
......
......@@ -15,17 +15,18 @@
Folders are the basic container objects and are analogous to directories.
$Id: Folder.py,v 1.101 2002/08/14 21:42:56 mj Exp $"""
$Id: Folder.py,v 1.102 2003/06/12 10:20:59 yuppie Exp $"""
__version__='$Revision: 1.101 $'[11:-2]
__version__='$Revision: 1.102 $'[11:-2]
import Globals, SimpleItem, ObjectManager, PropertyManager
import AccessControl.Role, webdav.Collection, FindSupport
from webdav.WriteLockInterface import WriteLockInterface
from AccessControl import getSecurityManager
from AccessControl import Unauthorized
from AccessControl.Permissions import add_page_templates
from AccessControl.Permissions import add_user_folders
from Globals import DTMLFile
from AccessControl import getSecurityManager
manage_addFolderForm=DTMLFile('dtml/folderAdd', globals())
......@@ -40,23 +41,22 @@ def manage_addFolder(self, id, title='',
value, an 'index_html' and a 'UserFolder' objects are created respectively
in the new folder.
"""
ob=Folder()
ob.id=str(id)
ob.title=title
ob = Folder(id)
ob.title = title
self._setObject(id, ob)
ob=self._getOb(id)
ob = self._getOb(id)
checkPermission=getSecurityManager().checkPermission
if createUserF:
if not checkPermission('Add User Folders', ob):
if not checkPermission(add_user_folders, ob):
raise Unauthorized, (
'You are not authorized to add User Folders.'
)
ob.manage_addUserFolder()
if createPublic:
if not checkPermission('Add Page Templates', ob):
if not checkPermission(add_page_templates, ob):
raise Unauthorized, (
'You are not authorized to add Page Templates.'
)
......@@ -67,7 +67,6 @@ def manage_addFolder(self, id, title='',
return self.manage_main(self, REQUEST, update_menu=1)
class Folder(
ObjectManager.ObjectManager,
PropertyManager.PropertyManager,
......@@ -100,5 +99,8 @@ class Folder(
__ac_permissions__=()
def __init__(self, id=None):
if id is not None:
self.id = str(id)
Globals.default__class_init__(Folder)
##############################################################################
#
# 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
#
##############################################################################
""" Order support interfaces.
$Id: IOrderSupport.py,v 1.2 2003/06/12 10:20:59 yuppie Exp $
"""
from Interface import Interface
class IOrderedContainer(Interface):
""" Ordered Container interface.
This interface provides a common mechanism for maintaining ordered
collections.
"""
def moveObjectsByDelta(ids, delta):
""" Move specified sub-objects by delta.
If delta is higher than the possible maximum, objects will be moved to
the bottom. If delta is lower than the possible minimum, objects will
be moved to the top.
The order of the objects specified by ids will always be preserved. So
if you don't want to change their original order, make sure the order
of ids corresponds to their original order.
If an object with id doesn't exist an error will be raised.
Permission -- Manage properties
Returns -- Number of moved sub-objects
"""
def moveObjectsUp(ids, delta=1):
""" Move specified sub-objects up by delta in container.
If no delta is specified, delta is 1. See moveObjectsByDelta for more
details.
Permission -- Manage properties
Returns -- Number of moved sub-objects
"""
def moveObjectsDown(ids, delta=1):
""" Move specified sub-objects down by delta in container.
If no delta is specified, delta is 1. See moveObjectsByDelta for more
details.
Permission -- Manage properties
Returns -- Number of moved sub-objects
"""
def moveObjectsToTop(ids):
""" Move specified sub-objects to top of container.
See moveObjectsByDelta for more details.
Permission -- Manage properties
Returns -- Number of moved sub-objects
"""
def moveObjectsToBottom(ids):
""" Move specified sub-objects to bottom of container.
See moveObjectsByDelta for more details.
Permission -- Manage properties
Returns -- Number of moved sub-objects
"""
def orderObjects(key, reverse=None):
""" Order sub-objects by key and direction.
Permission -- Manage properties
Returns -- Number of moved sub-objects
"""
def getObjectPosition(id):
""" Get the position of an object by its id.
Permission -- Access contents information
Returns -- Position
"""
def moveObjectToPosition(id, position):
""" Moves specified object to absolute position.
Permission -- Manage properties
Returns -- Number of moved sub-objects
"""
##############################################################################
#
# 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
#
##############################################################################
""" Order support for 'Object Manager'.
$Id: OrderSupport.py,v 1.2 2003/06/12 10:20:59 yuppie Exp $
"""
from types import StringType
from AccessControl import ClassSecurityInfo
from AccessControl.Permissions import access_contents_information
from AccessControl.Permissions import manage_properties
from DocumentTemplate.sequence import sort
from Globals import InitializeClass
from IOrderSupport import IOrderedContainer
from ObjectManager import ObjectManager
class OrderSupport:
""" Ordered container mixin class.
This is an extension to the regular ObjectManager. It saves the objects in
order and lets you change the order of the contained objects. This is
particular helpful, if the order does not depend on object attributes, but
is totally user-specific.
"""
__implements__ = IOrderedContainer
security = ClassSecurityInfo()
has_order_support = 1
_default_sort_key = 'position'
_default_sort_reverse = 0
manage_options = ( { 'label':'Contents',
'action':'manage_main',
'help':('OFSP','OrderSupport_Contents.stx') }
,
)
#
# ZMI Methods
#
security.declareProtected(manage_properties, 'manage_move_objects_up')
def manage_move_objects_up(self, REQUEST, ids=None, delta=None):
""" Move specified sub-objects up by delta in container.
"""
if ids:
try:
attempt = self.moveObjectsUp(ids, delta)
message = '%d item%s moved up.' % ( attempt,
( (attempt!=1) and 's' or '' ) )
except ValueError, errmsg:
message = 'Error: %s' % (errmsg)
else:
message = 'Error: No items were specified!'
return self.manage_main(self, REQUEST, skey='position',
manage_tabs_message=message)
security.declareProtected(manage_properties, 'manage_move_objects_down')
def manage_move_objects_down(self, REQUEST, ids=None, delta=None):
""" Move specified sub-objects down by delta in container.
"""
if ids:
try:
attempt = self.moveObjectsDown(ids, delta)
message = '%d item%s moved down.' % ( attempt,
( (attempt!=1) and 's' or '' ) )
except ValueError, errmsg:
message = 'Error: %s' % (errmsg)
else:
message = 'Error: No items were specified!'
return self.manage_main(self, REQUEST, skey='position',
manage_tabs_message=message)
security.declareProtected(manage_properties, 'manage_move_objects_to_top')
def manage_move_objects_to_top(self, REQUEST, ids=None):
""" Move specified sub-objects to top of container.
"""
if ids:
try:
attempt = self.moveObjectsToTop(ids)
message = '%d item%s moved to top.' % ( attempt,
( (attempt!=1) and 's' or '' ) )
except ValueError, errmsg:
message = 'Error: %s' % (errmsg)
else:
message = 'Error: No items were specified!'
return self.manage_main(self, REQUEST, skey='position',
manage_tabs_message=message)
security.declareProtected(manage_properties, 'manage_move_objects_to_bottom')
def manage_move_objects_to_bottom(self, REQUEST, ids=None):
""" Move specified sub-objects to bottom of container.
"""
if ids:
try:
attempt = self.moveObjectsToBottom(ids)
message = '%d item%s moved to bottom.' % ( attempt,
( (attempt!=1) and 's' or '' ) )
except ValueError, errmsg:
message = 'Error: %s' % (errmsg)
else:
message = 'Error: No items were specified!'
return self.manage_main(self, REQUEST, skey='position',
manage_tabs_message=message)
security.declareProtected(manage_properties, 'manage_set_default_sorting')
def manage_set_default_sorting(self, REQUEST, key, reverse):
""" Set default sorting key and direction.
"""
self.setDefaultSorting(key, reverse)
return self.manage_main(self, REQUEST)
#
# IOrderedContainer Interface Methods
#
security.declareProtected(manage_properties, 'moveObjectsByDelta')
def moveObjectsByDelta(self, ids, delta):
""" Move specified sub-objects by delta.
"""
if type(ids) is StringType:
ids = (ids,)
min_position = 0
objects = list(self._objects)
obj_dict = {}
for obj in self._objects:
obj_dict[ obj['id'] ] = obj
# unify moving direction
if delta > 0:
ids = list(ids)
ids.reverse()
objects.reverse()
counter = 0
for id in ids:
try:
object = obj_dict[id]
except KeyError:
raise (ValueError,
'The object with the id "%s" does not exist.' % id)
old_position = objects.index(object)
new_position = max( old_position - abs(delta), min_position )
if new_position == min_position:
min_position += 1
if not old_position == new_position:
objects.remove(object)
objects.insert(new_position, object)
counter += 1
if counter > 0:
if delta > 0:
objects.reverse()
self._objects = tuple(objects)
return counter
security.declareProtected(manage_properties, 'moveObjectsUp')
def moveObjectsUp(self, ids, delta=1):
""" Move specified sub-objects up by delta in container.
"""
return self.moveObjectsByDelta(ids, -delta)
security.declareProtected(manage_properties, 'moveObjectsDown')
def moveObjectsDown(self, ids, delta=1):
""" Move specified sub-objects down by delta in container.
"""
return self.moveObjectsByDelta(ids, delta)
security.declareProtected(manage_properties, 'moveObjectsToTop')
def moveObjectsToTop(self, ids):
""" Move specified sub-objects to top of container.
"""
return self.moveObjectsByDelta( ids, -len(self._objects) )
security.declareProtected(manage_properties, 'moveObjectsToBottom')
def moveObjectsToBottom(self, ids):
""" Move specified sub-objects to bottom of container.
"""
return self.moveObjectsByDelta( ids, len(self._objects) )
security.declareProtected(manage_properties, 'orderObjects')
def orderObjects(self, key, reverse=None):
""" Order sub-objects by key and direction.
"""
ids = [ id for id, obj in sort( self.objectItems(),
( (key, 'cmp', 'asc'), ) ) ]
if reverse:
ids.reverse()
return self.moveObjectsByDelta( ids, -len(self._objects) )
security.declareProtected(access_contents_information,
'getObjectPosition')
def getObjectPosition(self, id):
""" Get the position of an object by its id.
"""
ids = self.objectIds()
if id in ids:
return ids.index(id)
raise ValueError, 'The object with the id "%s" does not exist.' % id
security.declareProtected(manage_properties, 'moveObjectToPosition')
def moveObjectToPosition(self, id, position):
""" Move specified object to absolute position.
"""
delta = position - self.getObjectPosition(id)
return self.moveObjectsByDelta(id, delta)
security.declareProtected(access_contents_information, 'getDefaultSorting')
def getDefaultSorting(self):
""" Get default sorting key and direction.
"""
return self._default_sort_key, self._default_sort_reverse
security.declareProtected(manage_properties, 'setDefaultSorting')
def setDefaultSorting(self, key, reverse):
""" Set default sorting key and direction.
"""
self._default_sort_key = key
self._default_sort_reverse = reverse and 1 or 0
#
# Override Inherited Method of ObjectManager Subclass
#
_old_manage_renameObject = ObjectManager.inheritedAttribute(
'manage_renameObject')
def manage_renameObject(self, id, new_id, REQUEST=None):
""" Rename a particular sub-object without changing its position.
"""
old_position = self.getObjectPosition(id)
result = self._old_manage_renameObject(id, new_id, REQUEST)
self.moveObjectToPosition(new_id, old_position)
return result
InitializeClass(OrderSupport)
##############################################################################
#
# 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
#
##############################################################################
""" 'Folder' with order support.
$Id: OrderedFolder.py,v 1.2 2003/06/12 10:20:59 yuppie Exp $
"""
from AccessControl import getSecurityManager
from AccessControl import Unauthorized
from AccessControl.Permissions import add_page_templates
from AccessControl.Permissions import add_user_folders
from Globals import DTMLFile
from Folder import Folder
from OrderSupport import OrderSupport
manage_addOrderedFolderForm = DTMLFile('dtml/addOrderedFolder', globals())
def manage_addOrderedFolder(self, id, title='', createPublic=0, createUserF=0,
REQUEST=None):
"""Add a new ordered Folder object with id *id*.
If the 'createPublic' and 'createUserF' parameters are set to any true
value, an 'index_html' and a 'UserFolder' objects are created respectively
in the new folder.
"""
ob = OrderedFolder(id)
ob.title = title
self._setObject(id, ob)
ob = self._getOb(id)
checkPermission = getSecurityManager().checkPermission
if createUserF:
if not checkPermission(add_user_folders, ob):
raise Unauthorized, (
'You are not authorized to add User Folders.'
)
ob.manage_addUserFolder()
if createPublic:
if not checkPermission(add_page_templates, ob):
raise Unauthorized, (
'You are not authorized to add Page Templates.'
)
ob.manage_addProduct['PageTemplates'].manage_addPageTemplate(
id='index_html', title='')
if REQUEST:
return self.manage_main(self, REQUEST, update_menu=1)
class OrderedFolder(OrderSupport, Folder):
""" Extends the default Folder by order support.
"""
__implements__ = (OrderSupport.__implements__,
Folder.__implements__)
meta_type='Folder (Ordered)'
manage_options = ( OrderSupport.manage_options +
Folder.manage_options[1:] )
<dtml-var manage_page_header>
<dtml-var "manage_form_title(this(), _,
form_title='Add Folder (Ordered)',
help_product='OFSP',
help_topic='Folder_Add.stx'
)">
<p class="form-help">
A ordered Folder contains other objects. Use Folders to organize your
web objects in to logical groups. The <em>create public interface</em>
option creates an index document inside the Folder to give the
Folder a default HTML representation. The <em>create user folder</em>
option creates a User Folder inside the Folder to hold authorization
information for the Folder.
</p>
<form action="manage_addOrderedFolder" method="post">
<table cellspacing="0" cellpadding="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Id
</div>
</td>
<td align="left" valign="top">
<input type="text" name="id" size="40" />
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-optional">
Title
</div>
</td>
<td align="left" valign="top">
<input type="text" name="title" size="40" />
</td>
</tr>
<dtml-if
"_.SecurityCheckPermission('Add Documents, Images, and Files',this())">
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-text">
<input type="checkbox" name="createPublic:int" value="1"
id="cbCreatePublic">
<label for="cbCreatePublic">Create public interface</label>
</div>
</td>
</tr>
</dtml-if>
<dtml-if
"_.SecurityCheckPermission('Add User Folders',this())">
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-text">
<input type="checkbox" name="createUserF:int" value="1"
id="cbCreateUserF">
<label for="cbCreateUserF">Create user folder</label>
</div>
</td>
</tr>
</dtml-if>
<tr>
<td align="left" valign="top">
</td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit"
value="Add" />
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
......@@ -26,9 +26,6 @@ function toggleSelect() {
//-->
</script>
<dtml-unless skey><dtml-call expr="REQUEST.set('skey', 'id')"></dtml-unless>
<dtml-unless rkey><dtml-call expr="REQUEST.set('rkey', '')"></dtml-unless>
<!-- Add object widget -->
<br />
<dtml-if filtered_meta_types>
......@@ -62,11 +59,22 @@ function toggleSelect() {
<form action="&dtml-URL1;/" name="objectItems" method="post">
<dtml-if objectItems>
<dtml-let hasOrderSupport="_.hasattr(this().aq_self, 'has_order_support')">
<dtml-unless skey>
<dtml-if hasOrderSupport>
<dtml-call expr="REQUEST.set('skey', getDefaultSorting()[0])">
<dtml-call expr="REQUEST.set('rkey', getDefaultSorting()[1])">
<dtml-else>
<dtml-call expr="REQUEST.set('skey', 'id')">
</dtml-if>
</dtml-unless>
<dtml-unless rkey><dtml-call expr="REQUEST.set('rkey', '')"></dtml-unless>
<table width="100%" cellspacing="0" cellpadding="2" border="0">
<tr class="list-header">
<td width="5%" align="right" colspan="2"><div
class="list-item"><a href="./manage_main?skey=meta_type<dtml-if
"rkey == ''">&rkey=meta_type</dtml-if>"
"skey == 'meta_type' and not rkey">&rkey=meta_type</dtml-if>"
onMouseOver="window.status='Sort objects by type'; return true"
onMouseOut="window.status=''; return true"><dtml-if
"skey == 'meta_type' or rkey == 'meta_type'"
......@@ -74,7 +82,7 @@ function toggleSelect() {
</td>
<td width="50%" align="left"><div class="list-item"><a
href="./manage_main?skey=id<dtml-if
"rkey == ''">&rkey=id</dtml-if>"
"skey == 'id' and not rkey">&rkey=id</dtml-if>"
onMouseOver="window.status='Sort objects by name'; return true"
onMouseOut="window.status=''; return true"><dtml-if
"skey == 'id' or rkey == 'id'"
......@@ -82,23 +90,33 @@ function toggleSelect() {
</td>
<td width="15%" align="left"><div class="list-item"><a
href="./manage_main?skey=get_size<dtml-if
"rkey == ''">&rkey=get_size</dtml-if>"
"skey == 'get_size' and not rkey">&rkey=get_size</dtml-if>"
onMouseOver="window.status='Sort objects by size'; return true"
onMouseOut="window.status=''; return true"><dtml-if
"skey == 'get_size' or rkey == 'get_size'"
><strong>Size</strong><dtml-else>Size</dtml-if></a></div>
</td>
<td width="29%" align="left"><div class="list-item"><a
<td width="19%" align="left"><div class="list-item"><a
href="./manage_main?skey=bobobase_modification_time<dtml-if
"rkey == ''">&rkey=bobobase_modification_time</dtml-if
>"
"skey == 'bobobase_modification_time' and not rkey"
>&rkey=bobobase_modification_time</dtml-if>"
onMouseOver="window.status='Sort objects by modification time'; return true"
onMouseOut="window.status=''; return true"><dtml-if
"skey == 'bobobase_modification_time' or rkey == 'bobobase_modification_time'"
><strong>Last Modified</strong><dtml-else>Last Modified</dtml-if></a></div>
</td>
<dtml-if hasOrderSupport>
<td width="10%" align="left"><div class="list-item"><a
href="./manage_main?skey=position"
onMouseOver="window.status='Sort objects by position'; return true"
onMouseOut="window.status=''; return true"><dtml-if
"skey == 'position'"
><strong>Position</strong><dtml-else>Position</dtml-if></a></div>
</td>
</dtml-if>
</tr>
<dtml-in objectItems sort_expr="skey" reverse_expr="rkey">
<dtml-in objectItems sort_expr="skey+'/cmp/asc'" reverse_expr="rkey">
<dtml-if sequence-odd>
<tr class="row-normal">
<dtml-else>
......@@ -182,6 +200,18 @@ function toggleSelect() {
</div>
</td>
</dtml-with>
<dtml-if hasOrderSupport>
<td>
<div class="list-item">
<dtml-if "skey == 'position'">
<dtml-var sequence-number>
<dtml-else>
...
</dtml-if>
</div>
</td>
</dtml-if>
</tr>
</dtml-in>
</table>
......@@ -222,8 +252,48 @@ if (document.forms[0]) {
</div>
</td>
</tr>
<dtml-if "_.len(objectItems)>1">
<dtml-if "hasOrderSupport and
_.SecurityCheckPermission( 'Manage properties', this() )">
<tr>
<td align="left" valign="top" width="16"></td>
<td align="left" valign="top">
<div class="form-element">
<dtml-if expr="skey == 'position'">
<input class="form-element" type="submit"
name="manage_move_objects_up:method" value="Up" />
/
<input class="form-element" type="submit"
name="manage_move_objects_down:method" value="Down" />
by
<select name="delta:int">
<dtml-in "_.range(1,_.min(5,_.len(objectIds())))">
<option><dtml-var sequence-item></option>
</dtml-in>
<dtml-in "_.range(5,_.len(objectIds()),5)">
<option><dtml-var sequence-item></option>
</dtml-in>
</select>
<input class="form-element" type="submit"
name="manage_move_objects_to_top:method" value="Top" />
<input class="form-element" type="submit"
name="manage_move_objects_to_bottom:method" value="Bottom" />
</dtml-if>
<dtml-unless expr="(skey, rkey and 1 or 0) == getDefaultSorting()">
<input type="hidden" name="key" value="<dtml-var skey>">
<input type="hidden" name="reverse" value="<dtml-var rkey>">
<input class="form-element" type="submit"
name="manage_set_default_sorting:method"
value="Set View as Default" />
</dtml-unless>
</div>
</td>
</tr>
</dtml-if>
</dtml-if>
</table>
</dtml-let>
<dtml-else>
<table cellspacing="0" cellpadding="2" border="0">
<tr>
......@@ -259,16 +329,3 @@ window.parent.update_menu();
</dtml-if>
<dtml-var manage_page_footer>
from unittest import TestCase, TestSuite, makeSuite, main
import Zope
Zope.startup()
from Interface.Verify import verifyClass
from OFS.CopySupport import CopySource
from OFS.ObjectManager import ObjectManager
from OFS.OrderSupport import OrderSupport
class DummyObject(CopySource):
def __init__(self, id, meta_type):
self.id = id
self.meta_type = meta_type
def cb_isMoveable(self):
return 1
def manage_afterAdd(self, item, container):
return
def wl_isLocked(self):
return 0
class OrderedObjectManager(OrderSupport, ObjectManager):
# disable permission verification
def _verifyObjectPaste(self, object, validate_src=1):
return
class TestOrderSupport(TestCase):
def _makeOne(self):
f = OrderedObjectManager()
f._objects = ( {'id':'o1', 'meta_type':'mt1'}
, {'id':'o2', 'meta_type':'mt2'}
, {'id':'o3', 'meta_type':'mt1'}
, {'id':'o4', 'meta_type':'mt2'}
)
f.o1 = DummyObject('o1', 'mt1')
f.o2 = DummyObject('o2', 'mt2')
f.o3 = DummyObject('o3', 'mt1')
f.o4 = DummyObject('o4', 'mt2')
return f
def _doCanonTestA(self, methodname, table):
for arg1, order, rval in table:
f = self._makeOne()
method = getattr(f, methodname)
if rval == 'ValueError':
self.failUnlessRaises( ValueError, method, arg1 )
else:
self.failUnlessEqual( method(arg1), rval )
self.failUnlessEqual( f.objectIds(), order )
def _doCanonTestB(self, methodname, table):
for arg1, arg2, order, rval in table:
f = self._makeOne()
method = getattr(f, methodname)
if rval == 'ValueError':
self.failUnlessRaises( ValueError, method, arg1, arg2 )
else:
self.failUnlessEqual( method(arg1, arg2), rval )
self.failUnlessEqual( f.objectIds(), order )
def test_moveObjectsUp(self):
self._doCanonTestB( 'moveObjectsUp',
( ( 'o4', 1, ['o1', 'o2', 'o4', 'o3'], 1 )
, ( 'o4', 2, ['o1', 'o4', 'o2', 'o3'], 1 )
, ( ('o1', 'o3'), 1, ['o1', 'o3', 'o2', 'o4'], 1 )
, ( ('o1', 'o3'), 9, ['o1', 'o3', 'o2', 'o4'], 1 )
, ( ('o2', 'o3'), 1, ['o2', 'o3', 'o1', 'o4'], 2 )
, ( ('n2', 'o3'), 1, ['o1', 'o2', 'o3', 'o4'], 'ValueError')
, ( ('o3', 'o1'), 1, ['o1', 'o3', 'o2', 'o4'], 1 )
)
)
def test_moveObjectsDown(self):
self._doCanonTestB( 'moveObjectsDown',
( ( 'o1', 1, ['o2', 'o1', 'o3', 'o4'], 1 )
, ( 'o1', 2, ['o2', 'o3', 'o1', 'o4'], 1 )
, ( ('o2', 'o4'), 1, ['o1', 'o3', 'o2', 'o4'], 1 )
, ( ('o2', 'o4'), 9, ['o1', 'o3', 'o2', 'o4'], 1 )
, ( ('o2', 'o3'), 1, ['o1', 'o4', 'o2', 'o3'], 2 )
, ( ('n2', 'o3'), 1, ['o1', 'o2', 'o3', 'o4'], 'ValueError')
, ( ('o4', 'o2'), 1, ['o1', 'o3', 'o2', 'o4'], 1 )
)
)
def test_moveObjectsToTop(self):
self._doCanonTestA( 'moveObjectsToTop',
( ( 'o4', ['o4', 'o1', 'o2', 'o3'], 1 )
, ( ('o1', 'o3'), ['o1', 'o3', 'o2', 'o4'], 1 )
, ( ('o2', 'o3'), ['o2', 'o3', 'o1', 'o4'], 2 )
, ( ('n2', 'o3'), ['o1', 'o2', 'o3', 'o4'], 'ValueError')
, ( ('o3', 'o1'), ['o3', 'o1', 'o2', 'o4'], 1 )
)
)
def test_moveObjectsToBottom(self):
self._doCanonTestA( 'moveObjectsToBottom',
( ( 'o1', ['o2', 'o3', 'o4', 'o1'], 1 )
, ( ('o2', 'o4'), ['o1', 'o3', 'o2', 'o4'], 1 )
, ( ('o2', 'o3'), ['o1', 'o4', 'o2', 'o3'], 2 )
, ( ('n2', 'o3'), ['o1', 'o2', 'o3', 'o4'], 'ValueError')
, ( ('o4', 'o2'), ['o1', 'o3', 'o4', 'o2'], 1 )
)
)
def test_orderObjects(self):
self._doCanonTestB( 'orderObjects',
( ( 'id', 'id', ['o4', 'o3', 'o2', 'o1'], 3)
, ( 'meta_type', '', ['o1', 'o3', 'o2', 'o4'], 1)
, ( 'meta_type', 'n', ['o4', 'o2', 'o3', 'o1'], 3)
, ( 'position', 0, ['o1', 'o2', 'o3', 'o4'], 0)
, ( 'position', 1, ['o4', 'o3', 'o2', 'o1'], 3)
)
)
def test_getObjectPosition(self):
self._doCanonTestA( 'getObjectPosition',
( ( 'o2', ['o1', 'o2', 'o3', 'o4'], 1)
, ( 'o4', ['o1', 'o2', 'o3', 'o4'], 3)
, ( 'n2', ['o1', 'o2', 'o3', 'o4'], 'ValueError')
)
)
def test_moveObjectToPosition(self):
self._doCanonTestB( 'moveObjectToPosition',
( ( 'o2', 2, ['o1', 'o3', 'o2', 'o4'], 1)
, ( 'o4', 2, ['o1', 'o2', 'o4', 'o3'], 1)
, ( 'n2', 2, ['o1', 'o2', 'o3', 'o4'], 'ValueError')
)
)
def test_manage_renameObject(self):
self._doCanonTestB( 'manage_renameObject',
( ( 'o2', 'n2', ['o1', 'n2', 'o3', 'o4'], None )
, ( 'o3', 'n3', ['o1', 'o2', 'n3', 'o4'], None )
)
)
def test_interface(self):
from OFS.IOrderSupport import IOrderedContainer
verifyClass(IOrderedContainer, OrderSupport)
def test_suite():
return TestSuite( ( makeSuite(TestOrderSupport), ) )
if __name__ == '__main__':
main(defaultTest='test_suite')
from unittest import TestCase, TestSuite, makeSuite, main
import Zope
Zope.startup()
from Interface.Verify import verifyClass
from OFS.OrderedFolder import OrderedFolder
class TestOrderedFolder(TestCase):
def test_interface(self):
from OFS.IOrderSupport import IOrderedContainer
from webdav.WriteLockInterface import WriteLockInterface
verifyClass(IOrderedContainer, OrderedFolder)
verifyClass(WriteLockInterface, OrderedFolder)
def test_suite():
return TestSuite( ( makeSuite(TestOrderedFolder), ) )
if __name__ == '__main__':
main(defaultTest='test_suite')
......@@ -11,13 +11,16 @@
#
##############################################################################
__doc__='''Object system core
$Id: __init__.py,v 1.37 2002/08/14 22:16:04 mj Exp $'''
__version__='$Revision: 1.37 $'[11:-2]
$Id: __init__.py,v 1.38 2003/06/12 10:21:01 yuppie Exp $'''
__version__='$Revision: 1.38 $'[11:-2]
import Version, OFS.Image, OFS.Folder, AccessControl.User
import OFS.DTMLMethod, OFS.DTMLDocument, OFS.PropertySheets
import OFS.OrderedFolder
import ZClasses.ObjectManager
from AccessControl.Permissions import add_documents_images_and_files
from AccessControl.Permissions import add_folders
from ZClasses import createZClassForBase
createZClassForBase( OFS.DTMLMethod.DTMLMethod, globals()
......@@ -30,6 +33,7 @@ createZClassForBase( OFS.Image.File, globals()
, 'ZFile', 'File' )
createZClassForBase( OFS.Folder.Folder, globals()
, 'ZFolder', 'Folder' )
createZClassForBase( OFS.OrderedFolder.OrderedFolder, globals() )
createZClassForBase( AccessControl.User.UserFolder, globals()
, 'ZUserFolder', 'User Folder' )
createZClassForBase( AccessControl.User.User, globals()
......@@ -39,11 +43,9 @@ createZClassForBase( AccessControl.User.User, globals()
# that this more direct mechanism will be more understandable.
def initialize(context):
perm='Add Documents, Images, and Files'
context.registerClass(
OFS.DTMLMethod.DTMLMethod,
permission=perm,
permission=add_documents_images_and_files,
constructors=(OFS.DTMLMethod.addForm, OFS.DTMLMethod.addDTMLMethod,),
icon='images/dtmlmethod.gif',
legacy=(
......@@ -54,27 +56,25 @@ def initialize(context):
context.registerClass(
OFS.DTMLDocument.DTMLDocument,
permission=perm,
permission=add_documents_images_and_files,
constructors=(OFS.DTMLDocument.addForm,
OFS.DTMLDocument.addDTMLDocument),
icon='images/dtmldoc.gif',
legacy=(('manage_addDTMLDocument', OFS.DTMLDocument.addDTMLDocument),),
)
context.registerClass(
OFS.Image.Image,
permission=perm,
permission=add_documents_images_and_files,
constructors=(('imageAdd',OFS.Image.manage_addImageForm),
OFS.Image.manage_addImage),
icon='images/Image_icon.gif',
legacy=(OFS.Image.manage_addImage,),
)
context.registerClass(
OFS.Image.File,
permission=perm,
permission=add_documents_images_and_files,
constructors=(('fileAdd',OFS.Image.manage_addFileForm),
OFS.Image.manage_addFile),
icon='images/File_icon.gif',
......@@ -89,6 +89,14 @@ def initialize(context):
legacy=(OFS.Folder.manage_addFolder,),
)
context.registerClass(
OFS.OrderedFolder.OrderedFolder,
permission=add_folders,
constructors=(OFS.OrderedFolder.manage_addOrderedFolderForm,
OFS.OrderedFolder.manage_addOrderedFolder),
icon='images/Folder_icon.gif',
legacy=(OFS.OrderedFolder.manage_addOrderedFolder,),
)
context.registerClass(
AccessControl.User.UserFolder,
......
ObjectManager with OrderSupport - Contents: Edit contained objects.
Description
This view displays the contained objects and allows you to add,
delete, change and order them.
Each contained object is displayed on a line and is identified by
an icon, an id and a title in parenthesis. Additionally, the size
(if applicable) and the date during which the object was last modified
are displayed. You can manage an object by clicking on its identifying
link.
Sorting vs. Ordering
You can sort contained objects by type, name (id), size,
modification date or by position (fixed order, see below). To do so,
click on the appropriate column heading. Clicking a second time
on any column heading (except position) will reverse the sort
on that field. Sorting takes no actions on the contained
objects, but will only change the users personal point of view.
You can order contained objects with the controls on the bottom
of the page. The order of objects ('sort by position') is stored
in the database and remains fixed until it is changed by another
user.
Versions
If you are currently working in a version there will be a
notice at the top of the list of objects indicating this.
If there is a red diamond following the name of an object this
indicates that the object has been modified in the version you
are currently working in. If there is a red diamond with a lock
after an object, this indicates the the object has been modified
in another version.
Controls
'[Checkbox]' -- Selects the object in order to perform operations
on it. The operations you can perform are rename, cut, copy,
delete, and export. Some operations may not be visible if they are
not allowed.
'Rename' -- Changes the ids of the selected objects.
'Cut' -- Cuts selected objects and place them into the
clipboard. This is similar to cut in most file managers. Cut
objects can be pasted in a new location. When cut objects are
pasted into another location the old objects are deleted.
'Copy' -- Copies selected objects and place them in the
clipboard. This is similar to copy in most file managers. Copied
objects can be pasted in a new location.
'Paste' -- Allows you to paste objects from the clipboard into
this object. **Note: This option will only appear if objects have
previously been copied or cut.**
'Delete' -- Deletes the selected objects. Deleted objects are
*not* placed in the clipboard.
'Import/Export' -- Imports or exports a Zope object.
'Available Objects' -- Selects a type of object to add.
'Add' -- Adds an object specified in 'Available Objects'.
'Select All (Deselect All)' -- Toggles between selecting and
deselecting each item currently displayed in the contents view.
**Note: This control will only appear if your browser is
javascript-enabled.**
'Set View as Default' -- Sets current sorted view as default contents view
for this folder. **Note: This option will only appear if your current
sorted view is not the default view.**
**The following options will only appear in Position view:**
'Up' -- Moves selected objects up by the selected amount of steps
(default is 1).
'Down' -- Moves selected objects down by the selected amount of steps
(default is 1).
'Top' -- Moves selected objects to the top of the page.
'Bottom' -- Moves selected objects to the bottom of the page.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment