author | Aurelien Campeas <aurelien.campeas@logilab.fr> |
Mon, 24 Nov 2014 16:22:40 +0100 | |
branch | stable |
changeset 10049 | 8facecb02e42 |
parent 8976 | aeb7d400ee92 |
child 9256 | 697a8181ba30 |
permissions | -rw-r--r-- |
8190
2a3c1b787688
[vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8174
diff
changeset
|
1 |
# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
5421
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
2 |
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
3 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
4 |
# This file is part of CubicWeb. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
5 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
6 |
# CubicWeb is free software: you can redistribute it and/or modify it under the |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
7 |
# terms of the GNU Lesser General Public License as published by the Free |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
8 |
# Software Foundation, either version 2.1 of the License, or (at your option) |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
9 |
# any later version. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
10 |
# |
5424
8ecbcbff9777
replace logilab-common by CubicWeb in disclaimer
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5421
diff
changeset
|
11 |
# CubicWeb is distributed in the hope that it will be useful, but WITHOUT |
5421
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
12 |
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
13 |
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
14 |
# details. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
15 |
# |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
16 |
# You should have received a copy of the GNU Lesser General Public License along |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5389
diff
changeset
|
17 |
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
5528 | 18 |
"""abstract views and templates classes for CubicWeb web client""" |
0 | 19 |
|
20 |
__docformat__ = "restructuredtext en" |
|
1999
b9a8f5995658
obsolete methods
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1985
diff
changeset
|
21 |
_ = unicode |
0 | 22 |
|
6864
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
23 |
import types, new |
0 | 24 |
from cStringIO import StringIO |
4244
2c3de1953d00
rename need_navigation into paginable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
25 |
from warnings import warn |
7938
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
26 |
from functools import partial |
0 | 27 |
|
2613
5e19c2bb370e
R [all] logilab.common 0.44 provides only deprecated
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
2558
diff
changeset
|
28 |
from logilab.common.deprecation import deprecated |
8666
1dd655788ece
make ui configurations selectable (closes #2406609)
Florent Cayré <florent.cayre@logilab.fr>
parents:
8425
diff
changeset
|
29 |
from logilab.common.registry import yes |
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2217
diff
changeset
|
30 |
from logilab.mtconverter import xml_escape |
4058
b3578583b57b
properly escape arguments of user callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3973
diff
changeset
|
31 |
|
2644
100b81ba3a98
F [view] missing import
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2613
diff
changeset
|
32 |
from rql import nodes |
0 | 33 |
|
1181
620ec8e6ae19
cleanup, various fix to get something working
sylvain.thenault@logilab.fr
parents:
1144
diff
changeset
|
34 |
from cubicweb import NotAnEntity |
8190
2a3c1b787688
[vreg] move base registry implementation to logilab.common. Closes #1916014
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8174
diff
changeset
|
35 |
from cubicweb.predicates import non_final_entity, nonempty_rset, none_rset |
2656
a93ae0f6c0ad
R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2644
diff
changeset
|
36 |
from cubicweb.appobject import AppObject |
708
b4728112625f
move utils from cw.common to cw
sylvain.thenault@logilab.fr
parents:
707
diff
changeset
|
37 |
from cubicweb.utils import UStringIO, HTMLStream |
6044
9e48ebd5400c
[view] use the new magic js object to generate javascript func call for auto reload user callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6038
diff
changeset
|
38 |
from cubicweb.uilib import domid, js |
2217
3a8cee8f8778
explicit display_name import
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2207
diff
changeset
|
39 |
from cubicweb.schema import display_name |
633 | 40 |
|
0 | 41 |
# robots control |
42 |
NOINDEX = u'<meta name="ROBOTS" content="NOINDEX" />' |
|
43 |
NOFOLLOW = u'<meta name="ROBOTS" content="NOFOLLOW" />' |
|
44 |
||
8941
7b26fe71404f
drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
8666
diff
changeset
|
45 |
TRANSITIONAL_DOCTYPE_NOEXT = u'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n' |
7b26fe71404f
drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
8666
diff
changeset
|
46 |
TRANSITIONAL_DOCTYPE = TRANSITIONAL_DOCTYPE_NOEXT # bw compat |
0 | 47 |
|
6769
d784d64f28d0
Backed out changeset 84b67ae41a0d: with this fix, some
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6761
diff
changeset
|
48 |
STRICT_DOCTYPE_NOEXT = u'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n' |
8941
7b26fe71404f
drop xhtml content-type support (closes #2065651)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
8666
diff
changeset
|
49 |
STRICT_DOCTYPE = STRICT_DOCTYPE_NOEXT # bw compat |
0 | 50 |
|
661
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
51 |
# base view object ############################################################ |
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
52 |
|
2656
a93ae0f6c0ad
R [base classes] only AppObject remaning, no more AppRsetObject
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2644
diff
changeset
|
53 |
class View(AppObject): |
8419
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
54 |
"""This class is an abstraction of a view class, used as a base class for |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
55 |
every renderable object such as views, templates and other user interface |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
56 |
components. |
0 | 57 |
|
8419
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
58 |
A `View` is instantiated to render a result set or part of a result |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
59 |
set. `View` subclasses may be parametrized using the following class |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
60 |
attributes: |
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
61 |
|
8419
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
62 |
:py:attr:`templatable` indicates if the view may be embedded in a main |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
63 |
template or if it has to be rendered standalone (i.e. pure XML views must |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
64 |
not be embedded in the main template of HTML pages) |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
65 |
:py:attr:`content_type` if the view is not templatable, it should set the |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
66 |
`content_type` class attribute to the correct MIME type (text/xhtml being |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
67 |
the default) |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
68 |
:py:attr:`category` this attribute may be used in the interface to regroup |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
69 |
related objects (view kinds) together |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
70 |
|
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
71 |
:py:attr:`paginable` |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
72 |
|
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
73 |
:py:attr:`binary` |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
74 |
|
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
75 |
|
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
76 |
A view writes to its output stream thanks to its attribute `w` (the |
dd222fcc85d3
[doc] cubicweb.view documentation (closes: #2099962)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8204
diff
changeset
|
77 |
append method of an `UStreamIO`, except for binary views). |
0 | 78 |
|
4702
d9e51820d0c2
fix docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4459
diff
changeset
|
79 |
At instantiation time, the standard `_cw`, and `cw_rset` attributes are |
d9e51820d0c2
fix docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4459
diff
changeset
|
80 |
added and the `w` attribute will be set at rendering time to a write |
d9e51820d0c2
fix docstring
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4459
diff
changeset
|
81 |
function to use. |
0 | 82 |
""" |
816
9cd49a910fce
kill Template class and 'templates' registry
sylvain.thenault@logilab.fr
parents:
781
diff
changeset
|
83 |
__registry__ = 'views' |
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
84 |
|
0 | 85 |
templatable = True |
86 |
# content_type = 'application/xhtml+xml' # text/xhtml' |
|
87 |
binary = False |
|
88 |
add_to_breadcrumbs = True |
|
89 |
category = 'view' |
|
7990
a673d1d9a738
[diet]Â drop pre 3.6 API compatibility (but attempt to keep data cmopatibility). Closes #2017916
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7959
diff
changeset
|
90 |
paginable = True |
4244
2c3de1953d00
rename need_navigation into paginable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4212
diff
changeset
|
91 |
|
1143
8d097defbf2c
change the way selected/__init__ are used for AppRsetObject
sylvain.thenault@logilab.fr
parents:
1132
diff
changeset
|
92 |
def __init__(self, req=None, rset=None, **kwargs): |
2822
f26578339214
deprecate appobject.vreg and rename appobject instance attributes using cw_ prefix
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2819
diff
changeset
|
93 |
super(View, self).__init__(req, rset=rset, **kwargs) |
0 | 94 |
self.w = None |
95 |
||
96 |
@property |
|
97 |
def content_type(self): |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
98 |
return self._cw.html_content_type() |
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
99 |
|
0 | 100 |
def set_stream(self, w=None): |
101 |
if self.w is not None: |
|
102 |
return |
|
103 |
if w is None: |
|
104 |
if self.binary: |
|
105 |
self._stream = stream = StringIO() |
|
106 |
else: |
|
107 |
self._stream = stream = UStringIO() |
|
108 |
w = stream.write |
|
109 |
else: |
|
110 |
stream = None |
|
111 |
self.w = w |
|
112 |
return stream |
|
113 |
||
114 |
# main view interface ##################################################### |
|
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
115 |
|
1723 | 116 |
def render(self, w=None, **context): |
0 | 117 |
"""called to render a view object for a result set. |
118 |
||
119 |
This method is a dispatched to an actual method selected |
|
120 |
according to optional row and col parameters, which are locating |
|
121 |
a particular row or cell in the result set: |
|
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
122 |
|
1132 | 123 |
* if row is specified, `cell_call` is called |
0 | 124 |
* if none of them is supplied, the view is considered to apply on |
125 |
the whole result set (which may be None in this case), `call` is |
|
126 |
called |
|
127 |
""" |
|
6922
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
128 |
# XXX use .cw_row/.cw_col |
1132 | 129 |
row = context.get('row') |
0 | 130 |
if row is not None: |
131 |
context.setdefault('col', 0) |
|
132 |
view_func = self.cell_call |
|
133 |
else: |
|
134 |
view_func = self.call |
|
135 |
stream = self.set_stream(w) |
|
6563
33343d6eae0a
[view] log error on view_func call
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6458
diff
changeset
|
136 |
try: |
33343d6eae0a
[view] log error on view_func call
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6458
diff
changeset
|
137 |
view_func(**context) |
7815
2a164a9cf81c
[exceptions] stop catching any exception in various places (closes #1942716)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7670
diff
changeset
|
138 |
except Exception: |
6563
33343d6eae0a
[view] log error on view_func call
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6458
diff
changeset
|
139 |
self.debug('view call %s failed (context=%s)', view_func, context) |
33343d6eae0a
[view] log error on view_func call
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6458
diff
changeset
|
140 |
raise |
0 | 141 |
# return stream content if we have created it |
142 |
if stream is not None: |
|
143 |
return self._stream.getvalue() |
|
144 |
||
2795
59965167bef3
move tal_render to View
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
145 |
def tal_render(self, template, variables): |
59965167bef3
move tal_render to View
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
146 |
"""render a precompiled page template with variables in the given |
59965167bef3
move tal_render to View
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
147 |
dictionary as context |
59965167bef3
move tal_render to View
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
148 |
""" |
59965167bef3
move tal_render to View
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
149 |
from cubicweb.ext.tal import CubicWebContext |
59965167bef3
move tal_render to View
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
150 |
context = CubicWebContext() |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
151 |
context.update({'self': self, 'rset': self.cw_rset, '_' : self._cw._, |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
152 |
'req': self._cw, 'user': self._cw.user}) |
2795
59965167bef3
move tal_render to View
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
153 |
context.update(variables) |
59965167bef3
move tal_render to View
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
154 |
output = UStringIO() |
59965167bef3
move tal_render to View
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
155 |
template.expand(context, output) |
59965167bef3
move tal_render to View
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
156 |
return output.getvalue() |
59965167bef3
move tal_render to View
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2788
diff
changeset
|
157 |
|
0 | 158 |
# should default .call() method add a <div classs="section"> around each |
159 |
# rset item |
|
160 |
add_div_section = True |
|
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
161 |
|
0 | 162 |
def call(self, **kwargs): |
163 |
"""the view is called for an entire result set, by default loop |
|
164 |
other rows of the result set and call the same view on the |
|
165 |
particular row |
|
166 |
||
167 |
Views applicable on None result sets have to override this method |
|
168 |
""" |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
169 |
rset = self.cw_rset |
0 | 170 |
if rset is None: |
8204
332596be995e
[view] fix error messages of NotImplementedError
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
8174
diff
changeset
|
171 |
raise NotImplementedError("%r an rset is required" % self) |
0 | 172 |
wrap = self.templatable and len(rset) > 1 and self.add_div_section |
6922
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
173 |
# avoid re-selection if rset of size 1, we already have the most |
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
174 |
# specific view |
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
175 |
if rset.rowcount != 1: |
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
176 |
kwargs.setdefault('initargs', self.cw_extra_kwargs) |
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
177 |
for i in xrange(len(rset)): |
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
178 |
if wrap: |
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
179 |
self.w(u'<div class="section">') |
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
180 |
self.wview(self.__regid__, rset, row=i, **kwargs) |
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
181 |
if wrap: |
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
182 |
self.w(u"</div>") |
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
183 |
else: |
0 | 184 |
if wrap: |
185 |
self.w(u'<div class="section">') |
|
6922
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
186 |
kwargs.setdefault('col', 0) |
cb1dd14a768f
[view] fix/enhance view.render
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6909
diff
changeset
|
187 |
self.cell_call(row=0, **kwargs) |
0 | 188 |
if wrap: |
189 |
self.w(u"</div>") |
|
190 |
||
191 |
def cell_call(self, row, col, **kwargs): |
|
192 |
"""the view is called for a particular result set cell""" |
|
8204
332596be995e
[view] fix error messages of NotImplementedError
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
8174
diff
changeset
|
193 |
raise NotImplementedError(repr(self)) |
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
194 |
|
0 | 195 |
def linkable(self): |
196 |
"""return True if the view may be linked in a menu |
|
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
197 |
|
0 | 198 |
by default views without title are not meant to be displayed |
199 |
""" |
|
200 |
if not getattr(self, 'title', None): |
|
201 |
return False |
|
202 |
return True |
|
203 |
||
204 |
def is_primary(self): |
|
4045
f4a52abb6f4f
cw 3.6 api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents:
3998
diff
changeset
|
205 |
return self.cw_extra_kwargs.get('is_primary', self.__regid__ == 'primary') |
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
206 |
|
0 | 207 |
def url(self): |
208 |
"""return the url associated with this view. Should not be |
|
209 |
necessary for non linkable views, but a default implementation |
|
210 |
is provided anyway. |
|
211 |
""" |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
212 |
rset = self.cw_rset |
2468
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
213 |
if rset is None: |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
214 |
return self._cw.build_url('view', vid=self.__regid__) |
2468
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
215 |
coltypes = rset.column_types(0) |
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
216 |
if len(coltypes) == 1: |
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
217 |
etype = iter(coltypes).next() |
4045
f4a52abb6f4f
cw 3.6 api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents:
3998
diff
changeset
|
218 |
if not self._cw.vreg.schema.eschema(etype).final: |
2468
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
219 |
if len(rset) == 1: |
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
220 |
entity = rset.get_entity(0, 0) |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
221 |
return entity.absolute_url(vid=self.__regid__) |
2468
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
222 |
# don't want to generate /<etype> url if there is some restriction |
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
223 |
# on something else than the entity type |
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
224 |
restr = rset.syntax_tree().children[0].where |
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
225 |
# XXX norestriction is not correct here. For instance, in cases like |
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
226 |
# "Any P,N WHERE P is Project, P name N" norestriction should equal |
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
227 |
# True |
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
228 |
norestriction = (isinstance(restr, nodes.Relation) and |
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
229 |
restr.is_types_restriction()) |
93853b6f3bad
move all view.url() logic in a single implementation
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2418
diff
changeset
|
230 |
if norestriction: |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
231 |
return self._cw.build_url(etype.lower(), vid=self.__regid__) |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
232 |
return self._cw.build_url('view', rql=rset.printable_rql(), vid=self.__regid__) |
0 | 233 |
|
234 |
def set_request_content_type(self): |
|
235 |
"""set the content type returned by this view""" |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
236 |
self._cw.set_content_type(self.content_type) |
0 | 237 |
|
238 |
# view utilities ########################################################## |
|
1433 | 239 |
|
1985
9c1db4e06095
move view method's logic on the registry, so it's easier to call it from outside an appobject. Also make rset argument optional
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1977
diff
changeset
|
240 |
def wview(self, __vid, rset=None, __fallback_vid=None, **kwargs): |
0 | 241 |
"""shortcut to self.view method automatically passing self.w as argument |
242 |
""" |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
243 |
self._cw.view(__vid, rset, __fallback_vid, w=self.w, **kwargs) |
1433 | 244 |
|
0 | 245 |
def whead(self, data): |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
246 |
self._cw.html_headers.write(data) |
0 | 247 |
|
248 |
def wdata(self, data): |
|
249 |
"""simple helper that escapes `data` and writes into `self.w`""" |
|
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2217
diff
changeset
|
250 |
self.w(xml_escape(data)) |
0 | 251 |
|
252 |
def html_headers(self): |
|
253 |
"""return a list of html headers (eg something to be inserted between |
|
254 |
<head> and </head> of the returned page |
|
255 |
||
256 |
by default return a meta tag to disable robot indexation of the page |
|
257 |
""" |
|
258 |
return [NOINDEX] |
|
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
259 |
|
0 | 260 |
def page_title(self): |
261 |
"""returns a title according to the result set - used for the |
|
262 |
title in the HTML header |
|
263 |
""" |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
264 |
vtitle = self._cw.form.get('vtitle') |
0 | 265 |
if vtitle: |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
266 |
return self._cw._(vtitle) |
0 | 267 |
# class defined title will only be used if the resulting title doesn't |
268 |
# seem clear enough |
|
269 |
vtitle = getattr(self, 'title', None) or u'' |
|
270 |
if vtitle: |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
271 |
vtitle = self._cw._(vtitle) |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
272 |
rset = self.cw_rset |
0 | 273 |
if rset and rset.rowcount: |
274 |
if rset.rowcount == 1: |
|
275 |
try: |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
276 |
entity = rset.complete_entity(0, 0) |
0 | 277 |
# use long_title to get context information if any |
278 |
clabel = entity.dc_long_title() |
|
279 |
except NotAnEntity: |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
280 |
clabel = display_name(self._cw, rset.description[0][0]) |
0 | 281 |
clabel = u'%s (%s)' % (clabel, vtitle) |
282 |
else : |
|
283 |
etypes = rset.column_types(0) |
|
284 |
if len(etypes) == 1: |
|
285 |
etype = iter(etypes).next() |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
286 |
clabel = display_name(self._cw, etype, 'plural') |
0 | 287 |
else : |
288 |
clabel = u'#[*] (%s)' % vtitle |
|
289 |
else: |
|
290 |
clabel = vtitle |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
291 |
return u'%s (%s)' % (clabel, self._cw.property_value('ui.site-title')) |
0 | 292 |
|
6039
6e84db1b3e44
[view] deprecate create_url in favor of a cw_create_url class method on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5725
diff
changeset
|
293 |
@deprecated('[3.10] use vreg["etypes"].etype_class(etype).cw_create_url(req)') |
0 | 294 |
def create_url(self, etype, **kwargs): |
295 |
""" return the url of the entity creation form for a given entity type""" |
|
6039
6e84db1b3e44
[view] deprecate create_url in favor of a cw_create_url class method on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5725
diff
changeset
|
296 |
return self._cw.vreg["etypes"].etype_class(etype).cw_create_url( |
6e84db1b3e44
[view] deprecate create_url in favor of a cw_create_url class method on entity classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5725
diff
changeset
|
297 |
self._cw, **kwargs) |
0 | 298 |
|
6038
5c5d819e8e93
small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5725
diff
changeset
|
299 |
def field(self, label, value, row=True, show_label=True, w=None, tr=True, |
5c5d819e8e93
small cleanups
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5725
diff
changeset
|
300 |
table=False): |
3809
1b9b51ee543e
[web ui] PrimaryView.render_attributes now uses a table
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
3782
diff
changeset
|
301 |
"""read-only field""" |
0 | 302 |
if w is None: |
303 |
w = self.w |
|
3809
1b9b51ee543e
[web ui] PrimaryView.render_attributes now uses a table
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
3782
diff
changeset
|
304 |
if table: |
1b9b51ee543e
[web ui] PrimaryView.render_attributes now uses a table
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
3782
diff
changeset
|
305 |
w(u'<tr class="entityfield">') |
1b9b51ee543e
[web ui] PrimaryView.render_attributes now uses a table
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
3782
diff
changeset
|
306 |
else: |
1b9b51ee543e
[web ui] PrimaryView.render_attributes now uses a table
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
3782
diff
changeset
|
307 |
w(u'<div class="entityfield">') |
3326
e3089ceee1ea
don't show label if no label given
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3010
diff
changeset
|
308 |
if show_label and label: |
0 | 309 |
if tr: |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
310 |
label = display_name(self._cw, label) |
3809
1b9b51ee543e
[web ui] PrimaryView.render_attributes now uses a table
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
3782
diff
changeset
|
311 |
if table: |
1b9b51ee543e
[web ui] PrimaryView.render_attributes now uses a table
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
3782
diff
changeset
|
312 |
w(u'<th>%s</th>' % label) |
1b9b51ee543e
[web ui] PrimaryView.render_attributes now uses a table
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
3782
diff
changeset
|
313 |
else: |
6909
b8171392de16
[view] missing class on label span
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6864
diff
changeset
|
314 |
w(u'<span class="label">%s</span> ' % label) |
3809
1b9b51ee543e
[web ui] PrimaryView.render_attributes now uses a table
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
3782
diff
changeset
|
315 |
if table: |
3969
970a748684b5
when fields are displayed in a table and label should'nt be displayed, set colspan to 2 on the field value cell
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3839
diff
changeset
|
316 |
if not (show_label and label): |
970a748684b5
when fields are displayed in a table and label should'nt be displayed, set colspan to 2 on the field value cell
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3839
diff
changeset
|
317 |
w(u'<td colspan="2">%s</td></tr>' % value) |
970a748684b5
when fields are displayed in a table and label should'nt be displayed, set colspan to 2 on the field value cell
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3839
diff
changeset
|
318 |
else: |
970a748684b5
when fields are displayed in a table and label should'nt be displayed, set colspan to 2 on the field value cell
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3839
diff
changeset
|
319 |
w(u'<td>%s</td></tr>' % value) |
3809
1b9b51ee543e
[web ui] PrimaryView.render_attributes now uses a table
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
3782
diff
changeset
|
320 |
else: |
1b9b51ee543e
[web ui] PrimaryView.render_attributes now uses a table
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
3782
diff
changeset
|
321 |
w(u'<span>%s</span></div>' % value) |
1433 | 322 |
|
0 | 323 |
|
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
324 |
|
640
8e64f12be69c
drop EntityAction usage in cw, upgrade rql_condition and friends
sylvain.thenault@logilab.fr
parents:
635
diff
changeset
|
325 |
# concrete views base classes ################################################# |
8e64f12be69c
drop EntityAction usage in cw, upgrade rql_condition and friends
sylvain.thenault@logilab.fr
parents:
635
diff
changeset
|
326 |
|
8e64f12be69c
drop EntityAction usage in cw, upgrade rql_condition and friends
sylvain.thenault@logilab.fr
parents:
635
diff
changeset
|
327 |
class EntityView(View): |
843 | 328 |
"""base class for views applying on an entity (i.e. uniform result set)""" |
781
323656dd85a9
fix import, use non_final_entity instead of implements('Any')
sylvain.thenault@logilab.fr
parents:
757
diff
changeset
|
329 |
__select__ = non_final_entity() |
7670
6397a9051f65
[boxes] closes #1832844: translate views category in possible views boxes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7346
diff
changeset
|
330 |
category = _('entityview') |
640
8e64f12be69c
drop EntityAction usage in cw, upgrade rql_condition and friends
sylvain.thenault@logilab.fr
parents:
635
diff
changeset
|
331 |
|
5715
2c3e83817a8e
[view] add a new entity_call method to entity view protocol, allowing some to work with not yet created entities. Also, start considering 'eid' form parameters where we only consider 'rql', so we can move on bloquing arbitrary rql inputs (more to do on this...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5679
diff
changeset
|
332 |
def call(self, **kwargs): |
2c3e83817a8e
[view] add a new entity_call method to entity view protocol, allowing some to work with not yet created entities. Also, start considering 'eid' form parameters where we only consider 'rql', so we can move on bloquing arbitrary rql inputs (more to do on this...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5679
diff
changeset
|
333 |
if self.cw_rset is None: |
7833
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
334 |
# * cw_extra_kwargs is the place where extra selection arguments are |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
335 |
# stored |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
336 |
# * when calling req.view('somevid', entity=entity), 'entity' ends |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
337 |
# up in cw_extra_kwargs and kwargs |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
338 |
# |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
339 |
# handle that to avoid a TypeError with a sanity check |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
340 |
# |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
341 |
# Notice that could probably be avoided by handling entity_call in |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
342 |
# .render |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
343 |
entity = self.cw_extra_kwargs.pop('entity') |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
344 |
if 'entity' in kwargs: |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
345 |
assert kwargs.pop('entity') is entity |
f19e3203dff6
[view] fix TypeError when calling req.view('vid', entity=entity) (closes #1947474)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7815
diff
changeset
|
346 |
self.entity_call(entity, **kwargs) |
5715
2c3e83817a8e
[view] add a new entity_call method to entity view protocol, allowing some to work with not yet created entities. Also, start considering 'eid' form parameters where we only consider 'rql', so we can move on bloquing arbitrary rql inputs (more to do on this...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5679
diff
changeset
|
347 |
else: |
2c3e83817a8e
[view] add a new entity_call method to entity view protocol, allowing some to work with not yet created entities. Also, start considering 'eid' form parameters where we only consider 'rql', so we can move on bloquing arbitrary rql inputs (more to do on this...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5679
diff
changeset
|
348 |
super(EntityView, self).call(**kwargs) |
2c3e83817a8e
[view] add a new entity_call method to entity view protocol, allowing some to work with not yet created entities. Also, start considering 'eid' form parameters where we only consider 'rql', so we can move on bloquing arbitrary rql inputs (more to do on this...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5679
diff
changeset
|
349 |
|
2c3e83817a8e
[view] add a new entity_call method to entity view protocol, allowing some to work with not yet created entities. Also, start considering 'eid' form parameters where we only consider 'rql', so we can move on bloquing arbitrary rql inputs (more to do on this...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5679
diff
changeset
|
350 |
def cell_call(self, row, col, **kwargs): |
2c3e83817a8e
[view] add a new entity_call method to entity view protocol, allowing some to work with not yet created entities. Also, start considering 'eid' form parameters where we only consider 'rql', so we can move on bloquing arbitrary rql inputs (more to do on this...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5679
diff
changeset
|
351 |
self.entity_call(self.cw_rset.get_entity(row, col), **kwargs) |
2c3e83817a8e
[view] add a new entity_call method to entity view protocol, allowing some to work with not yet created entities. Also, start considering 'eid' form parameters where we only consider 'rql', so we can move on bloquing arbitrary rql inputs (more to do on this...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5679
diff
changeset
|
352 |
|
2c3e83817a8e
[view] add a new entity_call method to entity view protocol, allowing some to work with not yet created entities. Also, start considering 'eid' form parameters where we only consider 'rql', so we can move on bloquing arbitrary rql inputs (more to do on this...)
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5679
diff
changeset
|
353 |
def entity_call(self, entity, **kwargs): |
8204
332596be995e
[view] fix error messages of NotImplementedError
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
8174
diff
changeset
|
354 |
raise NotImplementedError('%r %r' % (self.__regid__, self.__class__)) |
640
8e64f12be69c
drop EntityAction usage in cw, upgrade rql_condition and friends
sylvain.thenault@logilab.fr
parents:
635
diff
changeset
|
355 |
|
6926 | 356 |
|
0 | 357 |
class StartupView(View): |
843 | 358 |
"""base class for views which doesn't need a particular result set to be |
359 |
displayed (so they can always be displayed !) |
|
0 | 360 |
""" |
707 | 361 |
__select__ = none_rset() |
1433 | 362 |
|
7670
6397a9051f65
[boxes] closes #1832844: translate views category in possible views boxes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7346
diff
changeset
|
363 |
category = _('startupview') |
1433 | 364 |
|
0 | 365 |
def html_headers(self): |
366 |
"""return a list of html headers (eg something to be inserted between |
|
367 |
<head> and </head> of the returned page |
|
368 |
||
369 |
by default startup views are indexed |
|
370 |
""" |
|
371 |
return [] |
|
372 |
||
373 |
||
374 |
class EntityStartupView(EntityView): |
|
375 |
"""base class for entity views which may also be applied to None |
|
376 |
result set (usually a default rql is provided by the view class) |
|
377 |
""" |
|
781
323656dd85a9
fix import, use non_final_entity instead of implements('Any')
sylvain.thenault@logilab.fr
parents:
757
diff
changeset
|
378 |
__select__ = none_rset() | non_final_entity() |
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
379 |
|
0 | 380 |
default_rql = None |
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
381 |
|
2418
8f06e4f02733
optional rset
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2312
diff
changeset
|
382 |
def __init__(self, req, rset=None, **kwargs): |
2890
fdcb8a2bb6eb
fix __init__ parameters
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2822
diff
changeset
|
383 |
super(EntityStartupView, self).__init__(req, rset=rset, **kwargs) |
0 | 384 |
if rset is None: |
385 |
# this instance is not in the "entityview" category |
|
386 |
self.category = 'startupview' |
|
387 |
||
388 |
def startup_rql(self): |
|
873 | 389 |
"""return some rql to be executed if the result set is None""" |
0 | 390 |
return self.default_rql |
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
391 |
|
8174
b3e87e6865ef
[base views] make it easier to override EntityStartupView behaviour when the rset is empty; closes #2126364
Florent Cayré <florent.cayre@gmail.com>
parents:
8013
diff
changeset
|
392 |
def no_entities(self, **kwargs): |
b3e87e6865ef
[base views] make it easier to override EntityStartupView behaviour when the rset is empty; closes #2126364
Florent Cayré <florent.cayre@gmail.com>
parents:
8013
diff
changeset
|
393 |
"""override to display something when no entities were found""" |
b3e87e6865ef
[base views] make it easier to override EntityStartupView behaviour when the rset is empty; closes #2126364
Florent Cayré <florent.cayre@gmail.com>
parents:
8013
diff
changeset
|
394 |
pass |
b3e87e6865ef
[base views] make it easier to override EntityStartupView behaviour when the rset is empty; closes #2126364
Florent Cayré <florent.cayre@gmail.com>
parents:
8013
diff
changeset
|
395 |
|
0 | 396 |
def call(self, **kwargs): |
873 | 397 |
"""override call to execute rql returned by the .startup_rql method if |
398 |
necessary |
|
0 | 399 |
""" |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
400 |
rset = self.cw_rset |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
401 |
if rset is None: |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
402 |
rset = self.cw_rset = self._cw.execute(self.startup_rql()) |
8174
b3e87e6865ef
[base views] make it easier to override EntityStartupView behaviour when the rset is empty; closes #2126364
Florent Cayré <florent.cayre@gmail.com>
parents:
8013
diff
changeset
|
403 |
if rset: |
b3e87e6865ef
[base views] make it easier to override EntityStartupView behaviour when the rset is empty; closes #2126364
Florent Cayré <florent.cayre@gmail.com>
parents:
8013
diff
changeset
|
404 |
for i in xrange(len(rset)): |
b3e87e6865ef
[base views] make it easier to override EntityStartupView behaviour when the rset is empty; closes #2126364
Florent Cayré <florent.cayre@gmail.com>
parents:
8013
diff
changeset
|
405 |
self.wview(self.__regid__, rset, row=i, **kwargs) |
b3e87e6865ef
[base views] make it easier to override EntityStartupView behaviour when the rset is empty; closes #2126364
Florent Cayré <florent.cayre@gmail.com>
parents:
8013
diff
changeset
|
406 |
else: |
b3e87e6865ef
[base views] make it easier to override EntityStartupView behaviour when the rset is empty; closes #2126364
Florent Cayré <florent.cayre@gmail.com>
parents:
8013
diff
changeset
|
407 |
self.no_entities(**kwargs) |
0 | 408 |
|
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
409 |
|
0 | 410 |
class AnyRsetView(View): |
411 |
"""base class for views applying on any non empty result sets""" |
|
707 | 412 |
__select__ = nonempty_rset() |
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
413 |
|
7670
6397a9051f65
[boxes] closes #1832844: translate views category in possible views boxes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7346
diff
changeset
|
414 |
category = _('anyrsetview') |
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
415 |
|
2203
efdd3a9f9028
update to new rql get_description api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1999
diff
changeset
|
416 |
def columns_labels(self, mainindex=0, tr=True): |
7938
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
417 |
"""compute the label of the rset colums |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
418 |
|
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
419 |
The logic is based on :meth:`~rql.stmts.Union.get_description`. |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
420 |
|
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
421 |
:param mainindex: The index of the main variable. This is an hint to get |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
422 |
more accurate label for various situation |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
423 |
:type mainindex: int |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
424 |
|
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
425 |
:param tr: Should the label be translated ? |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
426 |
:type tr: boolean |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
427 |
""" |
370
7e76f651314b
fix rset xml view
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
369
diff
changeset
|
428 |
if tr: |
7938
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
429 |
translate = partial(display_name, self._cw) |
370
7e76f651314b
fix rset xml view
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
369
diff
changeset
|
430 |
else: |
8011
23552e79316f
[column labels] full display_name prototype compat
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7959
diff
changeset
|
431 |
translate = lambda val, *args,**kwargs: val |
2203
efdd3a9f9028
update to new rql get_description api
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
1999
diff
changeset
|
432 |
# XXX [0] because of missing Union support |
7938
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
433 |
rql_syntax_tree = self.cw_rset.syntax_tree() |
7959
32349eb5d89d
[table view] fix bug introduced in 7938:80c6e2155c3d leading to not translated table headers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7938
diff
changeset
|
434 |
rqlstdescr = rql_syntax_tree.get_description(mainindex, translate)[0] |
369
c8a6edc224bb
new rsetxml view, reusing most code from csvexport view
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
361
diff
changeset
|
435 |
labels = [] |
7346
c6d8c3ce4a3e
[view] ability to define a column header through custom label_column_<colindex> method, useful for table view to customize a specific column without specifying others
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6931
diff
changeset
|
436 |
for colidx, label in enumerate(rqlstdescr): |
7938
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
437 |
labels.append(self.column_label(colidx, label, translate)) |
369
c8a6edc224bb
new rsetxml view, reusing most code from csvexport view
Sylvain Thenault <sylvain.thenault@logilab.fr>
parents:
361
diff
changeset
|
438 |
return labels |
543
c0f2b6378f70
simplification of lazy tabs mechanism
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
522
diff
changeset
|
439 |
|
7938
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
440 |
def column_label(self, colidx, default, translate_func=None): |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
441 |
"""return the label of a specified columns index |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
442 |
|
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
443 |
Overwrite me if you need to compute specific label. |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
444 |
|
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
445 |
:param colidx: The index of the column the call computes a label for. |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
446 |
:type colidx: int |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
447 |
|
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
448 |
:param default: Default value. If ``"Any"`` the default value will be |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
449 |
recomputed as coma separated list for all possible |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
450 |
etypes name. |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
451 |
:type colidx: string |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
452 |
|
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
453 |
:param translate_func: A function used to translate name. |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
454 |
:type colidx: function |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
455 |
""" |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
456 |
label = default |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
457 |
if label == 'Any': |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
458 |
etypes = self.cw_rset.column_types(colidx) |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
459 |
if translate_func is not None: |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
460 |
etypes = map(translate_func, etypes) |
7959
32349eb5d89d
[table view] fix bug introduced in 7938:80c6e2155c3d leading to not translated table headers
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
7938
diff
changeset
|
461 |
label = u','.join(etypes) |
7938
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
462 |
return label |
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
463 |
|
80c6e2155c3d
AnyRsetView: Refactor the columns_name method and update doc.
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
7833
diff
changeset
|
464 |
|
1433 | 465 |
|
0 | 466 |
# concrete template base classes ############################################## |
467 |
||
816
9cd49a910fce
kill Template class and 'templates' registry
sylvain.thenault@logilab.fr
parents:
781
diff
changeset
|
468 |
class MainTemplate(View): |
0 | 469 |
"""main template are primary access point to render a full HTML page. |
470 |
There is usually at least a regular main template and a simple fallback |
|
471 |
one to display error if the first one failed |
|
472 |
""" |
|
473 |
||
8976
aeb7d400ee92
[view] return HTML5 doctype. Closes #2869426
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
8941
diff
changeset
|
474 |
doctype = '<!DOCTYPE html>' |
0 | 475 |
|
1424 | 476 |
def set_stream(self, w=None): |
477 |
if self.w is not None: |
|
0 | 478 |
return |
479 |
if w is None: |
|
480 |
if self.binary: |
|
481 |
self._stream = stream = StringIO() |
|
482 |
else: |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
483 |
self._stream = stream = HTMLStream(self._cw) |
0 | 484 |
w = stream.write |
485 |
else: |
|
486 |
stream = None |
|
487 |
self.w = w |
|
488 |
return stream |
|
489 |
||
490 |
def write_doctype(self, xmldecl=True): |
|
491 |
assert isinstance(self._stream, HTMLStream) |
|
492 |
self._stream.doctype = self.doctype |
|
493 |
if not xmldecl: |
|
494 |
self._stream.xmldecl = u'' |
|
661
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
495 |
|
822 | 496 |
def linkable(self): |
497 |
return False |
|
1433 | 498 |
|
661
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
499 |
# concrete component base classes ############################################# |
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
500 |
|
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
501 |
class ReloadableMixIn(object): |
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
502 |
"""simple mixin for reloadable parts of UI""" |
1433 | 503 |
|
661
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
504 |
def user_callback(self, cb, args, msg=None, nonify=False): |
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
505 |
"""register the given user callback and return an url to call it ready to be |
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
506 |
inserted in html |
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
507 |
""" |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
508 |
self._cw.add_js('cubicweb.ajax.js') |
661
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
509 |
if nonify: |
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
510 |
_cb = cb |
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
511 |
def cb(*args): |
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
512 |
_cb(*args) |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3369
diff
changeset
|
513 |
cbname = self._cw.register_onetime_callback(cb, *args) |
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2217
diff
changeset
|
514 |
return self.build_js(cbname, xml_escape(msg or '')) |
1433 | 515 |
|
661
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
516 |
def build_update_js_call(self, cbname, msg): |
4059 | 517 |
rql = self.cw_rset.printable_rql() |
6044
9e48ebd5400c
[view] use the new magic js object to generate javascript func call for auto reload user callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6038
diff
changeset
|
518 |
return "javascript: %s" % js.userCallbackThenUpdateUI( |
9e48ebd5400c
[view] use the new magic js object to generate javascript func call for auto reload user callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6038
diff
changeset
|
519 |
cbname, self.__regid__, rql, msg, self.__registry__, self.domid) |
1433 | 520 |
|
4062
d16b2927afe6
oops, bad indent
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4060
diff
changeset
|
521 |
def build_reload_js_call(self, cbname, msg): |
6044
9e48ebd5400c
[view] use the new magic js object to generate javascript func call for auto reload user callbacks
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6038
diff
changeset
|
522 |
return "javascript: %s" % js.userCallbackThenReloadPage(cbname, msg) |
661
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
523 |
|
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
524 |
build_js = build_update_js_call # expect updatable component by default |
1433 | 525 |
|
6140
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
526 |
@property |
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
527 |
def domid(self): |
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
528 |
return domid(self.__regid__) |
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
529 |
|
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
530 |
@deprecated('[3.10] use .domid property') |
661
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
531 |
def div_id(self): |
6140
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
532 |
return self.domid |
661
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
533 |
|
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
534 |
|
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
535 |
class Component(ReloadableMixIn, View): |
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
536 |
"""base class for components""" |
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
537 |
__registry__ = 'components' |
707 | 538 |
__select__ = yes() |
661
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
539 |
|
6140
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
540 |
# XXX huummm, much probably useless (should be...) |
3010
684a0c546774
[ui props] drop htmlclass as a persistent property, this is definitly useless/unusable
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2656
diff
changeset
|
541 |
htmlclass = 'mainRelated' |
6140
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
542 |
@property |
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
543 |
def cssclass(self): |
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
544 |
return '%s %s' % (self.htmlclass, domid(self.__regid__)) |
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
545 |
|
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
546 |
# XXX should rely on ReloadableMixIn.domid |
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
547 |
@property |
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
548 |
def domid(self): |
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
549 |
return '%sComponent' % domid(self.__regid__) |
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
550 |
|
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
551 |
@deprecated('[3.10] use .cssclass property') |
661
4f61eb8a96b7
properly kill/depreciate component base class, only keep Component
sylvain.thenault@logilab.fr
parents:
660
diff
changeset
|
552 |
def div_class(self): |
6140
65a619eb31c4
[boxes] introduce new boxes system
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6047
diff
changeset
|
553 |
return self.cssclass |
5556
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
554 |
|
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
555 |
|
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
556 |
class Adapter(AppObject): |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
557 |
"""base class for adapters""" |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
558 |
__registry__ = 'adapters' |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
559 |
|
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
560 |
|
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
561 |
def implements_adapter_compat(iface): |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
562 |
def _pre39_compat(func): |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
563 |
def decorated(self, *args, **kwargs): |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
564 |
entity = self.entity |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
565 |
if hasattr(entity, func.__name__): |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
566 |
warn('[3.9] %s method is deprecated, define it on a custom ' |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
567 |
'%s for %s instead' % (func.__name__, iface, |
8666
1dd655788ece
make ui configurations selectable (closes #2406609)
Florent Cayré <florent.cayre@logilab.fr>
parents:
8425
diff
changeset
|
568 |
entity.__class__), |
5556
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
569 |
DeprecationWarning) |
5571
5d024bf9424b
[adapters compat] make implements_adapter_compat selector compatible with attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5556
diff
changeset
|
570 |
member = getattr(entity, func.__name__) |
5d024bf9424b
[adapters compat] make implements_adapter_compat selector compatible with attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5556
diff
changeset
|
571 |
if callable(member): |
5d024bf9424b
[adapters compat] make implements_adapter_compat selector compatible with attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5556
diff
changeset
|
572 |
return member(*args, **kwargs) |
5d024bf9424b
[adapters compat] make implements_adapter_compat selector compatible with attributes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5556
diff
changeset
|
573 |
return member |
5556
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
574 |
return func(self, *args, **kwargs) |
6864
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
575 |
decorated.decorated = func |
5556
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
576 |
return decorated |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5533
diff
changeset
|
577 |
return _pre39_compat |
6864
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
578 |
|
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
579 |
|
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
580 |
def unwrap_adapter_compat(cls): |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
581 |
parent = cls.__bases__[0] |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
582 |
for member_name in dir(parent): |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
583 |
member = getattr(parent, member_name) |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
584 |
if isinstance(member, types.MethodType) and hasattr(member.im_func, 'decorated') and not member_name in cls.__dict__: |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
585 |
method = new.instancemethod(member.im_func.decorated, None, cls) |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
586 |
setattr(cls, member_name, method) |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
587 |
|
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
588 |
|
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
589 |
class auto_unwrap_bw_compat(type): |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
590 |
def __new__(mcs, name, bases, classdict): |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
591 |
cls = type.__new__(mcs, name, bases, classdict) |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
592 |
if not classdict.get('__needs_bw_compat__'): |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
593 |
unwrap_adapter_compat(cls) |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
594 |
return cls |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
595 |
|
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
596 |
|
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
597 |
class EntityAdapter(Adapter): |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
598 |
"""base class for entity adapters (eg adapt an entity to an interface)""" |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
599 |
__metaclass__ = auto_unwrap_bw_compat |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
600 |
def __init__(self, _cw, **kwargs): |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
601 |
try: |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
602 |
self.entity = kwargs.pop('entity') |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
603 |
except KeyError: |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
604 |
self.entity = kwargs['rset'].get_entity(kwargs.get('row') or 0, |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
605 |
kwargs.get('col') or 0) |
ea95004494a2
[adapters] fix #1424467 caused by precedence of bw compat method while the adapter is concret for a given class
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
6769
diff
changeset
|
606 |
Adapter.__init__(self, _cw, **kwargs) |