Allow to edit One2Many on editable list with list view

This commit is contained in:
Cédric Krier committed 2008-03-31 12:50:16 +02:00
1 parent 1e9be5bf49
commit f209ec4d30
4 files changed
+217 -117

No files matched your search

@@ -74,6 +74,7 @@ class Screen(SignalEvent):
self.fields_view_tree = None
self.exclude_field = exclude_field
self.sort = sort
self.view_to_load = []
if view_type:
self.view_to_load = view_type[1:]
@@ -3,9 +3,107 @@ import gettext
from tryton.common import TRYTON_ICON
from interface import WidgetInterface
from tryton.gui.window.view_form.screen import Screen
from tryton.gui.window.view_form.model.group import ModelRecordGroup
_ = gettext.gettext
def _create_menu(self):
hbox = gtk.HBox(homogeneous=False, spacing=5)
menubar = gtk.MenuBar()
if hasattr(menubar, 'set_pack_direction') and \
hasattr(menubar, 'set_child_pack_direction'):
menubar.set_pack_direction(gtk.PACK_DIRECTION_LTR)
menubar.set_child_pack_direction(gtk.PACK_DIRECTION_LTR)
menuitem_title = gtk.ImageMenuItem(stock_id='gtk-preferences')
menu_title = gtk.Menu()
menuitem_set_to_default = gtk.MenuItem(_('Set to default value'), True)
menuitem_set_to_default.connect('activate',
lambda *x: self._menu_sig_default_get())
menu_title.add(menuitem_set_to_default)
menuitem_set_default = gtk.MenuItem(_('Set Default'), True)
menuitem_set_default.connect('activate',
lambda *x: self._menu_sig_default_set())
menu_title.add(menuitem_set_default)
menuitem_title.set_submenu(menu_title)
menubar.add(menuitem_title)
hbox.pack_start(menubar, expand=True, fill=True)
tooltips = gtk.Tooltips()
self.eb_new = gtk.EventBox()
tooltips.set_tip(self.eb_new, _('Create a new entry'))
self.eb_new.set_events(gtk.gdk.BUTTON_PRESS)
self.eb_new.connect('button_press_event', self._sig_new)
img_new = gtk.Image()
img_new.set_from_stock('gtk-new', gtk.ICON_SIZE_MENU)
img_new.set_alignment(0.5, 0.5)
self.eb_new.add(img_new)
hbox.pack_start(self.eb_new, expand=False, fill=False)
self.eb_open = gtk.EventBox()
tooltips.set_tip(self.eb_open, _('Edit this entry'))
self.eb_open.set_events(gtk.gdk.BUTTON_PRESS)
self.eb_open.connect('button_press_event', self._sig_edit)
img_open = gtk.Image()
img_open.set_from_stock('gtk-open', gtk.ICON_SIZE_MENU)
img_open.set_alignment(0.5, 0.5)
self.eb_open.add(img_open)
hbox.pack_start(self.eb_open, expand=False, fill=False)
self.eb_del = gtk.EventBox()
tooltips.set_tip(self.eb_del, _('Remove this entry'))
self.eb_del.set_events(gtk.gdk.BUTTON_PRESS)
self.eb_del.connect('button_press_event', self._sig_remove)
img_del = gtk.Image()
img_del.set_from_stock('gtk-delete', gtk.ICON_SIZE_MENU)
img_del.set_alignment(0.5, 0.5)
self.eb_del.add(img_del)
hbox.pack_start(self.eb_del, expand=False, fill=False)
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
eb_pre = gtk.EventBox()
tooltips.set_tip(eb_pre, _('Previous'))
eb_pre.set_events(gtk.gdk.BUTTON_PRESS)
eb_pre.connect('button_press_event', self._sig_previous)
img_pre = gtk.Image()
img_pre.set_from_stock('gtk-go-back', gtk.ICON_SIZE_MENU)
img_pre.set_alignment(0.5, 0.5)
eb_pre.add(img_pre)
hbox.pack_start(eb_pre, expand=False, fill=False)
self.label = gtk.Label('(0,0)')
hbox.pack_start(self.label, expand=False, fill=False)
eb_next = gtk.EventBox()
tooltips.set_tip(eb_next, _('Next'))
eb_next.set_events(gtk.gdk.BUTTON_PRESS)
eb_next.connect('button_press_event', self._sig_next)
img_next = gtk.Image()
img_next.set_from_stock('gtk-go-forward', gtk.ICON_SIZE_MENU)
img_next.set_alignment(0.5, 0.5)
eb_next.add(img_next)
hbox.pack_start(eb_next, expand=False, fill=False)
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
eb_switch = gtk.EventBox()
tooltips.set_tip(eb_switch, _('Switch'))
eb_switch.set_events(gtk.gdk.BUTTON_PRESS)
eb_switch.connect('button_press_event', self.switch_view)
img_switch = gtk.Image()
img_switch.set_from_stock('gtk-justify-left', gtk.ICON_SIZE_MENU)
img_switch.set_alignment(0.5, 0.5)
eb_switch.add(img_switch)
hbox.pack_start(eb_switch, expand=False, fill=False)
tooltips.enable()
return hbox, menuitem_title
class Dialog(object):
@@ -19,6 +117,12 @@ class Dialog(object):
if default_get_ctx is None:
default_get_ctx = {}
self.attrs = attrs
self.model_name = model_name
self.parent=parent
self.model_ctx = model_ctx
self.default_get_ctx = default_get_ctx
self.dia = gtk.Dialog(_('Tryton - Link'), window,
gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
self.window = window
@@ -44,6 +148,11 @@ class Dialog(object):
self.default_get_ctx = default_get_ctx
menuitem_title = None
if isinstance(model, ModelRecordGroup):
hbox, menuitem_title = _create_menu(self)
self.dia.vbox.pack_start(hbox, expand=False, fill=True)
scroll = gtk.ScrolledWindow()
scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
scroll.set_placement(gtk.CORNER_TOP_LEFT)
@@ -60,25 +169,36 @@ class Dialog(object):
self.screen.models._context.update(model_ctx)
if not model:
model = self.screen.new(context=default_get_ctx)
self.screen.models.model_add(model)
self.screen.current_model = model
if ('views' in attrs) and ('form' in attrs['views']):
arch = attrs['views']['form']['arch']
fields = attrs['views']['form']['fields']
if attrs.get('relation_field', False) \
and attrs['relation_field'] in fields:
del fields[attrs['relation_field']]
self.screen.add_view(arch, fields, display=True,
if isinstance(model, ModelRecordGroup):
self.screen.models_set(model)
self.screen.add_view_id(False, 'tree', display=True,
context=default_get_ctx)
self.screen.add_view_id(False, 'form', display=False,
context=default_get_ctx)
self.screen.signal_connect(self, 'record-message', self._sig_label)
self.screen.widget.connect('key_press_event', self.on_keypress)
else:
self.screen.add_view_id(False, 'form', display=True,
context=default_get_ctx)
self.screen.models.model_add(model)
self.screen.current_model = model
if ('views' in attrs) and ('form' in attrs['views']):
arch = attrs['views']['form']['arch']
fields = attrs['views']['form']['fields']
if attrs.get('relation_field', False) \
and attrs['relation_field'] in fields:
del fields[attrs['relation_field']]
self.screen.add_view(arch, fields, display=True,
context=default_get_ctx)
else:
self.screen.add_view_id(False, 'form', display=True,
context=default_get_ctx)
name = attrs.get('string', '')
if name:
name += ' - '
name += self.screen.current_view.title
self.dia.set_title(self.dia.get_title() + ' - ' + name)
if menuitem_title:
menuitem_title.get_child().set_text(name)
viewport.add(self.screen.widget)
width, height = self.screen.screen_container.size_get()
@@ -86,6 +206,79 @@ class Dialog(object):
self.dia.show_all()
self.screen.display()
def on_keypress(self, widget, event):
if (event.keyval in (gtk.keysyms.N, gtk.keysyms.n) \
and event.state & gtk.gdk.CONTROL_MASK) \
or event.keyval == gtk.keysyms.F1:
self._sig_new(widget, event)
return False
if event.keyval == gtk.keysyms.F2:
self._sig_edit(widget, event)
return False
if (event.keyval in (gtk.keysyms.L, gtk.keysyms.l) \
and event.state & gtk.gdk.CONTROL_MASK):
self.switch_view(widget, event)
return False
def switch_view(self, btn, arg):
self.screen.switch_view()
def _sig_new(self, widget, event):
if event.type in (gtk.gdk.BUTTON_PRESS, gtk.gdk.KEY_PRESS):
if (self.screen.current_view.view_type == 'form') \
or self.screen.editable_get():
self.screen.new(context=self.default_get_ctx)
self.screen.current_view.widget.set_sensitive(True)
else:
dia = Dialog(self.model_name, parent=self.parent,
attrs=self.attrs, model_ctx=self.model_ctx,
default_get_ctx=self.default_get_ctx,
window=self.window)
res = True
while res:
res, value = dia.run()
if res:
self.screen.models.model_add(value)
value.signal('record-changed', value.parent)
self.screen.display()
dia.new()
dia.destroy()
def _sig_edit(self, widget=None, event=None):
if self.screen.current_model:
dia = Dialog(self.model_name, parent=self.parent,
model=self.screen.current_model, attrs=self.attrs,
window=self.window)
res, value = dia.run()
dia.destroy()
def _sig_next(self, widget, event):
if event.type == gtk.gdk.BUTTON_PRESS:
self.screen.display_next()
def _sig_previous(self, widget, event):
if event.type == gtk.gdk.BUTTON_PRESS:
self.screen.display_prev()
def _sig_remove(self, widget, event):
if event.type == gtk.gdk.BUTTON_PRESS:
self.screen.remove()
if not self.screen.models.models:
self.screen.current_view.widget.set_sensitive(False)
def _sig_label(self, screen, signal_data):
name = '_'
if signal_data[0] >= 0:
name = str(signal_data[0] + 1)
line = '(%s/%s)' % (name, signal_data[1])
self.label.set_text(line)
def _menu_sig_default_get(self):
pass
def _menu_sig_default_set(self):
pass
def new(self):
model = self.screen.new(context=self.default_get_ctx)
self.screen.models.model_add(model)
@@ -97,7 +290,8 @@ class Dialog(object):
while not end:
res = self.dia.run()
end = (res != gtk.RESPONSE_OK) \
or self.screen.current_model.validate()
or (not self.screen.current_model \
or self.screen.current_model.validate())
if not end:
self.screen.display()
self.but_cancel.set_label(gtk.STOCK_CLOSE)
@@ -122,99 +316,8 @@ class One2Many(WidgetInterface):
self.widget = gtk.VBox(homogeneous=False, spacing=5)
hbox = gtk.HBox(homogeneous=False, spacing=5)
menubar = gtk.MenuBar()
if hasattr(menubar, 'set_pack_direction') and \
hasattr(menubar, 'set_child_pack_direction'):
menubar.set_pack_direction(gtk.PACK_DIRECTION_LTR)
menubar.set_child_pack_direction(gtk.PACK_DIRECTION_LTR)
hbox, menuitem_title = _create_menu(self)
menuitem_title = gtk.ImageMenuItem(stock_id='gtk-preferences')
menu_title = gtk.Menu()
menuitem_set_to_default = gtk.MenuItem(_('Set to default value'), True)
menuitem_set_to_default.connect('activate',
lambda *x: self._menu_sig_default_get())
menu_title.add(menuitem_set_to_default)
menuitem_set_default = gtk.MenuItem(_('Set Default'), True)
menuitem_set_default.connect('activate',
lambda *x: self._menu_sig_default_set())
menu_title.add(menuitem_set_default)
menuitem_title.set_submenu(menu_title)
menubar.add(menuitem_title)
hbox.pack_start(menubar, expand=True, fill=True)
tooltips = gtk.Tooltips()
self.eb_new = gtk.EventBox()
tooltips.set_tip(self.eb_new, _('Create a new entry'))
self.eb_new.set_events(gtk.gdk.BUTTON_PRESS)
self.eb_new.connect('button_press_event', self._sig_new)
img_new = gtk.Image()
img_new.set_from_stock('gtk-new', gtk.ICON_SIZE_MENU)
img_new.set_alignment(0.5, 0.5)
self.eb_new.add(img_new)
hbox.pack_start(self.eb_new, expand=False, fill=False)
self.eb_open = gtk.EventBox()
tooltips.set_tip(self.eb_open, _('Edit this entry'))
self.eb_open.set_events(gtk.gdk.BUTTON_PRESS)
self.eb_open.connect('button_press_event', self._sig_edit)
img_open = gtk.Image()
img_open.set_from_stock('gtk-open', gtk.ICON_SIZE_MENU)
img_open.set_alignment(0.5, 0.5)
self.eb_open.add(img_open)
hbox.pack_start(self.eb_open, expand=False, fill=False)
self.eb_del = gtk.EventBox()
tooltips.set_tip(self.eb_del, _('Remove this entry'))
self.eb_del.set_events(gtk.gdk.BUTTON_PRESS)
self.eb_del.connect('button_press_event', self._sig_remove)
img_del = gtk.Image()
img_del.set_from_stock('gtk-delete', gtk.ICON_SIZE_MENU)
img_del.set_alignment(0.5, 0.5)
self.eb_del.add(img_del)
hbox.pack_start(self.eb_del, expand=False, fill=False)
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
eb_pre = gtk.EventBox()
tooltips.set_tip(eb_pre, _('Previous'))
eb_pre.set_events(gtk.gdk.BUTTON_PRESS)
eb_pre.connect('button_press_event', self._sig_previous)
img_pre = gtk.Image()
img_pre.set_from_stock('gtk-go-back', gtk.ICON_SIZE_MENU)
img_pre.set_alignment(0.5, 0.5)
eb_pre.add(img_pre)
hbox.pack_start(eb_pre, expand=False, fill=False)
self.label = gtk.Label('(0,0)')
hbox.pack_start(self.label, expand=False, fill=False)
eb_next = gtk.EventBox()
tooltips.set_tip(eb_next, _('Next'))
eb_next.set_events(gtk.gdk.BUTTON_PRESS)
eb_next.connect('button_press_event', self._sig_next)
img_next = gtk.Image()
img_next.set_from_stock('gtk-go-forward', gtk.ICON_SIZE_MENU)
img_next.set_alignment(0.5, 0.5)
eb_next.add(img_next)
hbox.pack_start(eb_next, expand=False, fill=False)
hbox.pack_start(gtk.VSeparator(), expand=False, fill=True)
eb_switch = gtk.EventBox()
tooltips.set_tip(eb_switch, _('Switch'))
eb_switch.set_events(gtk.gdk.BUTTON_PRESS)
eb_switch.connect('button_press_event', self.switch_view)
img_switch = gtk.Image()
img_switch.set_from_stock('gtk-justify-left', gtk.ICON_SIZE_MENU)
img_switch.set_alignment(0.5, 0.5)
eb_switch.add(img_switch)
hbox.pack_start(eb_switch, expand=False, fill=False)
tooltips.enable()
self.widget.pack_start(hbox, expand=False, fill=True)
self.screen = Screen(attrs['relation'], self._window,
@@ -81,7 +81,7 @@ class EditableTreeView(gtk.TreeView):
self.screen.form.message_state(_('Relation Field: F1: New F2: Open/Search'))
elif focus_column and (focus_column._type in ('one2many')) \
and self.screen.form:
self.screen.form.message_state(_('Relation Field: F1: New'))
self.screen.form.message_state(_('Relation Field: F2: Open'))
elif focus_column and (focus_column._type in ('boolean')):
start_editing = False
elif self.screen.form:
@@ -10,11 +10,13 @@ import time
from tryton.gui.window.view_form.view.form_gtk.many2one import Dialog \
as M2ODialog
from tryton.gui.window.view_form.view.form_gtk.one2many import Dialog \
as O2MDialog
from tryton.gui.window.win_search import WinSearch
import tryton.rpc as rpc
import datetime as DT
from tryton.common import DT_FORMAT, DHM_FORMAT, COLORS, node_attributes
from tryton.common import DT_FORMAT, DHM_FORMAT, COLORS, node_attributes, TRYTON_ICON
if not hasattr(locale, 'nl_langinfo'):
locale.nl_langinfo = lambda *a: '%x'
@@ -458,21 +460,15 @@ class O2M(Char):
pass
def open_remote(self, model, create=True, changed=False, text=None):
if not create:
raise NotImplementedError
models = model.value[self.field_name]
modelfield = model.mgroup.mfields[self.field_name]
relation = modelfield.attrs['relation']
context = modelfield.context_get(model)
dia = O2MDialog(relation, parent=model, attrs=modelfield.attrs,
default_get_ctx=context, window=self.window)
res = True
while res:
res, value = dia.run()
if res:
model.value[self.field_name].model_add(value)
value.signal('record-changed', value.parent)
dia.new()
dia = O2MDialog(relation, parent=model, model=models,
attrs=modelfield.attrs, default_get_ctx=context,
window=self.window)
res, value = dia.run()
dia.destroy()
return False, False