13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
14 # details. |
14 # details. |
15 # |
15 # |
16 # You should have received a copy of the GNU Lesser General Public License along |
16 # You should have received a copy of the GNU Lesser General Public License along |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
18 """Set of HTML generic base views: |
18 """ |
19 |
19 HTML views |
20 * noresult, final |
20 ~~~~~~~~~~ |
21 * primary, sidebox |
21 |
22 * oneline, incontext, outofcontext, text |
22 Special views |
23 * list |
23 ````````````` |
|
24 |
|
25 .. autoclass:: NullView |
|
26 .. autoclass:: NoResultView |
|
27 .. autoclass:: FinalView |
|
28 |
|
29 |
|
30 Base entity views |
|
31 ````````````````` |
|
32 |
|
33 .. autoclass:: InContextView |
|
34 .. autoclass:: OutOfContextView |
|
35 .. autoclass:: OneLineView |
|
36 |
|
37 Those are used to display a link to an entity, whose label depends on the entity |
|
38 having to be displayed in or out of context (of another entity): some entities |
|
39 make sense in the context of another entity. For instance, the `Version` of a |
|
40 `Project` in forge. So one may expect that 'incontext' will be called when |
|
41 display a version from within the context of a project, while 'outofcontext"' |
|
42 will be called in other cases. In our example, the 'incontext' view of the |
|
43 version would be something like '0.1.2', while the 'outofcontext' view would |
|
44 include the project name, e.g. 'baz 0.1.2' (since only a version number without |
|
45 the associated project doesn't make sense if you don't know yet that you're |
|
46 talking about the famous 'baz' project. |cubicweb| tries to make guess and call |
|
47 'incontext'/'outofcontext' nicely. When it can't know, the 'oneline' view should |
|
48 be used. |
|
49 |
|
50 |
|
51 List entity views |
|
52 ````````````````` |
|
53 |
|
54 .. autoclass:: ListView |
|
55 .. autoclass:: SimpleListView |
|
56 .. autoclass:: SameETypeListView |
|
57 .. autoclass:: CSVView |
|
58 |
|
59 Those list views can be given a 'subvid' arguments, telling the view to use of |
|
60 each item in the list. When not specified, the value of the 'redirect_vid' |
|
61 attribute of :class:`ListItemView` (for 'listview') or of |
|
62 :class:`SimpleListView` will be used. This default to 'outofcontext' for 'list' |
|
63 / 'incontext' for 'simplelist' |
|
64 |
|
65 |
|
66 Text entity views |
|
67 ~~~~~~~~~~~~~~~~~ |
|
68 |
|
69 Basic HTML view have some variants to be used when generating raw text, not HTML |
|
70 (for notifications for instance). Also, as explained above, some of the HTML |
|
71 views use those text views as a basis. |
|
72 |
|
73 .. autoclass:: TextView |
|
74 .. autoclass:: InContextTextView |
|
75 .. autoclass:: OutOfContextView |
24 """ |
76 """ |
25 |
77 |
26 __docformat__ = "restructuredtext en" |
78 __docformat__ = "restructuredtext en" |
27 _ = unicode |
79 _ = unicode |
28 |
80 |
40 from cubicweb.uilib import cut, printable_value |
92 from cubicweb.uilib import cut, printable_value |
41 from cubicweb.web.views import calendar |
93 from cubicweb.web.views import calendar |
42 |
94 |
43 |
95 |
44 class NullView(AnyRsetView): |
96 class NullView(AnyRsetView): |
45 """default view when no result has been found""" |
97 """:__regid__: *null* |
|
98 |
|
99 This view is the default view used when nothing needs to be rendered. It is |
|
100 always applicable and is usually used as fallback view when calling |
|
101 :meth:`_cw.view` to display nothing if the result set is empty. |
|
102 """ |
46 __regid__ = 'null' |
103 __regid__ = 'null' |
47 __select__ = yes() |
104 __select__ = yes() |
48 def call(self, **kwargs): |
105 def call(self, **kwargs): |
49 pass |
106 pass |
50 cell_call = call |
107 cell_call = call |
51 |
108 |
52 |
109 |
53 class NoResultView(View): |
110 class NoResultView(View): |
54 """default view when no result has been found""" |
111 """:__regid__: *noresult* |
|
112 |
|
113 This view is the default view to be used when no result has been found |
|
114 (i.e. empty result set). |
|
115 |
|
116 It's usually used as fallback view when calling :meth:`_cw.view` to display |
|
117 "no results" if the result set is empty. |
|
118 """ |
|
119 __regid__ = 'noresult' |
55 __select__ = empty_rset() |
120 __select__ = empty_rset() |
56 __regid__ = 'noresult' |
|
57 |
121 |
58 def call(self, **kwargs): |
122 def call(self, **kwargs): |
59 self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n' |
123 self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n' |
60 % self._cw._('No result matching query')) |
124 % self._cw._('No result matching query')) |
61 |
125 |
62 |
126 |
63 class FinalView(AnyRsetView): |
127 class FinalView(AnyRsetView): |
64 """display values without any transformation (i.e. get a number for |
128 """:__regid__: *final* |
65 entities) |
129 |
|
130 Display the value of a result set cell with minimal transformations |
|
131 (i.e. you'll get a number for entities). It is applicable on any result set, |
|
132 though usually dedicated for cells containing an attribute's value. |
66 """ |
133 """ |
67 __regid__ = 'final' |
134 __regid__ = 'final' |
68 # record generated i18n catalog messages |
135 # record generated i18n catalog messages |
69 _('%d years') |
136 _('%d years') |
70 _('%d months') |
137 _('%d months') |
124 self.w(self._cw.__('%%d%sseconds' % space) % int(value.seconds)) |
191 self.w(self._cw.__('%%d%sseconds' % space) % int(value.seconds)) |
125 return |
192 return |
126 self.wdata(printable_value(self._cw, etype, value, props)) |
193 self.wdata(printable_value(self._cw, etype, value, props)) |
127 |
194 |
128 |
195 |
129 # XXX deprecated |
196 class InContextView(EntityView): |
130 class SecondaryView(EntityView): |
197 """:__regid__: *incontext* |
131 __regid__ = 'secondary' |
198 |
132 title = _('secondary') |
199 This view is used whenthe entity should be considered as displayed in its |
133 |
200 context. By default it produces the result of `textincontext` wrapped in a |
134 def cell_call(self, row, col, **kwargs): |
201 link leading to the primary view of the entity. |
135 """the secondary view for an entity |
202 """ |
136 secondary = icon + view(oneline) |
203 __regid__ = 'incontext' |
137 """ |
204 |
138 entity = self.cw_rset.get_entity(row, col) |
205 def cell_call(self, row, col): |
139 self.w(u' ') |
206 entity = self.cw_rset.get_entity(row, col) |
140 self.wview('oneline', self.cw_rset, row=row, col=col) |
207 desc = cut(entity.dc_description(), 50) |
|
208 self.w(u'<a href="%s" title="%s">' % ( |
|
209 xml_escape(entity.absolute_url()), xml_escape(desc))) |
|
210 self.w(xml_escape(self._cw.view('textincontext', self.cw_rset, |
|
211 row=row, col=col))) |
|
212 self.w(u'</a>') |
|
213 |
|
214 |
|
215 class OutOfContextView(EntityView): |
|
216 """:__regid__: *outofcontext* |
|
217 |
|
218 This view is used whenthe entity should be considered as displayed out of |
|
219 its context. By default it produces the result of `textoutofcontext` wrapped |
|
220 in a link leading to the primary view of the entity. |
|
221 """ |
|
222 __regid__ = 'outofcontext' |
|
223 |
|
224 def cell_call(self, row, col): |
|
225 entity = self.cw_rset.get_entity(row, col) |
|
226 desc = cut(entity.dc_description(), 50) |
|
227 self.w(u'<a href="%s" title="%s">' % ( |
|
228 xml_escape(entity.absolute_url()), xml_escape(desc))) |
|
229 self.w(xml_escape(self._cw.view('textoutofcontext', self.cw_rset, |
|
230 row=row, col=col))) |
|
231 self.w(u'</a>') |
141 |
232 |
142 |
233 |
143 class OneLineView(EntityView): |
234 class OneLineView(EntityView): |
|
235 """:__regid__: *oneline* |
|
236 |
|
237 This view is used when we can't tell if the entity should be considered as |
|
238 displayed in or out of context. By default it produces the result of the |
|
239 `text` view in a link leading to the primary view of the entity. |
|
240 """ |
144 __regid__ = 'oneline' |
241 __regid__ = 'oneline' |
145 title = _('oneline') |
242 title = _('oneline') |
146 |
243 |
147 def cell_call(self, row, col, **kwargs): |
244 def cell_call(self, row, col, **kwargs): |
148 """the one line view for an entity: linked text view |
245 """the one line view for an entity: linked text view |
151 self.w(u'<a href="%s">' % xml_escape(entity.absolute_url())) |
248 self.w(u'<a href="%s">' % xml_escape(entity.absolute_url())) |
152 self.w(xml_escape(self._cw.view('text', self.cw_rset, row=row, col=col))) |
249 self.w(xml_escape(self._cw.view('text', self.cw_rset, row=row, col=col))) |
153 self.w(u'</a>') |
250 self.w(u'</a>') |
154 |
251 |
155 |
252 |
|
253 # text views ################################################################### |
|
254 |
156 class TextView(EntityView): |
255 class TextView(EntityView): |
157 """the simplest text view for an entity""" |
256 """:__regid__: *text* |
|
257 |
|
258 This is the simplest text view for an entity. By default it returns the |
|
259 result of the entity's `dc_title()` method, which is cut to fit the |
|
260 `navigation.short-line-size` property if necessary. |
|
261 """ |
158 __regid__ = 'text' |
262 __regid__ = 'text' |
159 title = _('text') |
263 title = _('text') |
160 content_type = 'text/plain' |
264 content_type = 'text/plain' |
161 |
265 |
162 def call(self, **kwargs): |
266 def call(self, **kwargs): |
163 """the view is called for an entire result set, by default loop |
267 """The view is called for an entire result set, by default loop other |
164 other rows of the result set and call the same view on the |
268 rows of the result set and call the same view on the particular row. |
165 particular row |
269 |
166 |
270 Subclasses views that are applicable on None result sets will have to |
167 Views applicable on None result sets have to override this method |
271 override this method. |
168 """ |
272 """ |
169 rset = self.cw_rset |
273 rset = self.cw_rset |
170 if rset is None: |
274 if rset is None: |
171 raise NotImplementedError, self |
275 raise NotImplementedError, self |
172 for i in xrange(len(rset)): |
276 for i in xrange(len(rset)): |
177 def cell_call(self, row, col=0, **kwargs): |
281 def cell_call(self, row, col=0, **kwargs): |
178 entity = self.cw_rset.get_entity(row, col) |
282 entity = self.cw_rset.get_entity(row, col) |
179 self.w(cut(entity.dc_title(), |
283 self.w(cut(entity.dc_title(), |
180 self._cw.property_value('navigation.short-line-size'))) |
284 self._cw.property_value('navigation.short-line-size'))) |
181 |
285 |
|
286 |
|
287 class InContextTextView(TextView): |
|
288 """:__regid__: *textincontext* |
|
289 |
|
290 Similar to the `text` view, but called when an entity is considered in |
|
291 context (see description of incontext HTML view for more information on |
|
292 this). By default it displays what's returned by the `dc_title()` method of |
|
293 the entity. |
|
294 """ |
|
295 __regid__ = 'textincontext' |
|
296 title = None # not listed as a possible view |
|
297 def cell_call(self, row, col): |
|
298 entity = self.cw_rset.get_entity(row, col) |
|
299 self.w(entity.dc_title()) |
|
300 |
|
301 |
|
302 class OutOfContextTextView(InContextTextView): |
|
303 """:__regid__: *textoutofcontext* |
|
304 |
|
305 Similar to the `text` view, but called when an entity is considered out of |
|
306 context (see description of outofcontext HTML view for more information on |
|
307 this). By default it displays what's returned by the `dc_long_title()` |
|
308 method of the entity. |
|
309 """ |
|
310 __regid__ = 'textoutofcontext' |
|
311 |
|
312 def cell_call(self, row, col): |
|
313 entity = self.cw_rset.get_entity(row, col) |
|
314 self.w(entity.dc_long_title()) |
|
315 |
|
316 |
|
317 # list views ################################################################## |
|
318 |
|
319 class ListView(EntityView): |
|
320 """:__regid__: *list* |
|
321 |
|
322 This view displays a list of entities by creating a HTML list (`<ul>`) and |
|
323 call the view `listitem` for each entity of the result set. The 'list' view |
|
324 will generate HTML like: |
|
325 |
|
326 .. sourcecode:: html |
|
327 |
|
328 <ul class="section"> |
|
329 <li>"result of 'subvid' view for a row</li> |
|
330 ... |
|
331 </ul> |
|
332 |
|
333 If you wish to use a different view for each entity, either subclass and |
|
334 change the :attr:`item_vid` class attribute or specify a `subvid` argument |
|
335 when calling this view. |
|
336 """ |
|
337 __regid__ = 'list' |
|
338 title = _('list') |
|
339 item_vid = 'listitem' |
|
340 |
|
341 def call(self, klass=None, title=None, subvid=None, listid=None, **kwargs): |
|
342 """display a list of entities by calling their <item_vid> view |
|
343 |
|
344 :param listid: the DOM id to use for the root element |
|
345 """ |
|
346 # XXX much of the behaviour here should probably be outside this view |
|
347 if subvid is None and 'subvid' in self._cw.form: |
|
348 subvid = self._cw.form.pop('subvid') # consume it |
|
349 if listid: |
|
350 listid = u' id="%s"' % listid |
|
351 else: |
|
352 listid = u'' |
|
353 if title: |
|
354 self.w(u'<div%s class="%s"><h4>%s</h4>\n' % (listid, klass or 'section', title)) |
|
355 self.w(u'<ul>\n') |
|
356 else: |
|
357 self.w(u'<ul%s class="%s">\n' % (listid, klass or 'section')) |
|
358 for i in xrange(self.cw_rset.rowcount): |
|
359 self.cell_call(row=i, col=0, vid=subvid, **kwargs) |
|
360 self.w(u'</ul>\n') |
|
361 if title: |
|
362 self.w(u'</div>\n') |
|
363 |
|
364 def cell_call(self, row, col=0, vid=None, **kwargs): |
|
365 self.w(u'<li>') |
|
366 self.wview(self.item_vid, self.cw_rset, row=row, col=col, vid=vid, **kwargs) |
|
367 self.w(u'</li>\n') |
|
368 |
|
369 |
|
370 class ListItemView(EntityView): |
|
371 __regid__ = 'listitem' |
|
372 |
|
373 @property |
|
374 def redirect_vid(self): |
|
375 if self._cw.search_state[0] == 'normal': |
|
376 return 'outofcontext' |
|
377 return 'outofcontext-search' |
|
378 |
|
379 def cell_call(self, row, col, vid=None, **kwargs): |
|
380 if not vid: |
|
381 vid = self.redirect_vid |
|
382 try: |
|
383 self.wview(vid, self.cw_rset, row=row, col=col, **kwargs) |
|
384 except NoSelectableObject: |
|
385 if vid == self.redirect_vid: |
|
386 raise |
|
387 self.wview(self.redirect_vid, self.cw_rset, row=row, col=col, **kwargs) |
|
388 |
|
389 |
|
390 class SimpleListView(ListItemView): |
|
391 """:__regid__: *simplelist* |
|
392 |
|
393 Similar to :class:~cubicweb.web.views.baseviews.ListView but using '<div>' |
|
394 instead of '<ul>'. It rely on '<div>' behaviour to separate items. HTML will |
|
395 look like |
|
396 |
|
397 .. sourcecode:: html |
|
398 |
|
399 <div class="section">"result of 'subvid' view for a row</div> |
|
400 ... |
|
401 |
|
402 |
|
403 It relies on base :class:`~cubicweb.view.View` class implementation of the |
|
404 :meth:`call` method to insert those <div>. |
|
405 """ |
|
406 __regid__ = 'simplelist' |
|
407 redirect_vid = 'incontext' |
|
408 |
|
409 def call(self, subvid=None, **kwargs): |
|
410 """display a list of entities by calling their <item_vid> view |
|
411 |
|
412 :param listid: the DOM id to use for the root element |
|
413 """ |
|
414 if subvid is None and 'vid' in kwargs: |
|
415 warn("should give a 'subvid' argument instead of 'vid'", |
|
416 DeprecationWarning, stacklevel=2) |
|
417 else: |
|
418 kwargs['vid'] = subvid |
|
419 return super(SimpleListView, self).call(**kwargs) |
|
420 |
|
421 |
|
422 class SameETypeListView(EntityView): |
|
423 """:__regid__: *sameetypelist* |
|
424 |
|
425 This view displays a list of entities of the same type, in HTML section |
|
426 ('<div>') and call the view `sameetypelistitem` for each entity of the |
|
427 result set. It's designed to get a more adapted global list when displayed |
|
428 entities are all of the same type (for instance, display gallery if there |
|
429 are only images entities). |
|
430 """ |
|
431 __regid__ = 'sameetypelist' |
|
432 __select__ = EntityView.__select__ & one_etype_rset() |
|
433 item_vid = 'sameetypelistitem' |
|
434 |
|
435 @property |
|
436 def title(self): |
|
437 etype = iter(self.cw_rset.column_types(0)).next() |
|
438 return display_name(self._cw, etype, form='plural') |
|
439 |
|
440 def call(self, **kwargs): |
|
441 """display a list of entities by calling their <item_vid> view""" |
|
442 showtitle = kwargs.pop('showtitle', not 'vtitle' in self._cw.form) |
|
443 if showtitle: |
|
444 self.w(u'<h1>%s</h1>' % self.title) |
|
445 super(SameETypeListView, self).call(**kwargs) |
|
446 |
|
447 def cell_call(self, row, col=0, **kwargs): |
|
448 self.wview(self.item_vid, self.cw_rset, row=row, col=col, **kwargs) |
|
449 |
|
450 |
|
451 class SameETypeListItemView(EntityView): |
|
452 __regid__ = 'sameetypelistitem' |
|
453 |
|
454 def cell_call(self, row, col, **kwargs): |
|
455 self.wview('listitem', self.cw_rset, row=row, col=col, **kwargs) |
|
456 |
|
457 |
|
458 class CSVView(SimpleListView): |
|
459 """:__regid__: *csv* |
|
460 |
|
461 This view displays each entity in a coma separated list. It is NOT related |
|
462 to the well-known text file format. |
|
463 """ |
|
464 __regid__ = 'csv' |
|
465 redirect_vid = 'incontext' |
|
466 |
|
467 def call(self, subvid=None, **kwargs): |
|
468 if subvid is None and 'vid' in kwargs: |
|
469 warn("[3.9] should give a 'subvid' argument instead of 'vid'", |
|
470 DeprecationWarning, stacklevel=2) |
|
471 else: |
|
472 kwargs['vid'] = subvid |
|
473 rset = self.cw_rset |
|
474 for i in xrange(len(rset)): |
|
475 self.cell_call(i, 0, **kwargs) |
|
476 if i < rset.rowcount-1: |
|
477 self.w(u", ") |
|
478 |
|
479 |
|
480 # XXX to be documented views ################################################### |
182 |
481 |
183 class MetaDataView(EntityView): |
482 class MetaDataView(EntityView): |
184 """paragraph view of some metadata""" |
483 """paragraph view of some metadata""" |
185 __regid__ = 'metadata' |
484 __regid__ = 'metadata' |
186 show_eid = True |
485 show_eid = True |
211 self.w(u' (<span>%s</span>' % _('cw_source')) |
510 self.w(u' (<span>%s</span>' % _('cw_source')) |
212 self.w(u' <span class="value">%s</span>)' % meta['source']['uri']) |
511 self.w(u' <span class="value">%s</span>)' % meta['source']['uri']) |
213 self.w(u'</div>') |
512 self.w(u'</div>') |
214 |
513 |
215 |
514 |
216 class InContextTextView(TextView): |
|
217 __regid__ = 'textincontext' |
|
218 title = None # not listed as a possible view |
|
219 def cell_call(self, row, col): |
|
220 entity = self.cw_rset.get_entity(row, col) |
|
221 self.w(entity.dc_title()) |
|
222 |
|
223 |
|
224 class OutOfContextTextView(InContextTextView): |
|
225 __regid__ = 'textoutofcontext' |
|
226 |
|
227 def cell_call(self, row, col): |
|
228 entity = self.cw_rset.get_entity(row, col) |
|
229 self.w(entity.dc_long_title()) |
|
230 |
|
231 |
|
232 class InContextView(EntityView): |
|
233 __regid__ = 'incontext' |
|
234 |
|
235 def cell_call(self, row, col): |
|
236 entity = self.cw_rset.get_entity(row, col) |
|
237 desc = cut(entity.dc_description(), 50) |
|
238 self.w(u'<a href="%s" title="%s">' % ( |
|
239 xml_escape(entity.absolute_url()), xml_escape(desc))) |
|
240 self.w(xml_escape(self._cw.view('textincontext', self.cw_rset, |
|
241 row=row, col=col))) |
|
242 self.w(u'</a>') |
|
243 |
|
244 |
|
245 class OutOfContextView(EntityView): |
|
246 __regid__ = 'outofcontext' |
|
247 |
|
248 def cell_call(self, row, col): |
|
249 entity = self.cw_rset.get_entity(row, col) |
|
250 desc = cut(entity.dc_description(), 50) |
|
251 self.w(u'<a href="%s" title="%s">' % ( |
|
252 xml_escape(entity.absolute_url()), xml_escape(desc))) |
|
253 self.w(xml_escape(self._cw.view('textoutofcontext', self.cw_rset, |
|
254 row=row, col=col))) |
|
255 self.w(u'</a>') |
|
256 |
|
257 |
|
258 # list views ################################################################## |
|
259 |
|
260 class ListView(EntityView): |
|
261 __regid__ = 'list' |
|
262 title = _('list') |
|
263 item_vid = 'listitem' |
|
264 |
|
265 def call(self, klass=None, title=None, subvid=None, listid=None, **kwargs): |
|
266 """display a list of entities by calling their <item_vid> view |
|
267 |
|
268 :param listid: the DOM id to use for the root element |
|
269 """ |
|
270 # XXX much of the behaviour here should probably be outside this view |
|
271 if subvid is None and 'subvid' in self._cw.form: |
|
272 subvid = self._cw.form.pop('subvid') # consume it |
|
273 if listid: |
|
274 listid = u' id="%s"' % listid |
|
275 else: |
|
276 listid = u'' |
|
277 if title: |
|
278 self.w(u'<div%s class="%s"><h4>%s</h4>\n' % (listid, klass or 'section', title)) |
|
279 self.w(u'<ul>\n') |
|
280 else: |
|
281 self.w(u'<ul%s class="%s">\n' % (listid, klass or 'section')) |
|
282 for i in xrange(self.cw_rset.rowcount): |
|
283 self.cell_call(row=i, col=0, vid=subvid, **kwargs) |
|
284 self.w(u'</ul>\n') |
|
285 if title: |
|
286 self.w(u'</div>\n') |
|
287 |
|
288 def cell_call(self, row, col=0, vid=None, **kwargs): |
|
289 self.w(u'<li>') |
|
290 self.wview(self.item_vid, self.cw_rset, row=row, col=col, vid=vid, **kwargs) |
|
291 self.w(u'</li>\n') |
|
292 |
|
293 |
|
294 class ListItemView(EntityView): |
|
295 __regid__ = 'listitem' |
|
296 |
|
297 @property |
|
298 def redirect_vid(self): |
|
299 if self._cw.search_state[0] == 'normal': |
|
300 return 'outofcontext' |
|
301 return 'outofcontext-search' |
|
302 |
|
303 def cell_call(self, row, col, vid=None, **kwargs): |
|
304 if not vid: |
|
305 vid = self.redirect_vid |
|
306 try: |
|
307 self.wview(vid, self.cw_rset, row=row, col=col, **kwargs) |
|
308 except NoSelectableObject: |
|
309 if vid == self.redirect_vid: |
|
310 raise |
|
311 self.wview(self.redirect_vid, self.cw_rset, row=row, col=col, **kwargs) |
|
312 |
|
313 |
|
314 class SimpleListView(ListItemView): |
|
315 """list without bullets""" |
|
316 __regid__ = 'simplelist' |
|
317 redirect_vid = 'incontext' |
|
318 |
|
319 def call(self, subvid=None, **kwargs): |
|
320 """display a list of entities by calling their <item_vid> view |
|
321 |
|
322 :param listid: the DOM id to use for the root element |
|
323 """ |
|
324 if subvid is None and 'vid' in kwargs: |
|
325 warn("should give a 'subvid' argument instead of 'vid'", |
|
326 DeprecationWarning, stacklevel=2) |
|
327 else: |
|
328 kwargs['vid'] = subvid |
|
329 return super(SimpleListView, self).call(**kwargs) |
|
330 |
|
331 |
|
332 class SameETypeListView(EntityView): |
|
333 """list of entities of the same type, when asked explicitly for same etype list |
|
334 view (for instance, display gallery if only images) |
|
335 """ |
|
336 __regid__ = 'sameetypelist' |
|
337 __select__ = EntityView.__select__ & one_etype_rset() |
|
338 item_vid = 'sameetypelistitem' |
|
339 |
|
340 @property |
|
341 def title(self): |
|
342 etype = iter(self.cw_rset.column_types(0)).next() |
|
343 return display_name(self._cw, etype, form='plural') |
|
344 |
|
345 def call(self, **kwargs): |
|
346 """display a list of entities by calling their <item_vid> view""" |
|
347 showtitle = kwargs.pop('showtitle', not 'vtitle' in self._cw.form) |
|
348 if showtitle: |
|
349 self.w(u'<h1>%s</h1>' % self.title) |
|
350 super(SameETypeListView, self).call(**kwargs) |
|
351 |
|
352 def cell_call(self, row, col=0, **kwargs): |
|
353 self.wview(self.item_vid, self.cw_rset, row=row, col=col, **kwargs) |
|
354 |
|
355 |
|
356 class SameETypeListItemView(EntityView): |
|
357 __regid__ = 'sameetypelistitem' |
|
358 |
|
359 def cell_call(self, row, col, **kwargs): |
|
360 self.wview('listitem', self.cw_rset, row=row, col=col, **kwargs) |
|
361 |
|
362 |
|
363 class CSVView(SimpleListView): |
|
364 __regid__ = 'csv' |
|
365 redirect_vid = 'incontext' |
|
366 |
|
367 def call(self, subvid=None, **kwargs): |
|
368 if subvid is None and 'vid' in kwargs: |
|
369 warn("[3.9] should give a 'subvid' argument instead of 'vid'", |
|
370 DeprecationWarning, stacklevel=2) |
|
371 else: |
|
372 kwargs['vid'] = subvid |
|
373 rset = self.cw_rset |
|
374 for i in xrange(len(rset)): |
|
375 self.cell_call(i, 0, **kwargs) |
|
376 if i < rset.rowcount-1: |
|
377 self.w(u", ") |
|
378 |
|
379 |
|
380 class TreeItemView(ListItemView): |
515 class TreeItemView(ListItemView): |
381 __regid__ = 'treeitem' |
516 __regid__ = 'treeitem' |
382 |
517 |
383 def cell_call(self, row, col): |
518 def cell_call(self, row, col): |
384 self.wview('incontext', self.cw_rset, row=row, col=col) |
519 self.wview('incontext', self.cw_rset, row=row, col=col) |
|
520 |
385 |
521 |
386 class TextSearchResultView(EntityView): |
522 class TextSearchResultView(EntityView): |
387 """this view is used to display full-text search |
523 """this view is used to display full-text search |
388 |
524 |
389 It tries to highlight part of data where the search word appears. |
525 It tries to highlight part of data where the search word appears. |
423 __regid__ = 'tooltip' |
559 __regid__ = 'tooltip' |
424 def cell_call(self, row, col): |
560 def cell_call(self, row, col): |
425 self.wview('oneline', self.cw_rset, row=row, col=col) |
561 self.wview('oneline', self.cw_rset, row=row, col=col) |
426 |
562 |
427 |
563 |
428 # XXX bw compat |
|
429 |
|
430 from logilab.common.deprecation import class_moved |
|
431 |
|
432 try: |
|
433 from cubicweb.web.views.tableview import TableView |
|
434 TableView = class_moved(TableView) |
|
435 except ImportError: |
|
436 pass # gae has no tableview module (yet) |
|
437 |
|
438 from cubicweb.web.views import boxes, xmlrss, primary |
|
439 PrimaryView = class_moved(primary.PrimaryView) |
|
440 SideBoxView = class_moved(boxes.SideBoxView) |
|
441 XmlView = class_moved(xmlrss.XMLView) |
|
442 XmlItemView = class_moved(xmlrss.XMLItemView) |
|
443 XmlRsetView = class_moved(xmlrss.XMLRsetView) |
|
444 RssView = class_moved(xmlrss.RSSView) |
|
445 RssItemView = class_moved(xmlrss.RSSItemView) |
|
446 |
|
447 |
|
448 class GroupByView(EntityView): |
564 class GroupByView(EntityView): |
449 """grouped view of a result set. The `group_key` method return the group |
565 """grouped view of a result set. The `group_key` method return the group |
450 key of an entities (a string or tuple of string). |
566 key of an entities (a string or tuple of string). |
451 |
567 |
452 For each group, display a link to entities of this group by generating url |
568 For each group, display a link to entities of this group by generating url |
453 like <basepath>/<key> or <basepath>/<key item 1>/<key item 2>. |
569 like <basepath>/<key> or <basepath>/<key item 1>/<key item 2>. |
454 """ |
570 """ |
455 __abstrack__ = True |
571 __abstract__ = True |
456 __select__ = EntityView.__select__ & match_kwargs('basepath') |
572 __select__ = EntityView.__select__ & match_kwargs('basepath') |
457 entity_attribute = None |
573 entity_attribute = None |
458 reversed = False |
574 reversed = False |
459 |
575 |
460 def index_url(self, basepath, key, **kwargs): |
576 def index_url(self, basepath, key, **kwargs): |
548 for etype in etypes), |
664 for etype in etypes), |
549 'author': label} |
665 'author': label} |
550 url = self.index_url(basepath, key, vtitle=vtitle) |
666 url = self.index_url(basepath, key, vtitle=vtitle) |
551 title = self._cw._('archive for %(author)s') % {'author': key} |
667 title = self._cw._('archive for %(author)s') % {'author': key} |
552 return tags.a(label, href=url, title=title) |
668 return tags.a(label, href=url, title=title) |
|
669 |
|
670 |
|
671 # bw compat #################################################################### |
|
672 |
|
673 from logilab.common.deprecation import class_moved, class_deprecated |
|
674 |
|
675 from cubicweb.web.views import boxes, xmlrss, primary, tableview |
|
676 PrimaryView = class_moved(primary.PrimaryView) |
|
677 SideBoxView = class_moved(boxes.SideBoxView) |
|
678 XmlView = class_moved(xmlrss.XMLView) |
|
679 XmlItemView = class_moved(xmlrss.XMLItemView) |
|
680 XmlRsetView = class_moved(xmlrss.XMLRsetView) |
|
681 RssView = class_moved(xmlrss.RSSView) |
|
682 RssItemView = class_moved(xmlrss.RSSItemView) |
|
683 TableView = class_moved(tableview.TableView) |
|
684 |
|
685 |
|
686 class SecondaryView(EntityView): |
|
687 __metaclass__ = class_deprecated |
|
688 __deprecation_warning__ = '[3.9] the secondary view is deprecated, use one of oneline/incontext/outofcontext' |
|
689 __regid__ = 'secondary' |
|
690 |
|
691 def cell_call(self, row, col, **kwargs): |
|
692 entity = self.cw_rset.get_entity(row, col) |
|
693 self.w(u' ') |
|
694 self.wview('oneline', self.cw_rset, row=row, col=col) |