summaryrefslogtreecommitdiff
path: root/bin/addons/base/module
diff options
context:
space:
mode:
authorpinky <>2006-12-07 13:41:40 +0000
committerpinky <>2006-12-07 13:41:40 +0000
commit004a0b996ff8f269451e07346f71a129a1f3fbaf (patch)
tree48f43c1fc2ca4c1f4d5648e7e73553d3f4ccae06 /bin/addons/base/module
New trunk
bzr revid: pinky-3f10ee12cea3c4c75cef44ab04ad33ef47432907
Diffstat (limited to 'bin/addons/base/module')
-rw-r--r--bin/addons/base/module/__init__.py31
-rw-r--r--bin/addons/base/module/module.py274
-rw-r--r--bin/addons/base/module/module.py.old228
-rw-r--r--bin/addons/base/module/module_data.xml12
-rw-r--r--bin/addons/base/module/module_report.xml13
-rw-r--r--bin/addons/base/module/module_view.xml198
-rw-r--r--bin/addons/base/module/module_wizard.xml76
-rw-r--r--bin/addons/base/module/report/__init__.py29
-rw-r--r--bin/addons/base/module/report/ir_module_reference.rml173
-rw-r--r--bin/addons/base/module/report/ir_module_reference.sxwbin0 -> 12192 bytes
-rw-r--r--bin/addons/base/module/report/ir_module_reference_print.py60
-rw-r--r--bin/addons/base/module/wizard/__init__.py35
-rw-r--r--bin/addons/base/module/wizard/add_new.py100
-rw-r--r--bin/addons/base/module/wizard/wizard_export_lang.py91
-rw-r--r--bin/addons/base/module/wizard/wizard_import_lang.py75
-rw-r--r--bin/addons/base/module/wizard/wizard_install_module.py67
-rw-r--r--bin/addons/base/module/wizard/wizard_module_info_get.py46
-rw-r--r--bin/addons/base/module/wizard/wizard_module_lang_install.py83
-rw-r--r--bin/addons/base/module/wizard/wizard_module_upgrade.py81
-rw-r--r--bin/addons/base/module/wizard/wizard_update_module.py61
20 files changed, 1733 insertions, 0 deletions
diff --git a/bin/addons/base/module/__init__.py b/bin/addons/base/module/__init__.py
new file mode 100644
index 00000000000..bc74f4ed9a6
--- /dev/null
+++ b/bin/addons/base/module/__init__.py
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved.
+# Fabien Pinckaers <fp@tiny.Be>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import module
+import wizard
+import report
diff --git a/bin/addons/base/module/module.py b/bin/addons/base/module/module.py
new file mode 100644
index 00000000000..bc9aefc0a32
--- /dev/null
+++ b/bin/addons/base/module/module.py
@@ -0,0 +1,274 @@
+##############################################################################
+#
+# Copyright (c) 2005 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import tarfile
+import re
+import urllib
+import os
+import tools
+from osv import fields, osv
+
+class module_repository(osv.osv):
+ _name = "ir.module.repository"
+ _description = "Module Repository"
+ _columns = {
+ 'name': fields.char('Name', size=128),
+ 'url': fields.char('Url', size=256, required=True),
+ }
+module_repository()
+
+def get_module_info(name):
+ try:
+ f = file(os.path.join(tools.config['addons_path'], name, '__terp__.py'), 'r')
+ data = f.read()
+ info = eval(data)
+ f.close()
+ except:
+ return {}
+ return info
+
+class module_category(osv.osv):
+ _name = "ir.module.category"
+ _description = "Module Category"
+
+ 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 ('+','.join(map(str,ids))+') or category_id in (select id from ir_module_category where parent_id in ('+','.join(map(str,ids))+')) group by category_id')
+ result = dict(cr.fetchall())
+ for id in ids:
+ cr.execute('select id from ir_module_category where parent_id=%d', (id,))
+ childs = [c for c, in cr.fetchall()]
+ result[id] = reduce(lambda x,y:x+y, [result.get(c, 0) for c in childs], result.get(id, 0))
+ return result
+
+ _columns = {
+ 'name': fields.char("Name", size=128, required=True),
+ 'parent_id': fields.many2one('ir.module.category', 'Parent Category', select=True),
+ 'child_ids': fields.one2many('ir.module.category', 'parent_id', 'Parent Category'),
+ 'module_nr': fields.function(_module_nbr, method=True, string='# of Modules', type='integer')
+ }
+ _order = 'name'
+module_category()
+
+class module(osv.osv):
+ _name = "ir.module.module"
+ _description = "Module"
+
+ def _get_installed_version(self, cr, uid, ids, field_name=None, arg=None, context={}):
+ res = {}
+ for m in self.browse(cr, uid, ids):
+ res[m.id] = get_module_info(m.name).get('version', False)
+ return res
+
+ _columns = {
+ 'name': fields.char("Name", size=128, readonly=True, required=True),
+ 'category_id': fields.many2one('ir.module.category', 'Category', readonly=True),
+ 'shortdesc': fields.char('Short description', size=256, readonly=True),
+ 'description': fields.text("Description", readonly=True),
+ 'author': fields.char("Author", size=128, readonly=True),
+ 'website': fields.char("Website", size=256, readonly=True),
+ 'installed_version': fields.function(_get_installed_version, method=True, string='Installed version', type='char'),
+ 'latest_version': fields.char('Latest version', size=64, readonly=True),
+ 'url': fields.char('URL', size=128, readonly=True),
+ 'dependencies_id': fields.one2many('ir.module.module.dependency', 'module_id', 'Dependencies'),
+ 'state': fields.selection([
+ ('uninstallable','Uninstallable'),
+ ('uninstalled','Not Installed'),
+ ('installed','Installed'),
+ ('to upgrade','To be upgraded'),
+ ('to remove','To be removed'),
+ ('to install','To be installed')
+ ], string='State', readonly=True),
+ 'demo': fields.boolean('Demo data'),
+ }
+
+ _defaults = {
+ 'state': lambda *a: 'uninstalled',
+ 'demo': lambda *a: False,
+ }
+ _order = 'name'
+
+ def state_change(self, cr, uid, ids, newstate, context={}, level=50):
+ if level<1:
+ raise 'Recursion error in modules dependencies !'
+ ids_dest = []
+ for module in self.browse(cr, uid, ids):
+ for dep in module.dependencies_id:
+ ids2 = self.search(cr, uid, [('name','=',dep.name)])
+ for id in ids2:
+ if (id not in ids_dest):
+ ids_dest.append(id)
+ if module.state=='uninstalled':
+ self.write(cr, uid, [module.id], {'state': newstate})
+ if ids_dest:
+ self.state_change(cr, uid, ids_dest, newstate, context, level-1)
+
+ for module in self.browse(cr, uid, ids):
+ if module.state!='installed':
+ demo=True
+ for dep in module.dependencies_id:
+ ids2 = self.search(cr, uid, [('name', '=', dep.name)])
+ for module2 in self.browse(cr, uid, ids2):
+ demo = demo and module2.demo
+ self.write(cr, uid, [module.id], {'demo':demo})
+ return True
+
+ def button_install(self, cr, uid, ids, context={}):
+ return self.state_change(cr, uid, ids, 'to install', context)
+
+ def button_install_cancel(self, cr, uid, ids, context={}):
+ self.write(cr, uid, ids, {'state': 'uninstalled'})
+ return True
+
+ def button_uninstall(self, cr, uid, ids, context={}):
+ self.write(cr, uid, ids, {'state': 'to remove'})
+ return True
+
+ def button_remove_cancel(self, cr, uid, ids, context={}):
+ self.write(cr, uid, ids, {'state': 'installed'})
+ return True
+ def button_upgrade(self, cr, uid, ids, context={}):
+ self.write(cr, uid, ids, {'state': 'to upgrade'})
+ return True
+ def button_upgrade_cancel(self, cr, uid, ids, context={}):
+ self.write(cr, uid, ids, {'state': 'installed'})
+ return True
+ def button_update_translations(self, cr, uid, ids, context={}):
+ cr.execute('select code from res_lang where translatable=TRUE')
+ langs = [l[0] for l in cr.fetchall()]
+ modules = self.read(cr, uid, ids, ['name'])
+ for module in modules:
+ files = get_module_info(module['name']).get('translations', {})
+ for lang in langs:
+ if files.has_key(lang):
+ filepath = files[lang]
+ # if filepath does not contain :// we prepend the path of the module
+ if filepath.find('://') == -1:
+ filepath = os.path.join(tools.config['addons_path'], module['name'], filepath)
+ tools.trans_load(filepath, lang)
+ return True
+
+ # update the list of available packages
+ def update_list(self, cr, uid, context={}):
+ robj = self.pool.get('ir.module.repository')
+ adp = tools.config['addons_path']
+
+ # iterate through installed modules and mark them as being so
+ for name in os.listdir(adp):
+ if os.path.isdir(os.path.join(adp, name)):
+ version = get_module_info(name).get('version', False)
+ if version:
+ ids = self.search(cr, uid, [('name','=',name)])
+ if not ids:
+ id = self.create(cr, uid, {
+ 'name': name,
+ 'latest_version': version,
+ 'state': 'installed',
+ })
+ else:
+ self.write(cr, uid, ids, {'state': 'installed'})
+
+ # make the list of all installable modules
+ for repository in robj.browse(cr, uid, robj.search(cr, uid, [])):
+ index_page = urllib.urlopen(repository.url).read()
+ modules = re.findall('.*<a href="([a-zA-Z0-9.\-]+)_([a-zA-Z0-9.\-]+)\.tar\.gz">.*', index_page)
+ for name, version in modules:
+ # TODO: change this using urllib
+ url = os.path.join(repository.url, name + '_' + version + ".tar.gz")
+ ids = self.search(cr, uid, [('name','=',name)])
+ if not ids:
+ self.create(cr, uid, {
+ 'name': name,
+ 'latest_version': version,
+ 'url': url,
+ 'state': 'uninstalled',
+ })
+ else:
+ for r in self.read(cr, uid, ids, ['latest_version']):
+ if r['latest_version'] < version:
+ self.write(cr, uid, [r['id']], {'latest_version': version, 'url':url})
+ return True
+
+ #
+ # TODO: update dependencies
+ #
+ def info_get(self, cr, uid, ids, context={}):
+ categ_obj = self.pool.get('ir.module.category')
+
+ for module in self.browse(cr, uid, ids, context):
+ url = module.url
+ adp = tools.config['addons_path']
+ info = False
+ if url:
+ tar = tarfile.open(mode="r|gz", fileobj=urllib.urlopen(url))
+ for tarinfo in tar:
+ if tarinfo.name.endswith('__terp__.py'):
+ info = eval(tar.extractfile(tarinfo).read())
+ elif os.path.isdir(os.path.join(adp, module.name)):
+ info = get_module_info(module.name)
+ if info:
+ categ = info.get('category', 'Unclassified')
+ parent = False
+ for c in categ.split('/'):
+ ids = categ_obj.search(cr, uid, [('name','=',c), ('parent_id','=',parent)])
+ if not ids:
+ parent = categ_obj.create(cr, uid, {'name':c, 'parent_id':parent})
+ else:
+ parent = ids[0]
+ self.write(cr, uid, [module.id], {
+ 'author': info.get('author',False),
+ 'website': info.get('website',False),
+ 'shortdesc': info.get('name',False),
+ 'description': info.get('description',False),
+ 'category_id': parent
+ })
+ return True
+module()
+
+class module_dependency(osv.osv):
+ _name = "ir.module.module.dependency"
+ _description = "Module dependency"
+ _columns = {
+ 'name': fields.char('Name', size=128),
+ 'module_id': fields.many2one('ir.module.module', 'Module', select=True),
+ #'module_dest_id': fields.many2one('ir.module.module', 'Module'),
+ 'version_pattern': fields.char('Required Version', size=128),
+ }
+ # returns the ids of module version records which match all dependencies
+ # [version_id, ...]
+ def resolve(self, cr, uid, ids):
+ vobj = self.pool.get('ir.module.module.version')
+ objs = self.browse(cr, uid, ids)
+ res = {}
+ for o in objs:
+ pattern = o.version_pattern and eval(o.version_pattern) or []
+ print "pattern", pattern
+ res[o.id] = vobj.search(cr, uid, [('module','=',o.module.id)]+pattern)
+ #TODO: add smart dependencies resolver here
+ # it should compute the best version for each module
+ return [r[0] for r in res.itervalues()]
+module_dependency()
+
diff --git a/bin/addons/base/module/module.py.old b/bin/addons/base/module/module.py.old
new file mode 100644
index 00000000000..7f1512f7c03
--- /dev/null
+++ b/bin/addons/base/module/module.py.old
@@ -0,0 +1,228 @@
+##############################################################################
+#
+# Copyright (c) 2005 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import tarfile
+import re
+import urllib2
+import os
+import shutil
+from sets import Set
+
+from osv import fields, osv
+import tools
+
+class module(osv.osv):
+ _name = "module.module"
+ _description = "Module"
+
+ def _costs_get(self, cr, uid, ids, prop=None, unknown_none=None, unknown_dict={}):
+ dossiers = self.browse(cr, uid, ids)
+ res = {}
+ for d in dossiers:
+ costs = [l.amount_costs for l in d.lot_id]
+ cost_amount = reduce(lambda x, y: x+y, costs, 0.0)
+ res[d.id] = cost_amount
+ return res
+
+ _columns = {
+ 'name': fields.char("Name", size=128, readonly=True),
+ 'shortdesc': fields.char('Short description', size=256, readonly=True),
+ 'description': fields.text("Description", readonly=True),
+ 'author': fields.char("Author", size=128, readonly=True),
+ 'website': fields.char("Website", size=256, readonly=True),
+# 'running_version': fields.function(_get_installed_version, method=True, string='Installed version'),
+# 'installed_version': fields.function(_get_installed_version, method=True, string='Installed version'),
+ 'latest_version': fields.many2one('module.module.version', 'Latest version'),
+ 'versions': fields.one2many('module.module.version', 'module', 'Versions', readonly=True),
+ 'state': fields.selection([('uninstalled', 'Uninstalled'), ('preinstall','To install'),('installed','Installed'),('running','Running')], 'State'),
+# 'active': fields.boolean('Active'),
+ }
+
+ # update the list of available packages
+ def update(self, cr, uid, ids, *args):
+ vobj = self.pool.get('module.module.version')
+
+ # update installed_version
+
+ # get the index page containing available packages from the server
+ index_page = urllib2.urlopen('http://www.tinyerp.org/download/modules_test').read()
+# print index_page
+ # parses it
+ modules = re.findall('.*<a href="([a-zA-Z0-9.\-]+)_([a-zA-Z0-9.\-]+)\.tar\.gz">.*', index_page)
+ # create module.module records and module.module.version as needed
+ for name, version in modules:
+ print "name", name, "version", version
+ # open module package on the remote server and extract its __terp__.py
+ url = 'http://www.tinyerp.org/download/modules_test/' + name + '_' + version + ".tar.gz"
+ tar = tarfile.open(mode="r|gz", fileobj=urllib2.urlopen(url))
+ info = {}
+ # we need to go through the whole tar file, because we use a stream and we
+ # are not allowed to search backward in the stream, so we can't extract one
+ # particular file directly
+ for tarinfo in tar:
+ if tarinfo.name.endswith('__terp__.py'):
+ info = eval(tar.extractfile(tarinfo).read())
+ break
+ tar.close()
+ print info
+ ids = self.search(cr, uid, [('name','=',name)])
+ print ids
+ if not ids:
+ id = self.create(cr, uid, {
+ 'name': name,
+ 'shortdesc': info.get('name', False),
+ 'description': info.get('description', False),
+ 'author': info.get('author', False),
+ 'website': info.get('website', False),
+ 'state': 'uninstalled',
+ })
+ print "module_id", id
+ else:
+ assert len(ids)==1, "There shouldn't be two modules with the same name"
+ id = ids[0]
+
+ version_ids = vobj.search(cr, uid, [('module','=',id),('name','=',version)])
+ print version_ids
+ if not version_ids:
+ version_id = vobj.create(cr, uid, {
+ 'name': version,
+ 'module': id,
+ 'state': 'uninstalled',
+ })
+ print "version_id", version_id
+ # update latest_version
+ #TODO: compute latest version
+ self.write(cr, uid, [id], {'latest_version': version_id})
+# else:
+# assert len(version_ids)==1, "There shouldn't be two versions with the same name"
+# version_id = version_ids[0]
+
+ return True
+
+ def install(self, cr, uid, ids, *args):
+ objs = self.browse(cr, uid, ids)
+ vobj = self.pool.get('module.module.version')
+
+ # get the id of latest version for each module
+ version_ids = Set([o.latest_version.id for o in objs])
+# for o in objs:
+# version_ids.add()
+# version_ids = reduce(lambda dic, o: dic.update({o.latest_version.id:True}), objs, {})
+ print "version_ids", version_ids
+
+ # add the list of dependencies
+ dependencies_ids = vobj.get_dependencies(cr, uid, list(version_ids))
+ print "depends", dependencies_ids
+ version_ids.update(dependencies_ids)
+# version_ids = reduce(lambda dic, dep: dic.update({dep:True}), dependencies_ids, version_ids)
+ print "version_ids2", version_ids
+
+ # remove existing version of modules
+ self.remove(cr, uid, ids)
+
+ # install all selected modules and their dependencies
+ vobj.install(cr, uid, list(version_ids))
+ return True
+
+
+ # remove existing version of modules if they exist
+ def remove(self, cr, uid, ids, *args):
+ objs = self.browse(cr, uid, ids)
+ adp = tools.config['addons_path']
+ addons = os.listdir(adp)
+ for o in objs:
+ if o.name in addons:
+ shutil.rmtree(os.path.join(adp, o.name))
+ return True
+module()
+
+class module_version(osv.osv):
+ _name = "module.module.version"
+ _description = "Module Version"
+ _columns = {
+ 'name': fields.char('Name', size=64),
+ 'module': fields.many2one('module.module', "Module"),
+ 'dependencies': fields.one2many('module.module.dependency', 'version', 'Dependencies'),
+ 'state': fields.selection([('uninstalled','Uninstalled'), ('preinstall','To install'), ('installed','Installed'), ('running','Running')], 'State'),
+ }
+
+ def install(self, cr, uid, ids, *args):
+ print "install versions", ids
+ objs = self.browse(cr, uid, ids)
+
+ for o in objs:
+ # download and unpack to destination folder
+ url = 'http://www.tinyerp.org/download/modules_test/' + o.module.name + '_' + o.name + ".tar.gz"
+ tar = tarfile.open(mode="r|gz", fileobj=urllib2.urlopen(url))
+ for tarinfo in tar:
+ tar.extract(tarinfo, tools.config['addons_path'])
+ return True
+
+ def get_dependencies(self, cr, uid, ids, *args):
+ dobj = self.pool.get('module.module.dependency')
+ print "get_depends", ids
+ # for each dependency, get dependencies
+ objs = self.browse(cr, uid, ids)
+ depends = []
+ for o in objs:
+ print "name", o.name
+ o_depends = dobj.resolve(cr, uid, [d.id for d in o.dependencies])
+ print "depends", o_depends
+ depends.extend(o_depends)
+
+# depends.extend([d.id for d in o.dependencies])
+ print "total depends", depends
+ # merge the list
+ # return the list of ids
+ return depends
+module_version()
+
+# a module dependency record represents one dependency of a particular version of a module
+# it can depend on a range of version of one module
+class module_dependency(osv.osv):
+ _name = "module.module.dependency"
+ _description = "Module dependency"
+ _columns = {
+ 'dependency_for': fields.many2one('module.module.version', 'Version'),
+ 'module': fields.many2one('module.module', 'Module'),
+ 'version_pattern': fields.char('Version pattern', size=128),
+ }
+
+ # returns the ids of module version records which match all dependencies
+ # [version_id, ...]
+ def resolve(self, cr, uid, ids):
+ vobj = self.pool.get('module.module.version')
+ objs = self.browse(cr, uid, ids)
+ res = {}
+ for o in objs:
+ pattern = o.version_pattern and eval(o.version_pattern) or []
+ print "pattern", pattern
+ res[o.id] = vobj.search(cr, uid, [('module','=',o.module.id)]+pattern)
+ #TODO: add smart dependencies resolver here
+ # it should compute the best version for each module
+ return [r[0] for r in res.itervalues()]
+module_dependency()
diff --git a/bin/addons/base/module/module_data.xml b/bin/addons/base/module/module_data.xml
new file mode 100644
index 00000000000..930ebeefc8d
--- /dev/null
+++ b/bin/addons/base/module/module_data.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<terp>
+ <data>
+ <!--
+ <record model="ir.module.repository" id="module_repository_tiny">
+ <field name="name">Tiny ERP Base Repository</field>
+ <field name="url">http://tinyerp.org/download/modules/</field>
+ </record>
+ -->
+ </data>
+</terp>
+
diff --git a/bin/addons/base/module/module_report.xml b/bin/addons/base/module/module_report.xml
new file mode 100644
index 00000000000..f76dc02d21a
--- /dev/null
+++ b/bin/addons/base/module/module_report.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<terp>
+ <data>
+
+ <report id="ir_module_reference_print"
+ string="Technical guide"
+ model="ir.module.module"
+ name="ir.module.reference"
+ rml="base/module/report/ir_module_reference.rml"
+ auto="False" />
+
+ </data>
+</terp>
diff --git a/bin/addons/base/module/module_view.xml b/bin/addons/base/module/module_view.xml
new file mode 100644
index 00000000000..29f1d867d9c
--- /dev/null
+++ b/bin/addons/base/module/module_view.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" ?>
+<terp>
+ <data>
+
+ #
+ # Modules Categories
+ #
+
+ <record model="ir.ui.view" id="view_module_category_form">
+ <field name="name">ir.module.category.form</field>
+ <field name="model">ir.module.category</field>
+ <field name="type">form</field>
+ <field name="field_parent">child_ids</field>
+ <field name="arch" type="xml">
+ <form string="Module Category">
+ <field name="name" colspan="3"/>
+ <field name="parent_id" colspan="3"/>
+ </form>
+ </field>
+ </record>
+
+ <record model="ir.ui.view" id="view_module_category_tree">
+ <field name="name">ir.module.category.tree</field>
+ <field name="model">ir.module.category</field>
+ <field name="type">tree</field>
+ <field name="field_parent">child_ids</field>
+ <field name="arch" type="xml">
+ <tree string="Module Category">
+ <field name="name"/>
+ <field name="module_nr"/>
+ </tree>
+ </field>
+ </record>
+ <record model="ir.actions.act_window" id="action_module_category_tree">
+ <field name="name">ir.module.category</field>
+ <field name="res_model">ir.module.category</field>
+ <field name="view_type">tree</field>
+ <field name="domain">[('parent_id','=',False)]</field>
+ </record>
+ <menuitem
+ name="Administration/Modules Management/Categories of Modules"
+ action="action_module_category_tree"
+ />
+
+ #
+ # Click on a category
+ #
+
+ <record model="ir.actions.act_window" id="action_module_open_categ">
+ <field name="name">ir.module.module</field>
+ <field name="res_model">ir.module.module</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="domain">[('category_id','=',active_id)]</field>
+ </record>
+ <record model="ir.values" id="ir_action_module_category">
+ <field name="key2" eval="'tree_but_open'"/>
+ <field name="model" eval="'ir.module.category'"/>
+ <field name="name">Categorized Modules</field>
+ <field name="value" eval="'ir.actions.act_window,%d'%action_module_open_categ"/>
+ <field name="object" eval="True"/>
+ </record>
+
+
+ <!-- Modules -->
+
+ <record model="ir.ui.view" id="module_form">
+ <field name="name">ir.module.module.form</field>
+ <field name="model">ir.module.module</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Module">
+ <notebook>
+ <page string="Module">
+ <field name="name" select="1"/>
+ <field name="shortdesc" colspan="3"/>
+ <field name="description" colspan="3"/>
+ <field name="installed_version"/>
+ <field name="latest_version"/>
+ <field name="author"/>
+ <field name="website"/>
+ <field name="url"/>
+ <field name="demo" readonly="1"/>
+ <field name="state" readonly="1"/>
+ <group col="7" colspan="2">
+ <button string="Update Infos" name="info_get" type="object" states="uninstalled,installed,to upgrade,to remove"/>
+ <button string="Cancel Install" name="button_install_cancel" type="object" states="to install"/>
+ <button string="Install" name="button_install" type="object" states="uninstalled"/>
+ <!--
+ <button string="Cancel Upgrade" name="button_upgrade_cancel" type="object" states="to upgrade"/>
+ <button string="Cancel Remove" name="button_remove_cancel" type="object" states="to remove"/>
+ <button string="Uninstall" name="button_uninstall" type="object" states="installed"/>
+ -->
+ <button string="Upgrade" name="button_upgrade" type="object" states="installed"/>
+ <!--
+ <button string="Update translations" name="button_update_translations" type="object" states="installed"/>
+ -->
+ </group>
+ </page>
+ <page string="Dependencies">
+ <field name="dependencies_id" colspan="4" nolabel="1">
+ <tree string="Dependencies">
+ <field name="name"/>
+ <field name="version_pattern"/>
+ </tree>
+ </field>
+ </page>
+ </notebook>
+ </form>
+ </field>
+ </record>
+ <record model="ir.ui.view" id="module_tree">
+ <field name="name">ir.module.module.tree</field>
+ <field name="model">ir.module.module</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree string="Module list" colors="blue:state=='to upgrade' or state=='to install';grey:state=='uninstalled' or state=='uninstallable'">
+ <field name="name"/>
+ <field name="shortdesc"/>
+ <field name="author"/>
+ <field name="installed_version"/>
+ <field name="latest_version"/>
+ <field name="state"/>
+ </tree>
+ </field>
+ </record>
+ <record model="ir.actions.act_window" id="open_module_tree">
+ <field name="name">ir.module.module</field>
+ <field name="res_model">ir.module.module</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="domain"></field>
+ </record>
+ <menuitem name="Administration/Modules Management/Modules" action="open_module_tree"/>
+
+ <record model="ir.actions.act_window" id="open_module_tree_install">
+ <field name="name">ir.module.module</field>
+ <field name="res_model">ir.module.module</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="domain">[('state','=','installed')]</field>
+ </record>
+ <menuitem name="Administration/Modules Management/Modules/Installed Modules" action="open_module_tree_install"/>
+ <record model="ir.actions.act_window" id="open_module_tree_uninstall">
+ <field name="name">ir.module.module</field>
+ <field name="res_model">ir.module.module</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="domain">[('state','=','uninstalled')]</field>
+ </record>
+ <menuitem name="Administration/Modules Management/Modules/Uninstalled Modules" action="open_module_tree_uninstall"/>
+ <record model="ir.actions.act_window" id="open_module_tree_upgrade">
+ <field name="name">ir.module.module</field>
+ <field name="res_model">ir.module.module</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="domain">[('state','&lt;&gt;','uninstalled'),('state','&lt;&gt;','installed'),('state','&lt;&gt;','uninstallable'),]</field>
+ </record>
+ <menuitem name="Administration/Modules Management/Modules/Modules to be installed, upgraded or removed" action="open_module_tree_upgrade"/>
+
+ <record model="ir.ui.view" id="repository_form">
+ <field name="name">ir.module.repository.form</field>
+ <field name="model">ir.module.repository</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form string="Repository">
+ <field name="name" colspan="3" select="1"/>
+ <field name="url" colspan="3" select="1"/>
+ </form>
+ </field>
+ </record>
+ <record model="ir.ui.view" id="repository_tree">
+ <field name="name">ir.module.repository.tree</field>
+ <field name="model">ir.module.repository</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree string="Repository list">
+ <field name="name"/>
+ <field name="url"/>
+ </tree>
+ </field>
+ </record>
+ <record model="ir.actions.act_window" id="open_repository_tree">
+ <field name="name">ir.module.repository</field>
+ <field name="res_model">ir.module.repository</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+ <!--
+ <menuitem
+ name="Administration/Modules Management/Repositories"
+ action="open_repository_tree"
+ id="menu_module_repository_tree"
+ />
+ -->
+
+ </data>
+</terp>
diff --git a/bin/addons/base/module/module_wizard.xml b/bin/addons/base/module/module_wizard.xml
new file mode 100644
index 00000000000..4c6182a2055
--- /dev/null
+++ b/bin/addons/base/module/module_wizard.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0"?>
+<terp>
+ <data>
+ <wizard
+ id="wizard_info_get"
+ string="Request Info"
+ model="ir.module.module"
+ name="module.info_get"/>
+
+ <!--
+ <record model="ir.actions.wizard" id="wizard_update">
+ <field name="name">Download module list</field>
+ <field name="wiz_name">module.module.update</field>
+ </record>
+ <menuitem
+ name="Administration/Module Management/Download module list"
+ action="wizard_update"
+ type="wizard"
+ groups="admin"
+ icon="STOCK_CONVERT"
+ id="menu_module_update"/>
+ -->
+
+ <record model="ir.actions.wizard" id="wizard_upgrade">
+ <field name="name">Apply marked changes</field>
+ <field name="wiz_name">module.upgrade</field>
+ </record>
+ <menuitem
+ name="Administration/Modules Management/Apply Upgrades"
+ action="wizard_upgrade"
+ id="menu_wizard_upgrade"
+ type="wizard"/>
+
+ <record model="ir.actions.wizard" id="wizard_lang_install">
+ <field name="name">Install new language file</field>
+ <field name="wiz_name">module.lang.install</field>
+ </record>
+ <menuitem
+ name="Administration/Translations/Load a new language"
+ action="wizard_lang_install"
+ id="menu_wizard_lang_install"
+ type="wizard"/>
+
+ <record model="ir.actions.wizard" id="wizard_scan_addons">
+ <field name="name">Scan 'addons' path</field>
+ <field name="wiz_name">module.module.scan</field>
+ </record>
+ <menuitem
+ name="Administration/Modules Management/Update modules list"
+ action="wizard_scan_addons"
+ id="menu_wizard_module_scan"
+ type="wizard" />
+
+ <record model="ir.actions.wizard" id="wizard_lang_export">
+ <field name="name">Export a language</field>
+ <field name="wiz_name">module.lang.export</field>
+ </record>
+ <menuitem
+ name="Administration/Translations/Export a language"
+ action="wizard_lang_export"
+ id="menu_wizard_lang_export"
+ type="wizard"/>
+
+ <record model="ir.actions.wizard" id="wizard_lang_import">
+ <field name="name">Import a language</field>
+ <field name="wiz_name">module.lang.import</field>
+ </record>
+ <menuitem
+ name="Administration/Translations/Import a language"
+ action="wizard_lang_import"
+ id="menu_wizard_lang_import"
+ type="wizard"/>
+
+ </data>
+</terp>
+
diff --git a/bin/addons/base/module/report/__init__.py b/bin/addons/base/module/report/__init__.py
new file mode 100644
index 00000000000..49e3c07d385
--- /dev/null
+++ b/bin/addons/base/module/report/__init__.py
@@ -0,0 +1,29 @@
+##############################################################################
+#
+# Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved.
+# Fabien Pinckaers <fp@tiny.Be>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import ir_module_reference_print
diff --git a/bin/addons/base/module/report/ir_module_reference.rml b/bin/addons/base/module/report/ir_module_reference.rml
new file mode 100644
index 00000000000..ca1cef0f610
--- /dev/null
+++ b/bin/addons/base/module/report/ir_module_reference.rml
@@ -0,0 +1,173 @@
+<?xml version="1.0"?>
+<document filename="test.pdf">
+ <template pageSize="(595.0,842.0)" title="Test" author="Martin Simon" allowSplitting="20">
+ <pageTemplate id="first">
+ <frame id="first" x1="42.0" y1="42.0" width="511" height="758"/>
+ </pageTemplate>
+ </template>
+ <stylesheet>
+ <blockTableStyle id="Standard_Outline">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <blockTableStyle id="Table1">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <blockBackground colorName="#e6e6e6" start="0,0" stop="0,0"/>
+ <blockBackground colorName="#e6e6e6" start="1,0" stop="1,0"/>
+ <blockBackground colorName="#e6e6e6" start="2,0" stop="2,0"/>
+ <blockBackground colorName="#e6e6e6" start="0,1" stop="0,1"/>
+ <blockBackground colorName="#e6e6e6" start="1,1" stop="1,1"/>
+ <blockBackground colorName="#e6e6e6" start="2,1" stop="2,1"/>
+ </blockTableStyle>
+ <blockTableStyle id="Tableau1">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="GRID" colorName="black"/>
+ <blockBackground colorName="#ff6633" start="0,0" stop="0,0"/>
+ </blockTableStyle>
+ <blockTableStyle id="Tableau2">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <blockBackground colorName="#e6e6e6" start="0,0" stop="0,0"/>
+ <blockBackground colorName="#e6e6e6" start="1,0" stop="1,0"/>
+ <blockBackground colorName="#e6e6e6" start="0,1" stop="0,1"/>
+ <blockBackground colorName="#e6e6e6" start="1,1" stop="1,1"/>
+ </blockTableStyle>
+ <blockTableStyle id="Tableau3">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="GRID" colorName="black"/>
+ <blockBackground colorName="#ffcc99" start="0,0" stop="0,0"/>
+ </blockTableStyle>
+ <blockTableStyle id="Tableau4">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <initialize>
+ <paraStyle name="all" alignment="justify"/>
+ </initialize>
+ <paraStyle name="P1" fontName="Times-Roman" fontSize="20.0" leading="25" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="P2" fontName="Times-Roman" fontSize="10.0" leading="13" alignment="RIGHT" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="P3" fontName="Times-Roman" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="P4" fontName="Times-Roman" fontSize="11.0" leading="14" alignment="RIGHT" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="P5" fontName="Times-Roman" fontSize="16.0" leading="20" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="P6" fontName="Times-Roman"/>
+ <paraStyle name="P7" fontName="Times-Roman" fontSize="15.0" leading="19" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="P8" fontName="Times-Roman" fontSize="11.0" leading="14" alignment="LEFT" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="P9" fontName="Times-Roman" alignment="LEFT" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="Standard" fontName="Times-Roman"/>
+ <paraStyle name="Text body" fontName="Times-Roman" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="Heading" fontName="Helvetica" fontSize="14.0" leading="17" spaceBefore="12.0" spaceAfter="6.0"/>
+ <paraStyle name="List" fontName="Times-Roman" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="Table Contents" fontName="Times-Roman" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="Table Heading" fontName="Times-Roman" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="Caption" fontName="Times-Roman" fontSize="12.0" leading="15" spaceBefore="6.0" spaceAfter="6.0"/>
+ <paraStyle name="Index" fontName="Times-Roman"/>
+ </stylesheet>
+ <story>
+ <para style="Standard">
+ <font color="white"> </font>
+ </para>
+ <blockTable colWidths="139.0,220.0,152.0" repeatRows="1" style="Table1">
+ <tr>
+ <td>
+ <para style="Table Contents">
+ <font color="white"> </font>
+ </para>
+ </td>
+ <td>
+ <para style="P1">Reference Guide</para>
+ </td>
+ <td>
+ <para style="P2">
+ <font color="white"> </font>
+ </para>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <para style="Table Contents">[[ company.name ]]</para>
+ </td>
+ <td>
+ <para style="P3">Introspection report on objects</para>
+ </td>
+ <td>
+ <para style="P4">Printed: [[ time.strftime('%y-%m-%d')]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="Standard">
+ <font color="white"> </font>
+ </para>
+ <section>
+ <para style="Text body">[[ repeatIn(objects, 'module') ]]</para>
+ <blockTable colWidths="510.0" repeatRows="1" style="Tableau1">
+ <tr>
+ <td>
+ <para style="P5">Module: [[ module.name ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable colWidths="276.0,234.0" repeatRows="1" style="Tableau2">
+ <tr>
+ <td>
+ <para style="Standard">Name: [[ module.shortdesc]]</para>
+ </td>
+ <td>
+ <para style="Standard">Version: [[module.latest_version]]</para>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <para style="Standard">Directory: [[ module.name ]]</para>
+ </td>
+ <td>
+ <para style="Standard">Web: [[ module.website ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="P6">[[ module.description ]]</para>
+ <section>
+ <para style="Standard">[[ repeatIn(findobj(module.name) ,'object') ]]</para>
+ <blockTable colWidths="510.0" repeatRows="1" style="Tableau3">
+ <tr>
+ <td>
+ <para style="P7">Object: [[ object.name ]]</para>
+ <pre style="P8">[[ objdoc(object.model) ]]</pre>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable colWidths="113.0,397.0" repeatRows="1" style="Tableau4">
+ <tr>
+ <td>
+ <para style="P9"><font face="Times-Roman">[[ repeatIn(findflds(object.model), 'field') ]]</font> [[ field[0] ]]</para>
+ </td>
+ <td>
+ <para style="Standard">
+ <font face="Times-Roman">[[ field[1].get('string', 'Unknown') ]], [[ field[1]['type'] ]] [[field[1].get('required',False) and ', required']] [[field[1].get('readonly',False) and ', readonly']] </font>
+ </para>
+ <para style="Standard">[[ field[1].get('help', '') ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="Standard">
+ <font color="white"> </font>
+ </para>
+ </section>
+ <para style="Standard">
+ <font color="white"> </font>
+ </para>
+ <para style="Standard">
+ <font color="white"> </font>
+ </para>
+ <para style="Standard">
+ <font color="white"> </font>
+ </para>
+ </section>
+ <para style="Standard">
+ <font color="white"> </font>
+ </para>
+ </story>
+</document>
+
diff --git a/bin/addons/base/module/report/ir_module_reference.sxw b/bin/addons/base/module/report/ir_module_reference.sxw
new file mode 100644
index 00000000000..b97959a8d0a
--- /dev/null
+++ b/bin/addons/base/module/report/ir_module_reference.sxw
Binary files differ
diff --git a/bin/addons/base/module/report/ir_module_reference_print.py b/bin/addons/base/module/report/ir_module_reference_print.py
new file mode 100644
index 00000000000..3b3d3a7be7a
--- /dev/null
+++ b/bin/addons/base/module/report/ir_module_reference_print.py
@@ -0,0 +1,60 @@
+##############################################################################
+#
+# Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved.
+# Fabien Pinckaers <fp@tiny.Be>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import time
+from report import report_sxw
+
+class ir_module_reference_print(report_sxw.rml_parse):
+ def __init__(self, cr, uid, name, context):
+ super(ir_module_reference_print, self).__init__(cr, uid, name, context)
+ self.localcontext.update({
+ 'time': time,
+ 'findobj': self._object_find,
+ 'objdoc': self._object_doc,
+ 'findflds': self._fields_find,
+ })
+ def _object_doc(self, obj):
+ modobj = self.pool.get(obj)
+ return modobj.__doc__
+
+ def _object_find(self, module):
+ modobj = self.pool.get('ir.model')
+ if module=='base':
+ ids = modobj.search(self.cr, self.uid, [('model','=like','res%')])
+ ids += modobj.search(self.cr, self.uid, [('model','=like','ir%')])
+ else:
+ ids = modobj.search(self.cr, self.uid, [('model','=like',module+'%')])
+ return modobj.browse(self.cr, self.uid, ids)
+
+ def _fields_find(self, obj):
+ modobj = self.pool.get(obj)
+ res = modobj.fields_get(self.cr, self.uid).items()
+ return res
+
+report_sxw.report_sxw('report.ir.module.reference', 'ir.module.module', 'addons/base/module/report/ir_module_reference.rml', parser=ir_module_reference_print)
+
diff --git a/bin/addons/base/module/wizard/__init__.py b/bin/addons/base/module/wizard/__init__.py
new file mode 100644
index 00000000000..d74449872c0
--- /dev/null
+++ b/bin/addons/base/module/wizard/__init__.py
@@ -0,0 +1,35 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import wizard_install_module
+import wizard_update_module
+import wizard_module_upgrade
+import wizard_module_info_get
+import wizard_module_lang_install
+import add_new
+import wizard_export_lang
+import wizard_import_lang
diff --git a/bin/addons/base/module/wizard/add_new.py b/bin/addons/base/module/wizard/add_new.py
new file mode 100644
index 00000000000..63d7a2359dd
--- /dev/null
+++ b/bin/addons/base/module/wizard/add_new.py
@@ -0,0 +1,100 @@
+##############################################################################
+#
+# Copyright (c) 2004-2006 TINY SPRL. (http://tiny.be)
+#
+# $Id$
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contact a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import os
+import re
+import glob
+import time
+import imp
+
+import tools
+import wizard
+import pooler
+
+module_name_re = re.compile('.*addons.(.*?).__terp__.py$')
+
+_info_arch = '''<?xml version="1.0"?>
+<form string="Scan for new modules">
+ <label string="This function will check if you installed new modules in the 'addons' path of your server installation." colspan="4" />
+</form>
+'''
+_info_fields = {}
+
+def get_module_info(name):
+ try:
+ f = file(os.path.join(tools.config['addons_path'], name, '__terp__.py'), 'r')
+ data = f.read()
+ info = eval(data)
+ f.close()
+ except:
+ return {}
+ return info
+
+class wizard_install_module(wizard.interface):
+ def watch_dir(self, cr, uid, data, context):
+ mod_obj = pooler.get_pool(cr.dbname).get('ir.module.module')
+ all_mods = mod_obj.read(cr, uid, mod_obj.search(cr, uid, []), ['name', 'state'])
+ known_modules = set([x['name'] for x in all_mods])
+ ls_ad = glob.glob(os.path.join(tools.config['addons_path'], '*', '__terp__.py'))
+ modules = set([module_name_re.match(name).group(1) for name in ls_ad])
+ new_modules = modules - known_modules
+ for module in new_modules:
+ terp = get_module_info(module)
+ if not terp.get('installable', True):
+ continue
+ imp.load_module(module, *imp.find_module(module))
+ mod_id = mod_obj.create(cr, uid, {
+ 'name': module,
+ 'state': 'uninstalled',
+ 'description': terp.get('description', ''),
+ 'shortdesc': terp.get('name', ''),
+ 'author': terp.get('author', 'Unknown')})
+ dependencies = terp.get('depends', [])
+ for d in dependencies:
+ cr.execute('insert into ir_module_module_dependency (module_id,name) values (%s, %s)', (mod_id, d))
+ for module in known_modules:
+ terp = get_module_info(module)
+ if terp.get('installable', True):
+ for mod in all_mods:
+ if mod['name'] == module and mod['state'] == 'uninstallable':
+ mod_obj.write(cr, uid, [mod['id']], {'state': 'uninstalled'})
+ return {}
+
+ states = {
+ 'init': {
+ 'actions': [],
+ 'result': {'type':'form', 'arch': _info_arch, 'fields': _info_fields, 'state':[('end','Cancel','gtk-cancel'),('addmod','Check new modules','gtk-ok')]}
+ },
+ 'addmod': {
+ 'actions': [watch_dir],
+ 'result': {'type':'state', 'state':'end'}
+ },
+ }
+wizard_install_module('module.module.scan')
+
diff --git a/bin/addons/base/module/wizard/wizard_export_lang.py b/bin/addons/base/module/wizard/wizard_export_lang.py
new file mode 100644
index 00000000000..212e6b459c2
--- /dev/null
+++ b/bin/addons/base/module/wizard/wizard_export_lang.py
@@ -0,0 +1,91 @@
+# -*- coding: iso-8859-1 -*-
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+# Fabien Pinckaers <fp@tiny.Be>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import wizard
+import tools
+import base64
+import StringIO
+import csv
+import pooler
+
+view_form_init="""<?xml version="1.0"?>
+<form string="Export language">
+ <image name="gtk-info" size="64" colspan="2"/>
+ <group colspan="2" col="4">
+ <separator string="Export translation file" colspan="4"/>
+ <label align="0.0" string="Choose a language to export:" colspan="4"/>
+ <field name="lang" colspan="4"/>
+ </group>
+</form>"""
+
+view_form_finish="""<?xml version="1.0"?>
+<form string="Export language">
+ <image name="gtk-info" size="64" colspan="2"/>
+ <group colspan="2" col="4">
+ <separator string="Export done" colspan="4"/>
+ <field name="data" readonly="1" colspan="3"/>
+ <label align="0.0" string="Save this document to a .CSV file and open it with\n your favourite spreadsheet software. The file\n encoding is UTF-8. You have to translate the latest\n column before reimporting it." colspan="4"/>
+ </group>
+</form>"""
+
+class wizard_export_lang(wizard.interface):
+ def _get_language(self, cr, uid, context):
+ lang_obj=pooler.get_pool(cr.dbname).get('res.lang')
+ ids=lang_obj.search(cr, uid, [('active', '=', True),])
+ langs=lang_obj.browse(cr, uid, ids)
+ return [(lang.code, lang.translatable and lang.name or 'New language') for lang in langs]
+
+ def _get_file(self, cr, uid, data, context):
+ file=tools.trans_generate(data['form']['lang'], 'all')
+ buf=StringIO.StringIO()
+ writer=csv.writer(buf)
+ for row in file:
+ writer.writerow(row)
+ del file
+ out=base64.encodestring(buf.getvalue())
+ buf.close()
+ return {'data': out}
+
+ fields_form={
+ 'lang': {'string':'Language', 'type':'selection', 'selection':_get_language,},
+ }
+ fields_form_finish={
+ 'data': {'string':'File', 'type':'binary', 'readonly': True,},
+ }
+ states={
+ 'init':{
+ 'actions':[],
+ 'result':{'type':'form', 'arch':view_form_init, 'fields': fields_form, 'state':[('end', 'Cancel', 'gtk-cancel'),('finish', 'Ok', 'gtk-ok')]}
+ },
+ 'finish':{
+ 'actions':[_get_file],
+ 'result':{'type':'form', 'arch':view_form_finish, 'fields': fields_form_finish, 'state':[('end', 'Close', 'gtk-cancel')]}
+ },
+ }
+wizard_export_lang('module.lang.export')
diff --git a/bin/addons/base/module/wizard/wizard_import_lang.py b/bin/addons/base/module/wizard/wizard_import_lang.py
new file mode 100644
index 00000000000..226bece1ace
--- /dev/null
+++ b/bin/addons/base/module/wizard/wizard_import_lang.py
@@ -0,0 +1,75 @@
+# -*- coding: iso-8859-1 -*-
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+# Fabien Pinckaers <fp@tiny.Be>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import wizard
+import tools
+import base64
+import pooler
+
+view_form="""<?xml version="1.0"?>
+<form string="Import language">
+ <image name="gtk-info" size="64" colspan="2"/>
+ <group colspan="2" col="4">
+ <separator string="Import new language" colspan="4"/>
+ <field name="name"/>
+ <field name="code"/>
+ <field name="data" colspan="3"/>
+ <label string="You have to import a .CSV file wich is encoded in UTF-8.\nPlease check that the first line of your file is:" colspan="4" align="0.0"/>
+ <label string="type,name,res_id,src,value" colspan="4"/>
+ </group>
+</form>"""
+
+class wizard_import_lang(wizard.interface):
+ def _import_lang(self, cr, uid, data, context):
+ form=data['form']
+ lang_obj=pooler.get_pool(cr.dbname).get('res.lang')
+ ids=lang_obj.search(cr, uid, [('code', '=', form['code'])])
+ if ids:
+ lang_obj.write(cr, uid, ids, {'name': form['name']})
+ else:
+ lang_obj.create(cr, uid, {'code': form['code'], 'name': form['name']})
+ buf=base64.decodestring(data['form']['data']).split('\n')
+ tools.trans_load_data(cr.dbname, buf, data['form']['code'])
+ return {}
+ fields_form={
+ 'name':{'string':'Language name', 'type':'char', 'size':64, 'required':True},
+ 'code':{'string':'Code (eg:en_US)', 'type':'char', 'size':5, 'required':True},
+ 'data':{'string':'File', 'type':'binary', 'required':True},
+ }
+ states={
+ 'init':{
+ 'actions':[],
+ 'result':{'type':'form', 'arch':view_form, 'fields':fields_form, 'state':[('end', 'Cancel', 'gtk-cancel'), ('finish', 'Ok', 'gtk-ok')]}
+ },
+ 'finish':{
+ 'actions':[],
+ 'result':{'type':'action', 'action':_import_lang, 'state':'end'}
+ },
+ }
+wizard_import_lang('module.lang.import')
diff --git a/bin/addons/base/module/wizard/wizard_install_module.py b/bin/addons/base/module/wizard/wizard_install_module.py
new file mode 100644
index 00000000000..71a6be50848
--- /dev/null
+++ b/bin/addons/base/module/wizard/wizard_install_module.py
@@ -0,0 +1,67 @@
+# -*- coding: iso-8859-1 -*-
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import wizard
+import netsvc
+
+#TODO: upgraded modules
+#TODO: removed modules
+additional_changes_form = '''<?xml version="1.0"?>
+<form string="Additional modules">
+ <label string="The following additional modules need to be installed:"/>
+ <newline/>
+ <field name="additional"/>
+</form>'''
+
+additional_changes_fields = {
+ 'additional': {'string':'Additional modules', 'type':'one2many', 'relation':'ir.module.module', 'readonly':True},
+}
+
+class wizard_install_module(wizard.interface):
+ def _get_value(self, cr, uid, data, context):
+ service = netsvc.LocalService("object_proxy")
+ extra = service.execute(cr.dbname, uid, 'ir.module.module', 'get_extra_modules', data['ids'])
+ return {'additional': extra}
+
+ def _install_module(self, cr, uid, data, context):
+ service = netsvc.LocalService("object_proxy")
+ res = service.execute(cr.dbname, uid, 'ir.module.module', 'install', data['ids'])
+ return {}
+
+ states = {
+ 'init': {
+ 'actions': [_get_value],
+ 'result': {'type':'form', 'arch':additional_changes_form, 'fields':additional_changes_fields, 'state':[('install','Install'), ('end','Cancel')]}
+ },
+ 'install': {
+ 'actions': [_install_module],
+ 'result': {'type':'state', 'state':'end'}
+ },
+ }
+wizard_install_module('module.module.install')
+
diff --git a/bin/addons/base/module/wizard/wizard_module_info_get.py b/bin/addons/base/module/wizard/wizard_module_info_get.py
new file mode 100644
index 00000000000..124a6820b8b
--- /dev/null
+++ b/bin/addons/base/module/wizard/wizard_module_info_get.py
@@ -0,0 +1,46 @@
+# -*- coding: iso-8859-1 -*-
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+# Fabien Pinckaers <fp@tiny.Be>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import wizard
+import netsvc
+
+class wizard_info_get(wizard.interface):
+ def _update_module(self, cr, uid, data, context):
+ service = netsvc.LocalService("object_proxy")
+ service.execute(cr.dbname, uid, 'ir.module.module', 'info_get', data['ids'])
+ return {}
+
+ states = {
+ 'init': {
+ 'actions': [_update_module],
+ 'result': {'type':'state', 'state':'end'}
+ },
+ }
+wizard_info_get('module.info_get')
+
diff --git a/bin/addons/base/module/wizard/wizard_module_lang_install.py b/bin/addons/base/module/wizard/wizard_module_lang_install.py
new file mode 100644
index 00000000000..14f3e867a50
--- /dev/null
+++ b/bin/addons/base/module/wizard/wizard_module_lang_install.py
@@ -0,0 +1,83 @@
+# -*- coding: iso-8859-1 -*-
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+# Fabien Pinckaers <fp@tiny.Be>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import wizard
+import tools
+
+view_form_end = """<?xml version="1.0"?>
+<form string="Language file loaded.">
+ <image name="gtk-info" size="64" colspan="2"/>
+ <group colspan="2" col="4">
+ <separator string="Installation done" colspan="4"/>
+ <label align="0.0" string="The selected language has been successfully installed.\nYou must change the preferences of the user and open a new menu to view changes." colspan="4"/>
+ </group>
+</form>"""
+
+view_form = """<?xml version="1.0"?>
+<form string="System Upgrade">
+ <image name="gtk-info" size="64" colspan="2"/>
+ <group colspan="2" col="4">
+ <separator string="System Upgrade" colspan="4"/>
+ <label align="0.0" string="Choose a language to install:" colspan="4"/>
+ <field name="lang" colspan="4"/>
+ <label align="0.0" string="Note that this operation may take a few minutes." colspan="4"/>
+ </group>
+</form>"""
+
+
+class wizard_lang_install(wizard.interface):
+ def _lang_install(self, cr, uid, data, context):
+ print cr, uid, data, context
+
+ lang = data['form']['lang']
+ if lang and lang != 'en_EN':
+ filename = tools.config["root_path"] + "/i18n/" + lang + ".csv"
+ tools.trans_load(cr.dbname, filename, lang)
+ return {}
+
+ def _get_language(sel, cr, uid, context):
+ return tools.scan_languages()
+
+ fields_form = {
+ 'lang': {'string':'Language', 'type':'selection', 'selection':_get_language,
+ },
+ }
+
+ states = {
+ 'init': {
+ 'actions': [],
+ 'result': {'type':'form', 'arch':view_form, 'fields': fields_form, 'state':[('end','Cancel','gtk-cancel'),('start','Start installation','gtk-ok')]}
+ },
+ 'start': {
+ 'actions': [_lang_install],
+ 'result': {'type':'form', 'arch':view_form_end, 'fields': {}, 'state':[('end','Ok','gtk-ok')]}
+ },
+ }
+wizard_lang_install('module.lang.install')
+
diff --git a/bin/addons/base/module/wizard/wizard_module_upgrade.py b/bin/addons/base/module/wizard/wizard_module_upgrade.py
new file mode 100644
index 00000000000..65cfaa66a50
--- /dev/null
+++ b/bin/addons/base/module/wizard/wizard_module_upgrade.py
@@ -0,0 +1,81 @@
+# -*- coding: iso-8859-1 -*-
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+# Fabien Pinckaers <fp@tiny.Be>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import wizard
+import pooler
+
+view_form_end = """<?xml version="1.0"?>
+<form string="System upgrade done">
+ <separator string="System upgrade done"/>
+ <label align="0.0" string="The modules have been upgraded / installed !" colspan="4"/>
+ <label align="0.0" string="You may have to reinstall some language pack." colspan="4"/>
+ <label align="0.0" string="We suggest you to close all tabs and open a new menu window (Ctrl T)." colspan="4"/>
+</form>"""
+
+view_form = """<?xml version="1.0"?>
+<form string="System Upgrade">
+ <image name="gtk-info" size="64" colspan="2"/>
+ <group colspan="2" col="4">
+ <label align="0.0" string="Your system will be upgraded." colspan="4"/>
+ <label align="0.0" string="Note that this operation my take a few minutes." colspan="4"/>
+ <separator string="Modules to update"/>
+ <field name="module_info" nolabel="1" colspan="4"/>
+ </group>
+</form>"""
+
+view_field = {
+ "module_info": {'type':'text', 'string':'Modules', 'readonly':True}
+}
+
+class wizard_info_get(wizard.interface):
+ def _get_install(self, cr, uid, data, context):
+ pool=pooler.get_pool(cr.dbname)
+ ids = pool.get('ir.module.module').search(cr, uid, [
+ ('state','<>','uninstalled'),
+ ('state','<>','installed'),
+ ('state','<>','uninstallable')])
+ res = pool.get('ir.module.module').read(cr, uid, ids, ['name','state'], context)
+ return {'module_info':'\n'.join(map(lambda x: x['name']+' : '+x['state'], res))}
+
+ def _upgrade_module(self, cr, uid, data, context):
+ (db, pool)=pooler.restart_pool(cr.dbname, update_module=True)
+ return {}
+
+ states = {
+ 'init': {
+ 'actions': [_get_install],
+ 'result': {'type':'form', 'arch':view_form, 'fields': view_field, 'state':[('end','Cancel','gtk-cancel'),('start','Start Upgrade','gtk-ok')]}
+ },
+ 'start': {
+ 'actions': [_upgrade_module],
+ 'result': {'type':'form', 'arch':view_form_end, 'fields': {}, 'state':[('end','Close','gtk-close')]}
+ },
+ }
+wizard_info_get('module.upgrade')
+
diff --git a/bin/addons/base/module/wizard/wizard_update_module.py b/bin/addons/base/module/wizard/wizard_update_module.py
new file mode 100644
index 00000000000..5a2ec58912b
--- /dev/null
+++ b/bin/addons/base/module/wizard/wizard_update_module.py
@@ -0,0 +1,61 @@
+# -*- coding: iso-8859-1 -*-
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+# Fabien Pinckaers <fp@tiny.Be>
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import wizard
+import netsvc
+
+class wizard_update_module(wizard.interface):
+ def _update_module(self, cr, uid, data, context):
+ service = netsvc.LocalService("object_proxy")
+ service.execute(cr.dbname, uid, 'ir.module.module', 'update_list')
+ return {}
+
+ def _action_module_open(self, cr, uid, data, context):
+ return {
+ 'domain': "[]",
+ 'name': 'Open Module List',
+ 'view_type': 'form',
+ 'view_mode': 'tree,form',
+ 'res_model': 'ir.module.module',
+ 'view_id': False,
+ 'type': 'ir.actions.act_window'
+ }
+
+ states = {
+ 'init': {
+ 'actions': [_update_module],
+ 'result': {'type':'state', 'state':'open_window'}
+ },
+ 'open_window': {
+ 'actions': [],
+ 'result': {'type': 'action', 'action': _action_module_open, 'state':'end'}
+ }
+ }
+wizard_update_module('module.module.update')
+