From a63c30c30b433246e4d59800dbd1df381af940db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 11 Feb 2014 19:40:41 +0100 Subject: [PATCH] Add buttons of the view in actions menu review3011005 --- CHANGELOG | 2 + tryton/gui/window/form.py | 55 +++++++++++++------ tryton/gui/window/view_form/screen/screen.py | 37 ++++++++----- tryton/gui/window/view_form/view/form.py | 14 ++--- tryton/gui/window/view_form/view/graph.py | 3 - tryton/gui/window/view_form/view/interface.py | 7 +++ tryton/gui/window/view_form/view/list.py | 20 +++---- .../window/view_form/view/list_gtk/parser.py | 1 + tryton/gui/window/win_search.py | 2 +- 9 files changed, 85 insertions(+), 56 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index d8742aa6b7..1c9eac71ee 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Add tree_invisible attribute to button in tree view +* Add buttons of the view in actions menu * Don't evaluate anymore relate action with the record * Paste on editable list create new records if needed * Drop support of Python 2.6 diff --git a/tryton/gui/window/form.py b/tryton/gui/window/form.py index ed9ee634d0..d7f7b723f6 100644 --- a/tryton/gui/window/form.py +++ b/tryton/gui/window/form.py @@ -187,9 +187,6 @@ class Form(SignalEvent, TabContent): def destroy(self): self.screen.destroy() - def sel_ids_get(self): - return self.screen.sel_ids_get() - def ids_get(self): return self.screen.ids_get() @@ -304,9 +301,9 @@ class Form(SignalEvent, TabContent): return if not self.modified_save(): return - res_ids = self.sel_ids_get() + ids = [r.id for r in self.selected_records] try: - new_ids = RPCExecute('model', self.model, 'copy', res_ids, {}, + new_ids = RPCExecute('model', self.model, 'copy', ids, {}, context=self.context) except RPCException: return @@ -469,7 +466,7 @@ class Form(SignalEvent, TabContent): if not self.screen.save_current(): return record_id = self.screen.id_get() - record_ids = self.screen.sel_ids_get() + record_ids = [r.id for r in self.selected_records] action = Action.evaluate(action, atype, self.screen.current_record) data = { 'model': self.screen.model_name, @@ -521,6 +518,9 @@ class Form(SignalEvent, TabContent): menu = gtk.Menu() menu.connect('deactivate', self._popup_menu_hide, widget) + if keyword == 'action': + widget.connect('toggled', self._update_action_popup, menu) + for action in actions: new_action = action.copy() if special_action == 'print': @@ -535,18 +535,6 @@ class Form(SignalEvent, TabContent): menuitem.connect('activate', self._popup_menu_selected, widget, new_action, keyword) menu.add(menuitem) - if keyword == 'action': - menu.add(gtk.SeparatorMenuItem()) - for plugin in plugins.MODULES: - for name, func in plugin.get_plugins(self.model): - menuitem = gtk.MenuItem('_' + name) - menuitem.set_use_underline(True) - menuitem.connect('activate', lambda m, func: func({ - 'model': self.model, - 'ids': self.id_get(), - 'id': self.id_get(), - }), func) - menu.add(menuitem) return menu def _popup_menu_selected(self, menuitem, togglebutton, action, keyword): @@ -562,6 +550,37 @@ class Form(SignalEvent, TabContent): def _popup_menu_hide(self, menuitem, togglebutton): togglebutton.props.active = False + def _update_action_popup(self, tbutton, menu): + for item in menu.get_children(): + if (getattr(item, '_update_action', False) + or isinstance(item, gtk.SeparatorMenuItem)): + menu.remove(item) + + buttons = self.screen.get_buttons() + if buttons: + menu.add(gtk.SeparatorMenuItem()) + for button in buttons: + menuitem = gtk.ImageMenuItem(button.attrs.get('icon')) + menuitem.set_label('_' + button.attrs.get('string', _('Unknown'))) + menuitem.set_use_underline(True) + menuitem.connect('activate', + lambda m, attrs: self.screen.button(attrs), button.attrs) + menuitem._update_action = True + menu.add(menuitem) + + menu.add(gtk.SeparatorMenuItem()) + for plugin in plugins.MODULES: + for name, func in plugin.get_plugins(self.model): + menuitem = gtk.MenuItem('_' + name) + menuitem.set_use_underline(True) + menuitem.connect('activate', lambda m, func: func({ + 'model': self.model, + 'ids': self.id_get(), + 'id': self.id_get(), + }), func) + menuitem._update_action = True + menu.add(menuitem) + def set_cursor(self): if self.screen: self.screen.set_cursor(reset_view=False) diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index d2c9d3c4e5..b0626e554b 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -547,16 +547,12 @@ class Screen(SignalEvent): self.display() def unremove(self): - records = self.current_view.selected_records() + records = self.selected_records for record in records: self.group.unremove(record) def remove(self, delete=False, remove=False, force_remove=False): - records = None - if self.current_view.view_type == 'form' and self.current_record: - records = [self.current_record] - elif self.current_view.view_type == 'tree': - records = self.current_view.selected_records() + records = self.selected_records if not records: return if delete: @@ -830,8 +826,9 @@ class Screen(SignalEvent): self.set_cursor(reset_view=False) view.display() - def sel_ids_get(self): - return self.current_view.sel_ids_get() + @property + def selected_records(self): + return self.current_view.selected_records def id_get(self): if not self.current_record: @@ -849,6 +846,20 @@ class Screen(SignalEvent): self.current_record.on_change(fieldname, attr) self.display() + def get_buttons(self): + 'Return active buttons for the current view' + def is_active(record, button): + states = record.expr_eval(button.attrs.get('states', {})) + return not (states.get('invisible') or states.get('readonly')) + + buttons = self.current_view.get_buttons() + + for record in self.selected_records: + buttons = [b for b in buttons if is_active(record, b)] + if not buttons: + break + return buttons + def button(self, button): 'Execute button on the current record' if button.get('confirm', False) and not sur(button['confirm']): @@ -856,19 +867,19 @@ class Screen(SignalEvent): record = self.current_record if not record.save(force_reload=False): return - context = record.context_get() + ids = [r.id for r in self.selected_records] try: action_id = RPCExecute('model', self.model_name, button['name'], - [record.id], context=context) + ids, context=self.context) except RPCException: action_id = None if action_id: Action.execute(action_id, { 'model': self.model_name, 'id': record.id, - 'ids': [record.id], - }, context=context) - self.reload([record.id], written=True) + 'ids': ids, + }, context=self.context) + self.reload(ids, written=True) def get_url(self): query_string = [] diff --git a/tryton/gui/window/view_form/view/form.py b/tryton/gui/window/view_form/view/form.py index f5ce762519..dd3adff4ba 100644 --- a/tryton/gui/window/view_form/view/form.py +++ b/tryton/gui/window/view_form/view/form.py @@ -20,9 +20,8 @@ class ViewForm(ParserView): self.view_type = 'form' self.editable = True - for widget in self.state_widgets: - if isinstance(widget, gtk.Button): - widget.connect('clicked', self.button_clicked) + for button in self.get_buttons(): + button.connect('clicked', self.button_clicked) # Force to display the first time it switches on a page # This avoids glitch in position of widgets @@ -83,11 +82,7 @@ class ViewForm(ParserView): and widget.widget.get_focus_child())): widget.set_value(record, field) - def sel_ids_get(self): - if self.screen.current_record: - return [self.screen.current_record.id] - return [] - + @property def selected_records(self): if self.screen.current_record: return [self.screen.current_record] @@ -98,6 +93,9 @@ class ViewForm(ParserView): return any(w.modified for widgets in self.widgets.itervalues() for w in widgets) + def get_buttons(self): + return [b for b in self.state_widgets if isinstance(b, gtk.Button)] + def reset(self): record = self.screen.current_record if record: diff --git a/tryton/gui/window/view_form/view/graph.py b/tryton/gui/window/view_form/view/graph.py index 2c2c140d34..23c241a289 100644 --- a/tryton/gui/window/view_form/view/graph.py +++ b/tryton/gui/window/view_form/view/graph.py @@ -28,9 +28,6 @@ class ViewGraph(ParserView): def set_value(self): pass - def sel_ids_get(self): - return [] - def reset(self): pass diff --git a/tryton/gui/window/view_form/view/interface.py b/tryton/gui/window/view_form/view/interface.py index dbee8d6e0d..051beb56c5 100644 --- a/tryton/gui/window/view_form/view/interface.py +++ b/tryton/gui/window/view_form/view/interface.py @@ -32,9 +32,16 @@ class ParserView(object): self.children_field = children_field self.view_id = None + @property + def selected_records(self): + return [] + def get_fields(self): return self.children.keys() + def get_buttons(self): + return [] + @property def modified(self): return False diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index 9fc9c48af4..f874bb6eef 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -340,6 +340,10 @@ class ViewList(ParserView): def get_fields(self): return [col.name for col in self.widget_tree.get_columns() if col.name] + def get_buttons(self): + return [b for b in self.state_widgets + if isinstance(b.renderer, CellRendererButton)] + def on_keypress(self, widget, event): if (event.keyval == gtk.keysyms.c and event.state & gtk.gdk.CONTROL_MASK): @@ -829,7 +833,7 @@ class ViewList(ParserView): field.state_set(record) def update_children(self): - ids = self.sel_ids_get() + selected_records = self.selected_records for child in self.children: value = 0 value_selected = 0 @@ -842,7 +846,7 @@ class ViewList(ParserView): field_value = record.fields_get()[child_fieldname].get(record) if field_value is not None: value += field_value - if record.id in ids or not ids: + if record in selected_records or not selected_records: value_selected += field_value if loaded: @@ -872,17 +876,7 @@ class ViewList(ParserView): if (current_path != path and path not in selected_path) or new: self.widget_tree.set_cursor(path, focus_column, new) - def sel_ids_get(self): - def _func_sel_get(store, path, iter, ids): - record = store.on_get_iter(path) - if record and record.id >= 0: - ids.append(record.id) - ids = [] - sel = self.widget_tree.get_selection() - if sel: - sel.selected_foreach(_func_sel_get, ids) - return ids - + @property def selected_records(self): def _func_sel_get(store, path, iter, records): records.append(store.on_get_iter(path)) diff --git a/tryton/gui/window/view_form/view/list_gtk/parser.py b/tryton/gui/window/view_form/view/list_gtk/parser.py index f3848cf8ac..71fd7f0351 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -258,6 +258,7 @@ class ParserTree(ParserInterface): string = node_attrs.get('string', _('Unknown')) col = gtk.TreeViewColumn(string, renderer) col.name = None + col.set_visible(not node_attrs.get('tree_invisible', False)) label = gtk.Label(string) label.show() diff --git a/tryton/gui/window/win_search.py b/tryton/gui/window/win_search.py index cc5e1cb057..c8d20265fc 100644 --- a/tryton/gui/window/win_search.py +++ b/tryton/gui/window/win_search.py @@ -107,7 +107,7 @@ class WinSearch(NoModal): def response(self, win, response_id): res = None if response_id == gtk.RESPONSE_OK: - res = self.screen.sel_ids_get() + res = [r.id for r in self.screen.selected_records] elif response_id == gtk.RESPONSE_APPLY: self.screen.search_filter(self.screen.screen_container.get_text()) return