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()