diff --git a/CHANGELOG b/CHANGELOG index 7f0fb0aacc..de1ad4e311 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add server-side icons * Add support for file link to BinaryField * Add model field access * Add loading attribute on fields diff --git a/trytond/convert.py b/trytond/convert.py index 1f1f0a169c..2c3375d46b 100644 --- a/trytond/convert.py +++ b/trytond/convert.py @@ -62,7 +62,7 @@ class MenuitemTagHandler: # TODO maybe use a prefetch for this: cursor.execute(cursor.limit_clause( - "SELECT a.name, a.type, act.view_type, v.type " \ + "SELECT a.name, a.type, act.view_type, v.type, icon.name " \ "FROM ir_action a " \ "LEFT JOIN ir_action_report report ON (a.id = report.action) " \ "LEFT JOIN ir_action_act_window act ON (a.id = act.action) " \ @@ -70,14 +70,15 @@ class MenuitemTagHandler: "LEFT JOIN ir_action_url url ON (a.id = url.action) " \ "LEFT JOIN ir_action_act_window_view wv ON " \ "(act.id = wv.act_window) " \ - "LEFT JOIN ir_ui_view v on (v.id = wv.view) " \ + "LEFT JOIN ir_ui_view v ON (v.id = wv.view) " \ + "LEFT JOIN ir_ui_icon icon ON (a.icon = icon.id) " \ "WHERE report.id = %s " \ "OR act.id = %s " \ "OR wizard.id = %s " \ "OR url.id = %s " \ "ORDER by wv.sequence", 1), (action_id, action_id, action_id, action_id)) - action_name, action_type, view_type, view_mode = \ + action_name, action_type, view_type, view_mode, icon_name = \ cursor.fetchone() values['action'] = '%s,%s' % (action_type, action_id) @@ -85,6 +86,8 @@ class MenuitemTagHandler: icon = attributes.get('icon', '') if icon: values['icon'] = icon + elif icon_name: + values['icon'] = icon_name elif action_type == 'ir.action.wizard': values['icon'] = 'tryton-executable' elif action_type == 'ir.action.report': @@ -126,7 +129,6 @@ class MenuitemTagHandler: self.values = values - def characters(self, data): pass diff --git a/trytond/ir/action.py b/trytond/ir/action.py index 2d3629df31..831ba0cd64 100644 --- a/trytond/ir/action.py +++ b/trytond/ir/action.py @@ -22,6 +22,7 @@ class Action(ModelSQL, ModelView): 'Keywords') groups = fields.Many2Many('ir.action-res.group', 'action_id', 'gid', 'Groups') + icon = fields.Many2One('ir.ui.icon', 'Icon') active = fields.Boolean('Active', select=2) def __init__(self): @@ -183,15 +184,18 @@ class ActionKeyword(ModelSQL, ModelView): ('action', '=', action_keyword.action.id), ]) if action_id: - res.append(action_obj.read(action_id[0])) + columns = set(action_obj._columns.keys() + + action_obj._inherit_fields.keys()) + columns.add('icon.rec_name') if action_keyword.action.type == 'ir.action.report': - del res[-1]['report_content_data'] - del res[-1]['report_content'] - del res[-1]['style_content'] - res[-1]['email'] = encoder.encode(res[-1]['email']) + to_remove = ('report_content_data', 'report_content', + 'style_content') elif action_keyword.action.type == 'ir.action.act_window': - for field in ('domain', 'context', 'search_value'): - del res[-1][field] + to_remove = ('domain', 'context', 'search_value') + else: + to_remove = set() + columns.difference_update(to_remove) + res.append(action_obj.read(action_id[0], list(columns))) return res ActionKeyword() diff --git a/trytond/ir/ui/__init__.py b/trytond/ir/ui/__init__.py index f202ab800b..8b1589c582 100644 --- a/trytond/ir/ui/__init__.py +++ b/trytond/ir/ui/__init__.py @@ -2,3 +2,4 @@ #this repository contains the full copyright notices and license terms. from menu import * from view import * +from icon import * diff --git a/trytond/ir/ui/form.rnc b/trytond/ir/ui/form.rnc index 79c502484c..0096a8d990 100644 --- a/trytond/ir/ui/form.rnc +++ b/trytond/ir/ui/form.rnc @@ -181,6 +181,7 @@ page = | vpaned)* } attlist.page &= attribute angle { text }? +attlist.page &= attribute icon { text }? attlist.page &= [ a:defaultValue = "Unknown" ] attribute string { text }? attlist.page &= [ a:defaultValue = "4" ] attribute col { text }? diff --git a/trytond/ir/ui/form.rng b/trytond/ir/ui/form.rng index a2e191c2b0..a2aa8e6f11 100644 --- a/trytond/ir/ui/form.rng +++ b/trytond/ir/ui/form.rng @@ -671,6 +671,11 @@ + + + + + diff --git a/trytond/ir/ui/icon.py b/trytond/ir/ui/icon.py new file mode 100644 index 0000000000..90e1c4612b --- /dev/null +++ b/trytond/ir/ui/icon.py @@ -0,0 +1,52 @@ +# This file is part of Tryton. The COPYRIGHT file at the top level of this +# repository contains the full copyright notices and license terms. +from __future__ import with_statement + +import os + +from trytond.model import ModelView, ModelSQL, fields +from trytond.tools import file_open +from trytond.transaction import Transaction + + +class Icon(ModelSQL, ModelView): + 'Icon' + _name = 'ir.ui.icon' + _description = __doc__ + + name = fields.Char('Name', required=True, select=1) + module = fields.Char('Module', readonly=True) + path = fields.Char('SVG Path', readonly=True) + icon = fields.Function(fields.Char('Icon', depends=['path']), 'get_icon') + sequence = fields.Integer('Sequence') + + def __init__(self): + super(Icon, self).__init__() + self._order.insert(0, ('sequence', 'ASC')) + self._rpc.update({ + 'list_icons': False, + }) + + def default_module(self): + return Transaction().context.get('module') or '' + + def default_sequence(self): + return 10 + + def list_icons(self): + icons = {} + for icon in self.browse(self.search([], + order=[('sequence', 'ASC'), ('id', 'ASC')])): + if icon.name not in icons: + icons[icon.name] = icon.id + return sorted((icon_id, name) for name, icon_id in icons.iteritems()) + + def get_icon(self, ids, name): + result = {} + for icon in self.browse(ids): + path = os.path.join(icon.module, icon.path.replace('/', os.sep)) + with file_open(path, subdir='modules') as fp: + result[icon.id] = fp.read() + return result + +Icon()