[FIX] base: incorrect translation mark
[odoo/odoo.git] / openerp / addons / base / res / res_config.py
index 1732acf..1b6b17b 100644 (file)
@@ -28,6 +28,7 @@ from openerp.osv import osv, fields
 from openerp.tools import ustr
 from openerp.tools.translate import _
 from openerp import exceptions
+from lxml import etree
 
 _logger = logging.getLogger(__name__)
 
@@ -49,10 +50,10 @@ class res_config_module_installation_mixin(object):
                 to_install_missing_names.append(name)
             elif module.state == 'uninstalled':
                 to_install_ids.append(module.id)
-
+        result = None
         if to_install_ids:
-            ir_module.button_immediate_install(cr, uid, to_install_ids, context=context)
-
+            result = ir_module.button_immediate_install(cr, uid, to_install_ids, context=context)
+        #FIXME: if result is not none, the corresponding todo will be skipped because it was just marked done
         if to_install_missing_names:
             return {
                 'type': 'ir.actions.client',
@@ -60,7 +61,7 @@ class res_config_module_installation_mixin(object):
                 'params': {'modules': to_install_missing_names},
             }
 
-        return None
+        return result
 
 class res_config_configurable(osv.osv_memory):
     ''' Base classes for new-style configuration items
@@ -102,13 +103,10 @@ class res_config_configurable(osv.osv_memory):
             res = next.action_launch(context=context)
             res['nodestroy'] = False
             return res
-        # reload the client; open the first available root menu
-        menu_obj = self.pool['ir.ui.menu']
-        menu_ids = menu_obj.search(cr, uid, [('parent_id', '=', False)], context=context)
+
         return {
             'type': 'ir.actions.client',
             'tag': 'reload',
-            'params': {'menu_id': menu_ids and menu_ids[0] or False},
         }
 
     def start(self, cr, uid, ids, context=None):
@@ -131,6 +129,7 @@ class res_config_configurable(osv.osv_memory):
         """
         raise NotImplementedError(
             'Configuration items need to implement execute')
+
     def cancel(self, cr, uid, ids, context=None):
         """ Method called when the user click on the ``Skip`` button.
 
@@ -184,8 +183,6 @@ class res_config_configurable(osv.osv_memory):
         if next: return next
         return self.next(cr, uid, ids, context=context)
 
-res_config_configurable()
-
 class res_config_installer(osv.osv_memory, res_config_module_installation_mixin):
     """ New-style configuration base specialized for addons selection
     and installation.
@@ -225,10 +222,10 @@ class res_config_installer(osv.osv_memory, res_config_module_installation_mixin)
 
         _install_if = {
             ('sale','crm'): ['sale_crm'],
-            ('sale','project'): ['project_mrp'],
+            ('sale','project'): ['sale_service'],
         }
 
-    will install both ``sale_crm`` and ``project_mrp`` if all of
+    will install both ``sale_crm`` and ``sale_service`` if all of
     ``sale``, ``crm`` and ``project`` are selected for installation.
 
     Hook methods
@@ -297,10 +294,10 @@ class res_config_installer(osv.osv_memory, res_config_module_installation_mixin)
     def _already_installed(self, cr, uid, context=None):
         """ For each module (boolean fields in a res.config.installer),
         check if it's already installed (either 'to install', 'to upgrade'
-        or 'installed') and if it is return the module's browse_record
+        or 'installed') and if it is return the module's record
 
         :returns: a list of all installed modules in this installer
-        :rtype: [browse_record]
+        :rtype: recordset (collection of Record)
         """
         modules = self.pool['ir.module.module']
 
@@ -314,7 +311,6 @@ class res_config_installer(osv.osv_memory, res_config_module_installation_mixin)
                            context=context),
             context=context)
 
-
     def modules_to_install(self, cr, uid, ids, context=None):
         """ selects all modules to install:
 
@@ -337,7 +333,7 @@ class res_config_installer(osv.osv_memory, res_config_module_installation_mixin)
                    for installer in self.read(cr, uid, ids, context=context)
                    for module_name, to_install in installer.iteritems()
                    if module_name != 'id'
-                   if type(self._columns[module_name]) is fields.boolean
+                   if type(self._columns.get(module_name)) is fields.boolean
                    if to_install)
 
         hooks_results = set()
@@ -397,45 +393,6 @@ class res_config_installer(osv.osv_memory, res_config_module_installation_mixin)
 
         return self._install_modules(cr, uid, modules, context=context)
 
-res_config_installer()
-
-DEPRECATION_MESSAGE = 'You are using an addon using old-style configuration '\
-    'wizards (ir.actions.configuration.wizard). Old-style configuration '\
-    'wizards have been deprecated.\n'\
-    'The addon should be migrated to res.config objects.'
-class ir_actions_configuration_wizard(osv.osv_memory):
-    ''' Compatibility configuration wizard
-
-    The old configuration wizard has been replaced by res.config, but in order
-    not to break existing but not-yet-migrated addons, the old wizard was
-    reintegrated and gutted.
-    '''
-    _name='ir.actions.configuration.wizard'
-    _inherit = 'res.config'
-
-    def _next_action_note(self, cr, uid, ids, context=None):
-        next = self._next_action(cr, uid)
-        if next:
-            # if the next one is also an old-style extension, you never know...
-            if next.note:
-                return next.note
-            return _("Click 'Continue' to configure the next addon...")
-        return _("Your database is now fully configured.\n\n"\
-            "Click 'Continue' and enjoy your OpenERP experience...")
-
-    _columns = {
-        'note': fields.text('Next Wizard', readonly=True),
-        }
-    _defaults = {
-        'note': _next_action_note,
-        }
-
-    def execute(self, cr, uid, ids, context=None):
-        _logger.warning(DEPRECATION_MESSAGE)
-
-ir_actions_configuration_wizard()
-
-
 class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
     """ Base configuration wizard for application settings.  It provides support for setting
         default values, assigning groups to employee users, and installing modules.
@@ -459,6 +416,7 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
         *   For a boolean field like 'group_XXX', ``execute`` adds/removes 'implied_group'
             to/from the implied groups of 'group', depending on the field's value.
             By default 'group' is the group Employee.  Groups are given by their xml id.
+            The attribute 'group' may contain several xml ids, separated by commas.
 
         *   For a boolean field like 'module_XXX', ``execute`` triggers the immediate
             installation of the module named 'XXX' if the field has value ``True``.
@@ -477,11 +435,50 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
     def copy(self, cr, uid, id, values, context=None):
         raise osv.except_osv(_("Cannot duplicate configuration!"), "")
 
+    def fields_view_get(self, cr, user, view_id=None, view_type='form',
+                        context=None, toolbar=False, submenu=False):
+        ret_val = super(res_config_settings, self).fields_view_get(
+            cr, user, view_id=view_id, view_type=view_type, context=context,
+            toolbar=toolbar, submenu=submenu)
+
+        doc = etree.XML(ret_val['arch'])
+
+        for field in ret_val['fields']:
+            if not field.startswith("module_"):
+                continue
+            for node in doc.xpath("//field[@name='%s']" % field):
+                if 'on_change' not in node.attrib:
+                    node.set("on_change",
+                    "onchange_module(%s, '%s')" % (field, field))
+
+        ret_val['arch'] = etree.tostring(doc)
+        return ret_val
+
+    def onchange_module(self, cr, uid, ids, field_value, module_name, context={}):
+        module_pool = self.pool.get('ir.module.module')
+        module_ids = module_pool.search(
+            cr, uid, [('name', '=', module_name.replace("module_", '')),
+            ('state','in', ['to install', 'installed', 'to upgrade'])],
+            context=context)
+
+        if module_ids and not field_value:
+            dep_ids = module_pool.downstream_dependencies(cr, uid, module_ids, context=context)
+            dep_name = [x.shortdesc for x  in module_pool.browse(
+                cr, uid, dep_ids + module_ids, context=context)]
+            message = '\n'.join(dep_name)
+            return {
+                'warning': {
+                    'title': _('Warning!'),
+                    'message': _('Disabling this option will also uninstall the following modules \n%s') % message,
+                }
+            }
+        return {}
+
     def _get_classified_fields(self, cr, uid, context=None):
         """ return a dictionary with the fields classified by category::
 
                 {   'default': [('default_foo', 'model', 'foo'), ...],
-                    'group':   [('group_bar', browse_group, browse_implied_group), ...],
+                    'group':   [('group_bar', [browse_group], browse_implied_group), ...],
                     'module':  [('module_baz', browse_module), ...],
                     'other':   ['other_field', ...],
                 }
@@ -490,15 +487,15 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
         ir_module = self.pool['ir.module.module']
         def ref(xml_id):
             mod, xml = xml_id.split('.', 1)
-            return ir_model_data.get_object(cr, uid, mod, xml, context)
+            return ir_model_data.get_object(cr, uid, mod, xml, context=context)
 
         defaults, groups, modules, others = [], [], [], []
         for name, field in self._columns.items():
             if name.startswith('default_') and hasattr(field, 'default_model'):
                 defaults.append((name, field.default_model, name[8:]))
             elif name.startswith('group_') and isinstance(field, fields.boolean) and hasattr(field, 'implied_group'):
-                field_group = getattr(field, 'group', 'base.group_user')
-                groups.append((name, ref(field_group), ref(field.implied_group)))
+                field_groups = getattr(field, 'group', 'base.group_user').split(',')
+                groups.append((name, map(ref, field_groups), ref(field.implied_group)))
             elif name.startswith('module_') and isinstance(field, fields.boolean):
                 mod_ids = ir_module.search(cr, uid, [('name', '=', name[7:])])
                 record = ir_module.browse(cr, uid, mod_ids[0], context) if mod_ids else None
@@ -521,8 +518,8 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
                 res[name] = value
 
         # groups: which groups are implied by the group Employee
-        for name, group, implied_group in classified['group']:
-            res[name] = implied_group in group.implied_ids
+        for name, groups, implied_group in classified['group']:
+            res[name] = all(implied_group in group.implied_ids for group in groups)
 
         # modules: which modules are installed/to install
         for name, module in classified['module']:
@@ -536,23 +533,36 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
         return res
 
     def execute(self, cr, uid, ids, context=None):
+        if context is None:
+            context = {}
+
+        context = dict(context, active_test=False)
+        if uid != SUPERUSER_ID and not self.pool['res.users'].has_group(cr, uid, 'base.group_erp_manager'):
+            raise openerp.exceptions.AccessError(_("Only administrators can change the settings"))
+
         ir_values = self.pool['ir.values']
         ir_module = self.pool['ir.module.module']
-        classified = self._get_classified_fields(cr, uid, context)
+        res_groups = self.pool['res.groups']
+
+        classified = self._get_classified_fields(cr, uid, context=context)
 
         config = self.browse(cr, uid, ids[0], context)
 
         # default values fields
         for name, model, field in classified['default']:
-            ir_values.set_default(cr, uid, model, field, config[name])
+            ir_values.set_default(cr, SUPERUSER_ID, model, field, config[name])
 
         # group fields: modify group / implied groups
-        for name, group, implied_group in classified['group']:
+        for name, groups, implied_group in classified['group']:
+            gids = map(int, groups)
             if config[name]:
-                group.write({'implied_ids': [(4, implied_group.id)]})
+                res_groups.write(cr, uid, gids, {'implied_ids': [(4, implied_group.id)]}, context=context)
             else:
-                group.write({'implied_ids': [(3, implied_group.id)]})
-                implied_group.write({'users': [(3, u.id) for u in group.users]})
+                res_groups.write(cr, uid, gids, {'implied_ids': [(3, implied_group.id)]}, context=context)
+                uids = set()
+                for group in groups:
+                    uids.update(map(int, group.users))
+                implied_group.write({'users': [(3, u) for u in uids]})
 
         # other fields: execute all methods that start with 'set_'
         for method in dir(self):
@@ -623,7 +633,7 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
             structured as follows: module_name.menuitem_xml_id (e.g.: "base.menu_sale_config")
         :return tuple:
             - t[0]: string: full path to the menuitem (e.g.: "Settings/Configuration/Sales")
-            - t[1]: long: id of the menuitem's action
+            - t[1]: int or long: id of the menuitem's action
         """
         module_name, menu_xml_id = menu_xml_id.split('.')
         dummy, menu_id = self.pool['ir.model.data'].get_object_reference(cr, uid, module_name, menu_xml_id)
@@ -694,4 +704,5 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
         if (action_id):
             return exceptions.RedirectWarning(msg % values, action_id, _('Go to the configuration panel'))
         return exceptions.Warning(msg % values)
+
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: