diff --git a/tryton/action/main.py b/tryton/action/main.py index e3917bbb74..30621d8872 100644 --- a/tryton/action/main.py +++ b/tryton/action/main.py @@ -1,7 +1,7 @@ import time import datetime import tryton.rpc as rpc -#import tryton.wizard +from tryton.wizard import Wizard #import tryton.printer from tryton.common import message, error, selection from tryton.gui.window import Window @@ -76,7 +76,8 @@ class Action(object): datas = {} if 'type' not in action: return - win = None + from tryton.gui import Main + win = Main.get_main().window if 'window' in datas: win = datas['window'] del datas['window'] @@ -120,14 +121,12 @@ class Action(object): if datas.get('domain', False): domain.append(datas['domain']) - from tryton.gui import Main Window.create(view_ids, datas['res_model'], datas['res_id'], domain, - action['view_type'], datas.get('window', - Main.get_main().window), ctx, + action['view_type'], win, ctx, datas['view_mode'], name=action.get('name', False), limit=datas['limit'], auto_refresh=datas['auto_refresh']) elif action['type'] == 'ir.actions.wizard': - wizard.execute(action['wiz_name'], datas, parent=win, + Wizard.execute(action['wiz_name'], datas, win, context=context) elif action['type'] == 'ir.actions.report.custom': datas['report_id'] = action['report_id'] diff --git a/tryton/rpc.py b/tryton/rpc.py index 349cc5dbca..473e62e06b 100644 --- a/tryton/rpc.py +++ b/tryton/rpc.py @@ -150,8 +150,8 @@ class RPCSession(object): return sock.execute(method, *args) except socket.error, exception: from gui import Main - common.error(_('Connection refused !'), Main.get_main().window, - str(exception)) + common.error(_('Connection refused !'), str(exception), + Main.get_main().window) raise RPCException(69, _('Connection refused!')) except xmlrpclib.Fault, exception: raise RPCException(exception.faultCode, exception.faultString) @@ -209,8 +209,8 @@ class RPCSession(object): return sock.exec_auth(method, *args) except socket.error, exception: from gui import Main - common.error(_('Connection refused !'), Main.get_main().window, - str(exception)) + common.error(_('Connection refused !'), str(exception), + Main.get_main().window) raise RPCException(69, 'Connection refused!') except xmlrpclib.Fault, exception: self._process_exception(exception, obj, method, args) @@ -218,8 +218,8 @@ class RPCSession(object): self._process_exception(exception, obj, method, args) except Exception, exception: from gui import Main - common.error(_('Application Error'), Main.get_main().window, - str(exception)) + common.error(_('Application Error'), str(exception), + Main.get_main().window) else: raise RPCException(1, 'not logged') diff --git a/tryton/wizard/__init__.py b/tryton/wizard/__init__.py new file mode 100644 index 0000000000..918e828995 --- /dev/null +++ b/tryton/wizard/__init__.py @@ -0,0 +1 @@ +from main import * diff --git a/tryton/wizard/main.py b/tryton/wizard/main.py new file mode 100644 index 0000000000..c475773454 --- /dev/null +++ b/tryton/wizard/main.py @@ -0,0 +1,219 @@ +import gtk +import gettext +import tryton.rpc as rpc +import tryton.common as common +import thread, time +from tryton.gui.window.view_form.screen import Screen + +_ = gettext.gettext + + +class Dialog(object): + "Dialog for wizard" + + def __init__(self, arch, fields, state, name, parent=None): + self.states = [] + default = -1 + self.dia = gtk.Dialog('Tryton', parent, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + for i in state: + but = gtk.Button(i[1]) + but.show() + if len(i) >= 3: + icon = gtk.Image() + icon.set_from_stock(i[2], gtk.ICON_SIZE_BUTTON) + but.set_image(icon) + self.dia.add_action_widget(but, len(self.states)) + if len(i) >= 4 and i[3]: + but.set_flags(gtk.CAN_DEFAULT) + default = len(self.states) + self.states.append(i[0]) + if default >= 0: + self.dia.set_default_response(default) + + val = {} + for i in fields: + if 'value' in fields[i]: + val[i] = fields[i]['value'] + + self.screen = Screen('wizard.'+name, view_type=[], window=self.dia) + self.screen.new(default=False) + self.screen.add_view_custom(arch, fields, display=True) + self.screen.current_model.set(val) + + width, height = self.screen.screen_container.size_get() + parent_width, parent_height = parent.get_size() + self.screen.widget.set_size_request(min(parent_width - 20, width + 20), + min(parent_height - 60, height + 25)) + self.screen.widget.show() + + self.dia.vbox.pack_start(self.screen.widget) + self.dia.set_title(self.screen.current_view.title) + self.dia.show() + + def run(self, datas=None): + if datas is None: + datas = {} + while True: + res = self.dia.run() + self.screen.current_view.set_value() + if self.screen.current_model.validate() \ + or (res<0) or (self.states[res]=='end'): + break + self.screen.display() + if res < len(self.states) and res >= 0: + datas.update(self.screen.get()) + self.dia.destroy() + return (self.states[res], datas) + else: + self.dia.destroy() + return False + + +class Wizard(object): + + @staticmethod + def execute(action, datas, parent, state='init', context=None): + from tryton.action import Action + if not 'form' in datas: + datas['form'] = {} + wiz_id = rpc.session.rpc_exec_auth('/wizard', 'create', action) + while state != 'end': + wizardprogress = WizardProgress(wiz_id, state, datas, + parent, context) + res = wizardprogress.run() + if not res: + return False + + if 'datas' in res: + datas['form'].update( res['datas'] ) + if res['type'] == 'form': + dia = Dialog(res['arch'], res['fields'], res['state'], + action, parent) + dia.screen.current_model.set( datas['form'] ) + res = dia.run(datas['form']) + if not res: + break + (state, new_data) = res + for data in new_data: + if new_data[data] == None: + del new_data[data] + datas['form'].update(new_data) + del new_data + elif res['type'] == 'action': + Action._exec_action(res['action'], datas) + state = res['state'] + elif res['type'] == 'print': + datas['report_id'] = res.get('report_id', False) + if res.get('get_id_from_action', False): + backup_ids = datas['ids'] + datas['ids'] = datas['form']['ids'] + Action.exec_report(res['report'], datas) + datas['ids'] = backup_ids + else: + Action.exec_report(res['report'], datas) + state = res['state'] + elif res['type'] == 'state': + state = res['state'] + + +class WizardProgress(object): + + def __init__(self, wizard_id, state, datas, parent, context): + self.res = None + self.error = False + self.wizard_id = wizard_id + self.state = state + self.datas = datas + self.parent = parent + self.context = context + self.exception = None + + def run(self): + + def start(wiz_id, datas, state, context): + ctx = rpc.session.context.copy() + ctx.update(context) + try: + self.res = rpc.session.rpc_exec_auth_try('/wizard', + 'execute', wiz_id, datas, state, ctx) + except Exception, exception: + self.error = True + self.res = False + self.exception = exception + return True + if not self.res: + self.error = True + return True + + thread.start_new_thread(start, + (self.wizard_id, self.datas, self.state, self.context)) + + i = 0 + win = None + progressbar = None + while (not self.res) and (not self.error): + time.sleep(0.1) + i += 1 + if i > 10: + if not win or not progressbar: + win = gtk.Window(type=gtk.WINDOW_TOPLEVEL) + win.set_position(gtk.WIN_POS_CENTER_ON_PARENT) + vbox = gtk.VBox(False, 0) + hbox = gtk.HBox(False, 13) + hbox.set_border_width(10) + img = gtk.Image() + img.set_from_stock('gtk-dialog-info', gtk.ICON_SIZE_DIALOG) + hbox.pack_start(img, expand=True, fill=False) + vbox2 = gtk.VBox(False, 0) + label = gtk.Label() + label.set_markup(''+_('Operation in progress')+'') + label.set_alignment(0.0, 0.5) + vbox2.pack_start(label, expand=True, fill=False) + vbox2.pack_start(gtk.HSeparator(), expand=True, fill=True) + vbox2.pack_start(gtk.Label(_("Please wait,\n" \ + "this operation may take a while...")), + expand=True, fill=False) + hbox.pack_start(vbox2, expand=True, fill=True) + vbox.pack_start(hbox) + progressbar = gtk.ProgressBar() + progressbar.set_orientation(gtk.PROGRESS_LEFT_TO_RIGHT) + vbox.pack_start(progressbar, expand=True, fill=False) + win.add(vbox) + win.set_transient_for(self.parent) + win.show_all() + progressbar.pulse() + gtk.main_iteration() + if win: + win.destroy() + gtk.main_iteration() + if self.exception: + import xmlrpclib + import socket + from tryton.pysocket import PySocketException + from tryton.rpc import RPCException + try: + raise self.exception + except socket.error, exception: + common.error(_('Connection refused !'), str(exception), + self.parent, str(exception)) + except xmlrpclib.Fault, err: + rpc_exception = RPCException(err.faultCode, err.faultString) + if rpc_exception.type in ('warning', 'UserError'): + common.warning(rpc_exception.data, self.parent, + rpc_exception.message) + else: + common.error(_('Application Error'), err.faultCode, + self.parent, err.faultString) + except PySocketException, err: + rpc_exception = RPCException(err.faultCode, err.faultString) + if rpc_exception.type in ('warning', 'UserError'): + common.warning(rpc_exception.data, self.parent, + rpc_exception.message) + else: + common.error(_('Application Error'), err.faultCode, + self.parent, err.faultString) + except Exception, exception: + common.error(_('Application Error'), _('View details'), + self.parent, str(exception)) + return self.res