Prevent opening multiple popup window from the same widget

Closes #12819
This commit is contained in:
Cédric Krier committed 2023-12-11 19:28:39 +01:00
1 parent a101df7399
commit b06c9083e7
6 files changed
+163 -29

No files matched your search

+81 -1
View File
@@ -2521,6 +2521,7 @@ function eval_pyson(value){
}
this.el.change(this.focus_out.bind(this));
this._readonly = false;
this._popup = false;
},
get_screen: function(search) {
var domain = this.field.get_domain(this.record);
@@ -2703,6 +2704,11 @@ function eval_pyson(value){
this.focus();
return;
}
if (this._popup) {
return;
} else {
this._popup = true;
}
if (this.has_target(value)) {
var m2o_id =
this.id_from_value(record.field_get(this.field_name));
@@ -2727,6 +2733,7 @@ function eval_pyson(value){
value, true);
});
}
this._popup = false;
};
screen.switch_view().done(() => {
screen.load([m2o_id]);
@@ -2750,6 +2757,7 @@ function eval_pyson(value){
this.record.field_set_client(this.field_name,
value, true);
}
this._popup = false;
};
var parser = new Sao.common.DomainParser();
new Sao.Window.Search(
@@ -2768,12 +2776,18 @@ function eval_pyson(value){
});
return;
}
this._popup = false;
},
new_: function(defaults=null) {
var model = this.get_model();
if (!model || ! Sao.common.MODELACCESS.get(model).create) {
return;
}
if (this._popup) {
return;
} else {
this._popup = true;
}
var screen = this.get_screen(true);
if (defaults) {
defaults = jQuery.extend({}, defaults);
@@ -2791,6 +2805,7 @@ function eval_pyson(value){
this.record.field_set_client(this.field_name, value);
});
}
this._popup = false;
};
screen.switch_view().done(() => {
var win = new Sao.Window.Form(screen, callback, {
@@ -2846,6 +2861,11 @@ function eval_pyson(value){
var value = record.field_get(this.field_name);
var sao_model = new Sao.Model(model);
if (this._popup) {
return;
} else {
this._popup = true;
}
if (model && !this.has_target(value)) {
var text = this.entry.val();
if (!this._readonly && (text ||
@@ -2865,6 +2885,7 @@ function eval_pyson(value){
} else {
this.entry.val('');
}
this._popup = false;
};
var parser = new Sao.common.DomainParser();
var win = new Sao.Window.Search(
@@ -2882,8 +2903,10 @@ function eval_pyson(value){
title: this.attributes.string,
exclude_field: this.attributes.relation_field,
});
return;
}
}
this._popup = false;
},
_set_completion: function() {
if (this.wid_completion) {
@@ -3296,6 +3319,8 @@ function eval_pyson(value){
// Use keydown to not receive focus-in TAB
this.wid_text.on('keydown', this.key_press.bind(this));
}
this._popup = false;
},
get_access: function(type) {
var model = this.attributes.relation;
@@ -3491,6 +3516,12 @@ function eval_pyson(value){
domain = ['OR', domain, ['id', 'in', removed_ids]];
var text = this.wid_text.val();
if (this._popup) {
return;
} else {
this._popup = true;
}
var sequence = this._sequence();
const callback = result => {
@@ -3512,6 +3543,7 @@ function eval_pyson(value){
this.screen.set_cursor();
});
this.wid_text.val('');
this._popup = false;
};
var parser = new Sao.common.DomainParser();
var order = this.field.get_search_order(this.record);
@@ -3558,12 +3590,18 @@ function eval_pyson(value){
});
},
new_single: function(defaults=null) {
if (this._popup) {
return;
} else {
this._popup = true;
}
var sequence = this._sequence();
const update_sequence = () => {
if (sequence) {
this.screen.group.set_sequence(
sequence, this.screen.new_position);
}
this._popup = false;
};
if (this.screen.current_view.creatable) {
this.screen.new_().then(update_sequence);
@@ -3585,6 +3623,12 @@ function eval_pyson(value){
var product = {};
var screen = this.screen;
if (this._popup) {
return;
} else {
this._popup = true;
}
screen.new_(false).then(first => {
first.default_get(defaults).then(default_ => {
first.set_default(default_);
@@ -3622,6 +3666,7 @@ function eval_pyson(value){
};
const make_product = () => {
this._popup = false;
screen.group.remove(first, true);
if (jQuery.isEmptyObject(product)) {
return;
@@ -3681,7 +3726,14 @@ function eval_pyson(value){
return this.validate().then(() => {
var record = this.screen.current_record;
if (record) {
var win = new Sao.Window.Form(this.screen, function() {});
if (this._popup) {
return;
} else {
this._popup = true;
}
var win = new Sao.Window.Form(this.screen, () => {
this._popup = false;
});
}
});
},
@@ -3884,6 +3936,7 @@ function eval_pyson(value){
this.prm = this.screen.switch_view('tree').done(() => {
this.content.append(this.screen.screen_container.el);
});
this._popup = false;
},
get_access: function(type) {
var model = this.attributes.relation;
@@ -3993,6 +4046,12 @@ function eval_pyson(value){
var order = this.field.get_search_order(this.record);
var value = this.entry.val();
if (this._popup) {
return;
} else {
this._popup = true;
}
const callback = result => {
if (!jQuery.isEmptyObject(result)) {
var ids = [];
@@ -4004,6 +4063,7 @@ function eval_pyson(value){
this.screen.display();
}
this.entry.val('');
this._popup = false;
};
var parser = new Sao.common.DomainParser();
var win = new Sao.Window.Search(this.attributes.relation,
@@ -4068,6 +4128,11 @@ function eval_pyson(value){
if (jQuery.isEmptyObject(this.screen.current_record)) {
return;
}
if (this._popup) {
return;
} else {
this._popup = true;
}
// Create a new screen that is not linked to the parent otherwise
// on the save of the record will trigger the save of the parent
var screen = this._get_screen_form();
@@ -4082,6 +4147,7 @@ function eval_pyson(value){
}
});
}
this._popup = false;
};
screen.switch_view().done(() => {
screen.load([this.screen.current_record.id]);
@@ -4091,6 +4157,11 @@ function eval_pyson(value){
});
},
new_: function(defauts=null) {
if (this._popup) {
return;
} else {
this._popup = true;
}
var screen = this._get_screen_form();
if (defaults) {
defaults = jQuery.extend({}, defaults);
@@ -4105,6 +4176,7 @@ function eval_pyson(value){
this.screen.group.load([record.id], true);
}
this.entry.val('');
this._popup = false;
};
screen.switch_view().done(() => {
new Sao.Window.Form(screen, callback, {
@@ -4801,6 +4873,7 @@ function eval_pyson(value){
this._readonly = false;
this._record_id = null;
this._popup = false;
},
_required_el: function() {
return this.wid_text;
@@ -4813,6 +4886,12 @@ function eval_pyson(value){
var value = this.wid_text.val();
var domain = this.field.get_domain(this.record);
if (this._popup) {
return;
} else {
this._popup = true;
}
const callback = result => {
if (!jQuery.isEmptyObject(result)) {
var ids = result.map(function(e) {
@@ -4821,6 +4900,7 @@ function eval_pyson(value){
this.add_new_keys(ids);
}
this.wid_text.val('');
this._popup = false;
};
var parser = new Sao.common.DomainParser();
@@ -470,6 +470,7 @@ class DictWidget(Widget):
self._readonly = False
self._record_id = None
self._popup = False
@property
def _invalid_widget(self):
@@ -491,10 +492,16 @@ class DictWidget(Widget):
value = self.wid_text.get_text()
domain = self.field.domain_get(self.record)
if self._popup:
return
else:
self._popup = True
def callback(result):
if result:
self.add_new_keys([r[0] for r in result])
self.wid_text.set_text('')
self._popup = False
win = WinSearch(self.schema_model, callback, sel_multi=True,
context=context, domain=domain, new=False)
@@ -48,7 +48,6 @@ class Many2Many(Widget):
self.wid_text.set_placeholder_text(_('Search'))
self.wid_text.set_property('width_chars', 13)
self.wid_text.connect('focus-out-event', self._focus_out)
self.focus_out = True
hbox.pack_start(self.wid_text, expand=True, fill=True, padding=0)
if int(self.attrs.get('completion', 1)):
@@ -113,6 +112,8 @@ class Many2Many(Widget):
self.screen.widget.connect('key_press_event', self.on_keypress)
self.wid_text.connect('key_press_event', self.on_keypress)
self._popup = False
def on_keypress(self, widget, event):
editable = self.wid_text.get_editable()
activate_keys = [Gdk.KEY_Tab, Gdk.KEY_ISO_Left_Tab]
@@ -161,8 +162,6 @@ class Many2Many(Widget):
return int(self.attrs.get('create', 1)) and self.get_access('create')
def _sig_add(self, *args):
if not self.focus_out:
return
domain = self.field.domain_get(self.record)
add_remove = self.record.expr_eval(self.attrs.get('add_remove'))
if add_remove:
@@ -171,15 +170,18 @@ class Many2Many(Widget):
order = self.field.get_search_order(self.record)
value = self.wid_text.get_text()
self.focus_out = False
if self._popup:
return
else:
self._popup = True
def callback(result):
self.focus_out = True
if result:
ids = [x[0] for x in result]
self.screen.load(ids, modified=True)
self.screen.set_cursor()
self.wid_text.set_text('')
self._popup = False
win = WinSearch(self.attrs['relation'], callback, sel_multi=True,
context=context, domain=domain, order=order,
view_ids=self.attrs.get('view_ids', '').split(','),
@@ -215,6 +217,10 @@ class Many2Many(Widget):
def _sig_edit(self):
if not self.screen.current_record:
return
if self._popup:
return
else:
self._popup = True
# Create a new screen that is not linked to the parent otherwise on the
# save of the record will trigger the save of the parent
screen = self._get_screen_form()
@@ -231,22 +237,26 @@ class Many2Many(Widget):
self.screen.current_record.modified_fields.setdefault('id')
# Force a display to clear the CellCache
self.screen.display()
self._popup = False
WinForm(screen, callback)
def _sig_new(self, defaults=None):
if self._popup:
return
else:
self._popup = True
screen = self._get_screen_form()
defaults = defaults.copy() if defaults is not None else {}
defaults['rec_name'] = self.wid_text.get_text()
def callback(result):
self.focus_out = True
if result:
record = screen.current_record
self.screen.load([record.id], modified=True)
self.wid_text.set_text('')
self.wid_text.grab_focus()
self._popup = False
self.focus_out = False
WinForm(
screen, callback, new=True, save_current=True, defaults=defaults)
@@ -37,7 +37,7 @@ class Many2One(Widget):
lambda x, y: self._focus_out())
self.wid_text.connect('changed', self.sig_changed)
self.changed = True
self.focus_out = True
self._popup = False
if int(self.attrs.get('completion', 1)):
self.wid_text.connect('changed', self._update_completion)
@@ -103,13 +103,16 @@ class Many2One(Widget):
model = self.get_model()
if not model or not common.MODELACCESS[model]['read']:
return
if not self.focus_out or not self.field:
if not self.field:
return
self.changed = False
value = self.field.get(self.record)
model = self.get_model()
self.focus_out = False
if self._popup:
return
else:
self._popup = True
if model and not self.has_target(value):
if (not self._readonly
and (self.wid_text.get_text()
@@ -126,7 +129,7 @@ class Many2One(Widget):
self.value_from_id(*result[0]), force_change=True)
else:
self.wid_text.set_text('')
self.focus_out = True
self._popup = False
self.changed = True
win = WinSearch(model, callback, sel_multi=False,
@@ -139,7 +142,7 @@ class Many2One(Widget):
win.screen.search_filter(quote(text))
win.show()
return
self.focus_out = True
self._popup = False
self.changed = True
return
@@ -164,7 +167,10 @@ class Many2One(Widget):
def sig_new(self, defaults=None):
if not self.create_access:
return
self.focus_out = False
if self._popup:
return
else:
self._popup = True
screen = self.get_screen(search=True)
defaults = defaults.copy() if defaults is not None else {}
defaults['rec_name'] = self.wid_text.get_text()
@@ -174,7 +180,7 @@ class Many2One(Widget):
self.field.set_client(self.record,
self.value_from_id(screen.current_record.id,
screen.current_record.rec_name()))
self.focus_out = True
self._popup = False
WinForm(
screen, callback, new=True, save_current=True, defaults=defaults)
@@ -184,10 +190,9 @@ class Many2One(Widget):
model = self.get_model()
if not model or not common.MODELACCESS[model]['read']:
return
if not self.focus_out or not self.field:
if not self.field:
return
self.changed = False
self.focus_out = False
value = self.field.get(self.record)
if (icon_pos == Gtk.EntryIconPosition.SECONDARY
@@ -196,9 +201,12 @@ class Many2One(Widget):
self.field.set_client(self.record, self.value_from_id(None, ''))
self.wid_text.set_text('')
self.changed = True
self.focus_out = True
return
if self._popup:
return
else:
self._popup = True
if self.has_target(value):
m2o_id = self.id_from_value(self.field.get(self.record))
screen = self.get_screen()
@@ -211,7 +219,7 @@ class Many2One(Widget):
self.value_from_id(screen.current_record.id,
screen.current_record.rec_name()),
force_change=True)
self.focus_out = True
self._popup = False
self.changed = True
WinForm(screen, callback, save_current=True)
return
@@ -225,7 +233,7 @@ class Many2One(Widget):
if result:
self.field.set_client(self.record,
self.value_from_id(*result[0]), force_change=True)
self.focus_out = True
self._popup = False
self.changed = True
win = WinSearch(model, callback, sel_multi=False,
context=context, domain=domain, order=order,
@@ -236,7 +244,7 @@ class Many2One(Widget):
win.screen.search_filter(quote(text))
win.show()
return
self.focus_out = True
self._popup = False
self.changed = True
def sig_key_press(self, widget, event, *args):
@@ -75,7 +75,6 @@ class One2Many(Widget):
hbox.pack_start(Gtk.VSeparator(), expand=False, fill=True, padding=0)
self.focus_out = True
self.wid_completion = None
if attrs.get('add_remove'):
@@ -182,6 +181,8 @@ class One2Many(Widget):
if self.attrs.get('add_remove'):
self.wid_text.connect('key_press_event', self.on_keypress)
self._popup = False
def get_access(self, type_):
model = self.attrs['relation']
if model:
@@ -370,12 +371,17 @@ class One2Many(Widget):
self._new_single(defaults)
def _new_single(self, defaults=None):
if self._popup:
return
else:
self._popup = True
sequence = self._sequence()
def update_sequence():
if sequence:
self.screen.group.set_sequence(
field=sequence, position=self.screen.new_position)
self._popup = False
if self.screen.current_view.creatable:
self.screen.new()
@@ -392,6 +398,10 @@ class One2Many(Widget):
fields = self.attrs['product'].split(',')
product = {}
if self._popup:
return
else:
self._popup = True
first = self.screen.new(default=False)
default = first.default_get(defaults=defaults)
first.set_default(default)
@@ -420,6 +430,7 @@ class One2Many(Widget):
win_search.show()
def make_product():
self._popup = False
self.screen.group.remove(first, remove=True)
if not product:
return
@@ -448,7 +459,14 @@ class One2Many(Widget):
return
record = self.screen.current_record
if record:
WinForm(self.screen, lambda a: None)
if self._popup:
return
else:
self._popup = True
def callback(result):
self._popup = False
WinForm(self.screen, callback)
def _sig_next(self, widget):
if not self._validate():
@@ -475,8 +493,6 @@ class One2Many(Widget):
self.screen.unremove()
def _sig_add(self, *args):
if not self.focus_out:
return
if not self.write_access or not self.read_access:
return
self.view.set_value()
@@ -487,12 +503,14 @@ class One2Many(Widget):
domain = ['OR', domain, ('id', 'in', removed_ids)]
text = self.wid_text.get_text()
self.focus_out = False
if self._popup:
return
else:
self._popup = True
sequence = self._sequence()
def callback(result):
self.focus_out = True
if result:
ids = [x[0] for x in result]
self.screen.load(ids, modified=True)
@@ -501,6 +519,7 @@ class One2Many(Widget):
field=sequence, position=self.screen.new_position)
self.screen.set_cursor()
self.wid_text.set_text('')
self._popup = False
order = self.field.get_search_order(self.record)
win = WinSearch(self.attrs['relation'], callback, sel_multi=True,
@@ -802,6 +802,7 @@ class M2O(GenericText):
if renderer is None and int(attrs.get('completion', 1)):
renderer = partial(CellRendererTextCompletion, self.set_completion)
super(M2O, self).__init__(view, attrs, renderer=renderer)
self._popup = False
def get_model(self, record, field):
return self.attrs['relation']
@@ -830,7 +831,8 @@ class M2O(GenericText):
if model and common.get_toplevel_window().get_focus():
field = record[self.attrs['name']]
win = self.search_remote(record, field, text, callback=callback)
win.show()
if win:
win.show()
def editing_started(self, cell, editable, path):
super(M2O, self).editing_started(cell, editable, path)
@@ -899,7 +901,9 @@ class M2O(GenericText):
domain = field.domain_get(record)
context = field.get_context(record)
if not create and changed:
self.search_remote(record, field, text, callback=callback).show()
win = self.search_remote(record, field, text, callback=callback)
if win:
win.show()
return
target_id = self.id_from_value(field.get(record))
@@ -939,6 +943,11 @@ class M2O(GenericText):
access = common.MODELACCESS[model]
create_access = int(self.attrs.get('create', 1)) and access['create']
if self._popup:
return
else:
self._popup = True
def search_callback(found):
value = None
if found:
@@ -946,6 +955,7 @@ class M2O(GenericText):
field.set_client(record, value)
if callback:
callback()
self._popup = False
win = WinSearch(model, search_callback, sel_multi=False,
context=context, domain=domain,
order=order, view_ids=self.attrs.get('view_ids', '').split(','),