From 0befe14cd47ab3b0a07288a5efc632cfd1a103db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 20 Dec 2008 01:07:50 +0100 Subject: [PATCH 1/3] Add model graph report --- trytond/ir/model.py | 127 ++++++++++++++++++++++++++++++++++++++++++- trytond/ir/model.xml | 30 ++++++++++ 2 files changed, 156 insertions(+), 1 deletion(-) diff --git a/trytond/ir/model.py b/trytond/ir/model.py index a2efa6dfc6..7457e94fa4 100644 --- a/trytond/ir/model.py +++ b/trytond/ir/model.py @@ -1,8 +1,12 @@ -#This file is part of Tryton. The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. +#This file is part of Tryton. The COPYRIGHT file at the top level of +#this repository contains the full copyright notices and license terms. "model" from trytond.osv import fields, OSV from trytond.tools import Cache +from trytond.report import Report +from trytond.wizard import Wizard, WizardOSV import time +import base64 class Model(OSV): @@ -23,6 +27,7 @@ class Model(OSV): ('model_uniq', 'UNIQUE(model)', 'The model must be unique!'), ] + self._order.insert(0, ('model', 'ASC')) Model() @@ -48,6 +53,7 @@ class ModelField(OSV): ('name_model_uniq', 'UNIQUE(name, model)', 'The field name in model must be unique!'), ] + self._order.insert(0, ('name', 'ASC')) def default_name(self, cursor, user, context=None): return 'No Name' @@ -284,3 +290,122 @@ class ModelData(OSV): return self.read(cursor, user, ids[0], ['db_id'])['db_id'] ModelData() + + +class PrintModelGraphInit(WizardOSV): + _name = 'ir.model.print_model_graph.init' + level = fields.Integer('Level') + + def default_level(self, cursor, user, context=None): + return 1 + +PrintModelGraphInit() + + +class PrintModelGraph(Wizard): + _name = 'ir.model.print_model_graph' + states = { + 'init': { + 'result': { + 'type': 'form', + 'object': 'ir.model.print_model_graph.init', + 'state': [ + ('end', 'Cancel', 'tryton-cancel'), + ('print', 'Print', 'tryton-ok', True), + ], + }, + }, + 'print': { + 'result': { + 'type': 'print', + 'report': 'ir.model.graph', + 'state': 'end', + }, + }, + } + +PrintModelGraph() + + +class ModelGraph(Report): + _name = 'ir.model.graph' + + def execute(self, cursor, user, ids, datas, context=None): + import pydot + model_obj = self.pool.get('ir.model') + + if context is None: + context = {} + + models = model_obj.browse(cursor, user, ids, context=context) + + graph = pydot.Dot(fontsize="8") + graph.set('center', '1') + graph.set('ratio', 'auto') + self.fill_graph(cursor, user, models, graph, + level=datas['form']['level'], context=context) + data = graph.create(prog='dot', format='png') + return ('png', base64.encodestring(data), False) + + def fill_graph(self, cursor, user, models, graph, level=1, context=None): + import pydot + model_obj = self.pool.get('ir.model') + + sub_models = set() + if level > 0: + for model in models: + for field in model.fields: + if field.name in ('create_uid', 'write_uid'): + continue + if field.relation and not graph.get_node(field.relation): + sub_models.add(field.relation) + if sub_models: + model_ids = model_obj.search(cursor, user, [ + ('model', 'in', list(sub_models)), + ], context=context) + sub_models = model_obj.browse(cursor, user, model_ids, + context=context) + if set(sub_models) != set(models): + self.fill_graph(cursor, user, sub_models, graph, + level=level - 1, context=context) + + for model in models: + label = '{' + model.model + '\\n' + if model.fields: + label += '|' + for field in model.fields: + if field.name in ('create_uid', 'write_uid', + 'create_date', 'write_date', 'id'): + continue + label += '+ ' + field.name + ': ' + field.ttype + if field.relation: + label += ' ' + field.relation + label += '\l' + label += '}' + node = pydot.Node(model.model, shape='record', label=label) + graph.add_node(node) + + for field in model.fields: + if field.name in ('create_uid', 'write_uid'): + continue + if field.relation and graph.get_node(field.relation): + args = {} + if field.ttype == 'many2one': + edge = graph.get_edge(model.model, field.relation) + if edge: + continue + args['arrowhead'] = "normal" + elif field.ttype == 'one2many': + continue + elif field.ttype == 'many2many': + if graph.get_edge(model.model, field.relation): + continue + if graph.get_edge(field.relation, model.model): + continue + args['arrowtail'] = "inv" + args['arrowhead'] = "inv" + + edge = pydot.Edge(model.model, field.relation, **args) + graph.add_edge(edge) + +ModelGraph() diff --git a/trytond/ir/model.xml b/trytond/ir/model.xml index 996e3a31e3..5383a37a3c 100644 --- a/trytond/ir/model.xml +++ b/trytond/ir/model.xml @@ -190,5 +190,35 @@ this repository contains the full copyright notices and license terms. --> + + Graph + ir.model + ir.model.graph + + + + ir.model.print_model_graph.init + form + + + + + + Graph + ir.model.print_model_graph + ir.model + + + form_print + ir.model,0 + + + From 16e4afd78d11fb419e4548e143ef4d65d8420c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 20 Dec 2008 01:08:31 +0100 Subject: [PATCH 2/3] Add todo for order on page tag --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index 961d8241b4..3c833689ba 100644 --- a/TODO +++ b/TODO @@ -10,3 +10,4 @@ - Add check for index and constraint name lenght (limit 31) - Change _constraint to pass a BrowseRecordList instead of a list of ids - Change action, menu on res.user into a Many2Many +- Add order attribute on page tag From ac69bb8610f03ef69650483199ccc17f59b84e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 20 Dec 2008 11:27:19 +0100 Subject: [PATCH 3/3] Add one2many for model graph --- trytond/ir/model.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/trytond/ir/model.py b/trytond/ir/model.py index 7457e94fa4..2060b49253 100644 --- a/trytond/ir/model.py +++ b/trytond/ir/model.py @@ -390,13 +390,20 @@ class ModelGraph(Report): continue if field.relation and graph.get_node(field.relation): args = {} + tail = model.model + head = field.relation if field.ttype == 'many2one': edge = graph.get_edge(model.model, field.relation) if edge: continue args['arrowhead'] = "normal" elif field.ttype == 'one2many': - continue + edge = graph.get_edge(field.relation, model.model) + if edge: + continue + args['arrowhead'] = "normal" + tail = field.relation + head = model.model elif field.ttype == 'many2many': if graph.get_edge(model.model, field.relation): continue @@ -405,7 +412,7 @@ class ModelGraph(Report): args['arrowtail'] = "inv" args['arrowhead'] = "inv" - edge = pydot.Edge(model.model, field.relation, **args) + edge = pydot.Edge(tail, head, **args) graph.add_edge(edge) ModelGraph()