From 392631cc3283d75b8e072249214dc5ffbbfa85e0 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 26 Jan 2010 17:42:37 +0100 Subject: [PATCH] [fix] res.config so the state of a todo is changed after being done with it, not when it's displayed. Add the setting of states to ``skip`` (action_skip) and ``cancel`` (action_cancel) on top of ``done`` (action_next) plus a bit of documentation to the API. Also, fix res.config.users to use the right buttons/actions for its stuff, or clicking "Done" registers as having skipped the screen: create ``action_add`` event for "Add User" button, and hook "Done" to ``action_next`` with a NOOP ``execute``. bzr revid: xmo@tinyerp.com-20100126164237-0zvk4jc1dv9gqdc7 --- bin/addons/base/base_update.xml | 25 ++++++++-- bin/addons/base/res/res_config.py | 76 +++++++++++++++++++++++++++++-- bin/addons/base/res/res_user.py | 5 +- 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/bin/addons/base/base_update.xml b/bin/addons/base/base_update.xml index 180bd134a6e..3b969817d47 100644 --- a/bin/addons/base/base_update.xml +++ b/bin/addons/base/base_update.xml @@ -230,16 +230,31 @@ - - Done - gtk-go-forward - + action_add Add User gtk-add + + + + action_next + Done + gtk-go-forward + diff --git a/bin/addons/base/res/res_config.py b/bin/addons/base/res/res_config.py index e3b3d2df167..85a363c58a2 100644 --- a/bin/addons/base/res/res_config.py +++ b/bin/addons/base/res/res_config.py @@ -60,11 +60,30 @@ class res_config_configurable(osv.osv_memory): 'getting next %s' % todos) active_todos = todos.search(cr, uid, [('state','=','open'), ('active','=',True)], - limit=1, context=None) + limit=1) if active_todos: return todos.browse(cr, uid, active_todos[0], context=None) return None + def _set_previous_todo(self, cr, uid, state): + """ lookup the previous (which is still the next at this point) + ir.actions.todo, set it to whatever state was provided. + + Raises + `LookupError`: if we couldn't find *any* previous todo + `ValueError`: if no state is provided + anything ir_actions_todo.write can throw + """ + # this is ultra brittle, but apart from storing the todo id + # into the res.config view, I'm not sure how to do it + previous_todo = self._next_action(cr, uid) + if not previous_todo: + raise LookupError(_("Couldn't find previous ir.actions.todo")) + if not state: + raise ValueError(_("Can't set an ir.actions.todo's state to " + "nothingness")) + previous_todo.write({'state':state}) + def _next(self, cr, uid): self.logger.notifyChannel('actions', netsvc.LOG_INFO, 'getting next operation') @@ -72,9 +91,6 @@ class res_config_configurable(osv.osv_memory): self.logger.notifyChannel('actions', netsvc.LOG_INFO, 'next action is %s' % next) if next: - self.pool.get('ir.actions.todo').write(cr, uid, next.id, { - 'state':'done', - }, context=None) action = next.action_id return { 'view_mode': action.view_mode, @@ -93,21 +109,73 @@ class res_config_configurable(osv.osv_memory): # return the action associated with the menu return self.pool.get(current_user_menu.type)\ .read(cr, uid, current_user_menu.id) + def next(self, cr, uid, ids, context=None): + """ Returns the next action to execute execute (using the default + sort order) + """ return self._next(cr, uid) def execute(self, cr, uid, ids, context=None): + """ Method called when the user clicks on the ``Next`` button. + + Execute *must* be overloaded unless ``action_next`` is overloaded + (which is something you generally don't need to do). + + If ``execute`` returns an action dictionary, that action is executed + rather than just going to the next configuration item. + """ raise NotImplementedError( 'Configuration items need to implement execute') def cancel(self, cr, uid, ids, context=None): + """ Method called when the user click on the ``Skip`` button. + + ``cancel`` should be overloaded instead of ``action_skip``. As with + ``execute``, if it returns an action dictionary that action is + executed in stead of the default (going to the next configuration item) + + The default implementation is a NOOP. + """ pass def action_next(self, cr, uid, ids, context=None): + """ Action handler for the ``next`` event. + + Sets the status of the todo the event was sent from to + ``done``, calls ``execute`` and -- unless ``execute`` returned + an action dictionary -- executes the action provided by calling + ``next``. + """ + self._set_previous_todo(cr, uid, state='done') next = self.execute(cr, uid, ids, context=None) if next: return next return self.next(cr, uid, ids, context=context) def action_skip(self, cr, uid, ids, context=None): + """ Action handler for the ``skip`` event. + + Sets the status of the todo the event was sent from to + ``skip``, calls ``cancel`` and -- unless ``cancel`` returned + an action dictionary -- executes the action provided by calling + ``next``. + """ + self._set_previous_todo(cr, uid, state='skip') + next = self.cancel(cr, uid, ids, context=None) + if next: return next + return self.next(cr, uid, ids, context=context) + + def action_cancel(self, cr, uid, ids, context=None): + """ Action handler for the ``cancel`` event. That event isn't + generated by the res.config.view.base inheritable view, the + inherited view has to overload one of the buttons (or add one + more). + + Sets the status of the todo the event was sent from to + ``cancel``, calls ``cancel`` and -- unless ``cancel`` returned + an action dictionary -- executes the action provided by calling + ``next``. + """ + self._set_previous_todo(cr, uid, state='cancel') next = self.cancel(cr, uid, ids, context=None) if next: return next return self.next(cr, uid, ids, context=context) diff --git a/bin/addons/base/res/res_user.py b/bin/addons/base/res/res_user.py index eff550deba0..43f91e69917 100644 --- a/bin/addons/base/res/res_user.py +++ b/bin/addons/base/res/res_user.py @@ -388,8 +388,11 @@ class config_users(osv.osv_memory): body=self.get_welcome_mail_body( cr, uid, context=context) % user_data, reply_to="no@reply.to") - def execute(self, cr, uid, ids, context=None): + 'Do nothing on execution, just launch the next action/todo' + pass + def action_add(self, cr, uid, ids, context=None): + 'Create a user, and re-display the view' self.create_user(cr, uid, ids[0], context=context) return { 'view_type': 'form',