[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
This commit is contained in:
Xavier Morel 2010-01-26 17:42:37 +01:00
parent 16c8091429
commit 392631cc32
3 changed files with 96 additions and 10 deletions

View File

@ -230,16 +230,31 @@
<field colspan="4" nolabel="1" name="groups_id"/>
</group>
<xpath expr='//button[@name="action_skip"]'
position='attributes'>
<attribute name='string'>Done</attribute>
<attribute name='icon'>gtk-go-forward</attribute>
</xpath>
<xpath expr='//button[@name="action_next"]'
position='attributes'>
<attribute name="name">action_add</attribute>
<attribute name='string'>Add User</attribute>
<attribute name='icon'>gtk-add</attribute>
</xpath>
<xpath expr='//button[@name="action_skip"]'
position='attributes'>
<!-- if this one is performed first, it transforms
the action_skip into action_next, and the
transformation of action_next to action_add,
since it uses first-match, transforms the same
button. And we end up with [add] [next] instead
of [next] [add]
Would probably be simpler to just replace both
by nothing and create a pair of brand new
buttons... but we'd have to handle the groups
around the buttons... oh well...
-->
<attribute name="name">action_next</attribute>
<attribute name='string'>Done</attribute>
<attribute name='icon'>gtk-go-forward</attribute>
</xpath>
</data>
</field>
</record>

View File

@ -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)

View File

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