diff options
| author | Thibault Delavallée <tde@openerp.com> | 2012-12-21 11:03:20 +0100 |
|---|---|---|
| committer | Thibault Delavallée <tde@openerp.com> | 2012-12-21 11:03:20 +0100 |
| commit | 5b3fc4061ba0c84f7e0ff466c4d7025f9cfa44e9 (patch) | |
| tree | d07f2c5bb9ec0ce018b824f91caa5f6f1da9c090 /openerp/addons/base/module | |
| parent | 919c0d1152ba869af49e4d9186698d35dbb89541 (diff) | |
| parent | 73cb6d5321cc71d85456e6f6e61fc34b79b95c16 (diff) | |
[MERGE] Sync with trunk.
bzr revid: tde@openerp.com-20121221100320-ntn6zsdcqlvz52xn
Diffstat (limited to 'openerp/addons/base/module')
6 files changed, 242 insertions, 132 deletions
diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index a10b38cf586..47a4cfc8174 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -24,12 +24,22 @@ from docutils.transforms import Transform, writer_aux from docutils.writers.html4css1 import Writer import imp import logging +import os import re +import shutil +import tempfile import urllib +import urllib2 +import zipfile import zipimport +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO # NOQA + import openerp -from openerp import modules, pooler, release, tools, addons +from openerp import modules, pooler, tools, addons from openerp.modules.db import create_categories from openerp.tools.parse_version import parse_version from openerp.tools.translate import _ @@ -43,14 +53,29 @@ ACTION_DICT = { 'res_model': 'base.module.upgrade', 'target': 'new', 'type': 'ir.actions.act_window', - 'nodestroy':True, + 'nodestroy': True, } +def backup(path, raise_exception=True): + path = os.path.normpath(path) + if not os.path.exists(path): + if not raise_exception: + return None + raise OSError('path does not exists') + cnt = 1 + while True: + bck = '%s~%d' % (path, cnt) + if not os.path.exists(bck): + shutil.move(path, bck) + return bck + cnt += 1 + + class module_category(osv.osv): _name = "ir.module.category" _description = "Application" - def _module_nbr(self,cr,uid, ids, prop, unknow_none, context): + def _module_nbr(self, cr, uid, ids, prop, unknow_none, context): cr.execute('SELECT category_id, COUNT(*) \ FROM ir_module_module \ WHERE category_id IN %(ids)s \ @@ -58,7 +83,7 @@ class module_category(osv.osv): FROM ir_module_category \ WHERE parent_id IN %(ids)s) \ GROUP BY category_id', {'ids': tuple(ids)} - ) + ) result = dict(cr.fetchall()) for id in ids: cr.execute('select id from ir_module_category where parent_id=%s', (id,)) @@ -71,16 +96,16 @@ class module_category(osv.osv): 'parent_id': fields.many2one('ir.module.category', 'Parent Application', select=True), 'child_ids': fields.one2many('ir.module.category', 'parent_id', 'Child Applications'), 'module_nr': fields.function(_module_nbr, string='Number of Modules', type='integer'), - 'module_ids' : fields.one2many('ir.module.module', 'category_id', 'Modules'), - 'description' : fields.text("Description", translate=True), - 'sequence' : fields.integer('Sequence'), - 'visible' : fields.boolean('Visible'), + 'module_ids': fields.one2many('ir.module.module', 'category_id', 'Modules'), + 'description': fields.text("Description", translate=True), + 'sequence': fields.integer('Sequence'), + 'visible': fields.boolean('Visible'), 'xml_id': fields.function(osv.osv.get_external_id, type='char', size=128, string="External ID"), } _order = 'name' _defaults = { - 'visible' : 1, + 'visible': 1, } class MyFilterMessages(Transform): @@ -119,7 +144,6 @@ class module(osv.osv): info = {} try: info = modules.load_information_from_description_file(name) - info['version'] = release.major_version + '.' + info['version'] except Exception: _logger.debug('Error when trying to fetch informations for ' 'module %s', name, exc_info=True) @@ -134,9 +158,10 @@ class module(osv.osv): return res def _get_latest_version(self, cr, uid, ids, field_name=None, arg=None, context=None): - res = dict.fromkeys(ids, '') + default_version = modules.adapt_version('1.0') + res = dict.fromkeys(ids, default_version) for m in self.browse(cr, uid, ids): - res[m.id] = self.get_module_info(m.name).get('version', '') + res[m.id] = self.get_module_info(m.name).get('version', default_version) return res def _get_views(self, cr, uid, ids, field_name=None, arg=None, context=None): @@ -167,9 +192,11 @@ class module(osv.osv): continue # then, search and group ir.model.data records - imd_models = dict( [(m,[]) for m in dmodels]) - imd_ids = model_data_obj.search(cr,uid,[('module','=', module_rec.name), - ('model','in',tuple(dmodels))]) + imd_models = dict([(m, []) for m in dmodels]) + imd_ids = model_data_obj.search(cr, uid, [ + ('module', '=', module_rec.name), + ('model', 'in', tuple(dmodels)) + ]) for imd_res in model_data_obj.read(cr, uid, imd_ids, ['model', 'res_id'], context=context): imd_models[imd_res['model']].append(imd_res['res_id']) @@ -181,7 +208,7 @@ class module(osv.osv): view_ids = imd_models.get('ir.ui.view', []) for v in view_obj.browse(cr, uid, view_ids, context=context): aa = v.inherit_id and '* INHERIT ' or '' - res_mod_dic['views_by_module'].append(aa + v.name + '('+v.type+')') + res_mod_dic['views_by_module'].append('%s%s (%s)' % (aa, v.name, v.type)) report_ids = imd_models.get('ir.actions.report.xml', []) for rx in report_obj.browse(cr, uid, report_ids, context=context): @@ -191,15 +218,13 @@ class module(osv.osv): for um in menu_obj.browse(cr, uid, menu_ids, context=context): res_mod_dic['menus_by_module'].append(um.complete_name) except KeyError, e: - _logger.warning( - 'Data not found for items of %s', module_rec.name) + _logger.warning('Data not found for items of %s', module_rec.name) except AttributeError, e: - _logger.warning( - 'Data not found for items of %s %s', module_rec.name, str(e)) + _logger.warning('Data not found for items of %s %s', module_rec.name, str(e)) except Exception, e: - _logger.warning('Unknown error while fetching data of %s', - module_rec.name, exc_info=True) - for key, _ in res.iteritems(): + _logger.warning('Unknown error while fetching data of %s', module_rec.name, exc_info=True) + + for key in res.iterkeys(): for k, v in res[key].iteritems(): res[key][k] = "\n".join(sorted(v)) return res @@ -232,36 +257,34 @@ class module(osv.osv): # installed_version refer the latest version (the one on disk) # latest_version refer the installed version (the one in database) # published_version refer the version available on the repository - 'installed_version': fields.function(_get_latest_version, - string='Latest Version', type='char'), + 'installed_version': fields.function(_get_latest_version, string='Latest Version', type='char'), 'latest_version': fields.char('Installed Version', size=64, readonly=True), 'published_version': fields.char('Published Version', size=64, readonly=True), 'url': fields.char('URL', size=128, readonly=True), 'sequence': fields.integer('Sequence'), - 'dependencies_id': fields.one2many('ir.module.module.dependency', - 'module_id', 'Dependencies', readonly=True), + 'dependencies_id': fields.one2many('ir.module.module.dependency', 'module_id', 'Dependencies', readonly=True), 'auto_install': fields.boolean('Automatic Installation', - help='An auto-installable module is automatically installed by the ' - 'system when all its dependencies are satisfied. ' - 'If the module has no dependency, it is always installed.'), + help='An auto-installable module is automatically installed by the ' + 'system when all its dependencies are satisfied. ' + 'If the module has no dependency, it is always installed.'), 'state': fields.selection([ - ('uninstallable','Not Installable'), - ('uninstalled','Not Installed'), - ('installed','Installed'), - ('to upgrade','To be upgraded'), - ('to remove','To be removed'), - ('to install','To be installed') + ('uninstallable', 'Not Installable'), + ('uninstalled', 'Not Installed'), + ('installed', 'Installed'), + ('to upgrade', 'To be upgraded'), + ('to remove', 'To be removed'), + ('to install', 'To be installed') ], string='Status', readonly=True, select=True), 'demo': fields.boolean('Demo Data', readonly=True), 'license': fields.selection([ - ('GPL-2', 'GPL Version 2'), - ('GPL-2 or any later version', 'GPL-2 or later version'), - ('GPL-3', 'GPL Version 3'), - ('GPL-3 or any later version', 'GPL-3 or later version'), - ('AGPL-3', 'Affero GPL-3'), - ('Other OSI approved licence', 'Other OSI Approved Licence'), - ('Other proprietary', 'Other Proprietary') + ('GPL-2', 'GPL Version 2'), + ('GPL-2 or any later version', 'GPL-2 or later version'), + ('GPL-3', 'GPL Version 3'), + ('GPL-3 or any later version', 'GPL-3 or later version'), + ('AGPL-3', 'Affero GPL-3'), + ('Other OSI approved licence', 'Other OSI Approved Licence'), + ('Other proprietary', 'Other Proprietary') ], string='License', readonly=True), 'menus_by_module': fields.function(_get_views, string='Menus', type='text', multi="meta", store=True), 'reports_by_module': fields.function(_get_views, string='Reports', type='text', multi="meta", store=True), @@ -283,7 +306,7 @@ class module(osv.osv): return _('The name of the module must be unique !') _sql_constraints = [ - ('name_uniq', 'UNIQUE (name)',_name_uniq_msg ), + ('name_uniq', 'UNIQUE (name)', _name_uniq_msg), ] def unlink(self, cr, uid, ids, context=None): @@ -292,10 +315,9 @@ class module(osv.osv): if isinstance(ids, (int, long)): ids = [ids] mod_names = [] - for mod in self.read(cr, uid, ids, ['state','name'], context): + for mod in self.read(cr, uid, ids, ['state', 'name'], context): if mod['state'] in ('installed', 'to upgrade', 'to remove', 'to install'): - raise orm.except_orm(_('Error'), - _('You try to remove a module that is installed or will be installed')) + raise orm.except_orm(_('Error'), _('You try to remove a module that is installed or will be installed')) mod_names.append(mod['name']) #Removing the entry from ir_model_data #ids_meta = self.pool.get('ir.model.data').search(cr, uid, [('name', '=', 'module_meta_information'), ('module', 'in', mod_names)]) @@ -340,7 +362,7 @@ class module(osv.osv): raise orm.except_orm(_('Error'), msg % (module_name, e.args[0])) def state_update(self, cr, uid, ids, newstate, states_to_update, context=None, level=100): - if level<1: + if level < 1: raise orm.except_orm(_('Error'), _('Recursion error in modules dependencies !')) demo = False for module in self.browse(cr, uid, ids, context=context): @@ -348,9 +370,9 @@ class module(osv.osv): for dep in module.dependencies_id: if dep.state == 'unknown': raise orm.except_orm(_('Error'), _("You try to install module '%s' that depends on module '%s'.\nBut the latter module is not available in your system.") % (module.name, dep.name,)) - ids2 = self.search(cr, uid, [('name','=',dep.name)]) + ids2 = self.search(cr, uid, [('name', '=', dep.name)]) if dep.state != newstate: - mdemo = self.state_update(cr, uid, ids2, newstate, states_to_update, context, level-1,) or mdemo + mdemo = self.state_update(cr, uid, ids2, newstate, states_to_update, context, level - 1) or mdemo else: od = self.browse(cr, uid, ids2)[0] mdemo = od.demo or mdemo @@ -359,7 +381,7 @@ class module(osv.osv): if not module.dependencies_id: mdemo = module.demo if module.state in states_to_update: - self.write(cr, uid, [module.id], {'state': newstate, 'demo':mdemo}) + self.write(cr, uid, [module.id], {'state': newstate, 'demo': mdemo}) demo = demo or mdemo return demo @@ -403,7 +425,7 @@ class module(osv.osv): return self._button_immediate_function(cr, uid, ids, self.button_install, context=context) def button_install_cancel(self, cr, uid, ids, context=None): - self.write(cr, uid, ids, {'state': 'uninstalled', 'demo':False}) + self.write(cr, uid, ids, {'state': 'uninstalled', 'demo': False}) return True def module_uninstall(self, cr, uid, ids, context=None): @@ -421,12 +443,13 @@ class module(osv.osv): return True def downstream_dependencies(self, cr, uid, ids, known_dep_ids=None, - exclude_states=['uninstalled','uninstallable','to remove'], + exclude_states=['uninstalled', 'uninstallable', 'to remove'], context=None): """Return the ids of all modules that directly or indirectly depend on the given module `ids`, and that satisfy the `exclude_states` filter""" - if not ids: return [] + if not ids: + return [] known_dep_ids = set(known_dep_ids or []) cr.execute('''SELECT DISTINCT m.id FROM @@ -437,13 +460,13 @@ class module(osv.osv): d.name IN (SELECT name from ir_module_module where id in %s) AND m.state NOT IN %s AND m.id NOT IN %s ''', - (tuple(ids),tuple(exclude_states), tuple(known_dep_ids or ids))) + (tuple(ids), tuple(exclude_states), tuple(known_dep_ids or ids))) new_dep_ids = set([m[0] for m in cr.fetchall()]) missing_mod_ids = new_dep_ids - known_dep_ids known_dep_ids |= new_dep_ids if missing_mod_ids: known_dep_ids |= set(self.downstream_dependencies(cr, uid, list(missing_mod_ids), - known_dep_ids, exclude_states,context)) + known_dep_ids, exclude_states, context)) return list(known_dep_ids) def _button_immediate_function(self, cr, uid, ids, function, context=None): @@ -460,9 +483,9 @@ class module(osv.osv): menu_obj = self.pool.get('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} + 'type': 'ir.actions.client', + 'tag': 'reload', + 'params': {'menu_id': menu_ids and menu_ids[0] or False} } def button_immediate_uninstall(self, cr, uid, ids, context=None): @@ -496,20 +519,19 @@ class module(osv.osv): self.update_list(cr, uid) i = 0 - while i<len(todo): + while i < len(todo): mod = todo[i] i += 1 - if mod.state not in ('installed','to upgrade'): - raise orm.except_orm(_('Error'), - _("Can not upgrade module '%s'. It is not installed.") % (mod.name,)) + if mod.state not in ('installed', 'to upgrade'): + raise orm.except_orm(_('Error'), _("Can not upgrade module '%s'. It is not installed.") % (mod.name,)) self.check_external_dependencies(mod.name, 'to upgrade') iids = depobj.search(cr, uid, [('name', '=', mod.name)], context=context) for dep in depobj.browse(cr, uid, iids, context=context): - if dep.module_id.state=='installed' and dep.module_id not in todo: + if dep.module_id.state == 'installed' and dep.module_id not in todo: todo.append(dep.module_id) ids = map(lambda x: x.id, todo) - self.write(cr, uid, ids, {'state':'to upgrade'}, context=context) + self.write(cr, uid, ids, {'state': 'to upgrade'}, context=context) to_install = [] for mod in todo: @@ -517,7 +539,7 @@ class module(osv.osv): if dep.state == 'unknown': raise orm.except_orm(_('Error'), _('You try to upgrade a module that depends on the module: %s.\nBut this module is not available in your system.') % (dep.name,)) if dep.state == 'uninstalled': - ids2 = self.search(cr, uid, [('name','=',dep.name)]) + ids2 = self.search(cr, uid, [('name', '=', dep.name)]) to_install.extend(ids2) self.button_install(cr, uid, to_install, context=context) @@ -550,8 +572,9 @@ class module(osv.osv): # update the list of available packages def update_list(self, cr, uid, context=None): - res = [0, 0] # [update, add] + res = [0, 0] # [update, add] + default_version = modules.adapt_version('1.0') known_mods = self.browse(cr, uid, self.search(cr, uid, [])) known_mods_names = dict([(m.name, m) for m in known_mods]) @@ -570,7 +593,7 @@ class module(osv.osv): updated_values[key] = values[key] if terp.get('installable', True) and mod.state == 'uninstallable': updated_values['state'] = 'uninstalled' - if parse_version(terp.get('version', '')) > parse_version(mod.latest_version or ''): + if parse_version(terp.get('version', default_version)) > parse_version(mod.latest_version or default_version): res[0] += 1 if updated_values: self.write(cr, uid, mod.id, updated_values) @@ -587,24 +610,32 @@ class module(osv.osv): self._update_dependencies(cr, uid, mod, terp.get('depends', [])) self._update_category(cr, uid, mod, terp.get('category', 'Uncategorized')) + # Trigger load_addons if new module have been discovered it exists on + # wsgi handlers, so they can react accordingly + if tuple(res) != (0, 0): + for handler in openerp.service.wsgi_server.module_handlers: + if hasattr(handler,'load_addons'): + handler.load_addons() + return res def download(self, cr, uid, ids, download=True, context=None): res = [] + default_version = modules.adapt_version('1.0') for mod in self.browse(cr, uid, ids, context=context): if not mod.url: continue match = re.search('-([a-zA-Z0-9\._-]+)(\.zip)', mod.url, re.I) - version = '0' + version = default_version if match: version = match.group(1) - if parse_version(mod.installed_version or '0') >= parse_version(version): + if parse_version(mod.installed_version) >= parse_version(version): continue res.append(mod.url) if not download: continue zip_content = urllib.urlopen(mod.url).read() - fname = modules.get_module_path(str(mod.name)+'.zip', downloaded=True) + fname = modules.get_module_path(str(mod.name) + '.zip', downloaded=True) try: with open(fname, 'wb') as fp: fp.write(zip_content) @@ -614,17 +645,77 @@ class module(osv.osv): raise orm.except_orm(_('Error'), _('Can not create the module file:\n %s') % (fname,)) terp = self.get_module_info(mod.name) self.write(cr, uid, mod.id, self.get_values_from_terp(terp)) - cr.execute('DELETE FROM ir_module_module_dependency ' \ - 'WHERE module_id = %s', (mod.id,)) - self._update_dependencies(cr, uid, mod, terp.get('depends', - [])) - self._update_category(cr, uid, mod, terp.get('category', - 'Uncategorized')) + cr.execute('DELETE FROM ir_module_module_dependency WHERE module_id = %s', (mod.id,)) + self._update_dependencies(cr, uid, mod, terp.get('depends', [])) + self._update_category(cr, uid, mod, terp.get('category', 'Uncategorized')) # Import module zimp = zipimport.zipimporter(fname) zimp.load_module(mod.name) return res + def install_from_urls(self, cr, uid, urls, context=None): + OPENERP = 'openerp' + tmp = tempfile.mkdtemp() + try: + for module_name, url in urls.items(): + if not url: + continue # nothing to download, local version is already the last one + try: + content = urllib2.urlopen(url).read() + except Exception, e: + _logger.exception('ggr') + raise osv.except_osv('grrr', e) + else: + zipfile.ZipFile(StringIO(content)).extractall(tmp) + assert os.path.isdir(os.path.join(tmp, module_name)) + + for module_name in urls: + if module_name == OPENERP: + continue # special case. handled below + module_path = modules.get_module_path(module_name, downloaded=True, display_warning=False) + bck = backup(module_path, False) + shutil.move(os.path.join(tmp, module_name), module_path) + if bck: + shutil.rmtree(bck) + + if urls.get(OPENERP, None): + # special case. it containt the server and the base module. + # extract path is not the same + + base_path = os.path.dirname(modules.get_module_path('base')) + + # copy all modules in the SERVER/openerp/addons directory to the new "openerp" module (except base itself) + for d in os.listdir(base_path): + if d != 'base' and os.path.isdir(os.path.join(base_path, d)): + destdir = os.path.join(tmp, OPENERP, 'addons', d) # XXX 'openerp' subdirectory ? + shutil.copytree(os.path.join(base_path, d), destdir) + + # then replace the server by the new "base" module + server_dir = openerp.tools.config['root_path'] # XXX or dirname() + bck = backup(server_dir) + shutil.move(os.path.join(tmp, OPENERP), server_dir) + #if bck: + # shutil.rmtree(bck) + + self.update_list(cr, uid, context=context) + + ids = self.search(cr, uid, [('name', 'in', urls.keys())], context=context) + if self.search_count(cr, uid, [('id', 'in', ids), ('state', '=', 'installed')], context=context): + # if any to update + cr.commit() + openerp.service.restart_server() + return { + 'type': 'ir.actions.client', + 'tag': 'home', + 'params': {'wait': True}, + } + return self.button_immediate_install(cr, uid, ids, context=context) + finally: + shutil.rmtree(tmp) + + def install_by_names(self, cr, uid, names, context=None): + raise NotImplementedError('# TODO') + def _update_dependencies(self, cr, uid, mod_browse, depends=None): if depends is None: depends = [] @@ -679,20 +770,20 @@ class module_dependency(osv.osv): _columns = { # The dependency name - 'name': fields.char('Name', size=128, select=True), + 'name': fields.char('Name', size=128, select=True), # The module that depends on it 'module_id': fields.many2one('ir.module.module', 'Module', select=True, ondelete='cascade'), 'state': fields.function(_state, type='selection', selection=[ - ('uninstallable','Uninstallable'), - ('uninstalled','Not Installed'), - ('installed','Installed'), - ('to upgrade','To be upgraded'), - ('to remove','To be removed'), - ('to install','To be installed'), + ('uninstallable', 'Uninstallable'), + ('uninstalled', 'Not Installed'), + ('installed', 'Installed'), + ('to upgrade', 'To be upgraded'), + ('to remove', 'To be removed'), + ('to install', 'To be installed'), ('unknown', 'Unknown'), - ], string='Status', readonly=True, select=True), + ], string='Status', readonly=True, select=True), } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/module/module_view.xml b/openerp/addons/base/module/module_view.xml index 5f33a437f08..3a43a2591ba 100644 --- a/openerp/addons/base/module/module_view.xml +++ b/openerp/addons/base/module/module_view.xml @@ -1,9 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <openerp> <data> - <!-- Modules Categories --> - <record id="view_module_category_form" model="ir.ui.view"> <field name="name">ir.module.category.form</field> <field name="model">ir.module.category</field> @@ -32,7 +30,6 @@ </record> <!-- Click on a category --> - <record id="view_module_filter" model="ir.ui.view"> <field name="name">ir.module.module.list.select</field> <field name="model">ir.module.module</field> @@ -43,7 +40,7 @@ <filter name="app" icon="terp-check" string="Apps" domain="[('application', '=', 1)]"/> <filter name="extra" icon="terp-check" string="Extra" domain="[('application', '=', 0)]"/> <separator/> - <filter icon="terp-check" string="Installed" domain="[('state', 'in', ['installed', 'to upgrade', 'to remove'])]"/> + <filter name="installed" icon="terp-check" string="Installed" domain="[('state', 'in', ['installed', 'to upgrade', 'to remove'])]"/> <filter icon="terp-dialog-close" string="Not Installed" domain="[('state', 'in', ['uninstalled', 'uninstallable', 'to install'])]"/> <field name="category_id"/> <group expand="0" string="Group By..."> @@ -53,37 +50,6 @@ </search> </field> </record> - - <record model="ir.ui.view" id="module_view_kanban"> - <field name="name">Modules Kanban</field> - <field name="model">ir.module.module</field> - <field name="arch" type="xml"> - <kanban create="false"> - <field name="icon"/> - <field name="name"/> - <field name="state"/> - <field name="summary"/> - <templates> - <t t-name="kanban-box"> - <div class="oe_module_vignette"> - <t t-set="installed" t-value="record.state.raw_value == 'installed'"/> - <img t-attf-src="#{record.icon.value}" class="oe_module_icon"/> - <div class="oe_module_desc"> - <h4><a type="open"><field name="shortdesc"/></a></h4> - <p class="oe_module_name"> - <t t-if="record.summary.raw_value"><field name="summary"/><br/></t> - <i><field name="name" groups="base.group_no_one"/></i> - </p> - <button type="object" name="button_immediate_install" states="uninstalled">Install</button> - <button t-if="installed" disabled="disabled">Installed</button> - </div> - </div> - </t> - </templates> - </kanban> - </field> - </record> - <record id="action_module_open_categ" model="ir.actions.act_window"> <field name="name">Modules</field> <field name="res_model">ir.module.module</field> @@ -100,7 +66,6 @@ <!-- Modules --> - <record id="module_form" model="ir.ui.view"> <field name="name">ir.module.module.form</field> <field name="model">ir.module.module</field> @@ -176,20 +141,74 @@ </tree> </field> </record> + <record model="ir.ui.view" id="module_view_kanban"> + <field name="name">Modules Kanban</field> + <field name="model">ir.module.module</field> + <field name="arch" type="xml"> + <kanban create="false"> + <field name="icon"/> + <field name="name"/> + <field name="state"/> + <field name="summary"/> + <templates> + <t t-name="kanban-box"> + <div class="oe_module_vignette"> + <t t-set="installed" t-value="record.state.raw_value == 'installed'"/> + <img t-attf-src="#{record.icon.value}" class="oe_module_icon"/> + <div class="oe_module_desc"> + <h4><a type="open"><field name="shortdesc"/></a></h4> + <p class="oe_module_name"> + <t t-if="record.summary.raw_value"><field name="summary"/><br/></t> + <i><field name="name" groups="base.group_no_one"/></i> + </p> + <button type="object" name="button_immediate_install" states="uninstalled">Install</button> + <button t-if="installed" disabled="disabled">Installed</button> + </div> + </div> + </t> + </templates> + </kanban> + </field> + </record> <record id="open_module_tree" model="ir.actions.act_window"> - <field name="name">Install a Module</field> + <!-- uncomment on released + <field name="name">Installed Modules</field> + --> + <field name="name">Modules</field> <field name="res_model">ir.module.module</field> <field name="view_type">form</field> <field name="view_mode">kanban,tree,form</field> - <field name="context">{'search_default_app':1}</field> + <!-- uncomment on released + <field name="context">{'search_default_installed':1}</field> + --> <field name="search_view_id" ref="view_module_filter"/> <field name="help" type="html"> <p><b>No module found!</b></p> <p>You should try others search criteria.</p> </field> </record> - <menuitem id="menu_module_tree" parent="base.menu_management" name="Modules" - sequence="1" action="open_module_tree"/> + <menuitem id="menu_module_tree" parent="menu_management" name="Installed Modules" sequence="10" action="open_module_tree"/> + + + <!-- Apps modules --> + <record model="ir.actions.client" id="modules_act_cl"> + <field name="name">Apps</field> + <field name="tag">apps</field> + </record> + <!-- uncomment on released + <menuitem id="module_mi" parent="base.menu_management" sequence="3" action="modules_act_cl"/> + --> + <menuitem id="module_mi" parent="base.menu_management" sequence="20" action="modules_act_cl"/> + + <record model="ir.actions.client" id="modules_updates_act_cl"> + <field name="name">Updates</field> + <field name="tag">apps.updates</field> + <field name="params">{}</field> + </record> + <!-- uncomment on released + <menuitem id="menu_module_updates" parent="base.menu_management" sequence="7" action="modules_updates_act_cl"/> + --> + <menuitem id="menu_module_updates" parent="base.menu_management" sequence="30" action="modules_updates_act_cl"/> </data> </openerp> diff --git a/openerp/addons/base/module/wizard/base_export_language_view.xml b/openerp/addons/base/module/wizard/base_export_language_view.xml index cbf7104f957..f184186a500 100644 --- a/openerp/addons/base/module/wizard/base_export_language_view.xml +++ b/openerp/addons/base/module/wizard/base_export_language_view.xml @@ -11,7 +11,7 @@ <group states="choose" string="Export Settings"> <field name="lang"/> <field name="format"/> - <field name="modules"/> + <field name="modules" widget="many2many_tags"/> </group> <div states="get"> <h2>Export Complete</h2> diff --git a/openerp/addons/base/module/wizard/base_module_import_view.xml b/openerp/addons/base/module/wizard/base_module_import_view.xml index 192bf6c2a92..d9d6bb6ee78 100644 --- a/openerp/addons/base/module/wizard/base_module_import_view.xml +++ b/openerp/addons/base/module/wizard/base_module_import_view.xml @@ -43,7 +43,7 @@ id="menu_view_base_module_import" parent="menu_management" groups="base.group_no_one" - sequence="1"/> + sequence="6"/> --> </data> diff --git a/openerp/addons/base/module/wizard/base_module_update_view.xml b/openerp/addons/base/module/wizard/base_module_update_view.xml index 75d2b1316a6..cb9b9090294 100644 --- a/openerp/addons/base/module/wizard/base_module_update_view.xml +++ b/openerp/addons/base/module/wizard/base_module_update_view.xml @@ -18,17 +18,17 @@ </group> <footer> <div states="init"> - <button name="update_module" string="Update" type="object" class="oe_highlight"/> or + <button name="update_module" string="Update" type="object" class="oe_highlight"/> or <button special="cancel" string="Cancel" class="oe_link"/> </div> <div states="done"> - <button name="action_module_open" string="Open Modules" type="object" class="oe_highlight"/> or + <button name="action_module_open" string="Open Modules" type="object" class="oe_highlight"/> or <button special="cancel" string="Close" class="oe_link"/> </div> </footer> </form> </field> - </record> + </record> <record id="action_view_base_module_update" model="ir.actions.act_window"> <field name="name">Module Update</field> @@ -45,7 +45,7 @@ id="menu_view_base_module_update" groups="base.group_no_one" parent="menu_management" - sequence="2" + sequence="40" icon="STOCK_CONVERT"/> </data> diff --git a/openerp/addons/base/module/wizard/base_module_upgrade_view.xml b/openerp/addons/base/module/wizard/base_module_upgrade_view.xml index afd3a2e17b1..1a1225befcb 100644 --- a/openerp/addons/base/module/wizard/base_module_upgrade_view.xml +++ b/openerp/addons/base/module/wizard/base_module_upgrade_view.xml @@ -35,7 +35,7 @@ groups="base.group_no_one" id="menu_view_base_module_upgrade" parent="menu_management" - sequence="3"/> + sequence="50"/> <record id="view_base_module_upgrade_install" model="ir.ui.view"> <field name="name">Module Upgrade Install</field> |
