Mise à jour des utilities, beaucoup plus employés dans cette version de CMF / Zope.
[Plinn.git] / HugePlinnFolder.py
1 # -*- coding: utf-8 -*-
2 #######################################################################################
3 # Plinn - http://plinn.org #
4 # Copyright (C) 2005-2007 Benoît PIN <benoit.pin@ensmp.fr> #
5 # #
6 # This program is free software; you can redistribute it and/or #
7 # modify it under the terms of the GNU General Public License #
8 # as published by the Free Software Foundation; either version 2 #
9 # of the License, or (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program; if not, write to the Free Software #
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #
19 #######################################################################################
20 """ Plinn implementation of CMFBTree
21
22
23
24 """
25
26
27 from Products.BTreeFolder2.BTreeFolder2 import BTreeFolder2Base
28 from Products.ZCatalog.Lazy import LazyMap
29 from BTrees.IOBTree import IOBTree
30 from BTrees.OIBTree import OIBTree
31 from Folder import PlinnFolder
32 from zope.event import notify
33 try :
34 from zope.app.container.contained import notifyContainerModified
35 except ImportError :
36 ## Zope-2.13 compat
37 from zope.container.contained import notifyContainerModified
38 from events import ObjectPositionModified
39 from zope.component.factory import Factory
40 from Products.CMFCore.permissions import AddPortalFolders, \
41 ManageProperties, \
42 AccessContentsInformation
43 from AccessControl import ClassSecurityInfo
44 from Globals import InitializeClass
45 from types import StringType
46
47
48 class HugePlinnFolder(BTreeFolder2Base, PlinnFolder) :
49 """ Plinn Folder for large set of objects
50 """
51
52 security = ClassSecurityInfo()
53
54 def __init__(self, id, title='') :
55 PlinnFolder.__init__(self, id, title)
56 BTreeFolder2Base.__init__(self, id)
57
58 def _initBTrees(self):
59 super(HugePlinnFolder, self)._initBTrees()
60 self._pos2id_index = IOBTree()
61 self._id2pos_index = OIBTree()
62
63 def _checkId(self, id, allow_dup=0) :
64 PlinnFolder._checkId(self, id, allow_dup)
65 BTreeFolder2Base._checkId(self, id, allow_dup)
66
67 security.declareProtected(AddPortalFolders, 'manage_addHugePlinnFolder')
68 def manage_addHugePlinnFolder(self, id, title='', REQUEST=None) :
69 """ Add new a new HugePlinnFolder object with id *id*.
70 """
71 ob = HugePlinnFolder(id, title)
72 self._setObject(id, ob)
73 if REQUEST is not None :
74 return self.folder_contents(self, REQUEST, portal_status_message='Folder added')
75
76 def _setOb(self, id, object):
77 super(HugePlinnFolder, self)._setOb(id, object)
78 pos = self.objectCount() - 1
79 self._pos2id_index[pos] = id
80 self._id2pos_index[id] = pos
81
82 def _delOb(self, id):
83 pos = self._id2pos_index[id]
84 self._id2pos_index.pop(id)
85
86 for p in xrange(pos+1, self.objectCount()) :
87 ident = self._pos2id_index[p]
88 self._pos2id_index[p-1] = ident
89 self._id2pos_index[ident] = p-1
90
91 self._pos2id_index.pop(self.objectCount()-1)
92
93 super(HugePlinnFolder, self)._delOb(id)
94
95 security.declareProtected(AccessContentsInformation, 'objectIds')
96 def objectIds(self, spec=None) :
97 if spec is not None :
98 return super(HugePlinnFolder, self).objectIds(spec)
99
100 pos2id = lambda pos : self._pos2id_index[pos]
101 return LazyMap(pos2id, xrange(self.objectCount()))
102
103
104
105 security.declareProtected(ManageProperties, 'moveObjectsByDelta')
106 def moveObjectsByDelta(self, ids, delta, subset_ids=None,
107 suppress_events=False):
108 """ Move specified sub-objects by delta.
109 """
110 if isinstance(ids, StringType):
111 ids = (ids,)
112
113 id2pos = self._id2pos_index
114 pos2id = self._pos2id_index
115 for id in ids :
116 oldPosition = id2pos[id]
117 newPosition = max(oldPosition + delta, 0)
118
119 shift = delta > 0 and 1 or -1
120 for p in xrange(oldPosition, newPosition, shift) :
121 ident = pos2id[p+shift]
122 pos2id[p] = ident
123 id2pos[ident] = p
124 if not suppress_events :
125 notify(ObjectPositionModified(self[ident], self, p))
126
127 id2pos[id] = newPosition
128 pos2id[newPosition] = id
129 if not suppress_events :
130 notify(ObjectPositionModified(self[id], self, newPosition))
131
132 if not suppress_events :
133 notifyContainerModified(self)
134
135
136 def getObjectPosition(self, id):
137 """ Get the position of an object by its id.
138 """
139 try :
140 return self._id2pos_index[id]
141 except KeyError :
142 raise ValueError('The object with the id "%s" does not exist.' % id)
143
144
145 InitializeClass(HugePlinnFolder)
146 HugePlinnFolderFactory = Factory(HugePlinnFolder)
147 manage_addHugePlinnFolder = HugePlinnFolder.manage_addHugePlinnFolder.im_func