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',