author | Sylvain Thénault <sylvain.thenault@logilab.fr> |
Tue, 27 Jul 2010 12:37:27 +0200 | |
changeset 6020 | 6f3b4f20ee9f |
parent 6011 | b5f15098f282 |
child 6515 | 6e998b1be7fd |
permissions | -rw-r--r-- |
5421
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5309
diff
changeset
|
1 |
# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
8167de96c523
proper licensing information (LGPL-2.1). Hope I get it right this time.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5309
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:
5309
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:
5309
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:
5309
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:
5309
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:
5309
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:
5309
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:
5309
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:
5309
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:
5309
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:
5309
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:
5309
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:
5309
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:
5309
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:
5309
diff
changeset
|
17 |
# with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
5309
e8567135a927
[doc/book] fix docstrings, add notes
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4719
diff
changeset
|
18 |
"""mixins of entity/views organized somewhat in a graph or tree structure""" |
0 | 19 |
__docformat__ = "restructuredtext en" |
20 |
||
4401
4d973c834eb3
missing import
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4395
diff
changeset
|
21 |
from itertools import chain |
4d973c834eb3
missing import
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4395
diff
changeset
|
22 |
|
0 | 23 |
from logilab.common.decorators import cached |
5556
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
24 |
from logilab.common.deprecation import deprecated, class_deprecated |
0 | 25 |
|
692
800592b8d39b
replace deprecated cubicweb.common.selectors by its new module path (cubicweb.selectors)
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
471
diff
changeset
|
26 |
from cubicweb.selectors import implements |
5556
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
27 |
from cubicweb.interfaces import ITree |
0 | 28 |
|
29 |
||
30 |
class TreeMixIn(object): |
|
5309
e8567135a927
[doc/book] fix docstrings, add notes
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4719
diff
changeset
|
31 |
"""base tree-mixin implementing the tree interface |
0 | 32 |
|
33 |
This mixin has to be inherited explicitly and configured using the |
|
34 |
tree_attribute, parent_target and children_target class attribute to |
|
35 |
benefit from this default implementation |
|
36 |
""" |
|
5556
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
37 |
__metaclass__ = class_deprecated |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
38 |
__deprecation_warning__ = '[3.9] TreeMixIn is deprecated, use/override ITreeAdapter instead' |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
39 |
|
0 | 40 |
tree_attribute = None |
41 |
# XXX misnamed |
|
42 |
parent_target = 'subject' |
|
43 |
children_target = 'object' |
|
1451 | 44 |
|
0 | 45 |
def different_type_children(self, entities=True): |
46 |
"""return children entities of different type as this entity. |
|
1451 | 47 |
|
0 | 48 |
according to the `entities` parameter, return entity objects or the |
49 |
equivalent result set |
|
50 |
""" |
|
51 |
res = self.related(self.tree_attribute, self.children_target, |
|
52 |
entities=entities) |
|
53 |
if entities: |
|
54 |
return [e for e in res if e.e_schema != self.e_schema] |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3426
diff
changeset
|
55 |
return res.filtered_rset(lambda x: x.e_schema != self.e_schema, self.cw_col) |
0 | 56 |
|
57 |
def same_type_children(self, entities=True): |
|
58 |
"""return children entities of the same type as this entity. |
|
1451 | 59 |
|
0 | 60 |
according to the `entities` parameter, return entity objects or the |
61 |
equivalent result set |
|
62 |
""" |
|
63 |
res = self.related(self.tree_attribute, self.children_target, |
|
64 |
entities=entities) |
|
65 |
if entities: |
|
66 |
return [e for e in res if e.e_schema == self.e_schema] |
|
4395 | 67 |
return res.filtered_rset(lambda x: x.e_schema is self.e_schema, self.cw_col) |
1451 | 68 |
|
0 | 69 |
def iterchildren(self, _done=None): |
70 |
if _done is None: |
|
71 |
_done = set() |
|
72 |
for child in self.children(): |
|
73 |
if child.eid in _done: |
|
6011
b5f15098f282
[debug] when a loop is detected in a tree, log the entity involved in it to ease repair
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5895
diff
changeset
|
74 |
self.error('loop in %s tree: %s', self.__regid__.lower(), child) |
0 | 75 |
continue |
76 |
yield child |
|
77 |
_done.add(child.eid) |
|
78 |
||
79 |
def prefixiter(self, _done=None): |
|
80 |
if _done is None: |
|
81 |
_done = set() |
|
82 |
if self.eid in _done: |
|
83 |
return |
|
4383
e62a9efdd90a
it seems that prefixiter is expected to return child *folder* but was relying on a specific .children implementation, fix this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4351
diff
changeset
|
84 |
_done.add(self.eid) |
0 | 85 |
yield self |
4383
e62a9efdd90a
it seems that prefixiter is expected to return child *folder* but was relying on a specific .children implementation, fix this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4351
diff
changeset
|
86 |
for child in self.same_type_children(): |
e62a9efdd90a
it seems that prefixiter is expected to return child *folder* but was relying on a specific .children implementation, fix this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4351
diff
changeset
|
87 |
for entity in child.prefixiter(_done): |
e62a9efdd90a
it seems that prefixiter is expected to return child *folder* but was relying on a specific .children implementation, fix this
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4351
diff
changeset
|
88 |
yield entity |
1451 | 89 |
|
0 | 90 |
@cached |
91 |
def path(self): |
|
92 |
"""returns the list of eids from the root object to this object""" |
|
93 |
path = [] |
|
94 |
parent = self |
|
95 |
while parent: |
|
96 |
if parent.eid in path: |
|
6011
b5f15098f282
[debug] when a loop is detected in a tree, log the entity involved in it to ease repair
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5895
diff
changeset
|
97 |
self.error('loop in %s tree: %s', self.__regid__.lower(), parent) |
0 | 98 |
break |
99 |
path.append(parent.eid) |
|
100 |
try: |
|
101 |
# check we are not leaving the tree |
|
102 |
if (parent.tree_attribute != self.tree_attribute or |
|
103 |
parent.parent_target != self.parent_target): |
|
104 |
break |
|
105 |
parent = parent.parent() |
|
106 |
except AttributeError: |
|
107 |
break |
|
108 |
||
109 |
path.reverse() |
|
110 |
return path |
|
1451 | 111 |
|
4351
619c7f9302fc
get back iterparents implementation from folder cubes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
112 |
def iterparents(self, strict=True): |
173
a4a9e1a7e40f
TreeMixin : provide an iterator on the parents
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
62
diff
changeset
|
113 |
def _uptoroot(self): |
a4a9e1a7e40f
TreeMixin : provide an iterator on the parents
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
62
diff
changeset
|
114 |
curr = self |
a4a9e1a7e40f
TreeMixin : provide an iterator on the parents
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
62
diff
changeset
|
115 |
while True: |
a4a9e1a7e40f
TreeMixin : provide an iterator on the parents
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
62
diff
changeset
|
116 |
curr = curr.parent() |
a4a9e1a7e40f
TreeMixin : provide an iterator on the parents
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
62
diff
changeset
|
117 |
if curr is None: |
a4a9e1a7e40f
TreeMixin : provide an iterator on the parents
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
62
diff
changeset
|
118 |
break |
a4a9e1a7e40f
TreeMixin : provide an iterator on the parents
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
62
diff
changeset
|
119 |
yield curr |
4351
619c7f9302fc
get back iterparents implementation from folder cubes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
120 |
if not strict: |
619c7f9302fc
get back iterparents implementation from folder cubes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
121 |
return chain([self], _uptoroot(self)) |
173
a4a9e1a7e40f
TreeMixin : provide an iterator on the parents
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
62
diff
changeset
|
122 |
return _uptoroot(self) |
a4a9e1a7e40f
TreeMixin : provide an iterator on the parents
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
62
diff
changeset
|
123 |
|
0 | 124 |
## ITree interface ######################################################## |
125 |
def parent(self): |
|
126 |
"""return the parent entity if any, else None (e.g. if we are on the |
|
127 |
root |
|
128 |
""" |
|
129 |
try: |
|
130 |
return self.related(self.tree_attribute, self.parent_target, |
|
131 |
entities=True)[0] |
|
132 |
except (KeyError, IndexError): |
|
133 |
return None |
|
134 |
||
135 |
def children(self, entities=True, sametype=False): |
|
136 |
"""return children entities |
|
137 |
||
138 |
according to the `entities` parameter, return entity objects or the |
|
139 |
equivalent result set |
|
140 |
""" |
|
141 |
if sametype: |
|
142 |
return self.same_type_children(entities) |
|
143 |
else: |
|
144 |
return self.related(self.tree_attribute, self.children_target, |
|
145 |
entities=entities) |
|
146 |
||
147 |
def children_rql(self): |
|
5557
1a534c596bff
[entity] continue cleanup of Entity/AnyEntity namespace
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5556
diff
changeset
|
148 |
return self.cw_related_rql(self.tree_attribute, self.children_target) |
1451 | 149 |
|
0 | 150 |
def is_leaf(self): |
151 |
return len(self.children()) == 0 |
|
152 |
||
153 |
def is_root(self): |
|
154 |
return self.parent() is None |
|
155 |
||
156 |
def root(self): |
|
157 |
"""return the root object""" |
|
3426
6ea4a2ff01c9
[api] use cw_*
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3023
diff
changeset
|
158 |
return self._cw.entity_from_eid(self.path()[0]) |
0 | 159 |
|
160 |
||
161 |
class EmailableMixIn(object): |
|
162 |
"""base mixin providing the default get_email() method used by |
|
163 |
the massmailing view |
|
164 |
||
165 |
NOTE: The default implementation is based on the |
|
166 |
primary_email / use_email scheme |
|
167 |
""" |
|
5556
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
168 |
@deprecated("[3.9] use entity.cw_adapt_to('IEmailable').get_email()") |
0 | 169 |
def get_email(self): |
170 |
if getattr(self, 'primary_email', None): |
|
171 |
return self.primary_email[0].address |
|
172 |
if getattr(self, 'use_email', None): |
|
173 |
return self.use_email[0].address |
|
174 |
return None |
|
175 |
||
176 |
||
3926 | 177 |
"""pluggable mixins system: plug classes registered in MI_REL_TRIGGERS on entity |
178 |
classes which have the relation described by the dict's key. |
|
1451 | 179 |
|
3926 | 180 |
NOTE: pluggable mixins can't override any method of the 'explicit' user classes tree |
181 |
(eg without plugged classes). This includes bases Entity and AnyEntity classes. |
|
182 |
""" |
|
0 | 183 |
MI_REL_TRIGGERS = { |
184 |
('primary_email', 'subject'): EmailableMixIn, |
|
185 |
('use_email', 'subject'): EmailableMixIn, |
|
186 |
} |
|
187 |
||
188 |
||
5569
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
189 |
# XXX move to cubicweb.web.views.treeview once we delete usage from this file |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
190 |
def _done_init(done, view, row, col): |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
191 |
"""handle an infinite recursion safety belt""" |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
192 |
if done is None: |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
193 |
done = set() |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
194 |
entity = view.cw_rset.get_entity(row, col) |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
195 |
if entity.eid in done: |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
196 |
msg = entity._cw._('loop in %(rel)s relation (%(eid)s)') % { |
5718
8d246203730a
[ITree] fix adapter/_done_init to handle tree_[attribute|relation], add maxlevel argument to base tree view since one side effect of the new code is that it find tree view for entity types it didn't find before, hence one may want to limit tree view depth when it wasn't necessary before
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5569
diff
changeset
|
197 |
'rel': entity.cw_adapt_to('ITree').tree_relation, |
5569
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
198 |
'eid': entity.eid |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
199 |
} |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
200 |
return None, msg |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
201 |
done.add(entity.eid) |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
202 |
return done, entity |
cb14af012a96
[adapters] refactoring fixes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5557
diff
changeset
|
203 |
|
0 | 204 |
|
205 |
class TreeViewMixIn(object): |
|
206 |
"""a recursive tree view""" |
|
5556
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
207 |
__metaclass__ = class_deprecated |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
208 |
__deprecation_warning__ = '[3.9] TreeViewMixIn is deprecated, use/override BaseTreeView instead' |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
209 |
|
3457
0924d0d08d60
[api] __regid__, cw_* and friends
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3451
diff
changeset
|
210 |
__regid__ = 'tree' |
5895
6a3f776292a5
[selectors]Â avoid spurious warning when using implements by design
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5718
diff
changeset
|
211 |
__select__ = implements(ITree, warn=False) |
0 | 212 |
item_vid = 'treeitem' |
213 |
||
214 |
def call(self, done=None, **kwargs): |
|
215 |
if done is None: |
|
216 |
done = set() |
|
217 |
super(TreeViewMixIn, self).call(done=done, **kwargs) |
|
1451 | 218 |
|
5718
8d246203730a
[ITree] fix adapter/_done_init to handle tree_[attribute|relation], add maxlevel argument to base tree view since one side effect of the new code is that it find tree view for entity types it didn't find before, hence one may want to limit tree view depth when it wasn't necessary before
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5569
diff
changeset
|
219 |
def cell_call(self, row, col=0, vid=None, done=None, maxlevel=None, **kwargs): |
8d246203730a
[ITree] fix adapter/_done_init to handle tree_[attribute|relation], add maxlevel argument to base tree view since one side effect of the new code is that it find tree view for entity types it didn't find before, hence one may want to limit tree view depth when it wasn't necessary before
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5569
diff
changeset
|
220 |
assert maxlevel is None or maxlevel > 0 |
0 | 221 |
done, entity = _done_init(done, self, row, col) |
222 |
if done is None: |
|
223 |
# entity is actually an error message |
|
224 |
self.w(u'<li class="badcontent">%s</li>' % entity) |
|
225 |
return |
|
226 |
self.open_item(entity) |
|
227 |
entity.view(vid or self.item_vid, w=self.w, **kwargs) |
|
5718
8d246203730a
[ITree] fix adapter/_done_init to handle tree_[attribute|relation], add maxlevel argument to base tree view since one side effect of the new code is that it find tree view for entity types it didn't find before, hence one may want to limit tree view depth when it wasn't necessary before
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5569
diff
changeset
|
228 |
if maxlevel is not None: |
8d246203730a
[ITree] fix adapter/_done_init to handle tree_[attribute|relation], add maxlevel argument to base tree view since one side effect of the new code is that it find tree view for entity types it didn't find before, hence one may want to limit tree view depth when it wasn't necessary before
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5569
diff
changeset
|
229 |
maxlevel -= 1 |
8d246203730a
[ITree] fix adapter/_done_init to handle tree_[attribute|relation], add maxlevel argument to base tree view since one side effect of the new code is that it find tree view for entity types it didn't find before, hence one may want to limit tree view depth when it wasn't necessary before
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5569
diff
changeset
|
230 |
if maxlevel == 0: |
8d246203730a
[ITree] fix adapter/_done_init to handle tree_[attribute|relation], add maxlevel argument to base tree view since one side effect of the new code is that it find tree view for entity types it didn't find before, hence one may want to limit tree view depth when it wasn't necessary before
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5569
diff
changeset
|
231 |
self.close_item(entity) |
8d246203730a
[ITree] fix adapter/_done_init to handle tree_[attribute|relation], add maxlevel argument to base tree view since one side effect of the new code is that it find tree view for entity types it didn't find before, hence one may want to limit tree view depth when it wasn't necessary before
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5569
diff
changeset
|
232 |
return |
0 | 233 |
relatedrset = entity.children(entities=False) |
5718
8d246203730a
[ITree] fix adapter/_done_init to handle tree_[attribute|relation], add maxlevel argument to base tree view since one side effect of the new code is that it find tree view for entity types it didn't find before, hence one may want to limit tree view depth when it wasn't necessary before
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5569
diff
changeset
|
234 |
self.wview(self.__regid__, relatedrset, 'null', done=done, |
8d246203730a
[ITree] fix adapter/_done_init to handle tree_[attribute|relation], add maxlevel argument to base tree view since one side effect of the new code is that it find tree view for entity types it didn't find before, hence one may want to limit tree view depth when it wasn't necessary before
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5569
diff
changeset
|
235 |
maxlevel=maxlevel, **kwargs) |
0 | 236 |
self.close_item(entity) |
237 |
||
238 |
def open_item(self, entity): |
|
3457
0924d0d08d60
[api] __regid__, cw_* and friends
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3451
diff
changeset
|
239 |
self.w(u'<li class="%s">\n' % entity.__regid__.lower()) |
0 | 240 |
def close_item(self, entity): |
241 |
self.w(u'</li>\n') |
|
242 |
||
243 |
||
244 |
class TreePathMixIn(object): |
|
245 |
"""a recursive path view""" |
|
5556
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
246 |
__metaclass__ = class_deprecated |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
247 |
__deprecation_warning__ = '[3.9] TreePathMixIn is deprecated, use/override TreePathView instead' |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3426
diff
changeset
|
248 |
__regid__ = 'path' |
0 | 249 |
item_vid = 'oneline' |
2996
866a2c135c33
B #345282 xhtml requires to use   instead of
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
2748
diff
changeset
|
250 |
separator = u' > ' |
0 | 251 |
|
252 |
def call(self, **kwargs): |
|
253 |
self.w(u'<div class="pathbar">') |
|
254 |
super(TreePathMixIn, self).call(**kwargs) |
|
255 |
self.w(u'</div>') |
|
1451 | 256 |
|
0 | 257 |
def cell_call(self, row, col=0, vid=None, done=None, **kwargs): |
258 |
done, entity = _done_init(done, self, row, col) |
|
259 |
if done is None: |
|
260 |
# entity is actually an error message |
|
261 |
self.w(u'<span class="badcontent">%s</span>' % entity) |
|
262 |
return |
|
263 |
parent = entity.parent() |
|
264 |
if parent: |
|
3457
0924d0d08d60
[api] __regid__, cw_* and friends
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3451
diff
changeset
|
265 |
parent.view(self.__regid__, w=self.w, done=done) |
0 | 266 |
self.w(self.separator) |
267 |
entity.view(vid or self.item_vid, w=self.w) |
|
268 |
||
269 |
||
270 |
class ProgressMixIn(object): |
|
5309
e8567135a927
[doc/book] fix docstrings, add notes
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4719
diff
changeset
|
271 |
"""provide a default implementations for IProgress interface methods""" |
5556
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
272 |
__metaclass__ = class_deprecated |
9ab2b4c74baf
[entity] introduce a new 'adapters' registry
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
5424
diff
changeset
|
273 |
__deprecation_warning__ = '[3.9] ProgressMixIn is deprecated, use/override IProgressAdapter instead' |
0 | 274 |
|
275 |
@property |
|
276 |
def cost(self): |
|
277 |
return self.progress_info()['estimated'] |
|
278 |
||
279 |
@property |
|
280 |
def revised_cost(self): |
|
281 |
return self.progress_info().get('estimatedcorrected', self.cost) |
|
282 |
||
283 |
@property |
|
284 |
def done(self): |
|
285 |
return self.progress_info()['done'] |
|
286 |
||
287 |
@property |
|
288 |
def todo(self): |
|
289 |
return self.progress_info()['todo'] |
|
290 |
||
291 |
@cached |
|
292 |
def progress_info(self): |
|
293 |
raise NotImplementedError() |
|
294 |
||
295 |
def finished(self): |
|
296 |
return not self.in_progress() |
|
297 |
||
298 |
def in_progress(self): |
|
299 |
raise NotImplementedError() |
|
1451 | 300 |
|
0 | 301 |
def progress(self): |
302 |
try: |
|
303 |
return 100. * self.done / self.revised_cost |
|
304 |
except ZeroDivisionError: |
|
305 |
# total cost is 0 : if everything was estimated, task is completed |
|
961 | 306 |
if self.progress_info().get('notestimated'): |
0 | 307 |
return 0. |
308 |
return 100 |