示例#1
0
class one2many_list(interface.widget_interface):
    def __init__(self, window, parent, model, attrs={}):
        interface.widget_interface.__init__(self, window, parent, model, attrs)
        self.context = {}
        #TODO:
            # group by context are evaled here as we need the context in screen
            # while displaying.
            # We need a better way to eval context that has group_by'
            # We needed to do this as normal context also get evaled here
            # and results in a traceback which should not be evaled here.
        if str(attrs.get('context',"{}")).find('group_by') != -1:
            self.context = tools.expr_eval(attrs.get('context',"{}"))
        self._readonly = self.default_readonly
        self.widget = gtk.VBox(homogeneous=False, spacing=5)
        hb = 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)
        hb.pack_start(menubar, expand=True, fill=True)

        if self.context.get('group_by'):
            self.context['group_by'] = [self.context['group_by']]

        # the context to pass to default_get can be optionally specified in
        # the context of the one2many field. We also support a legacy
        # 'default_get' attribute for the same effect (pending removal)
        default_get_ctx = (attrs.get('default_get') or attrs.get('context'))

        self.screen = Screen(attrs['relation'],
                            view_type=attrs.get('mode','tree,form').split(','),
                            parent=self.parent, views_preload=attrs.get('views', {}),
                            tree_saves=attrs.get('saves', False),
                            create_new=True,
                            context=self.context,
                            row_activate=self._on_activate,
                            default_get=default_get_ctx,
                            window=self._window, readonly=self._readonly, limit=pager.DEFAULT_LIMIT)

        self.screen.type = 'one2many'

        self.pager = pager(object=self, relation=attrs['relation'], screen=self.screen)

        # Button New
        self.eb_new = self.pager.create_event_box(_('Create a new entry'), self._sig_new, 'gtk-new')
        hb.pack_start(self.eb_new, expand=False, fill=False)

        # Button Edit
        self.eb_open = self.pager.create_event_box(_('Edit this entry'), self._sig_edit, 'gtk-open')
        hb.pack_start(self.eb_open, expand=False, fill=False)

        # Button Delete
        self.eb_del = self.pager.create_event_box(_('Remove this entry'), self._sig_remove, 'gtk-delete')
        hb.pack_start(self.eb_del, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

      # Button Previous Page
        self.eb_prev_page = self.pager.create_event_box(_('Previous Page'), self._sig_prev_page, 'gtk-goto-first')
        hb.pack_start(self.eb_prev_page, expand=False, fill=False)

        # Button Previous Record
        self.eb_pre = self.pager.create_event_box(_('Previous Record'), self._sig_previous, 'gtk-go-back')
        hb.pack_start(self.eb_pre, expand=False, fill=False)

        # Record display
        self.label = gtk.Label('(0,0)')
        hb.pack_start(self.label, expand=False, fill=False)

        # Button Next
        self.eb_next = self.pager.create_event_box(_('Next Record'), self._sig_next, 'gtk-go-forward')
        hb.pack_start(self.eb_next, expand=False, fill=False)

        # Button Next Page
        self.eb_next_page = self.pager.create_event_box(_('Next Page'), self._sig_next_page, 'gtk-goto-last')
        hb.pack_start(self.eb_next_page, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

        # Button Switch
        self.eb_switch = self.pager.create_event_box(_('Switch'), self.switch_view, 'gtk-justify-left')
        hb.pack_start(self.eb_switch, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

          # Limit Combo
        self.cb = self.pager.create_combo_box(_('Choose Limit'), self.limit_changed)
        hb.pack_start(self.cb, expand=False, fill=False)

        self.widget.pack_start(hb, expand=False, fill=True)
        self.screen.signal_connect(self, 'record-message', self._sig_label)
        menuitem_title.get_child().set_markup('<b>'+self.screen.current_view.title.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')+'</b>')
        self.widget.pack_start(self.screen.widget, expand=True, fill=True)
        self.screen.widget.connect('key_press_event', self.on_keypress)
        self.model = None
        self.model_field = None
        self.name = attrs['name']

    def on_keypress(self, widget, event):
        if (not self._readonly) and ((event.keyval in (gtk.keysyms.N, gtk.keysyms.n) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK)):
            self._sig_new(widget, event)
            return False
        if event.keyval in (gtk.keysyms.E, gtk.keysyms.e) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK:
            self._sig_edit(widget, event)
            return False
        if event.keyval in (gtk.keysyms.L, gtk.keysyms.l) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK:
            self.switch_view(widget, event)
            return False

    def destroy(self):
        self.screen.destroy()

    def _on_activate(self, screen, *args):
        self._sig_edit()

    def click_and_action(self, type):
        pos = self.tree_view.pos_get()
        if pos!=None:
            val = self._value[pos]
            id = val.get('id', False)
            obj = service.LocalService('action.main')
            res = obj.exec_keyword(type, {'model':self.model, 'id': id or False, 'ids':[id], 'report_type': 'pdf'})
            return True
        else:
            common.message(_('You have to select a resource !'))
            return False

    def switch_view(self, btn, arg):
        self.screen.make_buttons_readonly(True)
        self.screen.switch_view()

    def _readonly_set(self, value):
        self._readonly = value
        self.eb_new.set_sensitive(not value)
        self.eb_del.set_sensitive(not value)
        self.screen.readonly = value
        self.screen.display()

    def set_disable(self, value):
        self.eb_open.set_sensitive(value)
        self.eb_switch.set_sensitive(value)
        if self._readonly:
            value = not self._readonly
        self.eb_del.set_sensitive(value)

    def _sig_new(self, *args):
        _, event = args
        ctx = dict(self._view.model.expr_eval(self.screen.default_get), **self.context)
        ctx.update(self._view.model.expr_eval('dict(%s)' % self.attrs.get('context', '{}')))
        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=ctx)
                self.screen.make_buttons_readonly()
                self._readonly = False
                self.screen.current_view.widget.set_sensitive(True)
                self.set_disable(True)
            else:
                ok = True
                dia = dialog(self.attrs['relation'], parent=self._view.model, attrs=self.attrs, model_ctx=self.screen.models._context, window=self._window, readonly=self._readonly, context=ctx)
                while ok:
                    ok, value, res = dia.run()
                    if ok or res == gtk.RESPONSE_APPLY:
                        self.screen.models.model_add(value)
                        value.signal('record-changed', value.parent)
                        self.screen.display()
                        dia.new()
                        self.set_disable(True)
                self.pager.reset_pager()
                dia.destroy()

    def _sig_edit(self, *args):
        ctx = dict(self._view.model.expr_eval(self.screen.default_get), **self.context)
        ctx.update(self._view.model.expr_eval('dict(%s)' % self.attrs.get('context', '{}')))
        if self.screen.current_model:
            ok = True
            edited_model = self.screen.current_model
            dia = dialog(self.attrs['relation'], parent=self._view.model,  model=self.screen.current_model, attrs=self.attrs, window=self._window, readonly=self._readonly, context=ctx)
            while ok:
                ok, value, res = dia.run()
                if res == gtk.RESPONSE_OK:
                    dia.new()
                if value and value != edited_model:
                    self.screen.models.model_add(value)
                    value.signal('record-changed', value.parent)
                    self.screen.display()
            self.pager.reset_pager()
            edited_model.modified = True
            dia.destroy()

    def limit_changed(self,*args):
        self.pager.limit_changed()

    def _sig_prev_page(self, *args):
        self.pager.prev_page()

    def _sig_next_page(self, *args):
        self.pager.next_page()

    def _sig_next(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.pager.next_record()

    def _sig_previous(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.pager.prev_record()

    def _sig_remove(self, *args):
        lst, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            if self.screen.current_view.view_type == 'form':
                msg = _('Are you sure to remove this record ?')
            else:
                msg = _('Are you sure to remove those records ?')
            if common.sur(msg):
                    model = self.screen.current_model
                    model.signal('record-changed', model.parent)
                    self.screen.remove()
                    self.pager.reset_pager()
                    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 of %s)' % (name, signal_data[1], signal_data[2])
        self.label.set_text(line)

    def _sig_refresh(self, *args):
        pass

    def _sig_sequence(self, *args):
        pass

    def display(self, model, model_field):
        self.model = model
        self.model_field = model_field
        if not model_field:
            self.screen.current_model = None
            self.screen.display()
            return False
        super(one2many_list, self).display(model, model_field)
        new_models = model_field.get_client(model)
        if self.screen.models != new_models:
            self.screen.models_set(new_models)
            if (self.screen.current_view.view_type=='tree') and self.screen.editable_get():
                if len(self.screen.models.models):
                    self.screen.current_model = self.screen.models.models[0]
                else:
                    self.screen.current_model = None
            if self.screen.current_view.view_type=='form':
                self.screen.make_buttons_readonly(self.screen.current_model \
                                            and self.screen.current_model.id and True or False)
        self.set_disable(self.screen.models.models and True or False)
        self.pager.search_count()
        self.pager.set_sensitivity()
        self.screen.display()
        return True

    def set_value(self, model, model_field):
        self.screen.current_view.set_value()
        if self.screen.is_modified():
            model.modified = True
            model.modified_fields.setdefault(model_field.name)
        return True

    def grab_focus(self):
        return self.screen.widget.grab_focus()
示例#2
0
class one2many_list(interface.widget_interface):
    def __init__(self, window, parent, model, attrs={}):
        interface.widget_interface.__init__(self, window, parent, model, attrs)
        self.context = {}
        self._readonly = self.default_readonly
        self.widget = gtk.VBox(homogeneous=False, spacing=5)
        hb = gtk.HBox(homogeneous=False, spacing=5)

        event_box = gtk.EventBox()
        event_box.set_events(gtk.gdk.BUTTON_PRESS_MASK)
        hb.pack_start(event_box, expand=True, fill=True)

        # the context to pass to default_get can be optionally specified in
        # the context of the one2many field. We also support a legacy
        # 'default_get' attribute for the same effect (pending removal)
        default_get_ctx = (attrs.get('default_get') or attrs.get('context'))

        self.context = tools.expr_eval(attrs.get('context',"{}"), {"__builtins__":None, "parent": parent})
        self.screen = Screen(attrs['relation'],
                            view_type=attrs.get('mode','tree,form').split(','),
                            parent=self.parent, views_preload=attrs.get('views', {}),
                            tree_saves=attrs.get('saves', False),
                            create_new=True,
                            context=self.context,
                            row_activate=self._on_activate,
                            default_get=default_get_ctx,
                            window=self._window, readonly=self._readonly, limit=pager.DEFAULT_LIMIT)

        self.screen.type = 'one2many'

        self.pager = pager(object=self, relation=attrs['relation'], screen=self.screen)

        # Button New
        self.eb_new = self.pager.create_event_box(_('Create a new entry'), self._sig_new, 'gtk-new')
        hb.pack_start(self.eb_new, expand=False, fill=False)

        # Button Edit
        self.eb_open = self.pager.create_event_box(_('Edit this entry'), self._sig_edit, 'gtk-open')
        hb.pack_start(self.eb_open, expand=False, fill=False)

        # Button Delete
        self.eb_del = self.pager.create_event_box(_('Remove this entry'), self._sig_remove, 'gtk-delete')
        hb.pack_start(self.eb_del, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

      # Button Previous Page
        self.eb_prev_page = self.pager.create_event_box(_('Previous Page'), self._sig_prev_page, 'gtk-goto-first')
        hb.pack_start(self.eb_prev_page, expand=False, fill=False)

        # Button Previous Record
        self.eb_pre = self.pager.create_event_box(_('Previous Record'), self._sig_previous, 'gtk-go-back')
        hb.pack_start(self.eb_pre, expand=False, fill=False)

        # Record display
        self.label = gtk.Label('(0,0)')
        hb.pack_start(self.label, expand=False, fill=False)

        # Button Next
        self.eb_next = self.pager.create_event_box(_('Next Record'), self._sig_next, 'gtk-go-forward')
        hb.pack_start(self.eb_next, expand=False, fill=False)

        # Button Next Page
        self.eb_next_page = self.pager.create_event_box(_('Next Page'), self._sig_next_page, 'gtk-goto-last')
        hb.pack_start(self.eb_next_page, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

        # Button Switch
        self.eb_switch = self.pager.create_event_box(_('Switch'), self.switch_view, 'gtk-justify-left')
        hb.pack_start(self.eb_switch, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

          # Limit Combo
        self.cb = self.pager.create_combo_box(_('Choose Limit'), self.limit_changed)
        hb.pack_start(self.cb, expand=False, fill=False)

        self.widget.pack_start(hb, expand=False, fill=True)
        self.screen.signal_connect(self, 'record-message', self._sig_label)
        menu_title = gtk.Label('<b>'+self.screen.current_view.title.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')+'</b>')
        menu_title.set_use_markup(True)
        menu_title.set_alignment(0, 0)
        event_box.add(menu_title)
        event_box.connect('button_press_event',self.load_menu)
        self.screen.widget.set_property('height-request', 100)


        self.widget.pack_start(self.screen.widget, expand=True, fill=True)
        self.screen.widget.connect('key_press_event', self.on_keypress)
        self.model = None
        self.model_field = None
        self.name = attrs['name']

    def load_menu(self, widget, event):
        if event.button != 3:
            return
        menu = 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.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.add(menuitem_set_default)
        menu.show_all()
        menu.popup(None,None,None,event.button,event.time)
        return True

    def on_keypress(self, widget, event):
        if (not self._readonly) and ((event.keyval in (gtk.keysyms.N, gtk.keysyms.n) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK)):
            self._sig_new(widget, event)
            return False
        if event.keyval in (gtk.keysyms.E, gtk.keysyms.e) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK:
            self._sig_edit(widget, event)
            return False
        if event.keyval in (gtk.keysyms.L, gtk.keysyms.l) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK:
            self.switch_view(widget, event)
            return False

    def destroy(self):
        self.screen.destroy()

    def _on_activate(self, screen, *args):
        self._sig_edit()

    def click_and_action(self, type):
        pos = self.tree_view.pos_get()
        if pos!=None:
            val = self._value[pos]
            id = val.get('id', False)
            obj = service.LocalService('action.main')
            res = obj.exec_keyword(type, {'model':self.model, 'id': id or False, 'ids':[id], 'report_type': 'pdf'})
            return True
        else:
            common.message(_('You have to select a resource !'))
            return False

    def switch_view(self, btn, arg):
        self.screen.make_buttons_readonly(True)
        self.screen.switch_view()

    def _readonly_set(self, value):
        self._readonly = value
        self.eb_new.set_sensitive(not value)
        self.eb_del.set_sensitive(not value)
        self.screen.readonly = value
        self.screen.display()

    def set_disable(self, value):
        self.eb_open.set_sensitive(value)
        self.eb_switch.set_sensitive(value)
        if self._readonly:
            value = not self._readonly
        self.eb_del.set_sensitive(value)
        
    ## This method is specially developed to store old values of 
    ## the modified records.
    def _get_old_values(self, models=None):

        group_model = {}
        model_value = {}
        if models is None:
            models = []
        for o2m_model in models:
            values = o2m_model.value.copy()
            model_value[o2m_model] = values.copy()
            group_model[o2m_model] = {}
            for key, val in values.iteritems():
                if isinstance(val, ModelRecordGroup):
                    group_model[o2m_model][key] = val.models[:]
                    del model_value[o2m_model][key]
        return model_value,group_model
    
    ## This method is specially developed to restore old values 
    def _restore_values(self, modified_model_values, group_model):
        for model, value in modified_model_values.iteritems():
            model.set(value, modified=True)
            for f_name, models in group_model.get(model, {}).iteritems():
                model.value[f_name].clear()
                for sub_model in models:
                    # add model in ModelRecordGroup
                    model.value[f_name].model_add(sub_model)
        return True
    
    def _sig_new(self, *args):
        _, event = args
        ctx = dict(self._view.model.expr_eval(self.screen.default_get), **self.context)
        ctx.update(self._view.model.expr_eval('dict(%s)' % self.attrs.get('context', '{}')))
        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=ctx)
                self.screen.make_buttons_readonly()
                self._readonly = False
                self.screen.current_view.widget.set_sensitive(True)
                self.set_disable(True)
            else:
                ok = True
                dia = dialog(self.attrs['relation'], parent=self._view.model, attrs=self.attrs, model_ctx=self.screen.models._context, window=self._window, readonly=self._readonly, context=ctx)
                while ok:
                    ok, value, res = dia.run()
                    if ok or res == gtk.RESPONSE_APPLY:
                        modified_model_values, group_model = self._get_old_values(self.screen.models.models)
                        self.screen.models.model_add(value)
                        value.signal('record-changed', value.parent)
                        self._restore_values(modified_model_values, group_model)
                        self.screen.display()
                        dia.new()
                        self.set_disable(True)
                self.pager.reset_pager()
                dia.destroy()
    
    def _sig_edit(self, *args):
        ctx = dict(self._view.model.expr_eval(self.screen.default_get), **self.context)
        ctx.update(self._view.model.expr_eval('dict(%s)' % self.attrs.get('context', '{}')))
        ok = True
        modified_model_values, group_model = self._get_old_values(self.screen.models.models)
        dia = dialog(self.attrs['relation'], parent=self._view.model,  model=self.screen.current_model, attrs=self.attrs, window=self._window, readonly=self._readonly, context=ctx)
        while ok:
            ok, value, res = dia.run()
            if not any([ok, value, res]) and dia.screen.is_modified():
                if modified_model_values:
                    self._restore_values(modified_model_values, group_model)
            if res == gtk.RESPONSE_OK:
                dia.new()
            if value and value.id is None:
                modified_model_values, group_model = self._get_old_values(self.screen.models.models)
                if value not in modified_model_values:
                    self.screen.models.model_add(value)
                    value.signal('record-changed', value.parent)
                if modified_model_values:
                    self._restore_values(modified_model_values, group_model)
                self.screen.display()
        self.pager.reset_pager()
        dia.destroy()

    def limit_changed(self,*args):
        self.pager.limit_changed()

    def _sig_prev_page(self, *args):
        self.pager.prev_page()

    def _sig_next_page(self, *args):
        self.pager.next_page()

    def _sig_next(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.pager.next_record()

    def _sig_previous(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.pager.prev_record()

    def _sig_remove(self, *args):
        lst, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            if self.screen.current_view.view_type == 'form':
                msg = _('Are you sure to remove this record ?')
            else:
                msg = _('Are you sure to remove those records ?')
            if common.sur(msg):
                model = self.screen.current_model
                model.signal('record-changed', model.parent)
                self.screen.remove()
                self.pager.reset_pager()
                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 of %s)' % (name, signal_data[1], signal_data[2])
        self.label.set_text(line)

    def _sig_refresh(self, *args):
        pass

    def _sig_sequence(self, *args):
        pass

    def display(self, model, model_field):
        if model:
            self.context.update(model.expr_eval(self.attrs.get('context',"{}")))
            self.screen.context.update(self.context)

        self.model = model
        self.model_field = model_field
        if not model_field:
            self.screen.current_model = None
            self.screen.display()
            return False
        super(one2many_list, self).display(model, model_field)
        new_models = model_field.get_client(model)
        if self.screen.models != new_models:
            self.screen.models_set(new_models)
            if (self.screen.current_view.view_type=='tree') and self.screen.editable_get():
                if len(self.screen.models.models):
                    self.screen.current_model = self.screen.models.models[0]
                else:
                    self.screen.current_model = None
            if self.screen.current_view.view_type=='form':
                self.screen.make_buttons_readonly(self.screen.current_model \
                                            and self.screen.current_model.id and True or False)
        self.set_disable(self.screen.models.models and True or False)
        self.pager.search_count()
        self.pager.set_sensitivity()
        self.screen.display()
        return True

    def set_value(self, model, model_field):
        self.screen.current_view.set_value()
        if self.screen.is_modified():
            model.modified = True
            model.modified_fields.setdefault(model_field.name)
        return True

    def grab_focus(self):
        return self.screen.widget.grab_focus()
class one2many_list(interface.widget_interface):
    def __init__(self, window, parent, model, attrs={}):
        interface.widget_interface.__init__(self, window, parent, model, attrs)
        self.context = {}
        #TODO:
        # group by context are evaled here as we need the context in screen
        # while displaying.
        # We need a better way to eval context that has group_by'
        # We needed to do this as normal context also get evaled here
        # and results in a traceback which should not be evaled here.
        if str(attrs.get('context', "{}")).find('group_by') != -1:
            self.context = tools.expr_eval(attrs.get('context', "{}"))
        self._readonly = self.default_readonly
        self.widget = gtk.VBox(homogeneous=False, spacing=5)
        hb = 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)
        hb.pack_start(menubar, expand=True, fill=True)

        if self.context.get('group_by'):
            self.context['group_by'] = [self.context['group_by']]

        # the context to pass to default_get can be optionally specified in
        # the context of the one2many field. We also support a legacy
        # 'default_get' attribute for the same effect (pending removal)
        default_get_ctx = (attrs.get('default_get') or attrs.get('context'))

        self.screen = Screen(attrs['relation'],
                             view_type=attrs.get('mode',
                                                 'tree,form').split(','),
                             parent=self.parent,
                             views_preload=attrs.get('views', {}),
                             tree_saves=attrs.get('saves', False),
                             create_new=True,
                             context=self.context,
                             row_activate=self._on_activate,
                             default_get=default_get_ctx,
                             window=self._window,
                             readonly=self._readonly,
                             limit=pager.DEFAULT_LIMIT)

        self.screen.type = 'one2many'

        self.pager = pager(object=self,
                           relation=attrs['relation'],
                           screen=self.screen)

        # Button New
        self.eb_new = self.pager.create_event_box(_('Create a new entry'),
                                                  self._sig_new, 'gtk-new')
        hb.pack_start(self.eb_new, expand=False, fill=False)

        # Button Edit
        self.eb_open = self.pager.create_event_box(_('Edit this entry'),
                                                   self._sig_edit, 'gtk-open')
        hb.pack_start(self.eb_open, expand=False, fill=False)

        # Button Delete
        self.eb_del = self.pager.create_event_box(_('Remove this entry'),
                                                  self._sig_remove,
                                                  'gtk-delete')
        hb.pack_start(self.eb_del, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

        # Button Previous Page
        self.eb_prev_page = self.pager.create_event_box(
            _('Previous Page'), self._sig_prev_page, 'gtk-goto-first')
        hb.pack_start(self.eb_prev_page, expand=False, fill=False)

        # Button Previous Record
        self.eb_pre = self.pager.create_event_box(_('Previous Record'),
                                                  self._sig_previous,
                                                  'gtk-go-back')
        hb.pack_start(self.eb_pre, expand=False, fill=False)

        # Record display
        self.label = gtk.Label('(0,0)')
        hb.pack_start(self.label, expand=False, fill=False)

        # Button Next
        self.eb_next = self.pager.create_event_box(_('Next Record'),
                                                   self._sig_next,
                                                   'gtk-go-forward')
        hb.pack_start(self.eb_next, expand=False, fill=False)

        # Button Next Page
        self.eb_next_page = self.pager.create_event_box(
            _('Next Page'), self._sig_next_page, 'gtk-goto-last')
        hb.pack_start(self.eb_next_page, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

        # Button Switch
        self.eb_switch = self.pager.create_event_box(_('Switch'),
                                                     self.switch_view,
                                                     'gtk-justify-left')
        hb.pack_start(self.eb_switch, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

        # Limit Combo
        self.cb = self.pager.create_combo_box(_('Choose Limit'),
                                              self.limit_changed)
        hb.pack_start(self.cb, expand=False, fill=False)

        self.widget.pack_start(hb, expand=False, fill=True)
        self.screen.signal_connect(self, 'record-message', self._sig_label)
        menuitem_title.get_child().set_markup(
            '<b>' +
            self.screen.current_view.title.replace('&', '&amp;').replace(
                '<', '&lt;').replace('>', '&gt;') + '</b>')
        self.widget.pack_start(self.screen.widget, expand=True, fill=True)
        self.screen.widget.connect('key_press_event', self.on_keypress)
        self.model = None
        self.model_field = None
        self.name = attrs['name']

    def on_keypress(self, widget, event):
        if (not self._readonly) and ((event.keyval in (gtk.keysyms.N, gtk.keysyms.n) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK)):
            self._sig_new(widget, event)
            return False
        if event.keyval in (gtk.keysyms.E, gtk.keysyms.e) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK:
            self._sig_edit(widget, event)
            return False
        if event.keyval in (gtk.keysyms.L, gtk.keysyms.l) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK:
            self.switch_view(widget, event)
            return False

    def destroy(self):
        self.screen.destroy()

    def _on_activate(self, screen, *args):
        self._sig_edit()

    def click_and_action(self, type):
        pos = self.tree_view.pos_get()
        if pos != None:
            val = self._value[pos]
            id = val.get('id', False)
            obj = service.LocalService('action.main')
            res = obj.exec_keyword(
                type, {
                    'model': self.model,
                    'id': id or False,
                    'ids': [id],
                    'report_type': 'pdf'
                })
            return True
        else:
            common.message(_('You have to select a resource !'))
            return False

    def switch_view(self, btn, arg):
        self.screen.make_buttons_readonly(True)
        self.screen.switch_view()

    def _readonly_set(self, value):
        self._readonly = value
        self.eb_new.set_sensitive(not value)
        self.eb_del.set_sensitive(not value)
        self.screen.readonly = value
        self.screen.display()

    def set_disable(self, value):
        self.eb_open.set_sensitive(value)
        self.eb_switch.set_sensitive(value)
        if self._readonly:
            value = not self._readonly
        self.eb_del.set_sensitive(value)

    def _sig_new(self, *args):
        _, event = args
        ctx = dict(self._view.model.expr_eval(self.screen.default_get),
                   **self.context)
        ctx.update(
            self._view.model.expr_eval('dict(%s)' %
                                       self.attrs.get('context', '{}')))
        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=ctx)
                self.screen.make_buttons_readonly()
                self._readonly = False
                self.screen.current_view.widget.set_sensitive(True)
                self.set_disable(True)
            else:
                ok = True
                dia = dialog(self.attrs['relation'],
                             parent=self._view.model,
                             attrs=self.attrs,
                             model_ctx=self.screen.models._context,
                             window=self._window,
                             readonly=self._readonly,
                             context=ctx)
                while ok:
                    ok, value, res = dia.run()
                    if ok or res == gtk.RESPONSE_APPLY:
                        self.screen.models.model_add(value)
                        value.signal('record-changed', value.parent)
                        self.screen.display()
                        dia.new()
                        self.set_disable(True)
                self.pager.reset_pager()
                dia.destroy()

    def _sig_edit(self, *args):
        ctx = dict(self._view.model.expr_eval(self.screen.default_get),
                   **self.context)
        ctx.update(
            self._view.model.expr_eval('dict(%s)' %
                                       self.attrs.get('context', '{}')))
        if self.screen.current_model:
            ok = True
            edited_model = self.screen.current_model
            dia = dialog(self.attrs['relation'],
                         parent=self._view.model,
                         model=self.screen.current_model,
                         attrs=self.attrs,
                         window=self._window,
                         readonly=self._readonly,
                         context=ctx)
            while ok:
                ok, value, res = dia.run()
                if res == gtk.RESPONSE_OK:
                    dia.new()
                if value and value != edited_model:
                    self.screen.models.model_add(value)
                    value.signal('record-changed', value.parent)
                    self.screen.display()
            self.pager.reset_pager()
            edited_model.modified = True
            dia.destroy()

    def limit_changed(self, *args):
        self.pager.limit_changed()

    def _sig_prev_page(self, *args):
        self.pager.prev_page()

    def _sig_next_page(self, *args):
        self.pager.next_page()

    def _sig_next(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.pager.next_record()

    def _sig_previous(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.pager.prev_record()

    def _sig_remove(self, *args):
        lst, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            if self.screen.current_view.view_type == 'form':
                msg = _('Are you sure to remove this record ?')
            else:
                msg = _('Are you sure to remove those records ?')
            if common.sur(msg):
                model = self.screen.current_model
                model.signal('record-changed', model.parent)
                self.screen.remove()
                self.pager.reset_pager()
                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 of %s)' % (name, signal_data[1], signal_data[2])
        self.label.set_text(line)

    def _sig_refresh(self, *args):
        pass

    def _sig_sequence(self, *args):
        pass

    def display(self, model, model_field):
        self.model = model
        self.model_field = model_field
        if not model_field:
            self.screen.current_model = None
            self.screen.display()
            return False
        super(one2many_list, self).display(model, model_field)
        new_models = model_field.get_client(model)
        if self.screen.models != new_models:
            self.screen.models_set(new_models)
            if (self.screen.current_view.view_type
                    == 'tree') and self.screen.editable_get():
                if len(self.screen.models.models):
                    self.screen.current_model = self.screen.models.models[0]
                else:
                    self.screen.current_model = None
            if self.screen.current_view.view_type == 'form':
                self.screen.make_buttons_readonly(self.screen.current_model \
                                            and self.screen.current_model.id and True or False)
        self.set_disable(self.screen.models.models and True or False)
        self.pager.search_count()
        self.pager.set_sensitivity()
        self.screen.display()
        return True

    def set_value(self, model, model_field):
        self.screen.current_view.set_value()
        if self.screen.is_modified():
            model.modified = True
            model.modified_fields.setdefault(model_field.name)
        return True

    def grab_focus(self):
        return self.screen.widget.grab_focus()
class one2many_list(interface.widget_interface):
    def __init__(self, window, parent, model, attrs={}):
        interface.widget_interface.__init__(self, window, parent, model, attrs)
        self.context = {}
        self._readonly = self.default_readonly
        self.widget = gtk.VBox(homogeneous=False, spacing=5)
        hb = gtk.HBox(homogeneous=False, spacing=5)

        event_box = gtk.EventBox()
        event_box.set_events(gtk.gdk.BUTTON_PRESS_MASK)
        hb.pack_start(event_box, expand=True, fill=True)

        # the context to pass to default_get can be optionally specified in
        # the context of the one2many field. We also support a legacy
        # 'default_get' attribute for the same effect (pending removal)
        default_get_ctx = (attrs.get('default_get') or attrs.get('context'))

        self.context = tools.expr_eval(attrs.get('context',"{}"), {"__builtins__":None, "parent": parent})
        self.screen = Screen(attrs['relation'],
                            view_type=attrs.get('mode','tree,form').split(','),
                            parent=self.parent, views_preload=attrs.get('views', {}),
                            tree_saves=attrs.get('saves', False),
                            create_new=True,
                            context=self.context,
                            row_activate=self._on_activate,
                            default_get=default_get_ctx,
                            window=self._window, readonly=self._readonly, limit=pager.DEFAULT_LIMIT)

        self.screen.type = 'one2many'

        self.pager = pager(object=self, relation=attrs['relation'], screen=self.screen)

        # Button New
        self.eb_new = self.pager.create_event_box(_('Create a new entry'), self._sig_new, 'gtk-new')
        hb.pack_start(self.eb_new, expand=False, fill=False)

        # Button Edit
        self.eb_open = self.pager.create_event_box(_('Edit this entry'), self._sig_edit, 'gtk-open')
        hb.pack_start(self.eb_open, expand=False, fill=False)

        # Button Delete
        self.eb_del = self.pager.create_event_box(_('Remove this entry'), self._sig_remove, 'gtk-delete')
        hb.pack_start(self.eb_del, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

      # Button Previous Page
        self.eb_prev_page = self.pager.create_event_box(_('Previous Page'), self._sig_prev_page, 'gtk-goto-first')
        hb.pack_start(self.eb_prev_page, expand=False, fill=False)

        # Button Previous Record
        self.eb_pre = self.pager.create_event_box(_('Previous Record'), self._sig_previous, 'gtk-go-back')
        hb.pack_start(self.eb_pre, expand=False, fill=False)

        # Record display
        self.label = gtk.Label('(0,0)')
        hb.pack_start(self.label, expand=False, fill=False)

        # Button Next
        self.eb_next = self.pager.create_event_box(_('Next Record'), self._sig_next, 'gtk-go-forward')
        hb.pack_start(self.eb_next, expand=False, fill=False)

        # Button Next Page
        self.eb_next_page = self.pager.create_event_box(_('Next Page'), self._sig_next_page, 'gtk-goto-last')
        hb.pack_start(self.eb_next_page, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

        # Button Switch
        self.eb_switch = self.pager.create_event_box(_('Switch'), self.switch_view, 'gtk-justify-left')
        hb.pack_start(self.eb_switch, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

          # Limit Combo
        self.cb = self.pager.create_combo_box(_('Choose Limit'), self.limit_changed)
        hb.pack_start(self.cb, expand=False, fill=False)

        self.widget.pack_start(hb, expand=False, fill=True)
        self.screen.signal_connect(self, 'record-message', self._sig_label)
        menu_title = gtk.Label('<b>'+self.screen.current_view.title.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')+'</b>')
        menu_title.set_use_markup(True)
        menu_title.set_alignment(0, 0)
        event_box.add(menu_title)
        event_box.connect('button_press_event',self.load_menu)
        self.screen.widget.set_property('height-request', 100)


        self.widget.pack_start(self.screen.widget, expand=True, fill=True)
        self.screen.widget.connect('key_press_event', self.on_keypress)
        self.model = None
        self.model_field = None
        self.name = attrs['name']

    def load_menu(self, widget, event):
        if event.button != 3:
            return
        menu = 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.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.add(menuitem_set_default)
        menu.show_all()
        menu.popup(None,None,None,event.button,event.time)
        return True

    def on_keypress(self, widget, event):
        if (not self._readonly) and ((event.keyval in (gtk.keysyms.N, gtk.keysyms.n) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK)):
            self._sig_new(widget, event)
            return False
        if event.keyval in (gtk.keysyms.E, gtk.keysyms.e) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK:
            self._sig_edit(widget, event)
            return False
        if event.keyval in (gtk.keysyms.L, gtk.keysyms.l) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK:
            self.switch_view(widget, event)
            return False

    def destroy(self):
        self.screen.destroy()

    def _on_activate(self, screen, *args):
        self._sig_edit()

    def click_and_action(self, type):
        pos = self.tree_view.pos_get()
        if pos!=None:
            val = self._value[pos]
            id = val.get('id', False)
            obj = service.LocalService('action.main')
            res = obj.exec_keyword(type, {'model':self.model, 'id': id or False, 'ids':[id], 'report_type': 'pdf'})
            return True
        else:
            common.message(_('You have to select a resource !'))
            return False

    def switch_view(self, btn, arg):
        self.screen.make_buttons_readonly(True)
        self.screen.switch_view()

    def _readonly_set(self, value):
        self._readonly = value
        self.eb_new.set_sensitive(not value)
        self.eb_del.set_sensitive(not value)
        self.screen.readonly = value
        self.screen.display()

    def set_disable(self, value):
        self.eb_open.set_sensitive(value)
        self.eb_switch.set_sensitive(value)
        if self._readonly:
            value = not self._readonly
        self.eb_del.set_sensitive(value)
        
    ## This method is specially developed to store old values of 
    ## the modified records.
    def _get_old_values(self, models=None):

        group_model = {}
        model_value = {}
        if models is None:
            models = []
        for o2m_model in models:
            values = o2m_model.value.copy()
            model_value.setdefault(o2m_model, values)
            group_model.setdefault(o2m_model, {})
            for key, val in values.iteritems():
                if isinstance(val, ModelRecordGroup):
                    group_model[o2m_model][key] = val.models[:]
                    del model_value[o2m_model][key]
        return model_value,group_model
    
    ## This method is specially developed to restore old values 
    def _restore_values(self, modified_model_values, group_model):
        for model, value in modified_model_values.iteritems():
            model.set(value, modified=True)
            for f_name, models in group_model.get(model, {}):
                model.value[f_name].clear()
                for sub_model in models:
                    # add model in ModelRecordGroup
                    model.value[f_name].model_add(sub_model)
        return True
    
    def _sig_new(self, *args):
        _, event = args
        ctx = dict(self._view.model.expr_eval(self.screen.default_get), **self.context)
        ctx.update(self._view.model.expr_eval('dict(%s)' % self.attrs.get('context', '{}')))
        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=ctx)
                self.screen.make_buttons_readonly()
                self._readonly = False
                self.screen.current_view.widget.set_sensitive(True)
                self.set_disable(True)
            else:
                ok = True
                dia = dialog(self.attrs['relation'], parent=self._view.model, attrs=self.attrs, model_ctx=self.screen.models._context, window=self._window, readonly=self._readonly, context=ctx)
                while ok:
                    ok, value, res = dia.run()
                    if ok or res == gtk.RESPONSE_APPLY:
                        modified_model_values, group_model = self._get_old_values(self.screen.models.models)
                        self.screen.models.model_add(value)
                        value.signal('record-changed', value.parent)
                        self._restore_values(modified_model_values, group_model)
                        self.screen.display()
                        dia.new()
                        self.set_disable(True)
                self.pager.reset_pager()
                dia.destroy()
    
    def _sig_edit(self, *args):
        ctx = dict(self._view.model.expr_eval(self.screen.default_get), **self.context)
        ctx.update(self._view.model.expr_eval('dict(%s)' % self.attrs.get('context', '{}')))
        ok = True
        modified_model_values, group_model = self._get_old_values(self.screen.models.models)
        dia = dialog(self.attrs['relation'], parent=self._view.model,  model=self.screen.current_model, attrs=self.attrs, window=self._window, readonly=self._readonly, context=ctx)
        while ok:
            ok, value, res = dia.run()
            if not any([ok, value, res]) and dia.screen.is_modified():
                if modified_model_values:
                    self._restore_values(modified_model_values, group_model)
            if res == gtk.RESPONSE_OK:
                dia.new()
            if value and value.id is None:
                modified_model_values, group_model = self._get_old_values(self.screen.models.models)
                if value not in modified_model_values:
                    self.screen.models.model_add(value)
                    value.signal('record-changed', value.parent)
                if modified_model_values:
                    self._restore_values(modified_model_values, group_model)
                self.screen.display()
        self.pager.reset_pager()
        dia.destroy()

    def limit_changed(self,*args):
        self.pager.limit_changed()

    def _sig_prev_page(self, *args):
        self.pager.prev_page()

    def _sig_next_page(self, *args):
        self.pager.next_page()

    def _sig_next(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.pager.next_record()

    def _sig_previous(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.pager.prev_record()

    def _sig_remove(self, *args):
        lst, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            if self.screen.current_view.view_type == 'form':
                msg = _('Are you sure to remove this record ?')
            else:
                msg = _('Are you sure to remove those records ?')
            if common.sur(msg):
                model = self.screen.current_model
                model.signal('record-changed', model.parent)
                self.screen.remove()
                self.pager.reset_pager()
                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 of %s)' % (name, signal_data[1], signal_data[2])
        self.label.set_text(line)

    def _sig_refresh(self, *args):
        pass

    def _sig_sequence(self, *args):
        pass

    def display(self, model, model_field):
        if model:
            self.context.update(model.expr_eval(self.attrs.get('context',"{}")))
            self.screen.context.update(self.context)

        self.model = model
        self.model_field = model_field
        if not model_field:
            self.screen.current_model = None
            self.screen.display()
            return False
        super(one2many_list, self).display(model, model_field)
        new_models = model_field.get_client(model)
        if self.screen.models != new_models:
            self.screen.models_set(new_models)
            if (self.screen.current_view.view_type=='tree') and self.screen.editable_get():
                if len(self.screen.models.models):
                    self.screen.current_model = self.screen.models.models[0]
                else:
                    self.screen.current_model = None
            if self.screen.current_view.view_type=='form':
                self.screen.make_buttons_readonly(self.screen.current_model \
                                            and self.screen.current_model.id and True or False)
        self.set_disable(self.screen.models.models and True or False)
        self.pager.search_count()
        self.pager.set_sensitivity()
        self.screen.display()
        return True

    def set_value(self, model, model_field):
        self.screen.current_view.set_value()
        if self.screen.is_modified():
            model.modified = True
            model.modified_fields.setdefault(model_field.name)
        return True

    def grab_focus(self):
        return self.screen.widget.grab_focus()
示例#5
0
class one2many_list(interface.widget_interface):
    def __init__(self, window, parent, model, attrs={}):
        interface.widget_interface.__init__(self, window, parent, model, attrs)

        self._readonly = self.default_readonly
        self.widget = gtk.VBox(homogeneous=False, spacing=5)

        hb = 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)
        hb.pack_start(menubar, expand=True, fill=True)

        self.eb_new = gtk.EventBox()
        self.eb_new.set_tooltip_text(_('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)
        hb.pack_start(self.eb_new, expand=False, fill=False)

        self.eb_open = gtk.EventBox()
        self.eb_open.set_tooltip_text(_('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)
        hb.pack_start(self.eb_open, expand=False, fill=False)

        self.eb_del = gtk.EventBox()
        self.eb_del.set_tooltip_text(_('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)
        hb.pack_start(self.eb_del, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

        eb_pre = gtk.EventBox()
        eb_pre.set_tooltip_text(_('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)
        hb.pack_start(eb_pre, expand=False, fill=False)

        self.label = gtk.Label('(0,0)')
        hb.pack_start(self.label, expand=False, fill=False)

        eb_next = gtk.EventBox()
        eb_next.set_tooltip_text(_('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)
        hb.pack_start(eb_next, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

        eb_switch = gtk.EventBox()
        eb_switch.set_tooltip_text(_('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)
        hb.pack_start(eb_switch, expand=False, fill=False)

        self.widget.pack_start(hb, expand=False, fill=True)

        self.screen = Screen(attrs['relation'], view_type=attrs.get('mode','tree,form').split(','), parent=self.parent, views_preload=attrs.get('views', {}), tree_saves=attrs.get('saves', False), create_new=True, row_activate=self._on_activate, default_get=attrs.get('default_get', {}), window=self._window, readonly=self._readonly)
        self.screen.signal_connect(self, 'record-message', self._sig_label)

        menuitem_title.get_child().set_markup('<b>'+self.screen.current_view.title.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')+'</b>')

        self.widget.pack_start(self.screen.widget, expand=True, fill=True)

        self.screen.widget.connect('key_press_event', self.on_keypress)

    def on_keypress(self, widget, event):
        if (not self._readonly) and ((event.keyval in (gtk.keysyms.N, gtk.keysyms.n) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK)):
            self._sig_new(widget, event)
            return False
        if event.keyval in (gtk.keysyms.E, gtk.keysyms.e) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK:
            self._sig_edit(widget, event)
            return False
        if event.keyval in (gtk.keysyms.L, gtk.keysyms.l) and event.state & gtk.gdk.CONTROL_MASK\
            and event.state & gtk.gdk.SHIFT_MASK:
            self.switch_view(widget, event)
            return False

    def destroy(self):
        self.screen.destroy()

    def _on_activate(self, screen, *args):
        self._sig_edit()

    def click_and_action(self, type):
        pos = self.tree_view.pos_get()
        if pos!=None:
            val = self._value[pos]
            id = val.get('id', False)
            obj = service.LocalService('action.main')
            res = obj.exec_keyword(type, {'model':self.model, 'id': id or False, 'ids':[id], 'report_type': 'pdf'})
            return True
        else:
            common.message(_('You have to select a resource !'))
            return False

    def switch_view(self, btn, arg):
        self.screen.switch_view()

    def _readonly_set(self, value):
        self._readonly = value
        self.eb_new.set_sensitive(not value)
        self.eb_del.set_sensitive(not value)
        self.screen.readonly = value
        self.screen.display()

    def _sig_new(self, *args):
        _, event = args
        ctx = self._view.model.expr_eval(self.screen.default_get)
        ctx.update(self._view.model.expr_eval('dict(%s)' % self.attrs.get('context', '')))
        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=ctx)
                self._readonly = False
                self.screen.current_view.widget.set_sensitive(True)
            else:
                ok = 1
                dia = dialog(self.attrs['relation'], parent=self._view.model, attrs=self.attrs, model_ctx=self.screen.models._context, default_get_ctx=ctx, window=self._window, readonly=self._readonly)
                while ok:
                    ok, value = dia.run()
                    if ok:
                        self.screen.models.model_add(value)
                        value.signal('record-changed', value.parent)
                        self.screen.display()
                        dia.new()
                dia.destroy()

    def _sig_edit(self, *args):
        if self.screen.current_model:
            dia = dialog(self.attrs['relation'], parent=self._view.model,  model=self.screen.current_model, attrs=self.attrs, window=self._window, readonly=self._readonly)
            ok, value = dia.run()
            dia.destroy()

    def _sig_next(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.screen.display_next()

    def _sig_previous(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.screen.display_prev()

    def _sig_remove(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            if self.screen.current_view.view_type == 'form':
                msg = 'Are you sure to remove this record ?'
            else:
                msg = 'Are you sure to remove those records ?'
            if common.sur(msg):
                    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 _sig_refresh(self, *args):
        pass

    def _sig_sequence(self, *args):
        pass

    def display(self, model, model_field):
        if not model_field:
            self.screen.current_model = None
            self.screen.display()
            return False
        super(one2many_list, self).display(model, model_field)
        new_models = model_field.get_client(model)
        if self.screen.models != new_models:
            self.screen.models_set(new_models)
            if (self.screen.current_view.view_type=='tree') and self.screen.editable_get():
                self.screen.current_model = None
        self.screen.display()
        return True

    def set_value(self, model, model_field):
        self.screen.current_view.set_value()
        if self.screen.is_modified():
            model.modified = True
            model.modified_fields.setdefault(model_field.name)
        return True
示例#6
0
class one2many_list(interface.widget_interface):
    def __init__(self, window, parent, model, attrs={}, label=None):
        interface.widget_interface.__init__(self, window, parent, model, attrs, label_ebox=label)
        self.context = {}
        self._readonly = self.default_readonly
        self.widget = gtk.VBox(homogeneous=False, spacing=5)
        hb = 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)
        hb.pack_start(menubar, expand=True, fill=True)

        # the context to pass to default_get can be optionally specified in
        # the context of the one2many field. We also support a legacy
        # 'default_get' attribute for the same effect (pending removal)
        default_get_ctx = attrs.get("default_get") or attrs.get("context")

        self.context = tools.expr_eval(attrs.get("context", "{}"), {"__builtins__": None})
        self.screen = Screen(
            attrs["relation"],
            view_type=attrs.get("mode", "tree,form").split(","),
            parent=self.parent,
            views_preload=attrs.get("views", {}),
            tree_saves=attrs.get("saves", False),
            create_new=True,
            row_activate=self._on_activate,
            default_get=default_get_ctx,
            context=self.context,
            window=self._window,
            readonly=self._readonly,
            limit=pager.DEFAULT_LIMIT,
        )

        self.screen.type = "one2many"

        self.pager = pager(object=self, relation=attrs["relation"], screen=self.screen)

        # Button New
        self.eb_new = self.pager.create_event_box(_("Create a new entry"), self._sig_new, "gtk-new")
        hb.pack_start(self.eb_new, expand=False, fill=False)

        # Button Edit
        self.eb_open = self.pager.create_event_box(_("Edit this entry"), self._sig_edit, "gtk-open")
        hb.pack_start(self.eb_open, expand=False, fill=False)

        # Button Delete
        self.eb_del = self.pager.create_event_box(_("Remove this entry"), self._sig_remove, "gtk-delete")
        hb.pack_start(self.eb_del, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

        # Button Previous Page
        self.eb_prev_page = self.pager.create_event_box(_("Previous Page"), self._sig_prev_page, "gtk-goto-first")
        hb.pack_start(self.eb_prev_page, expand=False, fill=False)

        # Button Previous Record
        self.eb_pre = self.pager.create_event_box(_("Previous Record"), self._sig_previous, "gtk-go-back")
        hb.pack_start(self.eb_pre, expand=False, fill=False)

        # Record display
        self.label = gtk.Label("(0,0)")
        hb.pack_start(self.label, expand=False, fill=False)

        # Button Next
        self.eb_next = self.pager.create_event_box(_("Next Record"), self._sig_next, "gtk-go-forward")
        hb.pack_start(self.eb_next, expand=False, fill=False)

        # Button Next Page
        self.eb_next_page = self.pager.create_event_box(_("Next Page"), self._sig_next_page, "gtk-goto-last")
        hb.pack_start(self.eb_next_page, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

        # Button Switch
        self.eb_switch = self.pager.create_event_box(_("Switch"), self.switch_view, "gtk-justify-left")
        hb.pack_start(self.eb_switch, expand=False, fill=False)

        hb.pack_start(gtk.VSeparator(), expand=False, fill=True)

        # Limit Combo
        self.cb = self.pager.create_combo_box(_("Choose Limit"), self.limit_changed)
        hb.pack_start(self.cb, expand=False, fill=False)

        self.widget.pack_start(hb, expand=False, fill=True)
        self.screen.signal_connect(self, "record-message", self._sig_label)
        menuitem_title.get_child().set_markup(
            "<b>"
            + self.screen.current_view.title.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
            + "</b>"
        )
        self.widget.pack_start(self.screen.widget, expand=True, fill=True)
        self.screen.widget.connect("key_press_event", self.on_keypress)
        self.model = None
        self.model_field = None
        self.name = attrs["name"]

    def on_keypress(self, widget, event):
        if (not self._readonly) and (
            (
                event.keyval in (gtk.keysyms.N, gtk.keysyms.n)
                and event.state & gtk.gdk.CONTROL_MASK
                and event.state & gtk.gdk.SHIFT_MASK
            )
        ):
            self._sig_new(widget, event)
            return False
        if (
            event.keyval in (gtk.keysyms.E, gtk.keysyms.e)
            and event.state & gtk.gdk.CONTROL_MASK
            and event.state & gtk.gdk.SHIFT_MASK
        ):
            self._sig_edit(widget, event)
            return False
        if (
            event.keyval in (gtk.keysyms.L, gtk.keysyms.l)
            and event.state & gtk.gdk.CONTROL_MASK
            and event.state & gtk.gdk.SHIFT_MASK
        ):
            self.switch_view(widget, event)
            return False

    def destroy(self):
        self.screen.destroy()

    def _on_activate(self, screen, *args):
        self._sig_edit()

    def click_and_action(self, type):
        pos = self.tree_view.pos_get()
        if pos != None:
            val = self._value[pos]
            id = val.get("id", False)
            obj = service.LocalService("action.main")
            res = obj.exec_keyword(type, {"model": self.model, "id": id or False, "ids": [id], "report_type": "pdf"})
            return True
        else:
            common.message(_("You have to select a resource !"))
            return False

    def switch_view(self, btn, arg):
        self.screen.make_buttons_readonly(True)
        self.screen.switch_view()

    def _readonly_set(self, value):
        self._readonly = value
        self.eb_new.set_sensitive(not value)
        self.eb_del.set_sensitive(not value)
        self.screen.readonly = value
        self.screen.display()

    def set_disable(self, value):
        self.eb_open.set_sensitive(value)
        self.eb_switch.set_sensitive(value)
        if self._readonly:
            value = not self._readonly
        self.eb_del.set_sensitive(value)

    def _sig_new(self, *args):
        _, event = args
        ctx = dict(self._view.model.expr_eval(self.screen.default_get), **self.context)
        ctx.update(self._view.model.expr_eval("dict(%s)" % self.attrs.get("context", "{}")))
        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=ctx)
                self.screen.make_buttons_readonly()
                self._readonly = False
                self.screen.current_view.widget.set_sensitive(True)
                self.set_disable(True)
            else:
                ok = True
                dia = dialog(
                    self.attrs["relation"],
                    parent=self._view.model,
                    attrs=self.attrs,
                    model_ctx=self.screen.models._context,
                    window=self._window,
                    readonly=self._readonly,
                    context=ctx,
                )
                while ok:
                    ok, value, res = dia.run()
                    if ok or res == gtk.RESPONSE_APPLY:
                        self.screen.models.model_add(value)
                        value.signal("record-changed", value.parent)
                        self.screen.display()
                        dia.new()
                        self.set_disable(True)
                self.pager.reset_pager()
                dia.destroy()

    def _sig_edit(self, *args):
        ctx = dict(self._view.model.expr_eval(self.screen.default_get), **self.context)
        ctx.update(self._view.model.expr_eval("dict(%s)" % self.attrs.get("context", "{}")))
        if self.screen.current_model:
            ok = True
            parent_modified = self.screen.current_model.parent.modified
            child_modifield = self.screen.current_model.modified
            edited_model = self.screen.current_model
            model_value = self.screen.current_model.value.copy()

            group_model = {}
            for key, val in model_value.items():
                if isinstance(val, ModelRecordGroup):
                    group_model[key] = val.models[:]
                    del model_value[key]

            dia = dialog(
                self.attrs["relation"],
                parent=self._view.model,
                model=self.screen.current_model,
                attrs=self.attrs,
                window=self._window,
                readonly=self._readonly,
                context=ctx,
            )
            while ok:
                ok, value, res = dia.run()
                if not any([ok, value, res]) and dia.screen.is_modified():
                    if child_modifield:
                        edited_model.set(model_value, modified=True)
                        for f_name, models in group_model.items():
                            edited_model.value[f_name].clear()
                            for model in models:
                                # add model in ModelRecordGroup
                                edited_model.value[f_name].model_add(model)
                    else:
                        edited_model.cancel()
                        edited_model.modified = False
                        self.screen.current_model.parent.modified = parent_modified
                if res == gtk.RESPONSE_OK:
                    dia.new()
                if value and value != edited_model:
                    self.screen.models.model_add(value)
                    value.signal("record-changed", value.parent)
                    self.screen.display()
            self.pager.reset_pager()
            dia.destroy()

    def limit_changed(self, *args):
        self.pager.limit_changed()

    def _sig_prev_page(self, *args):
        self.pager.prev_page()

    def _sig_next_page(self, *args):
        self.pager.next_page()

    def _sig_next(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.pager.next_record()

    def _sig_previous(self, *args):
        _, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            self.pager.prev_record()

    def _sig_remove(self, *args):
        lst, event = args
        if event.type == gtk.gdk.BUTTON_PRESS:
            if self.screen.current_view.view_type == "form":
                msg = _("Are you sure to remove this record ?")
            else:
                msg = _("Are you sure to remove those records ?")
            if common.sur(msg):
                model = self.screen.current_model
                self.screen.remove()
                model.signal("record-changed", model.parent)
                self.pager.reset_pager()
                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 of %s)" % (name, signal_data[1], signal_data[2])
        self.label.set_text(line)

    def _sig_refresh(self, *args):
        pass

    def _sig_sequence(self, *args):
        pass

    def display(self, model, model_field):
        if model:
            self.context.update(model.expr_eval(self.attrs.get("context", "{}")))
            self.screen.context.update(self.context)
        self.model = model
        self.model_field = model_field
        if not model_field:
            self.screen.current_model = None
            self.screen.display()
            return False
        super(one2many_list, self).display(model, model_field)
        new_models = model_field.get_client(model)
        if self.screen.models != new_models:
            self.screen.models_set(new_models)
            if (self.screen.current_view.view_type == "tree") and self.screen.editable_get():
                if len(self.screen.models.models):
                    self.screen.current_model = self.screen.models.models[0]
                else:
                    self.screen.current_model = None
            if self.screen.current_view.view_type == "form":
                self.screen.make_buttons_readonly(
                    self.screen.current_model and self.screen.current_model.id and True or False
                )
        self.set_disable(self.screen.models.models and True or False)
        self.pager.search_count()
        self.pager.set_sensitivity()
        self.screen.display()
        if self.screen.current_view.view_type == "tree":
            if not self.model_field.get_state_attrs(model).get("valid", True):
                self.screen.current_view.unselect_row(True)
        return True

    def set_value(self, model, model_field):
        self.screen.current_view.set_value()
        if self.screen.is_modified():
            model.modified = True
            model.modified_fields.setdefault(model_field.name)
        return True

    def grab_focus(self):
        return self.screen.widget.grab_focus()