[Zope-CVS] CVS: Products/CompositePage - utils.py:1.1 tool.py:1.8
transformers.py:1.8
Shane Hathaway
shane at zope.com
Sat Dec 27 23:33:18 EST 2003
Update of /cvs-repository/Products/CompositePage
In directory cvs.zope.org:/tmp/cvs-serv16763
Modified Files:
tool.py transformers.py
Added Files:
utils.py
Log Message:
Implemented the clipboard using Zope's __cp cookie.
XXX need unit tests.
=== Added File Products/CompositePage/utils.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.
#
##############################################################################
"""Utilities for handling ZODB objects.
(Copied from the Ape product.)
$Id: utils.py,v 1.1 2003/12/28 04:32:47 shane Exp $
"""
from cStringIO import StringIO
from cPickle import Pickler, Unpickler
from types import StringType
def copyOf(source):
"""Copies a ZODB object, loading subobjects as needed.
Re-ghostifies objects along the way to save memory.
"""
former_ghosts = []
zclass_refs = {}
def persistent_id(ob, former_ghosts=former_ghosts,
zclass_refs=zclass_refs):
if getattr(ob, '_p_changed', 0) is None:
# Load temporarily.
former_ghosts.append(ob)
ob._p_changed = 0
if hasattr(ob, '__bases__'):
m = getattr(ob, '__module__', None)
if (m is not None
and isinstance(m, StringType)
and m.startswith('*')):
n = getattr(ob, '__name__', None)
if n is not None:
# Pickling a ZClass instance. Store the reference to
# the ZClass class separately, so that the pickler
# and unpickler don't trip over the apparently
# missing module.
ref = (m, n)
zclass_refs[ref] = ob
return ref
return None
def persistent_load(ref, zclass_refs=zclass_refs):
return zclass_refs[ref]
stream = StringIO()
p = Pickler(stream, 1)
p.persistent_id = persistent_id
p.dump(source)
if former_ghosts:
for g in former_ghosts:
del g._p_changed
del former_ghosts[:]
stream.seek(0)
u = Unpickler(stream)
u.persistent_load = persistent_load
return u.load()
=== Products/CompositePage/tool.py 1.7 => 1.8 ===
--- Products/CompositePage/tool.py:1.7 Sat Dec 27 17:56:43 2003
+++ Products/CompositePage/tool.py Sat Dec 27 23:32:47 2003
@@ -20,12 +20,14 @@
from Acquisition import aq_base, aq_parent, aq_inner
from OFS.SimpleItem import SimpleItem
from OFS.Folder import Folder
+from OFS.CopySupport import _cb_encode, _cb_decode, cookie_path
from AccessControl import ClassSecurityInfo
from AccessControl.ZopeGuards import guarded_getattr
from interfaces import ISlot, ISlotDefinition, IRenderableInline
from interfaces import CompositeError
from render import adapt
+from utils import copyOf
_transformers = {}
@@ -92,8 +94,8 @@
self._reserved_names = ('slot_defs',)
security.declarePublic("moveElements")
- def moveElements(self, source_paths, target_path, target_index):
- """Moves elements to a slot.
+ def moveElements(self, source_paths, target_path, target_index, copy=0):
+ """Moves or copies elements to a slot.
"""
target_index = int(target_index)
# Coerce the paths to sequences of path elements.
@@ -138,14 +140,17 @@
changed_slots = {} # id(aq_base(slot)) -> slot
try:
- # Replace items with nulls to avoid changing indexes while moving.
- for source in sources:
- slot = root.restrictedTraverse(source[:-1])
- slot_id = id(aq_base(slot))
- if not changed_slots.has_key(slot_id):
- changed_slots[slot_id] = slot
- nullify = guarded_getattr(slot, "nullify") # Check security
- nullify(source[-1])
+ if not copy:
+ # Replace items with nulls to avoid changing indexes
+ # while moving.
+ for source in sources:
+ slot = root.restrictedTraverse(source[:-1])
+ slot_id = id(aq_base(slot))
+ if not changed_slots.has_key(slot_id):
+ changed_slots[slot_id] = slot
+ # Check security
+ nullify = guarded_getattr(slot, "nullify")
+ nullify(source[-1])
# Add the elements and reorder.
for element in elements:
@@ -160,9 +165,12 @@
element = aq_base(element)
new_id = target._get_id(element.getId())
+ if copy:
+ element = copyOf(element)
element._setId(new_id)
target._setObject(new_id, element)
- reorder = guarded_getattr(target, "reorder") # Check security
+ # Check security
+ reorder = guarded_getattr(target, "reorder")
reorder(new_id, target_index)
target_index += 1
finally:
@@ -201,7 +209,7 @@
def moveAndDelete(self, move_source_paths="", move_target_path="",
move_target_index="", delete_source_paths="",
REQUEST=None):
- """Move and delete elements.
+ """Move and/or delete elements.
"""
if move_source_paths:
p = move_source_paths.split(':')
@@ -214,6 +222,34 @@
REQUEST["RESPONSE"].redirect(REQUEST["HTTP_REFERER"])
+ security.declarePublic("useClipboard")
+ def useClipboard(self, func, REQUEST,
+ source_paths=None, target_path=None, target_index=None):
+ """Clipboard interaction.
+ """
+ resp = REQUEST['RESPONSE']
+ if func in ("cut", "copy"):
+ assert source_paths
+ items = [] # list of path tuples
+ cut = (func == 'cut')
+ for p in str(source_paths).split(':'):
+ items.append(p.split('/'))
+ data = _cb_encode((cut, items))
+ resp.setCookie('__cp', data, path=cookie_path(REQUEST))
+ elif func == 'paste':
+ assert target_path
+ assert target_index
+ assert REQUEST is not None
+ data = REQUEST['__cp']
+ cut, items = _cb_decode(data)
+ self.moveElements(
+ items, target_path, int(target_index), not cut)
+ resp.expireCookie('__cp', path=cookie_path(REQUEST))
+ else:
+ raise ValueError("Clipboard function %s unknown" % func)
+ resp.redirect(REQUEST["HTTP_REFERER"])
+
+
security.declarePublic("getRendererFor")
def getRendererFor(self, ob):
return adapt(ob, IRenderableInline)
@@ -228,5 +264,4 @@
dispatcher._setObject(ob.getId(), ob)
if REQUEST is not None:
return dispatcher.manage_main(dispatcher, REQUEST)
-
=== Products/CompositePage/transformers.py 1.7 => 1.8 ===
--- Products/CompositePage/transformers.py:1.7 Sat Dec 27 17:56:43 2003
+++ Products/CompositePage/transformers.py Sat Dec 27 23:32:47 2003
@@ -37,8 +37,7 @@
start_of_body_search = re.compile("(<body[^>]*>)", re.IGNORECASE).search
end_of_body_search = re.compile("(</body[^>]*>)", re.IGNORECASE).search
-default_html_page = """
-<html>
+default_html_page = """<html>
<head>
<title>Composite Page</title>
</head>
@@ -48,8 +47,7 @@
</html>
"""
-close_dialog_html = '''
-<html>
+close_dialog_html = '''<html>
<script type="text/javascript">
if (window.opener)
window.opener.location.reload();
@@ -58,7 +56,6 @@
</html>
'''
-
class CommonTransformer (SimpleItem):
"""Basic page transformer.
@@ -155,7 +152,7 @@
from composite import Composite
obj = self.getPhysicalRoot()
- parts = path.split('/')
+ parts = str(path).split('/')
for name in parts:
obj = obj.restrictedTraverse(name)
try:
@@ -178,7 +175,7 @@
obs = []
all_choices = None # {view -> 1}
current = None
- for path in paths.split(':'):
+ for path in str(paths).split(':'):
ob = root.restrictedTraverse(path)
obs.append(ob)
renderer = tool.getRendererFor(ob)
More information about the Zope-CVS
mailing list