LEFT | RIGHT |
1 #This file is part of Tryton. The COPYRIGHT file at the top level of | 1 #This file is part of Tryton. The COPYRIGHT file at the top level of |
2 #this repository contains the full copyright notices and license terms. | 2 #this repository contains the full copyright notices and license terms. |
3 import os | 3 import os |
4 import logging | 4 import logging |
5 from lxml import etree | 5 from lxml import etree |
6 from difflib import SequenceMatcher | 6 from difflib import SequenceMatcher |
7 from trytond.model import ModelView, ModelSQL, fields | 7 from trytond.model import ModelView, ModelSQL, fields |
8 from trytond.backend import TableHandler | 8 from trytond.backend import TableHandler |
9 from trytond.pyson import CONTEXT, Eval, Bool | 9 from trytond.pyson import CONTEXT, Eval, Bool |
10 from trytond.tools import safe_eval, file_open | 10 from trytond.tools import safe_eval, file_open |
11 from trytond.transaction import Transaction | 11 from trytond.transaction import Transaction |
12 from trytond.wizard import Wizard, StateView, StateAction, StateTransition, \ | 12 from trytond.wizard import Wizard, StateView, StateAction, Button |
13 Button | |
14 from trytond.pool import Pool | 13 from trytond.pool import Pool |
| 14 from trytond.rpc import RPC |
| 15 |
| 16 __all__ = [ |
| 17 'View', 'ShowViewStart', 'ShowView', 'ViewShortcut', 'ShowView', |
| 18 'OpenShortcut', 'ViewTreeWidth', 'ViewTreeExpandedState', |
| 19 ] |
15 | 20 |
16 | 21 |
17 class View(ModelSQL, ModelView): | 22 class View(ModelSQL, ModelView): |
18 "View" | 23 "View" |
19 _name = 'ir.ui.view' | 24 __name__ = 'ir.ui.view' |
20 _description = __doc__ | |
21 _rec_name = 'model' | 25 _rec_name = 'model' |
22 model = fields.Char('Model', select=True, states={ | 26 model = fields.Char('Model', select=True, states={ |
23 'required': Eval('type').in_([None, 'tree', 'form', 'graph']), | 27 'required': Eval('type').in_([None, 'tree', 'form', 'graph']), |
24 }) | 28 }) |
25 priority = fields.Integer('Priority', required=True, select=True) | 29 priority = fields.Integer('Priority', required=True, select=True) |
26 type = fields.Selection([ | 30 type = fields.Selection([ |
27 (None, ''), | 31 (None, ''), |
28 ('tree', 'Tree'), | 32 ('tree', 'Tree'), |
29 ('form', 'Form'), | 33 ('form', 'Form'), |
30 ('graph', 'Graph'), | 34 ('graph', 'Graph'), |
(...skipping 11 matching lines...) Expand all Loading... |
42 field_childs = fields.Char('Children Field', states={ | 46 field_childs = fields.Char('Children Field', states={ |
43 'invisible': Eval('type') != 'tree', | 47 'invisible': Eval('type') != 'tree', |
44 }, depends=['type']) | 48 }, depends=['type']) |
45 module = fields.Char('Module', states={ | 49 module = fields.Char('Module', states={ |
46 'invisible': ~Eval('module'), | 50 'invisible': ~Eval('module'), |
47 }, readonly=True) | 51 }, readonly=True) |
48 domain = fields.Char('Domain', states={ | 52 domain = fields.Char('Domain', states={ |
49 'invisible': ~Eval('inherit'), | 53 'invisible': ~Eval('inherit'), |
50 }, depends=['inherit']) | 54 }, depends=['inherit']) |
51 | 55 |
52 def __init__(self): | 56 @classmethod |
53 super(View, self).__init__() | 57 def __setup__(cls): |
54 self._constraints += [ | 58 super(View, cls).__setup__() |
| 59 cls._constraints += [ |
55 ('check_xml', 'invalid_xml'), | 60 ('check_xml', 'invalid_xml'), |
56 ] | 61 ] |
57 self._error_messages.update({ | 62 cls._error_messages.update({ |
58 'invalid_xml': 'Invalid XML for View!', | 63 'invalid_xml': 'Invalid XML for View!', |
59 }) | 64 }) |
60 self._order.insert(0, ('priority', 'ASC')) | 65 cls._order.insert(0, ('priority', 'ASC')) |
61 self._buttons.update({ | 66 cls._buttons.update({ |
62 'show': {}, | 67 'show': {}, |
63 }) | 68 }) |
64 | 69 |
65 def init(self, module_name): | 70 @classmethod |
| 71 def __register__(cls, module_name): |
66 cursor = Transaction().cursor | 72 cursor = Transaction().cursor |
67 table = TableHandler(cursor, self, module_name) | 73 table = TableHandler(cursor, cls, module_name) |
68 | 74 |
69 # Migration from 2.4 arch moved into data | 75 # Migration from 2.4 arch moved into data |
70 if table.column_exist('arch'): | 76 if table.column_exist('arch'): |
71 table.column_rename('arch', 'data') | 77 table.column_rename('arch', 'data') |
72 | 78 |
73 super(View, self).init(module_name) | 79 super(View, cls).__register__(module_name) |
74 table = TableHandler(cursor, self, module_name) | |
75 | 80 |
76 # Migration from 1.0 arch no more required | 81 # Migration from 1.0 arch no more required |
77 table.not_null_action('arch', action='remove') | 82 table.not_null_action('arch', action='remove') |
78 | 83 |
79 # Migration from 2.4 model no more required | 84 # Migration from 2.4 model no more required |
80 table.not_null_action('model', action='remove') | 85 table.not_null_action('model', action='remove') |
81 | 86 |
82 def default_priority(self): | 87 @staticmethod |
| 88 def default_priority(): |
83 return 16 | 89 return 16 |
84 | 90 |
85 def default_module(self): | 91 @staticmethod |
| 92 def default_module(): |
86 return Transaction().context.get('module') or '' | 93 return Transaction().context.get('module') or '' |
87 | 94 |
| 95 @classmethod |
88 @ModelView.button_action('ir.act_view_show') | 96 @ModelView.button_action('ir.act_view_show') |
89 def show(self, ids): | 97 def show(cls, views): |
90 pass | 98 pass |
91 | 99 |
92 def check_xml(self, ids): | 100 @classmethod |
| 101 def check_xml(cls, views): |
93 "Check XML" | 102 "Check XML" |
94 pool = Pool() | 103 pool = Pool() |
95 translation_obj = pool.get('ir.translation') | 104 Translation = pool.get('ir.translation') |
96 cursor = Transaction().cursor | 105 cursor = Transaction().cursor |
97 views = self.browse(ids) | |
98 for view in views: | 106 for view in views: |
99 cursor.execute('SELECT id, name, src FROM ir_translation ' \ | 107 cursor.execute('SELECT id, name, src FROM ir_translation ' \ |
100 'WHERE lang = %s ' \ | 108 'WHERE lang = %s ' \ |
101 'AND type = %s ' \ | 109 'AND type = %s ' \ |
102 'AND name = %s '\ | 110 'AND name = %s '\ |
103 'AND module = %s', | 111 'AND module = %s', |
104 ('en_US', 'view', view.model, view.module)) | 112 ('en_US', 'view', view.model, view.module)) |
105 trans_views = {} | 113 trans_views = {} |
106 for trans in cursor.dictfetchall(): | 114 for trans in cursor.dictfetchall(): |
107 trans_views[trans['src']] = trans | 115 trans_views[trans['src']] = trans |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 % (element.get('id') or element.get('name'), | 157 % (element.get('id') or element.get('name'), |
150 attr, str(e), xml)) | 158 attr, str(e), xml)) |
151 return False | 159 return False |
152 for child in element: | 160 for child in element: |
153 if not encode(child): | 161 if not encode(child): |
154 return False | 162 return False |
155 return True | 163 return True |
156 if not encode(root_element): | 164 if not encode(root_element): |
157 return False | 165 return False |
158 | 166 |
159 strings = self._translate_view(root_element) | 167 strings = cls._translate_view(root_element) |
160 with Transaction().set_user(0): | 168 with Transaction().set_user(0): |
161 view_ids = self.search([ | 169 views2 = cls.search([ |
162 ('model', '=', view.model), | 170 ('model', '=', view.model), |
163 ('id', '!=', view.id), | 171 ('id', '!=', view.id), |
164 ('module', '=', view.module), | 172 ('module', '=', view.module), |
165 ]) | 173 ]) |
166 for view2 in self.browse(view_ids): | 174 for view2 in views2: |
167 xml2 = view2.arch.strip() | 175 xml2 = view2.arch.strip() |
168 if not xml2: | 176 if not xml2: |
169 continue | 177 continue |
170 tree2 = etree.fromstring(xml2) | 178 tree2 = etree.fromstring(xml2) |
171 root2_element = tree2.getroottree().getroot() | 179 root2_element = tree2.getroottree().getroot() |
172 strings += self._translate_view(root2_element) | 180 strings += cls._translate_view(root2_element) |
173 if not strings: | 181 if not strings: |
174 continue | 182 continue |
175 for string in set(strings): | 183 for string in set(strings): |
176 done = False | 184 done = False |
177 if string in trans_views: | 185 if string in trans_views: |
178 del trans_views[string] | 186 del trans_views[string] |
179 continue | 187 continue |
180 string_md5 = translation_obj.get_src_md5(string) | 188 string_md5 = Translation.get_src_md5(string) |
181 for string_trans in trans_views: | 189 for string_trans in trans_views: |
182 if string_trans in strings: | 190 if string_trans in strings: |
183 continue | 191 continue |
184 seqmatch = SequenceMatcher(lambda x: x == ' ', | 192 seqmatch = SequenceMatcher(lambda x: x == ' ', |
185 string, string_trans) | 193 string, string_trans) |
186 if seqmatch.ratio() == 1.0: | 194 if seqmatch.ratio() == 1.0: |
187 del trans_views[string_trans] | 195 del trans_views[string_trans] |
188 done = True | 196 done = True |
189 break | 197 break |
190 if seqmatch.ratio() > 0.6: | 198 if seqmatch.ratio() > 0.6: |
(...skipping 17 matching lines...) Expand all Loading... |
208 if strings: | 216 if strings: |
209 cursor.execute('DELETE FROM ir_translation ' \ | 217 cursor.execute('DELETE FROM ir_translation ' \ |
210 'WHERE name = %s ' \ | 218 'WHERE name = %s ' \ |
211 'AND type = %s ' \ | 219 'AND type = %s ' \ |
212 'AND module = %s ' \ | 220 'AND module = %s ' \ |
213 'AND src NOT IN ' \ | 221 'AND src NOT IN ' \ |
214 '(' + ','.join(('%s',) * len(strings)) + ')', | 222 '(' + ','.join(('%s',) * len(strings)) + ')', |
215 (view.model, 'view', view.module) + tuple(strings)) | 223 (view.model, 'view', view.module) + tuple(strings)) |
216 return True | 224 return True |
217 | 225 |
218 def get_arch(self, ids, name): | 226 def get_arch(self, name): |
219 result = {} | 227 value = None |
220 for view in self.browse(ids): | 228 if self.name and self.module: |
221 value = None | 229 path = os.path.join(self.module, 'view', self.name + '.xml') |
222 if view.name and view.module: | 230 try: |
223 path = os.path.join(view.module, 'view', view.name + '.xml') | 231 with file_open(path, subdir='modules') as fp: |
224 try: | 232 value = fp.read() |
225 with file_open(path, subdir='modules') as fp: | 233 except IOError: |
226 value = fp.read() | 234 pass |
227 except IOError: | 235 if not value: |
228 pass | 236 value = self.data |
229 if not value: | 237 return value |
230 value = view.data | 238 |
231 result[view.id] = value | 239 @classmethod |
232 return result | 240 def set_arch(cls, views, name, value): |
233 | 241 cls.write(views, {'data': value}) |
234 def set_arch(self, ids, name, value): | 242 |
235 self.write(ids, {'data': value}) | 243 @classmethod |
236 | 244 def delete(cls, views): |
237 def delete(self, ids): | 245 super(View, cls).delete(views) |
238 res = super(View, self).delete(ids) | |
239 # Restart the cache | 246 # Restart the cache |
240 pool = Pool() | 247 ModelView._fields_view_get_cache.clear() |
241 for _, model in pool.iterobject(): | 248 |
242 try: | 249 @classmethod |
243 model.fields_view_get.reset() | 250 def create(cls, vals): |
244 except Exception: | 251 view = super(View, cls).create(vals) |
245 pass | |
246 return res | |
247 | |
248 def create(self, vals): | |
249 res = super(View, self).create(vals) | |
250 # Restart the cache | 252 # Restart the cache |
251 pool = Pool() | 253 ModelView._fields_view_get_cache.clear() |
252 for _, model in pool.iterobject(): | 254 return view |
253 try: | 255 |
254 model.fields_view_get.reset() | 256 @classmethod |
255 except Exception: | 257 def write(cls, views, vals): |
256 pass | 258 super(View, cls).write(views, vals) |
257 return res | |
258 | |
259 def write(self, ids, vals): | |
260 res = super(View, self).write(ids, vals) | |
261 # Restart the cache | 259 # Restart the cache |
262 pool = Pool() | 260 ModelView._fields_view_get_cache.clear() |
263 for _, model in pool.iterobject(): | 261 |
264 try: | 262 @classmethod |
265 model.fields_view_get.reset() | 263 def _translate_view(cls, element): |
266 except Exception: | |
267 pass | |
268 return res | |
269 | |
270 def _translate_view(self, element): | |
271 strings = [] | 264 strings = [] |
272 for attr in ('string', 'sum', 'confirm', 'help'): | 265 for attr in ('string', 'sum', 'confirm', 'help'): |
273 if element.get(attr): | 266 if element.get(attr): |
274 string = element.get(attr) | 267 string = element.get(attr) |
275 if string: | 268 if string: |
276 strings.append(string) | 269 strings.append(string) |
277 for child in element: | 270 for child in element: |
278 strings.extend(self._translate_view(child)) | 271 strings.extend(cls._translate_view(child)) |
279 return strings | 272 return strings |
280 | |
281 View() | |
282 | 273 |
283 | 274 |
284 class ShowViewStart(ModelView): | 275 class ShowViewStart(ModelView): |
285 'Show view' | 276 'Show view' |
286 _name = 'ir.ui.view.show.start' | 277 __name__ = 'ir.ui.view.show.start' |
287 | |
288 ShowViewStart() | |
289 | 278 |
290 | 279 |
291 class ShowView(Wizard): | 280 class ShowView(Wizard): |
292 'Show view' | 281 'Show view' |
293 _name = 'ir.ui.view.show' | 282 __name__ = 'ir.ui.view.show' |
294 | 283 |
295 class ShowStateView(StateView): | 284 class ShowStateView(StateView): |
296 | 285 |
297 def __init__(self, model_name, buttons): | 286 def __init__(self, model_name, buttons): |
298 StateView.__init__(self, model_name, None, buttons) | 287 StateView.__init__(self, model_name, None, buttons) |
299 | 288 |
300 def get_view(self): | 289 def get_view(self): |
301 pool = Pool() | 290 pool = Pool() |
302 view_obj = pool.get('ir.ui.view') | 291 View = pool.get('ir.ui.view') |
303 view_id = Transaction().context.get('active_id') | 292 view = View(Transaction().context.get('active_id')) |
304 view = view_obj.browse(view_id) | 293 Model = pool.get(view.model) |
305 model_obj = pool.get(view.model) | |
306 if view.type != 'form': | 294 if view.type != 'form': |
307 return model_obj.fields_view_get(view_type='form') | 295 return Model.fields_view_get(view_type='form') |
308 return model_obj.fields_view_get(view_id=view_id) | 296 return Model.fields_view_get(view_id=view.id) |
309 | 297 |
310 def get_defaults(self, wizard, session, state_name, fields): | 298 def get_defaults(self, wizard, state_name, fields): |
311 return {} | 299 return {} |
312 | 300 |
313 start = ShowStateView('ir.ui.view.show.start', [ | 301 start = ShowStateView('ir.ui.view.show.start', [ |
314 Button('Close', 'end', 'tryton-close', default=True), | 302 Button('Close', 'end', 'tryton-close', default=True), |
315 ]) | 303 ]) |
316 | 304 |
317 ShowView() | |
318 | |
319 | 305 |
320 class ViewShortcut(ModelSQL, ModelView): | 306 class ViewShortcut(ModelSQL, ModelView): |
321 "View shortcut" | 307 "View shortcut" |
322 _name = 'ir.ui.view_sc' | 308 __name__ = 'ir.ui.view_sc' |
323 _description = __doc__ | 309 |
324 name = fields.Char('Shortcut Name', required=True) | 310 name = fields.Char('Shortcut Name', required=True) |
325 res_id = fields.Integer('Resource Ref.', required=True) | 311 res_id = fields.Integer('Resource Ref.', required=True) |
326 sequence = fields.Integer('Sequence', required=True) | 312 sequence = fields.Integer('Sequence', required=True) |
327 user_id = fields.Many2One('res.user', 'User Ref.', required=True, | 313 user_id = fields.Many2One('res.user', 'User Ref.', required=True, |
328 ondelete='CASCADE') | 314 ondelete='CASCADE') |
329 resource = fields.Char('Resource Name', required=True) | 315 resource = fields.Char('Resource Name', required=True) |
330 | 316 |
331 def __init__(self): | 317 @classmethod |
332 super(ViewShortcut, self).__init__() | 318 def __setup__(cls): |
333 self._rpc.update({'get_sc': False}) | 319 super(ViewShortcut, cls).__setup__() |
334 self._order.insert(0, ('sequence', 'ASC')) | 320 cls.__rpc__.update({ |
335 | 321 'get_sc': RPC(), |
336 def get_sc(self, user_id, model='ir.ui.menu'): | 322 }) |
| 323 cls._order.insert(0, ('sequence', 'ASC')) |
| 324 |
| 325 @classmethod |
| 326 def get_sc(cls, user_id, model='ir.ui.menu'): |
337 "Provide user's shortcuts" | 327 "Provide user's shortcuts" |
338 result = [] | 328 result = [] |
339 ids = self.search([ | 329 shortcuts = cls.search([ |
340 ('user_id', '=', user_id), | 330 ('user_id', '=', user_id), |
341 ('resource', '=', model), | 331 ('resource', '=', model), |
342 ]) | 332 ]) |
343 for shorcut in self.browse(ids): | 333 for shorcut in shortcuts: |
344 result.append({ | 334 result.append({ |
345 'res_id': shorcut.res_id, | 335 'res_id': shorcut.res_id, |
346 'name': shorcut.name, | 336 'name': shorcut.name, |
347 }) | 337 }) |
348 return result | 338 return result |
349 | 339 |
350 def default_resource(self): | 340 @staticmethod |
| 341 def default_resource(): |
351 return 'ir.ui.menu' | 342 return 'ir.ui.menu' |
352 | |
353 ViewShortcut() | |
354 | 343 |
355 | 344 |
356 class OpenShortcut(Wizard): | 345 class OpenShortcut(Wizard): |
357 'Open a shortcut' | 346 'Open a shortcut' |
358 _name = 'ir.ui.view_sc.open' | 347 __name__ = 'ir.ui.view_sc.open' |
359 | 348 |
360 start_state = 'open_' | 349 start_state = 'open_' |
361 | 350 |
362 class OpenStateAction(StateAction): | 351 class OpenStateAction(StateAction): |
363 def __init__(self): | 352 def __init__(self): |
364 StateAction.__init__(self, None) | 353 StateAction.__init__(self, None) |
365 | 354 |
366 def get_action(self): | 355 def get_action(self): |
367 pass | 356 pass |
368 | 357 |
369 open_ = OpenStateAction() | 358 open_ = OpenStateAction() |
370 | 359 |
371 def transition_open_(self, session): | 360 @staticmethod |
| 361 def transition_open_(): |
372 return 'end' | 362 return 'end' |
373 | 363 |
374 def do_open_(self, session, action): | 364 @staticmethod |
| 365 def do_open_(action): |
375 pool = Pool() | 366 pool = Pool() |
376 view_sc_obj = pool.get('ir.ui.view_sc') | 367 ViewSC = pool.get('ir.ui.view_sc') |
377 action_keyword_obj = pool.get('ir.action.keyword') | 368 ActionKeyword = pool.get('ir.action.keyword') |
378 action_obj = pool.get('ir.action') | 369 Action = pool.get('ir.action') |
379 | 370 |
380 view_sc = view_sc_obj.browse(Transaction().context.get('active_id')) | 371 view_sc = ViewSC(Transaction().context.get('active_id')) |
381 models = ( | 372 models = ( |
382 '%s,%d' % (view_sc.resource, view_sc.res_id), | 373 '%s,%d' % (view_sc.resource, view_sc.res_id), |
383 '%s,0' % (view_sc.resource), | 374 '%s,0' % (view_sc.resource), |
384 ) | 375 ) |
385 action_keyword_ids = None | 376 action_keywords = None |
386 for model in models: | 377 for model in models: |
387 action_keyword_ids = action_keyword_obj.search([ | 378 action_keywords = ActionKeyword.search([ |
388 ('keyword', '=', 'tree_open'), | 379 ('keyword', '=', 'tree_open'), |
389 ('model', '=', model), | 380 ('model', '=', model), |
390 ]) | 381 ]) |
391 if action_keyword_ids: | 382 if action_keywords: |
392 break | 383 break |
393 if not action_keyword_ids: | 384 if not action_keywords: |
394 return {}, {} | 385 return {}, {} |
395 action_keyword = action_keyword_obj.browse(action_keyword_ids[0]) | 386 action_keyword = action_keywords[0] |
396 return action_obj.get_action_values(action_keyword.action.type, | 387 return Action.get_action_values(action_keyword.action.type, |
397 action_keyword.action.id), {} | 388 [action_keyword.action.id])[0], {} |
398 | |
399 OpenShortcut() | |
400 | 389 |
401 | 390 |
402 class ViewTreeWidth(ModelSQL, ModelView): | 391 class ViewTreeWidth(ModelSQL, ModelView): |
403 "View Tree Width" | 392 "View Tree Width" |
404 _name = 'ir.ui.view_tree_width' | 393 __name__ = 'ir.ui.view_tree_width' |
405 _description = __doc__ | |
406 _rec_name = 'model' | 394 _rec_name = 'model' |
407 model = fields.Char('Model', required=True, select=True) | 395 model = fields.Char('Model', required=True, select=True) |
408 field = fields.Char('Field', required=True, select=True) | 396 field = fields.Char('Field', required=True, select=True) |
409 user = fields.Many2One('res.user', 'User', required=True, | 397 user = fields.Many2One('res.user', 'User', required=True, |
410 ondelete='CASCADE', select=True) | 398 ondelete='CASCADE', select=True) |
411 width = fields.Integer('Width', required=True) | 399 width = fields.Integer('Width', required=True) |
412 | 400 |
413 def __init__(self): | 401 @classmethod |
414 super(ViewTreeWidth, self).__init__() | 402 def __setup__(cls): |
415 self._rpc.update({ | 403 super(ViewTreeWidth, cls).__setup__() |
416 'set_width': True, | 404 cls.__rpc__.update({ |
417 }) | 405 'set_width': RPC(readonly=False), |
418 | 406 }) |
419 def delete(self, ids): | 407 |
420 pool = Pool() | 408 @classmethod |
421 if isinstance(ids, (int, long)): | 409 def delete(cls, records): |
422 ids = [ids] | 410 ModelView._fields_view_get_cache.clear() |
423 views = self.browse(ids) | 411 super(ViewTreeWidth, cls).delete(records) |
424 for view in views: | 412 |
425 # Restart the cache | 413 @classmethod |
426 try: | 414 def create(cls, vals): |
427 pool.get(view.model).fields_view_get.reset() | 415 res = super(ViewTreeWidth, cls).create(vals) |
428 except Exception: | 416 ModelView._fields_view_get_cache.clear() |
429 pass | |
430 res = super(ViewTreeWidth, self).delete(ids) | |
431 return res | 417 return res |
432 | 418 |
433 def create(self, vals): | 419 @classmethod |
434 pool = Pool() | 420 def write(cls, records, vals): |
435 res = super(ViewTreeWidth, self).create(vals) | 421 super(ViewTreeWidth, cls).write(records, vals) |
436 if 'model' in vals: | 422 ModelView._fields_view_get_cache.clear() |
437 model = vals['model'] | 423 |
438 # Restart the cache | 424 @classmethod |
439 try: | 425 def set_width(cls, model, fields): |
440 pool.get(model).fields_view_get.reset() | |
441 except Exception: | |
442 pass | |
443 return res | |
444 | |
445 def write(self, ids, vals): | |
446 pool = Pool() | |
447 if isinstance(ids, (int, long)): | |
448 ids = [ids] | |
449 views = self.browse(ids) | |
450 for view in views: | |
451 # Restart the cache | |
452 try: | |
453 pool.get(view.model).fields_view_get.reset() | |
454 except Exception: | |
455 pass | |
456 res = super(ViewTreeWidth, self).write(ids, vals) | |
457 views = self.browse(ids) | |
458 for view in views: | |
459 # Restart the cache | |
460 try: | |
461 pool.get(view.model).fields_view_get.reset() | |
462 except Exception: | |
463 pass | |
464 return res | |
465 | |
466 def set_width(self, model, fields): | |
467 ''' | 426 ''' |
468 Set width for the current user on the model. | 427 Set width for the current user on the model. |
469 fields is a dictionary with key: field name and value: width. | 428 fields is a dictionary with key: field name and value: width. |
470 ''' | 429 ''' |
471 ids = self.search([ | 430 records = cls.search([ |
472 ('user', '=', Transaction().user), | 431 ('user', '=', Transaction().user), |
473 ('model', '=', model), | 432 ('model', '=', model), |
474 ('field', 'in', fields.keys()), | 433 ('field', 'in', fields.keys()), |
475 ]) | 434 ]) |
476 self.delete(ids) | 435 cls.delete(records) |
477 | 436 |
478 for field in fields.keys(): | 437 for field in fields.keys(): |
479 self.create({ | 438 cls.create({ |
480 'model': model, | 439 'model': model, |
481 'field': field, | 440 'field': field, |
482 'user': Transaction().user, | 441 'user': Transaction().user, |
483 'width': fields[field], | 442 'width': fields[field], |
484 }) | 443 }) |
485 | 444 |
486 ViewTreeWidth() | |
487 | |
488 | 445 |
489 class ViewTreeExpandedState(ModelSQL, ModelView): | 446 class ViewTreeExpandedState(ModelSQL, ModelView): |
490 _name = 'ir.ui.view_tree_expanded_state' | 447 'View Tree Expanded State' |
491 | 448 __name__ = 'ir.ui.view_tree_expanded_state' |
492 _rec_name = 'model' | 449 _rec_name = 'model' |
493 model = fields.Char('Model', required=True) | 450 model = fields.Char('Model', required=True) |
494 domain = fields.Char('Domain', required=True) | 451 domain = fields.Char('Domain', required=True) |
495 user = fields.Many2One('res.user', 'User', required=True, | 452 user = fields.Many2One('res.user', 'User', required=True, |
496 ondelete='CASCADE') | 453 ondelete='CASCADE') |
497 child_name = fields.Char('Child Name') | 454 child_name = fields.Char('Child Name') |
498 nodes = fields.Text('Expanded Nodes') | 455 nodes = fields.Text('Expanded Nodes') |
499 | 456 |
500 def __init__(self): | 457 @classmethod |
501 super(ViewTreeExpandedState, self).__init__() | 458 def __setup__(cls): |
502 self._rpc.update({ | 459 super(ViewTreeExpandedState, cls).__setup__() |
503 'set_expanded': True, | 460 cls.__rpc__.update({ |
504 'get_expanded': True, | 461 'set_expanded': RPC(readonly=False), |
| 462 'get_expanded': RPC(), |
505 }) | 463 }) |
506 | 464 |
507 def init(self, module_name): | 465 @classmethod |
508 super(ViewTreeExpandedState, self).init(module_name) | 466 def __register__(cls, module_name): |
| 467 super(ViewTreeExpandedState, cls).__register__(module_name) |
509 | 468 |
510 cursor = Transaction().cursor | 469 cursor = Transaction().cursor |
511 table = TableHandler(cursor, self, module_name) | 470 table = TableHandler(cursor, cls, module_name) |
512 table.index_action(['model', 'domain', 'user', 'child_name'], 'add') | 471 table.index_action(['model', 'domain', 'user', 'child_name'], 'add') |
513 | 472 |
514 def default_nodes(self): | 473 @staticmethod |
| 474 def default_nodes(): |
515 return '[]' | 475 return '[]' |
516 | 476 |
517 def set_expanded(self, model, domain, child_name, nodes): | 477 @classmethod |
| 478 def set_expanded(cls, model, domain, child_name, nodes): |
518 current_user = Transaction().user | 479 current_user = Transaction().user |
519 with Transaction().set_user(0): | 480 with Transaction().set_user(0): |
520 ids = self.search([ | 481 records = cls.search([ |
521 ('user', '=', current_user), | 482 ('user', '=', current_user), |
522 ('model', '=', model), | 483 ('model', '=', model), |
523 ('domain', '=', domain), | 484 ('domain', '=', domain), |
524 ('child_name', '=', child_name), | 485 ('child_name', '=', child_name), |
525 ]) | 486 ]) |
526 self.delete(ids) | 487 cls.delete(records) |
527 self.create({ | 488 cls.create({ |
528 'user': current_user, | 489 'user': current_user, |
529 'model': model, | 490 'model': model, |
530 'domain': domain, | 491 'domain': domain, |
531 'child_name': child_name, | 492 'child_name': child_name, |
532 'nodes': nodes, | 493 'nodes': nodes, |
533 }) | 494 }) |
534 | 495 |
535 def get_expanded(self, model, domain, child_name): | 496 @classmethod |
| 497 def get_expanded(cls, model, domain, child_name): |
536 current_user = Transaction().user | 498 current_user = Transaction().user |
537 with Transaction().set_user(0): | 499 with Transaction().set_user(0): |
538 try: | 500 try: |
539 expanded_info, = self.search([ | 501 expanded_info, = cls.search([ |
540 ('user', '=', current_user), | 502 ('user', '=', current_user), |
541 ('model', '=', model), | 503 ('model', '=', model), |
542 ('domain', '=', domain), | 504 ('domain', '=', domain), |
543 ('child_name', '=', child_name), | 505 ('child_name', '=', child_name), |
544 ], | 506 ], |
545 limit=1) | 507 limit=1) |
546 except ValueError: | 508 except ValueError: |
547 return '[]' | 509 return '[]' |
548 return self.browse(expanded_info).nodes | 510 return cls(expanded_info).nodes |
549 | |
550 | |
551 ViewTreeExpandedState() | |
LEFT | RIGHT |