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:

Reply via email to