diff options
| author | pinky <> | 2006-12-07 13:41:40 +0000 |
|---|---|---|
| committer | pinky <> | 2006-12-07 13:41:40 +0000 |
| commit | 004a0b996ff8f269451e07346f71a129a1f3fbaf (patch) | |
| tree | 48f43c1fc2ca4c1f4d5648e7e73553d3f4ccae06 /bin/addons/base/module | |
New trunk
bzr revid: pinky-3f10ee12cea3c4c75cef44ab04ad33ef47432907
Diffstat (limited to 'bin/addons/base/module')
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','<>','uninstalled'),('state','<>','installed'),('state','<>','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 Binary files differnew file mode 100644 index 00000000000..b97959a8d0a --- /dev/null +++ b/bin/addons/base/module/report/ir_module_reference.sxw 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') + |
