1
2
3
4
5
6
7
8
9
10
11 __doc__="""ZenTableManager
12
13 ZenTableManager is a Zope Product that helps manage and display
14 large sets of tabular data. It allows for column sorting,
15 break down of the set into pages, and filtering of elements
16 in the table. It also allows users to store their own default
17 page size (but publishes a hook to get this values from
18 a different location).
19
20
21 $Id: ZenTableManager.py,v 1.4 2004/04/03 04:18:22 edahl Exp $"""
22
23 __revision__ = "$Revision: 1.4 $"[11:-2]
24
25 import re
26 import ZTUtils
27 from Globals import InitializeClass
28 from Acquisition import aq_base
29 from OFS.SimpleItem import SimpleItem
30 from OFS.PropertyManager import PropertyManager
31 from DocumentTemplate.sequence.SortEx import sort
32
33 from ZenTableState import ZenTableState
34
35
37
38
50
52 """ZenTableManager manages display of tabular data"""
53
54 portal_type = meta_type = 'ZenTableManager'
55
56 _properties = (
57 {'id':'defaultBatchSize', 'type':'int','mode':'w'},
58 {'id':'abbrStartLabel', 'type':'int','mode':'w'},
59 {'id':'abbrEndLabel', 'type':'int','mode':'w'},
60 {'id':'abbrPadding', 'type':'int','mode':'w'},
61 {'id':'abbrSeparator', 'type':'string','mode':'w'},
62 )
63
64 manage_options = (
65 PropertyManager.manage_options +
66 SimpleItem.manage_options
67 )
68
69
71 self.id = id
72 self.defaultBatchSize = 40
73 self.abbrStartLabel = 15
74 self.abbrEndLabel = 5
75 self.abbrPadding = 5
76 self.abbrSeparator = ".."
77 self.abbrThresh = self.abbrStartLabel + \
78 self.abbrEndLabel + self.abbrPadding
79
80
87
88
95
96
97 - def getTableState(self, tableName, attrname=None, default=None, **keys):
98 """return an existing table state or a single value from the state"""
99 from Products.ZenUtils.Utils import unused
100 unused(default)
101 request = self.REQUEST
102 tableStates = self.getTableStates()
103 tableState = tableStates.get(tableName, None)
104 if not tableState:
105 dbs = self.getDefaultBatchSize()
106 tableStates[tableName] = ZenTableState(request,tableName,dbs,**keys)
107 tableState = tableStates[tableName]
108 if attrname == None:
109 return tableStates[tableName]
110 return getattr(tableState, attrname, None)
111
112
121
122
124 """Set the value of a table state attribute and return it."""
125 tableState = self.getTableState(tableName)
126 return tableState.setTableState(attrname, value)
127
128
136
137
138 - def getBatch(self, tableName, objects, **keys):
139 """Filter, sort and batch objects and pass return set.
140 """
141 if not objects:
142 objects = []
143 tableState = self.setupTableState(tableName, **keys)
144 if tableState.onlyMonitored and objects:
145 objects = [o for o in objects if getattr(o, 'isMonitored', o.monitored)()]
146 if tableState.filter and objects:
147 objects = self.filterObjects(objects, tableState.filter,
148 tableState.filterFields)
149
150 if not isinstance(objects, list):
151 objects = list(objects)
152 if tableState.sortedHeader:
153 objects = self.sortObjects(objects, tableState)
154 tableState.totalobjs = len(objects)
155 tableState.buildPageNavigation(objects)
156 if not hasattr(self.REQUEST, 'doExport'):
157 objects = ZTUtils.Batch(objects,
158 tableState.batchSize or len(objects),
159 start=tableState.start, orphan=0)
160 return objects
161
162
191
192
220
221
223 """Sort objects.
224 """
225 def dictAwareSort(objects, field, rule, sence):
226 if not objects:
227 return objects
228 class Wrapper:
229 def __init__(self, field, cargo):
230 if callable(field): field = field()
231 self.field = field
232 self.cargo = cargo
233 if isinstance(objects[0], dict):
234 objects = [Wrapper(o.get(field, ''), o) for o in objects]
235 else:
236 objects = [Wrapper(getattr(o, field, ''), o) for o in objects]
237 objects = sort(objects, (('field', rule, sence),))
238 return [w.cargo for w in objects]
239
240 if (getattr(aq_base(request), 'sortedHeader', False)
241 and getattr(aq_base(request),"sortedSence", False)):
242 sortedHeader = request.sortedHeader
243 sortedSence = request.sortedSence
244 sortRule = getattr(aq_base(request), "sortRule", "cmp")
245 objects = dictAwareSort(objects, sortedHeader, sortRule, sortedSence)
246 return objects
247
248
251 """generate a <th></th> tag that allows column sorting"""
252 href = self.getTableHeaderHref(tableName, fieldName, sortRule)
253 style = self.getTableHeaderStyle(tableName, fieldName, style)
254 tag = """<th class="%s" %s>""" % (style, attributes)
255 tag += """<a class="%s" href="%s""" % (style, href)
256 tag += fieldTitle + "</a></th>\n"
257 return tag
258
259
281
282
284 """apends "selected" onto the CSS style if this field is selected"""
285 if self.getTableState(tableName, "sortedHeader") == fieldName:
286 style = style + "selected"
287 return style
288
289
291 session = self.REQUEST.SESSION
292 try:
293 return session['zentablestates']
294 except KeyError:
295 init = {}
296 session['zentablestates'] = init
297 return init
298
299
302
303
304 - def getNavData(self, objects, batchSize, sortedHeader):
305 pagenav = []
306 if batchSize in ['', '0']:
307 batchSize = 0
308 else:
309 batchSize = int(batchSize)
310 for index in range(0, len(objects), batchSize or len(objects)):
311 if sortedHeader:
312 label = self._buildTextLabel(objects[index], sortedHeader)
313 elif batchSize:
314 label = str(1+index/batchSize)
315 else:
316 label = '1'
317 pagenav.append({ 'label': label, 'index': index })
318 return pagenav
319
320
321 - def _buildTextLabel(self, item, sortedHeader):
322 startAbbr = ""
323 endAbbr = ""
324 attr = getattr(item, sortedHeader, "")
325 if callable(attr): attr = attr()
326 label = str(attr)
327 if len(label) > self.abbrThresh:
328 startAbbr = label[:self.abbrStartLabel]
329 if self.abbrEndLabel > 0:
330 endAbbr = label[-self.abbrEndLabel:]
331 label = "".join((startAbbr, self.abbrSeparator, endAbbr))
332 return label
333
334
336 """setup the skins that come with ZenTableManager"""
337 layers = ('zentablemanager','zenui')
338 try:
339 import string
340 from Products.CMFCore.utils import getToolByName
341 from Products.CMFCore.DirectoryView import addDirectoryViews
342 skinstool = getToolByName(self, 'portal_skins')
343 for layer in layers:
344 if layer not in skinstool.objectIds():
345 addDirectoryViews(skinstool, 'skins', globals())
346 skins = skinstool.getSkinSelections()
347 for skin in skins:
348 path = skinstool.getSkinPath(skin)
349 path = map(string.strip, string.split(path,','))
350 for layer in layers:
351 if layer not in path:
352 try:
353 path.insert(path.index('custom')+1, layer)
354 except ValueError:
355 path.append(layer)
356 path = ','.join(path)
357 skinstool.addSkinSelection(skin, path)
358 except ImportError, e:
359 if "Products.CMFCore.utils" in e.args: pass
360 else: raise
361 except AttributeError, e:
362 if "portal_skin" in e.args: pass
363 else: raise
364
365
366 InitializeClass(ZenTableManager)
367