changeset 12e08efd3872 in tryton:default details: https://hg.tryton.org/tryton?cmd=changeset;node=12e08efd3872 description: Manage deletable and writable state from ir.rule
issue9357 review290101002 diffstat: CHANGELOG | 1 + tryton/gui/window/form.py | 14 ++++++++++- tryton/gui/window/view_form/model/record.py | 16 ++++++++++++- tryton/gui/window/view_form/screen/screen.py | 21 ++++++++++++++++-- tryton/gui/window/view_form/view/form_gtk/one2many.py | 8 +++++- tryton/gui/window/win_form.py | 5 +++- 6 files changed, 55 insertions(+), 10 deletions(-) diffs (217 lines): diff -r 388550da810a -r 12e08efd3872 CHANGELOG --- a/CHANGELOG Tue Sep 22 10:18:39 2020 +0200 +++ b/CHANGELOG Wed Sep 23 10:04:19 2020 +0200 @@ -1,3 +1,4 @@ +* Manage deletable and writable state * Support e-mail template * Send e-mail via the server * Support PYSON comparison of date and datetime diff -r 388550da810a -r 12e08efd3872 tryton/gui/window/form.py --- a/tryton/gui/window/form.py Tue Sep 22 10:18:39 2020 +0200 +++ b/tryton/gui/window/form.py Wed Sep 23 10:04:19 2020 +0200 @@ -302,7 +302,8 @@ self.menu_buttons[name].props.sensitive = False def sig_remove(self, widget=None): - if not common.MODELACCESS[self.model]['delete']: + if (not common.MODELACCESS[self.model]['delete'] + or not self.screen.deletable): return if self.screen.current_view.view_type == 'form': msg = _('Are you sure to remove this record?') @@ -379,7 +380,8 @@ # Called from button so we must save the tree state self.screen.save_tree_state() if not (common.MODELACCESS[self.model]['write'] - or common.MODELACCESS[self.model]['create']): + or common.MODELACCESS[self.model]['create'] + or self.screen.writable): return if self.screen.save_current(): self.message_info(_('Record saved.'), Gtk.MessageType.INFO) @@ -423,6 +425,7 @@ break self.screen.display(set_cursor=set_cursor) self.message_info() + self.set_buttons_sensitive() self.activate_save() self.screen.count_tab_domain() return True @@ -509,11 +512,18 @@ can_be_sensitive |= any( b.attrs.get('keyword', 'action') == action_type for b in screen.get_buttons()) + elif button_id == 'save': + can_be_sensitive &= not self.screen.readonly button.props.sensitive = (bool(signal_data[0]) and can_be_sensitive) button_switch = self.buttons['switch'] button_switch.props.sensitive = self.screen.number_of_views > 1 + menu_delete = self.menu_buttons['remove'] + menu_delete.props.sensitive = self.screen.deletable + menu_save = self.menu_buttons['save'] + menu_save.props.sensitive = not self.screen.readonly + msg = name + ' / ' + str(signal_data[1]) if signal_data[1] < signal_data[2]: msg += _(' of ') + str(signal_data[2]) diff -r 388550da810a -r 12e08efd3872 tryton/gui/window/view_form/model/record.py --- a/tryton/gui/window/view_form/model/record.py Tue Sep 22 10:18:39 2020 +0200 +++ b/tryton/gui/window/view_form/model/record.py Wed Sep 23 10:04:19 2020 +0200 @@ -28,6 +28,8 @@ self.state_attrs = {} self.modified_fields = {} self._timestamp = None + self._write = True + self._delete = True self.resources = None self.button_clicks = {} self.links_counts = {} @@ -73,7 +75,7 @@ in ('many2one', 'one2one', 'reference'))) if 'rec_name' not in fnames: fnames.append('rec_name') - fnames.append('_timestamp') + fnames.extend(['_timestamp', '_write', '_delete']) record_context = self.get_context() if loading == 'eager': @@ -226,10 +228,17 @@ deleted = property(get_deleted) def get_readonly(self): - return self.deleted or self.removed or self.exception + return (self.deleted + or self.removed + or self.exception + or not self._write) readonly = property(get_readonly) + @property + def deletable(self): + return self._delete + def fields_get(self): return self.group.fields @@ -436,6 +445,9 @@ if not self._timestamp: self._timestamp = value continue + if fieldname in {'_write', '_delete'}: + setattr(self, fieldname, value) + continue if fieldname not in self.group.fields: if fieldname == 'rec_name': self.value['rec_name'] = value diff -r 388550da810a -r 12e08efd3872 tryton/gui/window/view_form/screen/screen.py --- a/tryton/gui/window/view_form/screen/screen.py Tue Sep 22 10:18:39 2020 +0200 +++ b/tryton/gui/window/view_form/screen/screen.py Wed Sep 23 10:04:19 2020 +0200 @@ -142,6 +142,19 @@ def __repr__(self): return '<Screen %s at %s>' % (self.model_name, id(self)) + @property + def readonly(self): + return (self.__readonly + or any(r.readonly for r in self.selected_records)) + + @readonly.setter + def readonly(self, value): + self.__readonly = value + + @property + def deletable(self): + return all(r.deletable for r in self.selected_records) + def search_active(self, active=True): if active and not self.parent: self.screen_container.set_screen(self) @@ -413,7 +426,7 @@ def new_group(self, context=None): context = context if context is not None else self.context self.group = Group(self.model_name, {}, domain=self.domain, - context=context, readonly=self.readonly) + context=context, readonly=self.__readonly) def _group_cleared(self, group, signal): for view in self.views: @@ -1104,7 +1117,7 @@ @property def selected_records(self): - return self.current_view.selected_records + return self.current_view.selected_records if self.current_view else [] def clear(self): self.current_record = None @@ -1196,7 +1209,9 @@ if access['create']: self.new() elif action == 'delete': - if access['delete']: + if (access['delete'] + and (self.current_record.deletable + if self.current_record else True)): self.remove(delete=not self.parent, force_remove=not self.parent) elif action == 'remove': diff -r 388550da810a -r 12e08efd3872 tryton/gui/window/view_form/view/form_gtk/one2many.py --- a/tryton/gui/window/view_form/view/form_gtk/one2many.py Tue Sep 22 10:18:39 2020 +0200 +++ b/tryton/gui/window/view_form/view/form_gtk/one2many.py Wed Sep 23 10:04:19 2020 +0200 @@ -268,6 +268,7 @@ if isinstance(self._position, int): first = self._position <= 1 last = self._position >= self._length + deletable = self.screen.deletable self.but_new.set_sensitive(bool( not self._readonly @@ -277,6 +278,7 @@ self.but_del.set_sensitive(bool( not self._readonly and self.attrs.get('delete', True) + and deletable and self._position and access['delete'])) self.but_undel.set_sensitive(bool( @@ -427,11 +429,13 @@ def _sig_remove(self, widget, remove=False): access = common.MODELACCESS[self.screen.model_name] + writable = not self.screen.readonly + deletable = self.screen.deletable if remove: - if not access['write'] or not access['read']: + if not access['write'] or not writable or not access['read']: return else: - if not access['delete']: + if not access['delete'] or not deletable: return self.screen.remove(remove=remove) diff -r 388550da810a -r 12e08efd3872 tryton/gui/window/win_form.py --- a/tryton/gui/window/win_form.py Tue Sep 22 10:18:39 2020 +0200 +++ b/tryton/gui/window/win_form.py Wed Sep 23 10:04:19 2020 +0200 @@ -322,6 +322,9 @@ def _sig_label(self, screen, signal_data): name = '_' access = common.MODELACCESS[screen.model_name] + deletable = True + if screen.current_record: + deletable = screen.current_record.deletable readonly = screen.group.readonly if signal_data[0] >= 1: name = str(signal_data[0]) @@ -335,7 +338,7 @@ self.but_pre.set_sensitive(True) else: self.but_pre.set_sensitive(False) - if access['delete'] and not readonly: + if access['delete'] and not readonly and deletable: self.but_del.set_sensitive(True) self.but_undel.set_sensitive(True) else: