diff --git a/openerp/addons/base/ir/ir_values.py b/openerp/addons/base/ir/ir_values.py index bd619966b67..e5c26c6a20b 100644 --- a/openerp/addons/base/ir/ir_values.py +++ b/openerp/addons/base/ir/ir_values.py @@ -251,6 +251,21 @@ class ir_values(osv.osv): 'company_id': company_id, }) + def get_default(self, cr, uid, model, field_name, for_all_users=True, company_id=False, condition=False): + """ Return the default value defined for model, field_name, users, company and condition. + Return ``None`` if no such default exists. + """ + search_criteria = [ + ('key', '=', 'default'), + ('key2', '=', condition and condition[:200]), + ('model', '=', model), + ('name', '=', field_name), + ('user_id', '=', False if for_all_users else uid), + ('company_id','=', company_id) + ] + defaults = self.browse(cr, uid, self.search(cr, uid, search_criteria)) + return pickle.loads(defaults[0].value.encode('utf-8')) if defaults else None + def get_defaults(self, cr, uid, model, condition=False): """Returns any default values that are defined for the current model and user, (and match ``condition``, if specified), previously registered via diff --git a/openerp/addons/base/res/res_config.py b/openerp/addons/base/res/res_config.py index 357a8718e52..04a9102608d 100644 --- a/openerp/addons/base/res/res_config.py +++ b/openerp/addons/base/res/res_config.py @@ -397,95 +397,142 @@ class ir_actions_configuration_wizard(osv.osv_memory): ir_actions_configuration_wizard() + + class res_config_settings(osv.osv_memory): - ''' - Base classes for new-style configuration items. - ''' + """ Base configuration wizard for application settings. It provides support for setting + default values, assigning groups to employee users, and installing modules. + To make such a 'settings' wizard, define a model like:: + + class my_config_wizard(osv.osv_memory): + _name = 'sale.config.prefs' + _inherit = 'res.config.settings' + _columns = { + 'default_foo': fields.type(..., default_model='model'), + 'group_bar': fields.boolean(..., group='base.group_user', implied_group='xml_id'), + 'module_baz': fields.boolean(...), + 'other_field': fields.type(...), + } + + The method ``execute`` provides some support based on a naming convention: + + * For a field like 'default_XXX', ``execute`` sets the (global) default value of + the field 'XXX' in the model named by ``default_model`` to the field's value. + + * 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. + + * For a boolean field like 'module_XXX', ``execute`` triggers the immediate + installation of the module named 'XXX' if the field has value ``True``. + + * For other fields, the method ``execute`` only record their value for future + invocations of the wizard. Override the method to define their effect. + """ _name = 'res.config.settings' _inherit = 'res.config' - def create(self, cr, uid, vals, context=None): - ids = super(res_config_settings, self).create(cr, uid, vals, context=context) - self.execute(cr, uid, [ids], vals, context) - return ids + def _get_classified_fields(self, cr, uid, context=None): + """ return a dictionary with the fields classified by category:: - def write(self, cr, uid, ids, vals, context=None): - self.execute(cr, uid, ids, vals, context) - return super(res_config_settings, self).write(cr, uid, ids, vals, context=context) + { 'default': [('default_foo', 'model', 'foo'), ...], + 'group': [('group_bar', browse_group, browse_implied_group), ...], + 'module': [('module_baz', browse_module), ...], + 'other': ['other_field', ...], + } + """ + ir_model_data = self.pool.get('ir.model.data') + ir_module = self.pool.get('ir.module.module') + def ref(xml_id): + mod, xml = xml_id.split('.', 1) + return ir_model_data.get_object(cr, uid, mod, xml, context) - def execute(self, cr, uid, ids, vals, context=None): + 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))) + elif name.startswith('module_') and isinstance(field, fields.boolean): + mod_ids = ir_module.search(cr, uid, [('name', '=', name[7:])]) + modules.append((name, ir_module.browse(cr, uid, mod_ids[0], context))) + else: + others.append(name) + + return {'default': defaults, 'group': groups, 'module': modules, 'other': others} + + def default_get(self, cr, uid, fields, context=None): + ir_values = self.pool.get('ir.values') + ir_model_data = self.pool.get('ir.model.data') + classified = self._get_classified_fields(cr, uid, context) + + res = super(res_config_settings, self).default_get(cr, uid, fields, context) + + # defaults: take the corresponding default value they set + for name, model, field in classified['default']: + value = ir_values.get_default(cr, uid, model, field) + if value is not None: + 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 + + # modules: which modules are installed/to install + for name, module in classified['module']: + res[name] = module.state in ('installed', 'to install', 'to upgrade') + + # other fields: call all methods that start with 'get_default_' + for method in dir(self): + if method.startswith('get_default'): + res.update(getattr(self, method)(cr, uid, fields, context)) + + return res + + def fields_get(self, cr, uid, allfields=None, context=None, write_access=True): + # overridden to make fields of installed modules readonly + res = super(res_config_settings, self).fields_get(cr, uid, allfields, context, write_access) + classified = self._get_classified_fields(cr, uid, context) + for name, module in classified['module']: + if module.state in ('installed', 'to install', 'to upgrade'): + res[name]['readonly'] = True + return res + + def execute(self, cr, uid, ids, context=None): + ir_values = self.pool.get('ir.values') + ir_model_data = self.pool.get('ir.model.data') + ir_module = self.pool.get('ir.module.module') + res_groups = self.pool.get('res.groups') + classified = self._get_classified_fields(cr, uid, 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]) + + # group fields: modify group / implied groups + for name, group, implied_group in classified['group']: + if config[name]: + group.write({'implied_ids': [(4, implied_group.id)]}) + else: + group.write({'implied_ids': [(3, implied_group.id)]}) + implied_group.write({'users': [(3, u.id) for u in group.users]}) + + # other fields: execute all methods that start with 'set_' for method in dir(self): if method.startswith('set_'): - getattr(self, method)(cr, uid, ids, vals, context) - return True + getattr(self, method)(cr, uid, ids, context) - def default_get(self, cr, uid, fields_list, context=None): - result = super(res_config_settings, self).default_get( - cr, uid, fields_list, context=context) - for method in dir(self): - if method.startswith('get_default_'): - result.update(getattr(self, method)(cr, uid, [], context)) - return result - - def get_default_applied_groups(self, cr, uid, ids, context=None): - applied_groups = {} - user_obj = self.pool.get('res.users') - dataobj = self.pool.get('ir.model.data') - - groups = [] - user_group_ids = user_obj.browse(cr, uid, uid, context=context).groups_id - - for group_id in user_group_ids: - groups.append(group_id.id) - - for id in groups: - key_id = dataobj.search(cr, uid,[('res_id','=',id),('model','=','res.groups')],context=context) - key = dataobj.browse(cr, uid, key_id[0], context=context).name - applied_groups[key] = True - - return applied_groups - - def get_default_installed_modules(self, cr, uid, ids, context=None): - module_obj = self.pool.get('ir.module.module') - module_names = [] - module_ids = module_obj.search(cr, uid, - [('state','in',['to install', 'installed', 'to upgrade'])], - context=context) - modules_list = [mod.name for mod in module_obj.browse(cr, uid, module_ids, context=context)] - installed_modules = dict([('module_'+name, True) for name in modules_list]) - return installed_modules - - def set_installed_modules(self, cr, uid, ids, vals, context=None): - module_obj = self.pool.get('ir.module.module') - for module, value in vals.items(): - if module.startswith('module_'): - mod_name = module[len('module_'):] - installed = self.get_default_installed_modules(cr, uid, ids, context=context) - if value == True and not installed.get(mod_name): - module_id = module_obj.search(cr, uid, [('name','=',mod_name)]) - module_obj.button_immediate_install(cr, uid, module_id, context=context) - elif value == False and installed.get(mod_name): - module_id = module_obj.search(cr, uid, [('name','=',mod_name)]) - module_obj.button_uninstall(self, cr, uid, module_id, context=context) - module_obj.button_upgrade(self, cr, uid, module_id, context=context) - - def set_groups(self, cr, uid, ids, vals, context=None): - data_obj = self.pool.get('ir.model.data') - users_obj = self.pool.get('res.users') - groups_obj = self.pool.get('res.groups') - ir_values_obj = self.pool.get('ir.values') - dummy,user_group_id = data_obj.get_object_reference(cr, uid, 'base', 'group_user') - for group in vals.keys(): - if group.startswith('group_'): - dummy,group_id = data_obj.get_object_reference(cr, uid, 'base', group) - if vals[group]: - groups_obj.write(cr, uid, [user_group_id], {'implied_ids': [(4,group_id)]}) - users_obj.write(cr, uid, [uid], {'groups_id': [(4,group_id)]}) - ir_values_obj.set(cr, uid, 'default', False, 'groups_id', ['res.users'], [(4,group_id)]) - else: - groups_obj.write(cr, uid, [user_group_id], {'implied_ids': [(3,group_id)]}) - users_obj.write(cr, uid, [uid], {'groups_id': [(3,group_id)]}) - ir_values_obj.set(cr, uid, 'default', False, 'groups_id', ['res.users'], [(3,group_id)]) + # module fields: install immediately the selected modules + to_install = [] + for name, module in classified['module']: + if config[name] and module.state == 'uninstalled': + to_install.append(module.id) + if to_install: + return ir_module.button_immediate_install(cr, uid, to_install, context) + return {} res_config_settings()