1 # -*- coding: utf-8 -*-
2 #######################################################################################
3 # Plinn - http://plinn.org #
4 # Copyright (C) 2005-2007 Benoît PIN <benoit.pin@ensmp.fr> #
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. #
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. #
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
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
34 from zope
.app
.container
.contained
import notifyContainerModified
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
, \
42 AccessContentsInformation
43 from AccessControl
import ClassSecurityInfo
44 from Globals
import InitializeClass
45 from types
import StringType
48 class HugePlinnFolder(BTreeFolder2Base
, PlinnFolder
) :
49 """ Plinn Folder for large set of objects
52 security
= ClassSecurityInfo()
54 def __init__(self
, id, title
='') :
55 PlinnFolder
.__init
__(self
, id, title
)
56 BTreeFolder2Base
.__init
__(self
, id)
58 def _initBTrees(self
):
59 super(HugePlinnFolder
, self
)._initBTrees
()
60 self
._pos
2id
_index
= IOBTree()
61 self
._id
2pos
_index
= OIBTree()
63 def _checkId(self
, id, allow_dup
=0) :
64 PlinnFolder
._checkId
(self
, id, allow_dup
)
65 BTreeFolder2Base
._checkId
(self
, id, allow_dup
)
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*.
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')
76 def _setOb(self
, id, object):
77 super(HugePlinnFolder
, self
)._setOb
(id, object)
78 pos
= self
.objectCount() - 1
79 self
._pos
2id
_index
[pos
] = id
80 self
._id
2pos
_index
[id] = pos
83 pos
= self
._id
2pos
_index
[id]
84 self
._id
2pos
_index
.pop(id)
86 for p
in xrange(pos
+1, self
.objectCount()) :
87 ident
= self
._pos
2id
_index
[p
]
88 self
._pos
2id
_index
[p
-1] = ident
89 self
._id
2pos
_index
[ident
] = p
-1
91 self
._pos
2id
_index
.pop(self
.objectCount()-1)
93 super(HugePlinnFolder
, self
)._delOb
(id)
95 security
.declareProtected(AccessContentsInformation
, 'objectIds')
96 def objectIds(self
, spec
=None) :
98 return super(HugePlinnFolder
, self
).objectIds(spec
)
100 pos2id
= lambda pos
: self
._pos
2id
_index
[pos
]
101 return LazyMap(pos2id
, xrange(self
.objectCount()))
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.
110 if isinstance(ids
, StringType
):
113 id2pos
= self
._id
2pos
_index
114 pos2id
= self
._pos
2id
_index
116 oldPosition
= id2pos
[id]
117 newPosition
= max(oldPosition
+ delta
, 0)
119 shift
= delta
> 0 and 1 or -1
120 for p
in xrange(oldPosition
, newPosition
, shift
) :
121 ident
= pos2id
[p
+shift
]
124 if not suppress_events
:
125 notify(ObjectPositionModified(self
[ident
], self
, p
))
127 id2pos
[id] = newPosition
128 pos2id
[newPosition
] = id
129 if not suppress_events
:
130 notify(ObjectPositionModified(self
[id], self
, newPosition
))
132 if not suppress_events
:
133 notifyContainerModified(self
)
136 def getObjectPosition(self
, id):
137 """ Get the position of an object by its id.
140 return self
._id
2pos
_index
[id]
142 raise ValueError('The object with the id "%s" does not exist.' % id)
145 InitializeClass(HugePlinnFolder
)
146 HugePlinnFolderFactory
= Factory(HugePlinnFolder
)
147 manage_addHugePlinnFolder
= HugePlinnFolder
.manage_addHugePlinnFolder
.im_func