/
PloneBatch.py
195 lines (167 loc) · 8.54 KB
/
PloneBatch.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
from __future__ import nested_scopes
from ZTUtils.Batch import Batch as ZTUBatch
from ZTUtils import make_query
from ExtensionClass import Base
# These have to be duplicated from ZTUtils.Batch to use the correct Batch
# class, otherwise orphans will come out wrong in the 'show x next messages'.
class LazyPrevBatch(Base):
def __of__(self, parent):
return Batch(parent._sequence, parent._size,
parent.first - parent._size + parent.overlap, 0,
parent.orphan, parent.overlap)
class LazyNextBatch(Base):
def __of__(self, parent):
try: parent._sequence[parent.end]
except IndexError: return None
return Batch(parent._sequence, parent._size,
parent.end - parent.overlap, 0,
parent.orphan, parent.overlap)
class LazySequenceLength(Base):
def __of__(self, parent):
parent.sequence_length = l = len(parent._sequence)
return l
class Batch(ZTUBatch):
"""Create a sequence batch"""
__allow_access_to_unprotected_subobjects__ = 1
previous = LazyPrevBatch()
next = LazyNextBatch()
sequence_length = LazySequenceLength()
size = first= start = end = orphan = overlap = navlist = None
numpages = pagenumber = pagerange = pagerangeend = pagerangestart = pagenumber = quantumleap = None
def __init__( self, sequence, size, start=0, end=0, orphan=0, overlap=0, pagerange=7, quantumleap=0, b_start_str='b_start'):
""" Encapsulate sequence in batches of size
sequence - the data to batch.
size - the number of items in each batch. This will be computed if left out.
start - the first element of sequence to include in batch (0-index)
end - the last element of sequence to include in batch (0-index, optional)
orphan - the next page will be combined with the current page if it does not contain more than orphan elements
overlap - the number of overlapping elements in each batch
pagerange - the number of pages to display in the navigation
quantumleap - 0 or 1 to indicate if bigger increments should be used in the navigation list for big results.
b_start_str - the request variable used for start, default 'b_start'
"""
start = start + 1
start,end,sz = opt(start,end,size,orphan,sequence)
self._sequence = sequence
self.size = sz
self._size = size
self.start = start
self.end = end
self.orphan = orphan
self.overlap = overlap
self.first = max(start - 1, 0)
self.length = self.end - self.first
self.b_start_str = b_start_str
self.last = self.sequence_length - size
# Set up next and previous
if self.first == 0:
self.previous = None
# Set up the total number of pages
self.numpages = calculate_pagenumber(self.sequence_length - self.orphan, self.size, self.overlap)
# Set up the current page number
self.pagenumber = calculate_pagenumber(self.start, self.size, self.overlap)
# Set up pagerange for the navigation quick links
self.pagerange, self.pagerangestart, self.pagerangeend = calculate_pagerange(self.pagenumber,self.numpages,pagerange)
# Set up the lists for the navigation: 4 5 [6] 7 8
# navlist is the complete list, including pagenumber
# prevlist is the 4 5 in the example above
# nextlist is 7 8 in the example above
self.navlist = self.prevlist = self.nextlist = []
if self.pagerange and self.numpages >= 1:
self.navlist = range(self.pagerangestart, self.pagerangeend)
self.prevlist = range(self.pagerangestart, self.pagenumber)
self.nextlist = range(self.pagenumber + 1, self.pagerangeend)
# QuantumLeap - faster navigation for big result sets
self.quantumleap = quantumleap
self.leapback = self.leapforward = []
if self.quantumleap:
self.leapback = calculate_leapback(self.pagenumber, self.numpages, self.pagerange)
self.leapforward = calculate_leapforward(self.pagenumber, self.numpages, self.pagerange)
def pageurl(self, formvariables, pagenumber=-1):
""" Makes the url for a given page """
if pagenumber == -1:
pagenumber = self.pagenumber
b_start = pagenumber * (self.size - self.overlap) - self.size
return make_query(formvariables, {self.b_start_str:b_start})
def navurls(self, formvariables, navlist=[]):
""" Returns the page number and url for the navigation quick links """
if not navlist: navlist = self.navlist
return map(lambda x, formvariables = formvariables: (x, self.pageurl(formvariables, x)), navlist)
def prevurls(self, formvariables):
""" Helper method to get prev navigation list from templates """
return self.navurls(formvariables, self.prevlist)
def nexturls(self, formvariables):
""" Helper method to get next navigation list from templates """
return self.navurls(formvariables, self.nextlist)
# Calculate start, end, batchsize
# This is copied from ZTUtils.Batch.py because orphans were not correct there.
# 04/16/04 modified by Danny Bloemendaal (_ender_). Removed try/except structs because
# in some situations they cause some unexpected problems. Also fixed some problems with the orphan stuff. Seems to work now.
def opt(start,end,size,orphan,sequence):
length = len(sequence)
if size < 1:
if start > 0 and end > 0 and end >= start:
size = end + 1 - start
else: size = 25
if start > 0:
if start>length:
start = length
if end > 0:
if end < start: end = start
else:
end = start + size - 1
if (end+orphan)>=length:
end = length
elif end > 0:
if (end)>length:
end = length
start = end + 1 - size
if start - 1 < orphan: start = 1
else:
start = 1
end = start + size - 1
if (end+orphan)>=length:
end = length
return start,end,size
def calculate_pagenumber(elementnumber, batchsize, overlap=0):
""" Calculate the pagenumber for the navigation """
# To find first element in a page,
# elementnumber = pagenumber * (size - overlap) - size (- orphan?)
try:
pagenumber,remainder = divmod(elementnumber, batchsize - overlap)
except ZeroDivisionError:
pagenumber, remainder = divmod(elementnumber, 1)
if remainder > overlap:
pagenumber = pagenumber + 1
pagenumber = max(pagenumber, 1)
return pagenumber
def calculate_pagerange(pagenumber, numpages, pagerange):
""" Calculate the pagerange for the navigation quicklinks """
# Pagerange is the number of pages linked to in the navigation, odd number
pagerange = max(0 , pagerange + pagerange % 2 - 1)
# Making sure the list will not start with negative values
pagerangestart = max ( 1, pagenumber - (pagerange - 1 ) / 2 )
# Making sure the list does not expand beyond the last page
pagerangeend = min ( pagenumber + (pagerange - 1 ) / 2, numpages) + 1
return pagerange, pagerangestart, pagerangeend
def calculate_quantum_leap_gap(numpages, pagerange):
""" Find the QuantumLeap gap. Current width of list is 6 clicks (30/5) """
return int(max(1,round(float(numpages - pagerange)/30))*5)
def calculate_leapback(pagenumber, numpages, pagerange):
""" Check the distance between start and 0 and add links as necessary """
leapback = []
quantum_leap_gap = calculate_quantum_leap_gap(numpages, pagerange)
num_back_leaps = max(0,min(3, int(round(float(pagenumber - pagerange)/quantum_leap_gap) - 0.3)))
if num_back_leaps:
pagerange, pagerangestart, pagerangeend = calculate_pagerange( pagenumber, numpages, pagerange)
leapback = range(pagerangestart - num_back_leaps * quantum_leap_gap, pagerangestart, quantum_leap_gap)
return leapback
def calculate_leapforward(pagenumber, numpages, pagerange):
""" Check the distance between end and length and add links as necessary """
leapforward = []
quantum_leap_gap = calculate_quantum_leap_gap(numpages, pagerange)
num_forward_leaps = max(0,min(3, int(round(float(numpages - pagenumber - pagerange)/quantum_leap_gap) - 0.3)))
if num_forward_leaps:
pagerange, pagerangestart, pagerangeend = calculate_pagerange( pagenumber, numpages, pagerange)
leapforward = range(pagerangeend-1 + quantum_leap_gap, pagerangeend-1 + (num_forward_leaps+1) * quantum_leap_gap, quantum_leap_gap)
return leapforward