From 6f06be168105f4440b9683e4e36d0b08ec3bed22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 13 Apr 2024 15:35:15 +0200 Subject: [PATCH] Test if current view is defined on screen before using it Closes #13178 (grafted from 6f0ae4c7719fbf129ffd0221aa9b1fa008df23e2) --HG-- branch : 6.0 --- sao/src/screen.js | 102 ++++++++++++------ .../gui/window/view_form/screen/screen.py | 91 ++++++++++------ 2 files changed, 123 insertions(+), 70 deletions(-) diff --git a/sao/src/screen.js b/sao/src/screen.js index 96f8e11abd..49e6c51046 100644 --- a/sao/src/screen.js +++ b/sao/src/screen.js @@ -1293,8 +1293,12 @@ set_cursor = true; } this.group.load(ids, modified); - this.current_view.reset(); - if (ids.length && this.current_view.view_type != 'calendar') { + if (this.current_view) { + this.current_view.reset(); + } + if (ids.length && + this.current_view && + this.current_view.view_type != 'calendar') { this.current_record = this.group.get(ids[0]); } else { this.current_record = null; @@ -1315,7 +1319,7 @@ } else { this.current_record = null; } - if (this.views) { + if (this.views && this.current_view) { var search_prm = this.search_active( ~['tree', 'graph', 'calendar'].indexOf( this.current_view.view_type)); @@ -1354,7 +1358,8 @@ var view = this.current_view; view.set_value(); this.set_cursor(false, false); - if (~['tree', 'form', 'list-form'].indexOf(view.view_type) && + if (view && + ~['tree', 'form', 'list-form'].indexOf(view.view_type) && this.current_record && this.current_record.group) { var group = this.current_record.group; var record = this.current_record; @@ -1381,9 +1386,12 @@ }, display_previous: function() { var view = this.current_view; - view.set_value(); + if (view) { + view.set_value(); + } this.set_cursor(false, false); - if (~['tree', 'form', 'list-form'].indexOf(view.view_type) && + if (view && + ~['tree', 'form', 'list-form'].indexOf(view.view_type) && this.current_record && this.current_record.group) { var group = this.current_record.group; var record = this.current_record; @@ -1406,7 +1414,7 @@ this.current_record = this.group[0]; } this.set_cursor(false, false); - return view.display(); + return view ? view.display() : jQuery.when(); }, get selected_records() { if (this.current_view) { @@ -1442,7 +1450,8 @@ }); }, default_row_activate: function() { - if ((this.current_view.view_type == 'tree') && + if (this.current_view && + (this.current_view.view_type == 'tree') && (this.current_view.attributes.keyword_open == 1)) { var id = this.get_id(); if (id) { @@ -1469,7 +1478,8 @@ default_ = true; } var prm = jQuery.when(); - if (this.current_view.view_type == 'calendar') { + if (this.current_view && + this.current_view.view_type == 'calendar') { var selected_date = this.current_view.get_selected_date(); prm = this.switch_view('form', undefined, false); } @@ -1480,7 +1490,7 @@ prm = this.switch_view('form', undefined, false); } return prm.then(function() { - if (!this.current_view.editable) { + if (!this.current_view || !this.current_view.editable) { return; } var group; @@ -1561,19 +1571,22 @@ save_current: function() { var current_record = this.current_record; if (!current_record) { - if ((this.current_view.view_type == 'tree') && - this.group && this.group.length) { + if (this.current_view && + (this.current_view.view_type == 'tree') && + this.group && this.group.length) { this.current_record = this.group[0]; current_record = this.current_record; } else { return jQuery.when(); } } - this.current_view.set_value(); - var fields = this.current_view.get_fields(); + if (this.current_view) { + this.current_view.set_value(); + var fields = this.current_view.get_fields(); + } var path = current_record.get_path(this.group); var prm = jQuery.Deferred(); - if (this.current_view.view_type == 'tree') { + if (this.current_view && (this.current_view.view_type == 'tree')) { prm = this.group.save().then(function() { return this.current_record; }.bind(this)); @@ -1581,7 +1594,7 @@ prm = current_record.save().then(function() { return current_record; }); - } else { + } else if (this.current_view) { return this.current_view.display().then(function() { this.set_cursor(); return jQuery.Deferred().reject(); @@ -1617,7 +1630,7 @@ var test = function(record) { return (record.has_changed() || record.id < 0); }; - if (this.current_view.view_type != 'tree') { + if (this.current_view && (this.current_view.view_type != 'tree')) { if (this.current_record) { if (test(this.current_record)) { return true; @@ -1628,20 +1641,24 @@ return true; } } - if (this.current_view.modified) { + if (this.current_view && this.current_view.modified) { return true; } return false; }, unremove: function() { - var records = this.current_view.selected_records; - records.forEach(function(record) { - record.group.unremove(record); - }); + if (this.current_view) { + var records = this.current_view.selected_records; + records.forEach(function(record) { + record.group.unremove(record); + }); + } }, remove: function(delete_, remove, force_remove, records) { var prm = jQuery.when(); - records = records || this.current_view.selected_records; + if (!records && this.current_view) { + records = this.current_view.selected_records; + } if (jQuery.isEmptyObject(records)) { return prm; } @@ -1699,7 +1716,8 @@ }, copy: function() { var dfd = jQuery.Deferred(); - var records = this.current_view.selected_records; + var records = ( + this.current_view ? this.current_view.selected_records : []); this.model.copy(records, this.context) .then(function(new_ids) { this.group.load(new_ids, false, this.new_position); @@ -1884,14 +1902,18 @@ if (!this.current_record) { return null; } - this.current_view.set_value(); + if (this.current_view) { + this.current_view.set_value(); + } return this.current_record.get(); }, get_on_change_value: function() { if (!this.current_record) { return null; } - this.current_view.set_value(); + if (this.current_view) { + this.current_view.set_value(); + } return this.current_record.get_on_change_value(); }, reload: function(ids, written) { @@ -1908,11 +1930,13 @@ }.bind(this)); }, get_buttons: function() { - var selected_records = this.current_view.selected_records; + var selected_records = ( + this.current_view ? this.current_view.selected_records : []); if (jQuery.isEmptyObject(selected_records)) { return []; } - var buttons = this.current_view.get_buttons(); + var buttons = ( + this.current_view ? this.current_view.get_buttons() : []); selected_records.forEach(function(record) { buttons = buttons.filter(function(button) { if (button.attributes.type === 'instance') { @@ -1942,9 +1966,11 @@ }.bind(this)); }; - var selected_records = this.current_view.selected_records; - this.current_view.set_value(); - var fields = this.current_view.get_fields(); + if (this.current_view) { + var selected_records = this.current_view.selected_records; + this.current_view.set_value(); + var fields = this.current_view.get_fields(); + } var prms = []; var reset_state = function(record) { @@ -2043,7 +2069,8 @@ } else if (action.startsWith('switch')) { this.switch_view.apply(this, action.split(' ', 3).slice(1)); } else if (action == 'reload') { - if (~['tree', 'graph', 'calendar'].indexOf(this.current_view.view_type) && + if (this.current_view && + ~['tree', 'graph', 'calendar'].indexOf(this.current_view.view_type) && !this.group.parent) { this.search_filter(); } @@ -2082,7 +2109,7 @@ var path = ['model', this.model_name]; var view_ids = this.views.map( function(v) {return v.view_id;}).concat(this.view_ids); - if (this.current_view.view_type != 'form') { + if (this.current_view && (this.current_view.view_type != 'form')) { var search_value; if (this.attributes.search_value) { search_value = this.attributes.search_value; @@ -2095,8 +2122,10 @@ } } else if (this.current_record && (this.current_record.id > -1)) { path.push(this.current_record.id); - var i = view_ids.indexOf(this.current_view.view_id); - view_ids = view_ids.slice(i).concat(view_ids.slice(0, i)); + if (this.current_view) { + var i = view_ids.indexOf(this.current_view.view_id); + view_ids = view_ids.slice(i).concat(view_ids.slice(0, i)); + } } if (!jQuery.isEmptyObject(view_ids)) { query_string.push(['views', dumps(view_ids)]); @@ -2180,6 +2209,9 @@ set_tree_state: function() { var parent_, state, state_prm, tree_state_model; var view = this.current_view; + if (!view) { + return jQuery.when(); + } if (!~['tree', 'form'].indexOf(view.view_type)) { return jQuery.when(); } diff --git a/tryton/tryton/gui/window/view_form/screen/screen.py b/tryton/tryton/gui/window/view_form/screen/screen.py index 891ee6da39..c7071e0f18 100644 --- a/tryton/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/tryton/gui/window/view_form/screen/screen.py @@ -113,11 +113,10 @@ class Screen(SignalEvent): return child # Remove first level Viewport and ScrolledWindow to fill the Vbox - for widget in [ - self.context_screen.screen_container.viewport, - self.context_screen.current_view.widget.get_children()[0], - ]: - remove_bin(widget) + remove_bin(self.context_screen.screen_container.viewport) + if self.context_screen.current_view: + remove_bin( + self.context_screen.current_view.widget.get_children()[0]) self.screen_container.filter_vbox.pack_start( context_widget, expand=False, fill=True, padding=0) @@ -490,7 +489,8 @@ class Screen(SignalEvent): self.group.destroy() def default_row_activate(self): - if (self.current_view.view_type == 'tree' + if (self.current_view + and self.current_view.view_type == 'tree' and int(self.current_view.attributes.get('keyword_open', 0))): return Action.exec_keyword('tree_open', { 'model': self.model_name, @@ -611,7 +611,7 @@ class Screen(SignalEvent): def new(self, default=True, rec_name=None): previous_view = self.current_view - if self.current_view.view_type == 'calendar': + if self.current_view and self.current_view.view_type == 'calendar': selected_date = self.current_view.get_selected_date() if self.current_view and not self.current_view.editable: self.switch_view('form', display=False) @@ -664,16 +664,19 @@ class Screen(SignalEvent): def save_current(self): if not self.current_record: - if self.current_view.view_type == 'tree' and len(self.group): + if (self.current_view + and self.current_view.view_type == 'tree' + and len(self.group)): self.current_record = self.group[0] else: return True - self.current_view.set_value() saved = False record_id = None - fields = self.current_view.get_fields() + if self.current_view: + self.current_view.set_value() + fields = self.current_view.get_fields() path = self.current_record.get_path(self.group) - if self.current_view.view_type == 'tree': + if self.current_view and self.current_view.view_type == 'tree': # False value must be not saved saved = all(( x is not False and x >= 0 @@ -683,7 +686,7 @@ class Screen(SignalEvent): record_id = self.current_record.save(force_reload=True) # False value must be not saved saved = record_id is not False and record_id >= 0 - else: + elif self.current_view: self.set_cursor() self.current_view.display() return False @@ -711,17 +714,19 @@ class Screen(SignalEvent): def get(self): if not self.current_record: return None - self.current_view.set_value() + if self.current_view: + self.current_view.set_value() return self.current_record.get() def get_on_change_value(self): if not self.current_record: return None - self.current_view.set_value() + if self.current_view: + self.current_view.set_value() return self.current_record.get_on_change_value() def modified(self): - if self.current_view.view_type != 'tree': + if self.current_view and self.current_view.view_type != 'tree': if self.current_record: if self.current_record.modified or self.current_record.id < 0: return True @@ -729,7 +734,7 @@ class Screen(SignalEvent): for record in self.group: if record.modified or record.id < 0: return True - if self.current_view.modified: + if self.current_view and self.current_view.modified: return True return False @@ -807,6 +812,8 @@ class Screen(SignalEvent): def set_tree_state(self): view = self.current_view + if not view: + return if view.view_type not in ('tree', 'form'): return if id(view) in self.tree_states_done: @@ -909,8 +916,10 @@ class Screen(SignalEvent): def load(self, ids, set_cursor=True, modified=False, position=-1): self.group.load(ids, modified=modified, position=position) - self.current_view.reset() - if ids and self.current_view.view_type != 'calendar': + if self.current_view: + self.current_view.reset() + if (ids and self.current_view + and self.current_view.view_type != 'calendar'): self.display(ids[0]) else: self.current_record = None @@ -929,7 +938,7 @@ class Screen(SignalEvent): self.current_record = self.group[0] else: self.current_record = None - if self.views: + if self.views and self.current_view: self.search_active(self.current_view.view_type in ('tree', 'graph', 'calendar')) for view in self.views: @@ -974,7 +983,8 @@ class Screen(SignalEvent): model = view.treeview.get_model() iter_ = model.get_iter(end) self.current_record = model.get_value(iter_, 0) - elif (view.view_type == 'form' + elif (view + and view.view_type == 'form' and self.current_record and self.current_record.group): group = self.current_record.group @@ -1002,12 +1012,14 @@ class Screen(SignalEvent): record = next break self.current_record = record - elif (view.view_type == 'list-form' and len(self.group) + elif (view + and view.view_type == 'list-form' + and len(self.group) and self.current_record in self.group): idx = self.group.index(self.current_record) if 0 <= idx < len(self.group) - 1: self.current_record = self.group[idx + 1] - elif view.view_type == 'calendar': + elif view and view.view_type == 'calendar': record = self.current_record goocalendar = view.widgets.get('goocalendar') if goocalendar: @@ -1039,9 +1051,10 @@ class Screen(SignalEvent): def display_prev(self): view = self.current_view - view.set_value() + if view: + view.set_value() self.set_cursor(reset_view=False) - if view.view_type == 'tree' and len(self.group): + if view and view.view_type == 'tree' and len(self.group): range_ = view.treeview.get_visible_range() if range_: start, end = range_ @@ -1052,7 +1065,8 @@ class Screen(SignalEvent): model = view.treeview.get_model() iter_ = model.get_iter(start) self.current_record = model.get_value(iter_, 0) - elif (view.view_type == 'form' + elif (view + and view.view_type == 'form' and self.current_record and self.current_record.group): group = self.current_record.group @@ -1070,7 +1084,7 @@ class Screen(SignalEvent): if parent and record.model_name == parent.model_name: record = parent self.current_record = record - elif view.view_type == 'calendar': + elif view and view.view_type == 'calendar': record = self.current_record goocalendar = view.widgets.get('goocalendar') if goocalendar: @@ -1095,7 +1109,9 @@ class Screen(SignalEvent): if prev_id >= 0: self.current_record = events[prev_id].record break - elif (view.view_type == 'list-form' and len(self.group) + elif (view + and view.view_type == 'list-form' + and len(self.group) and self.current_record in self.group): idx = self.group.index(self.current_record) if 0 < idx <= len(self.group) - 1: @@ -1103,7 +1119,8 @@ class Screen(SignalEvent): else: self.current_record = self.group[-1] if len(self.group) else None self.set_cursor(reset_view=False) - view.display() + if view: + view.display() def invalid_message(self, record=None): if record is None: @@ -1174,7 +1191,7 @@ class Screen(SignalEvent): if not self.selected_records: return [] - buttons = self.current_view.get_buttons() + buttons = self.current_view.get_buttons() if self.current_view else [] for record in self.selected_records: buttons = [b for b in buttons if is_active(record, b)] @@ -1184,8 +1201,9 @@ class Screen(SignalEvent): def button(self, button): 'Execute button on the selected records' - self.current_view.set_value() - fields = self.current_view.get_fields() + if self.current_view: + self.current_view.set_value() + fields = self.current_view.get_fields() for record in self.selected_records: domain = record.expr_eval( button.get('states', {})).get('pre_validate', []) @@ -1266,7 +1284,9 @@ class Screen(SignalEvent): elif action.startswith('switch'): self.switch_view(*action.split(None, 2)[1:]) elif action == 'reload': - if (self.current_view.view_type in ['tree', 'graph', 'calendar'] + if (self.current_view + and self.current_view.view_type in [ + 'tree', 'graph', 'calendar'] and not self.parent): self.search_filter() elif action == 'reload menu': @@ -1296,7 +1316,7 @@ class Screen(SignalEvent): cls=JSONEncoder, separators=(',', ':')))) path = [CONFIG['login.db'], 'model', self.model_name] view_ids = [v.view_id for v in self.views] + self.view_ids - if self.current_view.view_type != 'form': + if self.current_view and self.current_view.view_type != 'form': if self.search_value: search_value = self.search_value else: @@ -1308,8 +1328,9 @@ class Screen(SignalEvent): separators=(',', ':')))) elif self.current_record and self.current_record.id > -1: path.append(str(self.current_record.id)) - i = view_ids.index(self.current_view.view_id) - view_ids = view_ids[i:] + view_ids[:i] + if self.current_view: + i = view_ids.index(self.current_view.view_id) + view_ids = view_ids[i:] + view_ids[:i] if view_ids: query_string.append(('views', json.dumps( view_ids, separators=(',', ':'))))