From b5a2eb18c17c1ecb4a7eeafd6ca0c7152a6de0d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 24 Oct 2011 16:14:49 +0200 Subject: [PATCH 001/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index 45ecaae4af..77eeb3869e 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.0" +VERSION = "2.2.1" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From f8129d023968cac33a8a507b1ef25f4f6417ab07 Mon Sep 17 00:00:00 2001 From: Udo Spallek Date: Wed, 2 Nov 2011 11:12:56 +0100 Subject: [PATCH 002/122] Do not use PYSONDecoder() to eval states of button in list view issue2244 (transplanted from a5609b61695b8a7bdb6f7b21a96054b04a5d047a) --- tryton/gui/window/view_form/view/list_gtk/parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 48a5db18e8..104c5e7abd 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -921,8 +921,8 @@ class Button(object): store = self.treeview.get_model() record = store.get_value(store.get_iter(path), 0) - state_changes = PYSONDecoder().decode(record.expr_eval( - self.attrs.get('states', {}), check_load=False)) + state_changes = record.expr_eval( + self.attrs.get('states', {}), check_load=False) if state_changes.get('invisible') \ or state_changes.get('readonly'): return True From bfdaaa25ee85d9b34988d71c7695a83901fd2480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 2 Nov 2011 21:16:42 +0100 Subject: [PATCH 003/122] Test if editable has set_text_column GTK 2.24 and above use a ComboBox instead of a ComboBoxEntry issue2211 (transplanted from 44a56ceafb3436ed61985af1fe5c44c0fc425d7c) --- tryton/gui/window/view_form/view/list_gtk/parser.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 104c5e7abd..f5440280ee 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -790,7 +790,9 @@ class Selection(Char): self.update_selection(record) model = self.get_model(self.selection) editable.set_model(model) - editable.set_text_column(0) + # GTK 2.24 and above use a ComboBox instead of a ComboBoxEntry + if hasattr(editable, 'set_text_column'): + editable.set_text_column(0) completion = gtk.EntryCompletion() #Only available in PyGTK 2.6 and above. if hasattr(completion, 'set_inline_selection'): From 6ee3e8803fbd49d83c1d1415c3d9c7e48a008721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 4 Nov 2011 17:26:45 +0100 Subject: [PATCH 004/122] Fix EvalEnvironment - works also on id - use the same eval_type for parent - fix __contains__ with parent - use eval_type in __contains__ review169002 (transplanted from 86f1e613dabb911d526ccc89037cb348b202d5dd) --- tryton/common/environment.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tryton/common/environment.py b/tryton/common/environment.py index 3cc9ca2986..84a29dec40 100644 --- a/tryton/common/environment.py +++ b/tryton/common/environment.py @@ -12,8 +12,11 @@ class EvalEnvironment(dict): self.eval_type = eval_type def __getitem__(self, item): + if item == 'id': + return self.parent.id if item == '_parent_' + self.parent.parent_name and self.parent.parent: - return EvalEnvironment(self.parent.parent, self.check_load) + return EvalEnvironment(self.parent.parent, self.check_load, + eval_type=self.eval_type) if self.eval_type == 'eval': return self.parent.get_eval(check_load=self.check_load)[item] else: @@ -42,6 +45,11 @@ class EvalEnvironment(dict): __repr__ = __str__ def __contains__(self, item): + if item == 'id': + return True if item == '_parent_' + self.parent.parent_name and self.parent.parent: - return item in EvalEnvironment(self.parent.parent, self.check_load) - return item in self.parent.get_eval(check_load=self.check_load) + return True + if self.eval_type == 'eval': + return item in self.parent.get_eval(check_load=self.check_load) + else: + return item in self.parent.group.fields From b8d873c3cf9179b7ba6643ce18a7cfeff2e2df41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 14 Nov 2011 18:01:15 +0100 Subject: [PATCH 005/122] Add allowed ops in safe_eval for Python 2.7 (transplanted from 886cd06d78838bfca94095d8d6fc3e5809dd2f1f) --- tryton/common/common.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tryton/common/common.py b/tryton/common/common.py index 8ef10bc2e3..05db28965a 100644 --- a/tryton/common/common.py +++ b/tryton/common/common.py @@ -1420,6 +1420,7 @@ _ALLOWED_CODES = set(dis.opmap[x] for x in [ 'STORE_MAP', 'LOAD_NAME', 'CALL_FUNCTION', 'COMPARE_OP', 'LOAD_ATTR', 'STORE_NAME', 'GET_ITER', 'FOR_ITER', 'LIST_APPEND', 'JUMP_ABSOLUTE', 'DELETE_NAME', 'JUMP_IF_TRUE', 'JUMP_IF_FALSE', 'JUMP_IF_FALSE_OR_POP', + 'JUMP_IF_TRUE_OR_POP', 'POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE', 'BINARY_SUBSCR', ] if x in dis.opmap) From 4ec8449cea68d243110cc801668b0b3171b6962c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 19 Nov 2011 19:41:06 +0100 Subject: [PATCH 006/122] Fix default value of trees The fields definition should be passed to the child group review178004 (transplanted from 67a0338cb58a0e43373262ad86ba1efeae1ab85d) --- tryton/gui/window/view_form/model/field.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index f5f9c1ed94..de3df47e14 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -557,9 +557,6 @@ class O2MField(CharField): if fields: fields = dict((fname, field.attrs) for fname, field in fields.iteritems()) - - # value is a list of dict - fields_dict = {} if value and len(value): context = self.context_get(record) field_names = [] @@ -572,18 +569,17 @@ class O2MField(CharField): args = ('model', self.attrs['relation'], 'fields_get', field_names, context) try: - fields_dict = rpc.execute(*args) + fields = rpc.execute(*args) except TrytonServerError, exception: - fields_dict = common.process_exception(exception, *args) - if not fields_dict: + fields = common.process_exception(exception, *args) + if not fields: return False parent_name = self.attrs.get('relation_field', '') - group = Group(self.attrs['relation'], fields_dict, + group = Group(self.attrs['relation'], fields, parent=record, parent_name=parent_name, child_name=self.name, context=self.context, parent_datetime_field=self.attrs.get('datetime_field')) - group.load_fields(fields_dict) if record.value.get(self.name): group.record_deleted.extend(x for x in record.value[self.name] if x.id >= 0) From 2d545447ba73d3a904ec4213a9ffa72a9fb6a511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 19 Nov 2011 19:42:09 +0100 Subject: [PATCH 007/122] domain part can have more than 3 elements issue2285 review178003 (transplanted from 5bd25b87a9d05725a344741e228ca8cd08e0f04a) --- tryton/common/domain_inversion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/common/domain_inversion.py b/tryton/common/domain_inversion.py index fbca01c6ec..62b262fb63 100644 --- a/tryton/common/domain_inversion.py +++ b/tryton/common/domain_inversion.py @@ -223,7 +223,7 @@ class Or(And): elif is_leaf(part) and self.base(part[0]) == symbol: result.append(part) else: - field, _, _ = part + field = part[0] field = self.base(field) if (field in context and eval_leaf(part, context, operator.or_)): From c88f3a527df5ec7400eda522aa6c56c2554a26d1 Mon Sep 17 00:00:00 2001 From: Phillip Heller Date: Tue, 22 Nov 2011 13:15:45 -0500 Subject: [PATCH 008/122] Fix discovery of gdk-pixbuf-loaders gdk-pixbuf-loaders location has changed with recent builds of gtk, which breaks the build of binary client distributions. This changeset discovers their proper location by parsing output of gdk-pixbuf-query-loaders. issue1976 review176001 (transplanted from 01783c935c47d0d718f1b33e8706f05541ab4fa5) --- setup.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index b955ab25f4..f98546eb80 100644 --- a/setup.py +++ b/setup.py @@ -6,6 +6,7 @@ from setuptools import setup, find_packages import os import glob import sys +import re def read(fname): return open(os.path.join(os.path.dirname(__file__), fname)).read() @@ -269,7 +270,7 @@ elif os.name == 'mac' \ 'gtk+-2.0'], stdout=PIPE).stdout.read().strip() dist_dir = dist.command_obj['py2app'].dist_dir - resources_dir = os.path.join(dist_dir, 'tryton.app', 'Contents', 'Resources') + resources_dir = os.path.join(dist_dir, 'Tryton.app', 'Contents', 'Resources') gtk_2_dist_dir = os.path.join(resources_dir, 'lib', 'gtk-2.0') pango_dist_dir = os.path.join(resources_dir, 'lib', 'pango') @@ -288,10 +289,6 @@ elif os.name == 'mac' \ pangorc.write('[Pango]\n') pangorc.write('ModuleFiles=./pango.modules\n') - if os.path.isdir(os.path.join(gtk_2_dist_dir, gtk_binary_version, 'loaders')): - shutil.rmtree(os.path.join(gtk_2_dist_dir, gtk_binary_version, 'loaders')) - shutil.copytree(os.path.join(gtk_dir, 'lib', 'gtk-2.0', gtk_binary_version, - 'loaders'), os.path.join(gtk_2_dist_dir, gtk_binary_version, 'loaders')) if not os.path.isdir(os.path.join(gtk_2_dist_dir, gtk_binary_version, 'engines')): os.makedirs(os.path.join(gtk_2_dist_dir, gtk_binary_version, 'engines')) shutil.copyfile(os.path.join(gtk_dir, 'lib', 'gtk-2.0', gtk_binary_version, @@ -300,6 +297,15 @@ elif os.name == 'mac' \ query_loaders = Popen(os.path.join(gtk_dir,'bin','gdk-pixbuf-query-loaders'), stdout=PIPE).stdout.read() + loader_dir, = re.findall('# LoaderDir = (.*)', query_loaders) + loader_pkg = (loader_dir.replace(os.path.join(gtk_dir,'lib'), ''). + split(os.path.sep)[-3]) + loader_dist_dir = os.path.join(resources_dir, 'lib', loader_pkg, + gtk_binary_version, 'loaders') + if os.path.isdir(loader_dist_dir): + shutil.rmtree(loader_dist_dir) + if os.path.isdir(loader_dir): + shutil.copytree(loader_dir, loader_dist_dir) query_loaders = query_loaders.replace(gtk_dir, '@executable_path/../Resources') loaders_path = os.path.join(resources_dir, 'gdk-pixbuf.loaders') @@ -330,7 +336,7 @@ elif os.name == 'mac' \ # fix pathes within shared libraries for library in chain( - iglob(os.path.join(gtk_2_dist_dir, gtk_binary_version, 'loaders', '*.so')), + iglob(os.path.join(loader_dist_dir, '*.so')), iglob(os.path.join(gtk_2_dist_dir, gtk_binary_version, 'engines', '*.so')), iglob(os.path.join(gtk_2_dist_dir, gtk_binary_version, 'immodules', '*.so')), iglob(os.path.join(pango_dist_dir,'*','modules','*.so'))): From 56e78b325912fc4606cf49c3c4c1ac053abc247c Mon Sep 17 00:00:00 2001 From: Phillip Heller Date: Wed, 23 Nov 2011 20:42:04 -0500 Subject: [PATCH 009/122] Fix recognition of Mac OS X based systems Previously, Mac OS X was recognized during py2app invocation, as well as runtime by comparison of os.name with 'macos'. The value of os.name reports as 'posix' under more recent version of Python built on Mac OS X. Now, the recognition is instead done by comparing sys.platform with 'darwin'. issue2258 review171004 (transplanted from d2d9d6ec6da433a5d7df4b07e089f21536b9e4fb) --- setup.py | 6 ++---- tryton/common/common.py | 3 +-- tryton/config.py | 3 +-- tryton/gui/main.py | 5 ++--- tryton/gui/window/view_form/view/list.py | 7 ++----- tryton/translate.py | 4 ++-- 6 files changed, 10 insertions(+), 18 deletions(-) diff --git a/setup.py b/setup.py index f98546eb80..817acea543 100644 --- a/setup.py +++ b/setup.py @@ -86,8 +86,7 @@ if os.name == 'nt': args['windows'][0]['other_resources'] = [(24, 1, manifest)] -elif os.name == 'mac' \ - or (hasattr(os, 'uname') and os.uname()[0] == 'Darwin'): +elif sys.platform == 'darwin': import py2app from modulegraph.find_modules import PY_SUFFIXES PY_SUFFIXES.append('') @@ -249,8 +248,7 @@ if os.name == 'nt': Popen([makensis, "/DVERSION=" + VERSION, str(os.path.join(os.path.dirname(__file__), 'setup-single.nsi'))]).wait() -elif os.name == 'mac' \ - or (hasattr(os, 'uname') and os.uname()[0] == 'Darwin'): +elif sys.platform == 'darwin': def find_gtk_dir(): for directory in os.environ['PATH'].split(':'): if not os.path.isdir(directory): diff --git a/tryton/common/common.py b/tryton/common/common.py index 05db28965a..a68a88d978 100644 --- a/tryton/common/common.py +++ b/tryton/common/common.py @@ -419,8 +419,7 @@ def file_open(filename, type, print_p=False): save_p.close() file_p.close() return - elif os.name == 'mac' or \ - (hasattr(os, 'uname') and os.uname()[0] == 'Darwin'): + elif sys.platform == 'darwin': pid = os.fork() if not pid: pid = os.fork() diff --git a/tryton/config.py b/tryton/config.py index be2a0ca9f2..4683034d29 100644 --- a/tryton/config.py +++ b/tryton/config.py @@ -32,8 +32,7 @@ if not os.path.isdir(get_config_dir()): def find_path(progs, args): if os.name == 'nt': return '' - if os.name == 'mac' or \ - (hasattr(os, 'uname') and os.uname()[0] == 'Darwin'): + if sys.platform == 'darwin': return '' paths = [x for x in os.environ['PATH'].split(':') if os.path.isdir(x)] diff --git a/tryton/gui/main.py b/tryton/gui/main.py index 95e9b5d5c2..17a6ad5bbd 100644 --- a/tryton/gui/main.py +++ b/tryton/gui/main.py @@ -88,7 +88,7 @@ class Main(object): gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/File/Quit', gtk.keysyms.Q, gtk.gdk.CONTROL_MASK) - if os.name != 'mac': + if sys.platform != 'darwin': gtk.accel_map_add_entry('/User/Menu Reload', gtk.keysyms.T, gtk.gdk.MOD1_MASK) gtk.accel_map_add_entry('/User/Menu Toggle', gtk.keysyms.T, @@ -187,8 +187,7 @@ class Main(object): self.sig_statusbar_show() - if os.name in ('nt', 'mac') or \ - (hasattr(os, 'uname') and os.uname()[0] == 'Darwin'): + if os.name == 'nt' or sys.platform == 'darwin': # Disable actions, on win32 we use os.startfile # and on mac we use /usr/bin/open self.menuitem_actions.set_sensitive(False) diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index d8f5b4079f..69d93e7d10 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -307,9 +307,7 @@ class ViewList(ParserView): elif self.widget_tree.sequence: dnd = True # Disable DnD on mac until it is fully supported - if os.name == 'mac': - dnd = False - elif hasattr(os, 'uname') and os.uname()[0] == 'Darwin': + if sys.platform == 'darwin': dnd = False if screen.readonly: dnd = False @@ -412,8 +410,7 @@ class ViewList(ParserView): # Don't use set_with_data on mac see: # http://bugzilla.gnome.org/show_bug.cgi?id=508601 if selection.count_selected_rows() < 100 \ - or os.name == 'mac' \ - or (hasattr(os, 'uname') and os.uname()[0] == 'Darwin'): + or sys.platform == 'darwin': data = [] selection.selected_foreach(self.copy_foreach, data) clipboard.set_text('\n'.join(data)) diff --git a/tryton/translate.py b/tryton/translate.py index 5ff8104fe5..ac7971f577 100644 --- a/tryton/translate.py +++ b/tryton/translate.py @@ -8,6 +8,7 @@ from version import PACKAGE from tryton.client import CURRENT_DIR, PREFIX import logging import gtk +import sys _ = gettext.gettext @@ -169,8 +170,7 @@ def setlang(lang=None, locale_dict=None): lang2 = lang if os.name == 'nt': lang2 = _LOCALE2WIN32.get(lang, lang) - elif os.name == 'mac' or \ - (hasattr(os, 'uname') and os.uname()[0] == 'Darwin'): + elif sys.platform == 'darwin': encoding = 'UTF-8' # ensure environment variable are str lang, lang2, encoding = str(lang), str(lang2), str(encoding) From 30d969bf72e54bb1438e7f209cf31e5a470592ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 28 Nov 2011 10:19:49 +0100 Subject: [PATCH 010/122] Fix response of wizard in form review184003 (transplanted from ffde9423355d0c0afe496229a8a65c55cb5b53c8) --- tryton/gui/window/wizard.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tryton/gui/window/wizard.py b/tryton/gui/window/wizard.py index c0cb89db23..a15d7b2fed 100644 --- a/tryton/gui/window/wizard.py +++ b/tryton/gui/window/wizard.py @@ -272,7 +272,8 @@ class WizardForm(Wizard,SignalEvent): def _get_button(self, state): button = super(WizardForm, self)._get_button(state) - button.connect('clicked', self.response, state[0]) + response = len(self.states) + button.connect('clicked', self.response, response) self.hbuttonbox.pack_start(button) return button From 42d767180c2b442ffd1a6c0e9acdf0ff05fb801b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 1 Dec 2011 15:28:38 +0100 Subject: [PATCH 011/122] Fix in operator to work with xxx2many review186004 (transplanted from 9b406777703293f8c3f4cab683e69d913a80cf6b) --- tryton/common/domain_inversion.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/tryton/common/domain_inversion.py b/tryton/common/domain_inversion.py index 62b262fb63..8da0a6aa2a 100644 --- a/tryton/common/domain_inversion.py +++ b/tryton/common/domain_inversion.py @@ -4,6 +4,12 @@ import operator import types +def in_(a, b): + if isinstance(a, (list, tuple)): + return any(operator.contains(b, x) for x in a) + else: + return operator.contains(b, a) + OPERATORS = { '=': operator.eq, '>': operator.gt, @@ -11,8 +17,8 @@ OPERATORS = { '<=': operator.le, '>=': operator.ge, '!=': operator.ne, - 'in': lambda a, b: operator.contains(b, a), - 'not in': lambda a, b: not operator.contains(b, a), + 'in': in_, + 'not in': lambda a, b: not in_(b, a), # Those operators are not supported (yet ?) 'like': lambda a, b: True, 'ilike': lambda a, b: True, @@ -390,6 +396,13 @@ def test_evaldomain(): assert eval_domain(domain, {'x': 6}) assert not eval_domain(domain, {'x': 4}) + domain = [['x', 'in', [3, 5]]] + assert eval_domain(domain, {'x': 3}) + assert not eval_domain(domain, {'x': 4}) + assert eval_domain(domain, {'x': [3]}) + assert eval_domain(domain, {'x': [3, 4]}) + assert not eval_domain(domain, {'x': [1, 2]}) + domain = ['OR', ['x', '>', 10], ['x', '<', 0]] assert eval_domain(domain, {'x': 11}) assert eval_domain(domain, {'x': -4}) From 9c9efdfc5837298832c66c597ac63bac7ea92a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 2 Dec 2011 11:43:40 +0100 Subject: [PATCH 012/122] Set fallback value of tdp to 0 for number fields issue2299 review191002 (transplanted from fdf105d7a334a0e33eae5fefda09ce345f4a6b4e) --- tryton/common/tdp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tryton/common/tdp.py b/tryton/common/tdp.py index 898965052e..9b7f372bd1 100644 --- a/tryton/common/tdp.py +++ b/tryton/common/tdp.py @@ -51,17 +51,17 @@ def cast(field, value): return conv(value) except ValueError: continue - return False + return 0 elif type_ == 'float': try: return float(value) except ValueError: - return False + return 0.0 elif type_ == 'numeric': try: return Decimal(value) except decimal.InvalidOperation: - return False + return Decimal(0) elif type_ in ('selection', 'reference'): for key, text in field['selection']: if text == value: From 9f6e5a87b4f46c9be592d7abd103ed0b9934ec72 Mon Sep 17 00:00:00 2001 From: Korbinian Preisler Date: Fri, 2 Dec 2011 07:26:13 +0100 Subject: [PATCH 013/122] Fix set_default of One2Many field issue2317 review193001 (transplanted from 5da1267ff35c7e9e74b8e5d7294c12e8fa3a9b86) --- tryton/gui/window/view_form/model/field.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index de3df47e14..d0f469e853 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -569,7 +569,7 @@ class O2MField(CharField): args = ('model', self.attrs['relation'], 'fields_get', field_names, context) try: - fields = rpc.execute(*args) + fields.update(rpc.execute(*args)) except TrytonServerError, exception: fields = common.process_exception(exception, *args) if not fields: From bc11841001933ac9d976a6bdd7e76db6b4d2dc4a Mon Sep 17 00:00:00 2001 From: Udo Spallek Date: Thu, 15 Dec 2011 16:03:37 +0100 Subject: [PATCH 014/122] Fix dialog hiding on row-activate signal in WinForm The fixed issue appeared only on screens using WinForm, like the attachment list opened from the toolbar. Screens used on a tab are not affected. issue2266 review201002 (transplanted from e19c447ee16c52f540da1d77e5dd1630e94eef48) --- tryton/gui/window/view_form/screen/screen.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index 90624554e5..3853549b54 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -288,12 +288,6 @@ class Screen(SignalEvent): def default_row_activate(self): from tryton.action import Action - from tryton.gui.main import Main - main = Main.get_main() - current_form = main.get_page() - if current_form: - for dialog in current_form.dialogs: - dialog.hide() if (self.current_view.view_type == 'tree' and self.current_view.widget_tree.keyword_open): From 12bf607fb5f1f6f2039e0350c8fa93be0802f5f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 17 Dec 2011 21:13:22 +0100 Subject: [PATCH 015/122] Test instance also for ComboBox GTK 2.24 and above use a ComboBox instead of a ComboBoxEntry issue2288 review207001 (transplanted from acdc4008c2fbaaf3e4d0c6079ea871c0544aee77) --- tryton/gui/window/view_form/view/list_gtk/editabletree.py | 2 +- tryton/gui/window/view_form/view/list_gtk/parser.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tryton/gui/window/view_form/view/list_gtk/editabletree.py b/tryton/gui/window/view_form/view/list_gtk/editabletree.py index d013c85fc5..3c79a7b592 100644 --- a/tryton/gui/window/view_form/view/list_gtk/editabletree.py +++ b/tryton/gui/window/view_form/view/list_gtk/editabletree.py @@ -265,5 +265,5 @@ class EditableTreeView(gtk.TreeView): record = model.get_value(model.get_iter(path), 0) if isinstance(entry, gtk.Entry): self.on_quit_cell(record, column.name, entry.get_text()) - elif isinstance(entry, gtk.ComboBoxEntry): + elif isinstance(entry, (gtk.ComboBoxEntry, gtk.ComboBox)): self.on_quit_cell(record, column.name, entry.get_active_text()) 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 f5440280ee..ac66ca0c21 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -36,7 +36,7 @@ def send_keys(renderer, editable, position, treeview): editable.connect('key_press_event', treeview.on_keypressed) editable.editing_done_id = editable.connect('editing_done', treeview.on_editing_done) - if isinstance(editable, gtk.ComboBoxEntry): + if isinstance(editable, (gtk.ComboBoxEntry, gtk.ComboBox)): editable.connect('changed', treeview.on_editing_done) def sort_model(column, treeview, screen): From 579ee4b4a790e393620024eb72a77882ff7d6344 Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 26 Dec 2011 10:41:38 +0100 Subject: [PATCH 016/122] Prepare release 2.2.1 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 41e964a0e7..5d86a51ab9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.2.1 - 2011-12-26 +* Bug fixes (see mercurial logs for details) + Version 2.2.0 - 2011-10-24 * Bug fixes (see mercurial logs for details) * New search widget From 17ebb7242b51f1653fb73533c72f20312d69b255 Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 26 Dec 2011 10:41:38 +0100 Subject: [PATCH 017/122] Added tag 2.2.1 for changeset 3fdf4ae699be --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index e368610e90..0118ac4448 100644 --- a/.hgtags +++ b/.hgtags @@ -5,3 +5,4 @@ de84c1443d4bad908eabb99c381578b988c2117f 1.4.0 8aa050da53cbdfabe1353a37da91c011b7fff549 1.8.0 1876747b3f963ba6011b4bcf6968e681624c6e24 2.0.0 5364f8ca6cd2cccfb5f7f39c69bb20bae2b5f495 2.2.0 +3fdf4ae699be5abbf9ebbb83fea5678e7f370179 2.2.1 From 5f91db6c873c7340309102d57dfc5a6a94b8be5f Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 26 Dec 2011 10:42:07 +0100 Subject: [PATCH 018/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index 77eeb3869e..3b71650e0b 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.1" +VERSION = "2.2.2" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 0afebcb6f962709fdb818e44eff86e8257fe73ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 2 Jan 2012 18:50:01 +0100 Subject: [PATCH 019/122] Remove entry added to combobox in win_import review210009 (transplanted from 40d5157e9d58f50a00464d280de36a4a0af4a876) --- tryton/gui/window/win_import.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tryton/gui/window/win_import.py b/tryton/gui/window/win_import.py index 06f6b441aa..e9c9b3797a 100644 --- a/tryton/gui/window/win_import.py +++ b/tryton/gui/window/win_import.py @@ -145,9 +145,6 @@ class WinImport(object): self.import_csv_enc = gtk.combo_box_new_text() self.import_csv_enc.append_text("UTF-8") self.import_csv_enc.append_text("Latin1") - cboxent_import_csv_enc = gtk.Entry() - cboxent_import_csv_enc.unset_flags(gtk.CAN_FOCUS) - self.import_csv_enc.add(cboxent_import_csv_enc) table.attach(self.import_csv_enc, 1, 2, 1, 2) label_import_csv_skip = gtk.Label(_("Lines to Skip:")) From 0b243e8d2d8b73f1af13bea0ce4325fbf60955c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 4 Jan 2012 20:05:54 +0100 Subject: [PATCH 020/122] Fix reseting reference value on focus_out issue2364 review212005 (transplanted from 2e96554600a4ef9988e07704ecb58ed6e0cae6e1) --- tryton/gui/window/view_form/view/form_gtk/reference.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/view/form_gtk/reference.py b/tryton/gui/window/view_form/view/form_gtk/reference.py index adb7d11303..b84f82ca85 100644 --- a/tryton/gui/window/view_form/view/form_gtk/reference.py +++ b/tryton/gui/window/view_form/view/form_gtk/reference.py @@ -212,7 +212,8 @@ class Reference(WidgetInterface): WinSearch(model, callback, sel_multi=False, ids=ids, context=context, domain=domain) return - self.field.set_client(self.record, ('', (name, name))) + else: + self.field.set_client(self.record, ('', (name, name))) self.focus_out = True self.changed = True self.display(self.record, self.field) From da811e97303bd719bf0fdb4cef793ef4e40a1412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 9 Jan 2012 21:05:26 +0100 Subject: [PATCH 021/122] Let faultString as unicode issue2359 (transplanted from 24682669fee7ff4dd1011ac315155bff3430ce6a) --- tryton/jsonrpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/jsonrpc.py b/tryton/jsonrpc.py index a38f4a97c0..a4c1c1767c 100644 --- a/tryton/jsonrpc.py +++ b/tryton/jsonrpc.py @@ -29,7 +29,7 @@ class ResponseError(xmlrpclib.ResponseError): class Fault(xmlrpclib.Fault): def __init__(self, faultCode, faultString='', **extra): - super(Fault, self).__init__(faultCode, str(faultString), **extra) + super(Fault, self).__init__(faultCode, faultString, **extra) self.args = faultString From 93ba979102c082c1a313ca6107d2735852d0b2ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 10 Jan 2012 00:28:15 +0100 Subject: [PATCH 022/122] set_value before testing if screen was modified Behavior of Screen.modified was changed in c003e96b971d issue2352 review207005 (transplanted from 3584ce0cf70ee3c93e2ab291dc4a1020f9d48d50) --- tryton/gui/window/form.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tryton/gui/window/form.py b/tryton/gui/window/form.py index 7c9e27df5e..7e46d07cfa 100644 --- a/tryton/gui/window/form.py +++ b/tryton/gui/window/form.py @@ -476,6 +476,7 @@ class Form(SignalEvent, TabContent): self.activate_save() def modified_save(self, reload=True): + self.screen.current_view.set_value() if self.screen.modified(): value = sur_3b( _('This record has been modified\n' \ From 319d7ac1ef60f8dda8e7109036365f425a6282cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 11 Jan 2012 10:44:26 +0100 Subject: [PATCH 023/122] Ensure that loading is always eager for fields on tree view issue2378 review220001 (transplanted from 65513b69d0913f4443eb53ebe1a4e449ae1570b9) --- tryton/gui/window/view_form/screen/screen.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index 3853549b54..4b08eab039 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -368,6 +368,8 @@ class Screen(SignalEvent): self.fields_view_tree = view break + # Ensure that loading is always eager for fields on tree view + # and always lazy for fields only on form view if node.localName == 'tree': loading = 'eager' else: @@ -375,6 +377,9 @@ class Screen(SignalEvent): for field in fields: if field not in self.group.fields: fields[field]['loading'] = loading + else: + fields[field]['loading'] = \ + self.group.fields[field].attrs['loading'] children_field = view.get('field_childs') From 6af4c5ddae8cfda427c3b70becf9584a1930ba72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 17 Jan 2012 13:56:50 +0100 Subject: [PATCH 024/122] Fix float_time widget to round value according to digits review222007 (transplanted from 2aa50bbdde4d89b314fd85b24ec4dcf7f4f0a56d) --- tryton/gui/window/view_form/view/form_gtk/float_time.py | 3 ++- tryton/gui/window/view_form/view/list_gtk/parser.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tryton/gui/window/view_form/view/form_gtk/float_time.py b/tryton/gui/window/view_form/view/form_gtk/float_time.py index 1644babecf..86c2d497eb 100644 --- a/tryton/gui/window/view_form/view/form_gtk/float_time.py +++ b/tryton/gui/window/view_form/view/form_gtk/float_time.py @@ -35,8 +35,9 @@ class FloatTime(WidgetInterface): value = self.entry.get_text() if not value: return field.set_client(record, 0.0) + digits = record.expr_eval(field.attrs.get('digits', (16, 2))) return field.set_client(record, - common.text_to_float_time(value, self.conv)) + round(common.text_to_float_time(value, self.conv), digits[1])) def display(self, record, field): super(FloatTime, self).display(record, field) 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 ac66ca0c21..75854982c3 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -501,7 +501,9 @@ class FloatTime(Char): def value_from_text(self, record, text, callback=None): field = record[self.field_name] - field.set_client(record, common.text_to_float_time(text, self.conv)) + digits = record.expr_eval(field.attrs.get('digits', (16, 2))) + field.set_client(record, + round(common.text_to_float_time(text, self.conv), digits[1])) if callback: callback() From 11c19240d7a1c43fd2036f6490ab5ec59686431a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 17 Jan 2012 15:38:02 +0100 Subject: [PATCH 025/122] Destroy also values of record Otherwise the groups of xxx2many records stay in the memory due to reference cycle between Group and Record. review222006 (transplanted from 34842c74fbc585bd9b8e9a3be64fa2640967ece7) --- tryton/gui/window/view_form/model/record.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py index 128f3a41b1..9f9890f457 100644 --- a/tryton/gui/window/view_form/model/record.py +++ b/tryton/gui/window/view_form/model/record.py @@ -584,5 +584,8 @@ class Record(SignalEvent): def destroy(self): super(Record, self).destroy() self.group = None + for v in self.value.itervalues(): + if hasattr(v, 'destroy'): + v.destroy() self.value = None self.next = None From 8da66191a1e952aed38bd918a21f31f9a37c8f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 22 Jan 2012 00:13:19 +0100 Subject: [PATCH 026/122] Fix pyflakes error on board parser review228003 (transplanted from 0f5e073360cd080788040b5609b4b9b3433fa6ae) --- tryton/gui/window/view_board/parser.py | 48 +++++++++----------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/tryton/gui/window/view_board/parser.py b/tryton/gui/window/view_board/parser.py index 7aa0abedd0..e22021cf80 100644 --- a/tryton/gui/window/view_board/parser.py +++ b/tryton/gui/window/view_board/parser.py @@ -2,10 +2,13 @@ #this repository contains the full copyright notices and license terms. 'Parser' import gtk -from tryton.gui.window.view_form.view.form_gtk.parser import _container +import gettext +from tryton.gui.window.view_form.view.form_gtk.parser import _container, VBox import tryton.common as common from action import Action -from tryton.config import CONFIG, TRYTON_ICON +from tryton.config import CONFIG + +_ = gettext.gettext class ParserBoard(object): @@ -47,13 +50,6 @@ class ParserBoard(object): xexpand=xexpand, xfill=xfill) elif node.localName == 'separator': text = attrs.get('string', '') - if 'string' in attrs or 'name' in attrs: - if not text: - if 'name' in attrs and attrs['name'] in fields: - if 'states' in fields[attrs['name']]: - attrs['states'] = \ - fields[attrs['name']]['states'] - text = fields[attrs['name']]['string'] vbox = VBox(attrs=attrs) if text: label = gtk.Label(text) @@ -68,22 +64,6 @@ class ParserBoard(object): xexpand=xexpand, xfill=xfill) elif node.localName == 'label': text = attrs.get('string', '') - if not text: - if 'name' in attrs and attrs['name'] in fields: - if 'states' in fields[attrs['name']]: - attrs['states'] = fields[attrs['name']]['states'] - if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: - text = _(':') + fields[attrs['name']]['string'] - else: - text = fields[attrs['name']]['string'] + _(':') - if 'align' not in attrs: - attrs['align'] = 1.0 - else: - for node in node.childNodes: - if node.nodeType == node.TEXT_NODE: - text += node.data - else: - text += node.toxml() if not text: container.empty_add(int(attrs.get('colspan', 1))) continue @@ -115,7 +95,8 @@ class ParserBoard(object): container.wid_add(notebook, colspan=int(attrs.get('colspan', 4)), yexpand=True, yfill=True) - widget, new_widgets = self.parse(node, notebook, tooltips=tooltips) + widget, new_widgets = self.parse(node, notebook, + tooltips=tooltips) widgets += new_widgets elif node.localName == 'page': if CONFIG['client.form_tab'] == 'left': @@ -124,9 +105,10 @@ class ParserBoard(object): angle = -90 else: angle = 0 - label = gtk.Label(attrs.get('string','No String Attr.')) + label = gtk.Label(attrs.get('string', _('No String Attr.'))) label.set_angle(angle) - widget, new_widgets = self.parse(node, notebook, tooltips=tooltips) + widget, new_widgets = self.parse(node, notebook, + tooltips=tooltips) widgets += new_widgets notebook.append_page(widget, label) elif node.localName == 'group': @@ -145,7 +127,8 @@ class ParserBoard(object): hpaned = gtk.HPaned() container.wid_add(hpaned, colspan=int(attrs.get('colspan', 4)), yexpand=True, yfill=True) - widget, new_widgets = self.parse(node, paned=hpaned, tooltips=tooltips) + widget, new_widgets = self.parse(node, paned=hpaned, + tooltips=tooltips) widgets += new_widgets if 'position' in attrs: hpaned.set_position(int(attrs['position'])) @@ -153,19 +136,20 @@ class ParserBoard(object): vpaned = gtk.VPaned() container.wid_add(vpaned, colspan=int(attrs.get('colspan', 4)), yexpand=True, yfill=True) - widget, new_widgets = self.parse(node, paned=vpaned, tooltips=tooltips) + widget, new_widgets = self.parse(node, paned=vpaned, + tooltips=tooltips) widgets += new_widgets if 'position' in attrs: vpaned.set_position(int(attrs['position'])) elif node.localName == 'child': - widget, new_widgets = self.parse(node, paned=paned, tooltips=tooltips) + widget, new_widgets = self.parse(node, paned=paned, + tooltips=tooltips) widgets += new_widgets if not paned.get_child1(): paned.pack1(widget, resize=True, shrink=True) elif not paned.get_child2(): paned.pack2(widget, resize=True, shrink=True) elif node.localName == 'action': - name = str(attrs['name']) widget_act = Action(attrs, self.context) widgets.append(widget_act) yexpand = bool(attrs.get('yexpand', 1)) From e57a6ca44664113c9b4236e34fe1299c78834c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 22 Jan 2012 00:14:49 +0100 Subject: [PATCH 027/122] Fix pyflakes error on WinForm review226006 (transplanted from 9e489858af8ae6720dbc31d94dfc49ca9078f68b) --- tryton/gui/window/win_form.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/tryton/gui/window/win_form.py b/tryton/gui/window/win_form.py index c81cf0c286..da34c31041 100644 --- a/tryton/gui/window/win_form.py +++ b/tryton/gui/window/win_form.py @@ -1,6 +1,6 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. -from tryton.common import TRYTON_ICON +from tryton.common import TRYTON_ICON, COLOR_SCHEMES import tryton.common as common from tryton.config import CONFIG import gtk @@ -8,6 +8,7 @@ import pango import gettext from tryton.exceptions import TrytonServerError from tryton.gui.window.nomodal import NoModal +import tryton.rpc as rpc _ = gettext.gettext @@ -56,7 +57,7 @@ class WinForm(NoModal): if new and many: self.but_ok.add_accelerator('clicked', self.accel_group, gtk.keysyms.Return, - gtk.gdk.CONTROL_MASK|gtk.gdk.SHIFT_MASK, + gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK, gtk.ACCEL_VISIBLE) self.but_new = self.win.add_button(gtk.STOCK_NEW, @@ -130,7 +131,8 @@ class WinForm(NoModal): tooltips.set_tip(self.but_del, _('Delete selected record')) self.but_del.connect('clicked', self._sig_remove) img_del = gtk.Image() - img_del.set_from_stock('tryton-delete', gtk.ICON_SIZE_SMALL_TOOLBAR) + img_del.set_from_stock('tryton-delete', + gtk.ICON_SIZE_SMALL_TOOLBAR) img_del.set_alignment(0.5, 0.5) self.but_del.add(img_del) self.but_del.set_relief(gtk.RELIEF_NONE) @@ -142,7 +144,8 @@ class WinForm(NoModal): tooltips.set_tip(but_pre, _('Previous')) but_pre.connect('clicked', self._sig_previous) img_pre = gtk.Image() - img_pre.set_from_stock('tryton-go-previous', gtk.ICON_SIZE_SMALL_TOOLBAR) + img_pre.set_from_stock('tryton-go-previous', + gtk.ICON_SIZE_SMALL_TOOLBAR) img_pre.set_alignment(0.5, 0.5) but_pre.add(img_pre) but_pre.set_relief(gtk.RELIEF_NONE) @@ -155,7 +158,8 @@ class WinForm(NoModal): tooltips.set_tip(but_next, _('Next')) but_next.connect('clicked', self._sig_next) img_next = gtk.Image() - img_next.set_from_stock('tryton-go-next', gtk.ICON_SIZE_SMALL_TOOLBAR) + img_next.set_from_stock('tryton-go-next', + gtk.ICON_SIZE_SMALL_TOOLBAR) img_next.set_alignment(0.5, 0.5) but_next.add(img_next) but_next.set_relief(gtk.RELIEF_NONE) @@ -167,7 +171,8 @@ class WinForm(NoModal): tooltips.set_tip(but_switch, _('Switch')) but_switch.connect('clicked', self.switch_view) img_switch = gtk.Image() - img_switch.set_from_stock('tryton-fullscreen', gtk.ICON_SIZE_SMALL_TOOLBAR) + img_switch.set_from_stock('tryton-fullscreen', + gtk.ICON_SIZE_SMALL_TOOLBAR) img_switch.set_alignment(0.5, 0.5) but_switch.add(img_switch) but_switch.set_relief(gtk.RELIEF_NONE) @@ -251,6 +256,7 @@ class WinForm(NoModal): from tryton.gui.window.win_search import WinSearch domain = [] context = rpc.CONTEXT.copy() + model_name = self.screen.model_name try: if self.wid_text.get_text(): @@ -258,7 +264,7 @@ class WinForm(NoModal): '%' + self.wid_text.get_text() + '%'), domain] else: dom = domain - ids = rpc.execute('model', self.attrs['relation'], 'search', dom, + ids = rpc.execute('model', model_name, 'search', dom, 0, CONFIG['client.limit'], None, context) except TrytonServerError, exception: common.process_exception(exception) @@ -275,9 +281,8 @@ class WinForm(NoModal): self.wid_text.set_text('') if len(ids) != 1: - WinSearch(self.attrs['relation'], callback, sel_multi=True, - ids=ids, context=context, domain=domain, - views_preload=self.attrs.get('views', {})) + WinSearch(model_name, callback, sel_multi=True, + ids=ids, context=context, domain=domain) else: callback(ids) From 59855bd600ca6838ebf2a5efef96ef7bc99776fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 22 Jan 2012 00:43:47 +0100 Subject: [PATCH 028/122] Fix typo new_ids -> new_id (transplanted from 59b613997c39fddb8c3520373806ffd83c489ce9) --- tryton/gui/window/win_export.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/gui/window/win_export.py b/tryton/gui/window/win_export.py index 94499aa958..32cf1dfd94 100644 --- a/tryton/gui/window/win_export.py +++ b/tryton/gui/window/win_export.py @@ -327,7 +327,7 @@ class WinExport(object): try: new_id = rpc.execute(*args) except TrytonServerError, exception: - new_ids = common.process_exception(exception, self.dialog, *args) + new_id = common.process_exception(exception, self.dialog, *args) if not new_id: return self.predef_model.append(( From 53246baa8fe68550e345c01077db17055f693371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 22 Jan 2012 23:33:43 +0100 Subject: [PATCH 029/122] Fix send_bugtracker call (transplanted from e9e8737463ca83ad999abc01351fdd123a02e881) --- tryton/common/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/common/common.py b/tryton/common/common.py index a68a88d978..f4f96a186b 100644 --- a/tryton/common/common.py +++ b/tryton/common/common.py @@ -954,7 +954,7 @@ def send_bugtracker(msg): and 'roundup.cgi.exceptions.Unauthorised' in exception.faultString): message(_('Connection error!\nBad username or password!')) - return send_bugtracker(msg, parent) + return send_bugtracker(msg) tb_s = reduce(lambda x, y: x + y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)) From 0a9facf971879e75cb02870fa976f2181180d1e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Fri, 27 Jan 2012 12:27:07 +0100 Subject: [PATCH 030/122] Set selection on treeview when they receive focus review210008 issue2355 (transplanted from 010c12a566b110ed2a7e8125a305511370ad8873) --- tryton/gui/window/view_form/screen/screen.py | 2 ++ tryton/gui/window/view_form/view/list_gtk/parser.py | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index 4b08eab039..3bd4907f7c 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -545,6 +545,8 @@ class Screen(SignalEvent): records = [self.current_record] elif self.current_view.view_type == 'tree': records = self.current_view.selected_records() + if not records: + return if delete: if not self.group.delete(records): return False 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 75854982c3..c1736cd0be 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -90,6 +90,7 @@ class ParserTree(ParserInterface): treeview.sequence = attrs.get('sequence', False) treeview.colors = attrs.get('colors', '"black"') treeview.keyword_open = attrs.get('keyword_open', False) + treeview.connect('focus', self.set_selection) self.treeview = treeview treeview.set_property('rules-hint', True) if not self.title: @@ -258,6 +259,12 @@ class ParserTree(ParserInterface): treeview.set_fixed_height_mode(True) return treeview, dict_widget, button_list, on_write, [], None + def set_selection(self, treeview, direction): + selection = treeview.get_selection() + if len(treeview.get_model()): + selection.select_path(0) + return False + class Char(object): From f5f72a3ae4a28c3a3c793786db5d989770ff8be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 7 Feb 2012 14:00:10 +0100 Subject: [PATCH 031/122] Fix timezoned usage introduced in 3b034f9ce9c0 issue2439 review237003 --- tryton/common/common.py | 10 ++++++++-- tryton/gui/window/view_form/view/form_gtk/calendar.py | 4 ++-- tryton/gui/window/view_form/view/list_gtk/parser.py | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tryton/common/common.py b/tryton/common/common.py index a68a88d978..d5b1e91e49 100644 --- a/tryton/common/common.py +++ b/tryton/common/common.py @@ -1461,11 +1461,17 @@ def safe_eval(source, data=None): 'dict': dict, }}, data) -def timezoned_date(date): - if pytz and rpc.CONTEXT.get('timezone'): +def timezoned_date(date, reverse=False): + if pytz and rpc.CONTEXT.get('timezone') and rpc.TIMEZONE: lzone = pytz.timezone(rpc.CONTEXT['timezone']) szone = pytz.timezone(rpc.TIMEZONE) + if reverse: + lzone, szone = szone, lzone sdt = szone.localize(date, is_dst=True) ldt = sdt.astimezone(lzone) date = ldt return date + + +def untimezoned_date(date): + return timezoned_date(date, reverse=True).replace(tzinfo=None) diff --git a/tryton/gui/window/view_form/view/form_gtk/calendar.py b/tryton/gui/window/view_form/view/form_gtk/calendar.py index 0966ee1d28..2a3e1bb256 100644 --- a/tryton/gui/window/view_form/view/form_gtk/calendar.py +++ b/tryton/gui/window/view_form/view/form_gtk/calendar.py @@ -8,7 +8,7 @@ import locale from interface import WidgetInterface import tryton.rpc as rpc from tryton.common import DT_FORMAT, DHM_FORMAT, HM_FORMAT, message, \ - TRYTON_ICON, timezoned_date + TRYTON_ICON, timezoned_date, untimezoned_date from tryton.common import date_widget, Tooltips, datetime_strftime, \ get_toplevel_window from tryton.translate import date_format @@ -192,7 +192,7 @@ class DateTime(WidgetInterface): date = datetime.datetime(*time.strptime(value, self.format)[:6]) except ValueError: return False - date = timezoned_date(date) + date = untimezoned_date(date) return datetime_strftime(date, DHM_FORMAT) def set_value(self, record, field): 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 ac66ca0c21..a346eadd49 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -446,7 +446,7 @@ class Datetime(Date): try: date = datetime.datetime(*time.strptime(text, self.display_format)[:6]) - date = common.timezoned_date(date) + date = common.untimezoned_date(date) date = common.datetime_strftime(date, self.server_format) except ValueError: date = False From c0157e618615ff1a10c0de945fa047a8cb2fcbae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 29 Jan 2012 16:29:12 +0100 Subject: [PATCH 032/122] Fix missing no-modal convertion in import/export dialogs issue2337 review233003 (transplanted from 0bcfcc837ebbc625597566c03fea5eed5133d0dd) --- tryton/gui/window/win_export.py | 6 +++--- tryton/gui/window/win_import.py | 15 ++++++--------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/tryton/gui/window/win_export.py b/tryton/gui/window/win_export.py index 32cf1dfd94..609391920b 100644 --- a/tryton/gui/window/win_export.py +++ b/tryton/gui/window/win_export.py @@ -327,7 +327,7 @@ class WinExport(object): try: new_id = rpc.execute(*args) except TrytonServerError, exception: - new_id = common.process_exception(exception, self.dialog, *args) + new_id = common.process_exception(exception, *args) if not new_id: return self.predef_model.append(( @@ -348,7 +348,7 @@ class WinExport(object): try: rpc.execute(*args) except TrytonServerError, exception: - if not common.process_exception(exception, self.dialog, *args): + if not common.process_exception(exception, *args): return for i in range(len(self.predef_model)): if self.predef_model[i][0] == export_id: @@ -444,6 +444,6 @@ class WinExport(object): datas = rpc.execute('model', model, 'export_data', ids, fields, ctx) except TrytonServerError, exception: - common.process_exception(exception, self.dialog) + common.process_exception(exception) return [] return datas diff --git a/tryton/gui/window/win_import.py b/tryton/gui/window/win_import.py index e9c9b3797a..b9d0f7c3c7 100644 --- a/tryton/gui/window/win_import.py +++ b/tryton/gui/window/win_import.py @@ -228,7 +228,7 @@ class WinImport(object): try: return rpc.execute(*args) except TrytonServerError, exception: - return common.process_exception(exception, self.dialog, *args) + return common.process_exception(exception, *args) def on_row_expanded(self, treeview, iter, path): child = self.model1.iter_children(iter) @@ -242,8 +242,7 @@ class WinImport(object): def sig_autodetect(self, widget=None): fname = self.import_csv_file.get_filename() if not fname: - common.message(_('You must select an import file first!'), - self.dialog) + common.message(_('You must select an import file first!')) return True csvsep = self.import_csv_sep.get_text() csvdel = self.import_csv_del.get_text() @@ -255,8 +254,7 @@ class WinImport(object): data = csv.reader(open(fname, 'rb'), quotechar=csvdel, delimiter=csvsep) except IOError: - common.warning(_('Error opening CSV file'), self.dialog, - _('Error')) + common.warning(_('Error opening CSV file'), _('Error')) return True self.sig_unsel_all() word = '' @@ -284,9 +282,8 @@ class WinImport(object): name = self.fields[word][0] field = word else: - common.warning( - _('Error processing the file at field %s.') % - word, self.dialog, _('Error')) + common.warning(_('Error processing the file at field %s.') + % word, _('Error')) return True num = self.model2.append() self.model2.set(num, 0, name, 1, field) @@ -353,7 +350,7 @@ class WinImport(object): res = rpc.execute('model', model, 'import_data', fields, datas, rpc.CONTEXT) except TrytonServerError, exception: - common.process_exception(exception, self.dialog) + common.process_exception(exception) return False if res[0] >= 0: if res[0] == 1: From 1e72923b179603211c1768b232e38e388a0ef734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 31 Jan 2012 13:07:35 +0100 Subject: [PATCH 033/122] Better management of focus out in Many2Many review233004 (transplanted from 90cbdbd119a95a05e7dd5ac5c129b9978cd46191) --- tryton/gui/window/view_form/view/form_gtk/many2many.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tryton/gui/window/view_form/view/form_gtk/many2many.py b/tryton/gui/window/view_form/view/form_gtk/many2many.py index fc5915f04f..c429d46b06 100644 --- a/tryton/gui/window/view_form/view/form_gtk/many2many.py +++ b/tryton/gui/window/view_form/view/form_gtk/many2many.py @@ -37,6 +37,7 @@ class Many2Many(WidgetInterface): self.wid_text.set_property('width_chars', 13) self.wid_text.connect('activate', self._sig_activate) self.wid_text.connect('focus-out-event', self._focus_out) + self.focus_out = True hbox.pack_start(self.wid_text, expand=True, fill=True) self.but_add = gtk.Button() @@ -120,10 +121,13 @@ class Many2Many(WidgetInterface): self._sig_add() def _sig_add(self, *args): + if not self.focus_out: + return domain = self.field.domain_get(self.record) context = self.field.context_get(self.record) value = self.wid_text.get_text() + self.focus_out = False try: if value: dom = [('rec_name', 'ilike', '%' + value + '%'), domain] @@ -133,12 +137,14 @@ class Many2Many(WidgetInterface): dom , 0, CONFIG['client.limit'], None, context) except TrytonServerError, exception: common.process_exception(exception) + self.focus_out = True return False def callback(ids): res_id = None if ids: res_id = ids[0] + self.focus_out = True self.screen.load(ids, modified=True) self.screen.display(res_id=res_id) if self.screen.current_view: From bdd2985995d61ceae3135c283341cbad8b77cdef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 31 Jan 2012 13:09:36 +0100 Subject: [PATCH 034/122] Prevent unnecessary refresh of database review233005 (transplanted from ab5901dee41e8ef380d9d771b211436640f6c4d8) --- tryton/gui/window/dblogin.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tryton/gui/window/dblogin.py b/tryton/gui/window/dblogin.py index 4e28d7c2bb..99e65b6984 100644 --- a/tryton/gui/window/dblogin.py +++ b/tryton/gui/window/dblogin.py @@ -26,6 +26,7 @@ class DBListEditor(object): self.profiles = profiles self.current_database = None self.old_profile, self.current_profile = None, None + self.db_cache = None self.updating_db = False # GTK Stuffs @@ -290,6 +291,8 @@ class DBListEditor(object): port = self.port_entry.get_text() if not (host and port): return + if (host, port, self.current_profile['name']) == self.db_cache: + return if self.updating_db: return if dbname is None: @@ -307,6 +310,7 @@ class DBListEditor(object): def callback(dbs, createdb): self.updating_db = False + self.db_cache = (host, port, self.current_profile['name']) if dbs is None and createdb is None: pass @@ -343,6 +347,7 @@ class DBListEditor(object): port = int(self.port_entry.get_text()) dia = DBCreate(host, port) dbname = dia.run() + self.db_cache = None self.username_entry.set_text('admin') self.display_dbwidget(None, None, dbname) From 2a80c683a24940405587110557211b89886738b0 Mon Sep 17 00:00:00 2001 From: Oscar Alvarez Date: Mon, 30 Jan 2012 22:06:29 -0500 Subject: [PATCH 035/122] Fix the export wizard for load all predef fields saved It modified using method iter_children issue2383 review219002 (transplanted from 232508536908ca64d4f8380896e884d6d1093acf) --- tryton/gui/window/win_export.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tryton/gui/window/win_export.py b/tryton/gui/window/win_export.py index 609391920b..bf857d99ad 100644 --- a/tryton/gui/window/win_export.py +++ b/tryton/gui/window/win_export.py @@ -368,9 +368,12 @@ class WinExport(object): (prefix + parent): self.on_row_expanded(self.view1, iter, self.model1.get_path(iter)) + iter = self.model1.iter_children(iter) + prefix = parent + '/' break - iter = self.model1.iter_next(iter) - prefix = parent + '/' + else: + iter = self.model1.iter_next(iter) + if field not in self.fields_data: continue self.model2.append((self.fields_data[field]['string'], field)) From 67f46a7dc5670efc5e76d1f3b5cfed368b11ad2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 1 Feb 2012 17:11:41 +0100 Subject: [PATCH 036/122] Remove edit_canceled as empty profile is managed by edit_profilename issue2292 review237001 (transplanted from 9a4dc93abe96d51322877c973768ee31fa09ec8f) --- tryton/gui/window/dblogin.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tryton/gui/window/dblogin.py b/tryton/gui/window/dblogin.py index 99e65b6984..5079cf30c7 100644 --- a/tryton/gui/window/dblogin.py +++ b/tryton/gui/window/dblogin.py @@ -44,7 +44,6 @@ class DBListEditor(object): self.cell.set_property('editable', True) self.cell.connect('edited', self.edit_profilename) self.cell.connect('editing-started', self.edit_started) - self.cell.connect('editing-canceled', self.edit_canceled) self.profile_tree = gtk.TreeView() self.profile_tree.set_model(profile_store) self.profile_tree.insert_column_with_attributes(-1, _(u'Profile'), @@ -232,12 +231,6 @@ class DBListEditor(object): self.display_dbwidget(None, None, self.current_database) - def edit_canceled(self, renderer): - model = self.profile_tree.get_model() - for i, row in enumerate(list(model)): - if not row[0]: - del model[i] - def check_edit_cancel(self, editable, event, renderer, path): renderer.emit('edited', path, editable.get_text()) return False From 52afe2fba73f50a159cfb854104c7e19401992cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 21 Feb 2012 16:19:03 +0100 Subject: [PATCH 037/122] Remove trailing space (transplanted from af3e207f00156b9388eb124ce13cb3380e81b670) --- tryton/gui/window/win_export.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/gui/window/win_export.py b/tryton/gui/window/win_export.py index bf857d99ad..79dae47296 100644 --- a/tryton/gui/window/win_export.py +++ b/tryton/gui/window/win_export.py @@ -373,7 +373,7 @@ class WinExport(object): break else: iter = self.model1.iter_next(iter) - + if field not in self.fields_data: continue self.model2.append((self.fields_data[field]['string'], field)) From 78219075cd287268ee8140a6ae0192d40cee1bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 22 Feb 2012 11:50:38 +0100 Subject: [PATCH 038/122] Return textview when duplicate Text widget for translation issue2460 review249005 --- tryton/gui/window/view_form/view/form_gtk/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/view/form_gtk/parser.py b/tryton/gui/window/view_form/view/form_gtk/parser.py index 19bef6269c..36fa795bcd 100644 --- a/tryton/gui/window/view_form/view/form_gtk/parser.py +++ b/tryton/gui/window/view_form/view/form_gtk/parser.py @@ -732,7 +732,7 @@ class ParserForm(ParserInterface): scrolledwindow.set_size_request(-1, 80) scrolledwindow.add(textview) textview.set_accepts_tab(False) - return scrolledwindow, gtk.FILL | gtk.EXPAND + return textview, gtk.FILL | gtk.EXPAND else: return None, False From 368790bc0c9c0cb98e464e57b1e030dbc74c19d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 9 Mar 2012 23:10:48 +0100 Subject: [PATCH 039/122] Manage timezone in get_value of DateTime widget The code was wrongly removed in changeset 3b034f9ce9c0 issue2486 --- tryton/gui/window/view_form/view/form_gtk/calendar.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/view/form_gtk/calendar.py b/tryton/gui/window/view_form/view/form_gtk/calendar.py index 2a3e1bb256..a3982ee6ce 100644 --- a/tryton/gui/window/view_form/view/form_gtk/calendar.py +++ b/tryton/gui/window/view_form/view/form_gtk/calendar.py @@ -192,7 +192,8 @@ class DateTime(WidgetInterface): date = datetime.datetime(*time.strptime(value, self.format)[:6]) except ValueError: return False - date = untimezoned_date(date) + if timezone: + date = untimezoned_date(date) return datetime_strftime(date, DHM_FORMAT) def set_value(self, record, field): From 79dc2d1d297b5ca523c11e6e42e08d3e2500513a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 12 Mar 2012 15:17:03 +0100 Subject: [PATCH 040/122] Manage timezone in show of DateTime widget issue2490 --- tryton/gui/window/view_form/view/form_gtk/calendar.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/view/form_gtk/calendar.py b/tryton/gui/window/view_form/view/form_gtk/calendar.py index a3982ee6ce..e6e28ae09c 100644 --- a/tryton/gui/window/view_form/view/form_gtk/calendar.py +++ b/tryton/gui/window/view_form/view/form_gtk/calendar.py @@ -211,7 +211,8 @@ class DateTime(WidgetInterface): self.entry.clear() else: date = datetime.datetime(*time.strptime(dt_val, DHM_FORMAT)[:6]) - date = timezoned_date(date) + if timezone: + date = timezoned_date(date) value = datetime_strftime(date, self.format) if len(value) > self.entry.get_width_chars(): self.entry.set_width_chars(len(value)) From 3a7c52920581b60d3d4cb4b2814de3fa4a5faa1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 22 Feb 2012 17:20:50 +0100 Subject: [PATCH 041/122] Prevent double sent of edited event Rely only on the focus-out-event of the editable otherwise the edited event can be sent twice and if the selected profile was removed it generates a IndexError. (transplanted from 14d5bec084d1cf4550faa04bbd850b4004e8246d) --- tryton/gui/window/dblogin.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tryton/gui/window/dblogin.py b/tryton/gui/window/dblogin.py index 5079cf30c7..44a75264e7 100644 --- a/tryton/gui/window/dblogin.py +++ b/tryton/gui/window/dblogin.py @@ -42,7 +42,6 @@ class DBListEditor(object): vbox_profiles = gtk.VBox(homogeneous=False, spacing=6) self.cell = gtk.CellRendererText() self.cell.set_property('editable', True) - self.cell.connect('edited', self.edit_profilename) self.cell.connect('editing-started', self.edit_started) self.profile_tree = gtk.TreeView() self.profile_tree.set_model(profile_store) @@ -231,16 +230,13 @@ class DBListEditor(object): self.display_dbwidget(None, None, self.current_database) - def check_edit_cancel(self, editable, event, renderer, path): - renderer.emit('edited', path, editable.get_text()) - return False - def edit_started(self, renderer, editable, path): if isinstance(editable, gtk.Entry): - editable.connect('focus-out-event', self.check_edit_cancel, + editable.connect('focus-out-event', self.edit_profilename, renderer, path) - def edit_profilename(self, renderer, path, newtext): + def edit_profilename(self, editable, event, renderer, path): + newtext = editable.get_text() model = self.profile_tree.get_model() oldname = model[path][0] if oldname == newtext == '': From 4974bb20cc010e7d1475ae315ca82bd8b6865509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 22 Feb 2012 17:23:19 +0100 Subject: [PATCH 042/122] Block update_profiles when clearing profile entries Otherwise the wrong profile can be updated as update_profiles will be called before the new profile is selected. issue2458 (transplanted from d6484588772e24a5b61a2ee18b76c096b93d674a) --- tryton/gui/window/dblogin.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tryton/gui/window/dblogin.py b/tryton/gui/window/dblogin.py index 44a75264e7..e11312194f 100644 --- a/tryton/gui/window/dblogin.py +++ b/tryton/gui/window/dblogin.py @@ -173,10 +173,12 @@ class DBListEditor(object): def clear_entries(self): for entryname in ('host', 'port', 'database', 'username'): entry = getattr(self, '%s_entry' % entryname) + entry.handler_block_by_func(self.update_profiles) if entryname == 'port': entry.set_text('8000') else: entry.set_text('') + entry.handler_unblock_by_func(self.update_profiles) self.current_database = None self.database_combo.set_active(-1) self.database_combo.get_model().clear() From f20f416407bdb2e5fa9545e7f552d358903fce04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 1 Mar 2012 10:18:31 +0100 Subject: [PATCH 043/122] Return empty list when calling O2M.get if empty Test on required state except to have a value evaluated to False in case of empty O2M. issue2382 review258002 (transplanted from 9364d03b9467364498b3f0e97b0fd2e0e85dfa10) --- tryton/gui/window/view_form/model/field.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index d0f469e853..6aa65306b7 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -483,6 +483,8 @@ class O2MField(CharField): get_readonly=readonly) values.pop(parent_name, None) result.append(('create', values)) + if not result[0][1]: + del result[0] if record_removed: result.append(('unlink', [x.id for x in record_removed])) if record_deleted: From 13b953282654b0b4de1d0aeef62e25ed7f4c8504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 5 Mar 2012 10:15:53 +0100 Subject: [PATCH 044/122] Use relativedelta to make all the datetime computation issue2469 (transplanted from 9516267d90bd89a0c49c225d639380cbc991e928) --- tryton/pyson.py | 59 ++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/tryton/pyson.py b/tryton/pyson.py index 9c7dde7e93..1656eaf087 100644 --- a/tryton/pyson.py +++ b/tryton/pyson.py @@ -6,6 +6,7 @@ try: except ImportError: import json import datetime +from dateutil.relativedelta import relativedelta from functools import reduce @@ -453,23 +454,14 @@ class Date(PYSON): @staticmethod def eval(dct, context): - date = datetime.date.today() - replace = {} - for i, j in (('y', 'year'), ('M', 'month'), ('d', 'day')): - if dct[i] is not None: - replace[j] = dct[i] - date = date.replace(**replace) - if dct['dy']: - year = date.year + dct['dy'] - date = date.replace(year=year) - if dct['dM']: - month = date.month + dct['dM'] - year = date.year + month // 12 - month = month % 12 - date = date.replace(year=year, month=month) - if dct['dd']: - date += datetime.timedelta(days=dct['dd']) - return date + return datetime.date.today() + relativedelta( + year=dct['y'], + month=dct['M'], + day=dct['d'], + years=dct['dy'], + months=dct['dM'], + days=dct['dd'], + ) class DateTime(Date): @@ -517,22 +509,23 @@ class DateTime(Date): @staticmethod def eval(dct, context): - date = Date.eval(dct, context) - datetime_ = datetime.datetime.combine(date, - datetime.datetime.now().time()) - replace = {} - for i, j in (('h', 'hour'), ('m', 'minute'), ('s', 'second'), - ('ms', 'microsecond')): - if dct[i] is not None: - replace[j] = dct[i] - datetime_ = datetime_.replace(**replace) - delta = {} - for i, j in (('dh', 'hours'), ('dm', 'minutes'), ('ds', 'seconds'), - ('dms', 'microseconds')): - if dct[i]: - delta[j] = dct[i] - datetime_ += datetime.timedelta(**delta) - return datetime_ + return datetime.datetime.now() + relativedelta( + year=dct['y'], + month=dct['M'], + day=dct['d'], + hour=dct['h'], + minute=dct['m'], + second=dct['s'], + microsecond=dct['ms'], + years=dct['dy'], + months=dct['dM'], + days=dct['dd'], + hours=dct['dh'], + minutes=dct['dm'], + seconds=dct['ds'], + microseconds=dct['dms'], + ) + CONTEXT = { 'Eval': Eval, From 4647c7e2b87eb63a0c6cd1a1f7628901ab2b8307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 5 Mar 2012 10:30:36 +0100 Subject: [PATCH 045/122] Reload context at the end of wizard only for config wizard Reloading context at the end of all wizard, makes the client lost the company context of the current session. issue2457 review252001 (transplanted from a364efdbde2c35fe59bf9be0fcc3a12fee51b2f9) --- tryton/gui/window/wizard.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tryton/gui/window/wizard.py b/tryton/gui/window/wizard.py index a15d7b2fed..04f02183b6 100644 --- a/tryton/gui/window/wizard.py +++ b/tryton/gui/window/wizard.py @@ -135,8 +135,8 @@ class Wizard(object): try: rpc.execute('wizard', self.action, 'delete', self.wiz_id, rpc.CONTEXT) - #XXX to remove when company displayed in status bar - rpc.context_reload() + if self.action == 'ir.module.module.config_wizard': + rpc.context_reload() except TrytonServerError: pass From a90bb04431e0ff1a0935099dfcd2f91a005623a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 5 Mar 2012 10:32:29 +0100 Subject: [PATCH 046/122] Reload the screen directly under when destroying wizard issue2279 review262002 (transplanted from 8ac761f1e1b23d4be5cef60840521dea1ad911b1) --- tryton/gui/window/wizard.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tryton/gui/window/wizard.py b/tryton/gui/window/wizard.py index 04f02183b6..863787bf5c 100644 --- a/tryton/gui/window/wizard.py +++ b/tryton/gui/window/wizard.py @@ -355,9 +355,13 @@ class WizardDialog(Wizard, NoModal): if current_form: for dialog in current_form.dialogs: dialog.show() - if hasattr(self.page, 'screen'): - self.page.screen.reload(written=True) super(WizardDialog, self).destroy() + if self.page.dialogs: + dialog = self.page.dialogs[-1] + else: + dialog = self.page + if hasattr(dialog, 'screen'): + dialog.screen.reload(written=True) def end(self): super(WizardDialog, self).end() From 44e8a7dad3488bb2aefaf953a17b6c8c98635700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 6 Mar 2012 12:27:01 +0100 Subject: [PATCH 047/122] process_exception is no modal now (transplanted from aa7c906c0aa31be36a971aece98b2e025a890030) --- tryton/gui/window/preference.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tryton/gui/window/preference.py b/tryton/gui/window/preference.py index 3f0359675c..c86088ba7b 100644 --- a/tryton/gui/window/preference.py +++ b/tryton/gui/window/preference.py @@ -96,8 +96,7 @@ class Preference(object): try: rpc.execute(*args) except TrytonServerError, exception: - if not common.process_exception(exception, self.win, - *args): + if not common.process_exception(exception, *args): continue res = True break From ce65c68abd8afa0ba383110c3f7f98649a3b61b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 7 Mar 2012 16:17:19 +0100 Subject: [PATCH 048/122] Use field.context_get instead of evaluating the context attribute (transplanted from 676c65f18b1142f3d97df308a0b1253a44775973) --- tryton/gui/window/view_form/view/form_gtk/one2many.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/view/form_gtk/one2many.py b/tryton/gui/window/view_form/view/form_gtk/one2many.py index 11863cd2fa..21ae30c37b 100644 --- a/tryton/gui/window/view_form/view/form_gtk/one2many.py +++ b/tryton/gui/window/view_form/view/form_gtk/one2many.py @@ -230,7 +230,7 @@ class One2Many(WidgetInterface): self.screen.display() return ctx = {} - ctx.update(self.record.expr_eval(self.attrs.get('context', {}))) + ctx.update(self.field.context_get(self.record)) sequence = None if self.screen.current_view.view_type == 'tree': sequence = self.screen.current_view.widget_tree.sequence From b4a0a93d8914c3de6d6fee480f02e7e61a9bfd3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 18 Mar 2012 21:08:00 +0100 Subject: [PATCH 049/122] Don't present parent window if it is already destroyed When creating a new record from the search dialog, the callback destroys the search dialog before the form dialog is destroyed. (transplanted from 5b5d0c1660e9d94ef8b02d819c53534caed523d9) --- tryton/gui/window/nomodal.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tryton/gui/window/nomodal.py b/tryton/gui/window/nomodal.py index c100e2b596..95e5206602 100644 --- a/tryton/gui/window/nomodal.py +++ b/tryton/gui/window/nomodal.py @@ -1,5 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. +import gtk + from tryton.gui.main import Main import tryton.common as common @@ -22,6 +24,9 @@ class NoModal(object): def destroy(self): self.page.dialogs.remove(self) + # Test if the parent is not already destroyed + if self.parent not in gtk.window_list_toplevels(): + return self.parent.present() self.sensible_widget.props.sensitive = True if self.parent_focus: From da7d9fdda21cf71f6f7dbc16a7464248136b99bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 11 Apr 2012 12:50:47 +0200 Subject: [PATCH 050/122] Make search window activate always response ok (transplanted from 1be85e761db5133f1fa10bffc6d5c4c15631ebbe) --- tryton/gui/window/win_search.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tryton/gui/window/win_search.py b/tryton/gui/window/win_search.py index 4712a6c75b..8495aa7891 100644 --- a/tryton/gui/window/win_search.py +++ b/tryton/gui/window/win_search.py @@ -85,10 +85,8 @@ class WinSearch(NoModal): def sig_activate(self, *args): self.view.widget_tree.emit_stop_by_name('row_activated') - if not self.sel_multi: - self.win.response(gtk.RESPONSE_OK) - return True - return False + self.win.response(gtk.RESPONSE_OK) + return True def sig_button(self, view, event): if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: From 111ea87df6d81841f1168eb8a59be315f0d71142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 13 Apr 2012 11:42:14 +0200 Subject: [PATCH 051/122] Loading a record, already there, must trigger signals review322003 (transplanted from 731b2c915a0869532e27d8ad2421301e2b2a758d) --- tryton/gui/window/view_form/model/group.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tryton/gui/window/view_form/model/group.py b/tryton/gui/window/view_form/model/group.py index 338cf67462..809aa43c74 100644 --- a/tryton/gui/window/view_form/model/group.py +++ b/tryton/gui/window/view_form/model/group.py @@ -201,15 +201,15 @@ class Group(SignalEvent, list): new_records = [] for id in ids: - if self.get(id): - continue - new_record = Record(self.model_name, id, group=self) - self.append(new_record) + new_record = self.get(id) + if not new_record: + new_record = Record(self.model_name, id, group=self) + self.append(new_record) + new_record.signal_connect(self, 'record-changed', + self._record_changed) + new_record.signal_connect(self, 'record-modified', + self._record_modified) new_records.append(new_record) - new_record.signal_connect(self, 'record-changed', - self._record_changed) - new_record.signal_connect(self, 'record-modified', - self._record_modified) # Remove previously removed or deleted records for record in self.record_removed[:]: From 621c9774d197287121ac9c6f99e9079705d9982c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 13 Apr 2012 14:24:08 +0200 Subject: [PATCH 052/122] PixbufLoader must be closed before getting pixbuf On windows, jpeg loader needs to be closed to return correct pixbuf. issue2482 (transplanted from 726bb7cfc5e424cdc919ce9cdc37b4fa5f553cf0) --- tryton/gui/window/view_form/view/form_gtk/image.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tryton/gui/window/view_form/view/form_gtk/image.py b/tryton/gui/window/view_form/view/form_gtk/image.py index 3422406ae5..efc9ac5e70 100644 --- a/tryton/gui/window/view_form/view/form_gtk/image.py +++ b/tryton/gui/window/view_form/view/form_gtk/image.py @@ -207,8 +207,8 @@ class Image(WidgetInterface): try: loader = gtk.gdk.PixbufLoader(ftype) loader.write(data, len(data)) - pixbuf = loader.get_pixbuf() loader.close() + pixbuf = loader.get_pixbuf() except glib.GError: continue if pixbuf: @@ -216,8 +216,8 @@ class Image(WidgetInterface): if not pixbuf: loader = gtk.gdk.PixbufLoader('png') loader.write(NOIMAGE, len(NOIMAGE)) - pixbuf = loader.get_pixbuf() loader.close() + pixbuf = loader.get_pixbuf() img_height = pixbuf.get_height() if img_height > self.height: From 733d034f7e65f86ec11da5c97429e618790867e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 18 Apr 2012 20:00:06 +0200 Subject: [PATCH 053/122] Reset current_record before clearing group (transplanted from 6c8591e020f818a25b62925a3e4eccd4e49a057f) --- tryton/gui/window/view_form/screen/screen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index 3bd4907f7c..3ff1368102 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -754,8 +754,8 @@ class Screen(SignalEvent): return [x.id for x in self.group if x.id] def clear(self): - self.group.clear() self.current_record = None + self.group.clear() def on_change(self, fieldname, attr): self.current_record.on_change(fieldname, attr) From fcd4ef26c6d4bbc2802130bc90c82486c14582f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 19 Apr 2012 23:34:49 +0200 Subject: [PATCH 054/122] Fix infinit loop when computing root_group (transplanted from bdea2cca8183d2e59e2e02b8c80419b7d5172ba9) --- tryton/gui/window/view_form/model/group.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tryton/gui/window/view_form/model/group.py b/tryton/gui/window/view_form/model/group.py index 809aa43c74..7e88343667 100644 --- a/tryton/gui/window/view_form/model/group.py +++ b/tryton/gui/window/view_form/model/group.py @@ -161,6 +161,7 @@ class Group(SignalEvent, list): parent = self.parent while parent: root = parent.group + parent = parent.parent return root def written(self, ids): From 0802c04b5d6282aa3d8202197e5fbc59d1e33bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 20 Apr 2012 19:46:47 +0200 Subject: [PATCH 055/122] Fix group usage in Record.delete It must always use the root_group for on_write_ids call and group comparison. review336001 (transplanted from cafce80c50b35c5b3ce4d5ad442fb3f18a86857b) --- tryton/gui/window/view_form/model/record.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py index 9f9890f457..b459869846 100644 --- a/tryton/gui/window/view_form/model/record.py +++ b/tryton/gui/window/view_form/model/record.py @@ -277,9 +277,9 @@ class Record(SignalEvent): if not records: return record = records[0] - group = record.group + root_group = record.group.root_group assert all(r.model_name == record.model_name for r in records) - assert all(r.group == group for r in records) + assert all(r.group.root_group == root_group for r in records) records = [r for r in records if r.id >= 0] ctx = {} ctx.update(rpc.CONTEXT) @@ -288,7 +288,7 @@ class Record(SignalEvent): for rec in records: ctx['_timestamp'].update(rec.get_timestamp()) record_ids = set(r.id for r in records) - reload_ids = set(group.on_write_ids(list(record_ids))) + reload_ids = set(root_group.on_write_ids(list(record_ids))) reload_ids -= record_ids reload_ids = list(reload_ids) args = ('model', record.model_name, 'delete', list(record_ids), ctx) @@ -298,7 +298,7 @@ class Record(SignalEvent): if not common.process_exception(exception, *args): return False if reload_ids: - group.root_group.reload(reload_ids) + root_group.reload(reload_ids) return True def default_get(self, domain=None, context=None): From 0dd098c12e2f3bddfd29383911f59e69bffdace4 Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 7 May 2012 11:10:32 +0200 Subject: [PATCH 056/122] Prepare release 2.2.2 --- CHANGELOG | 3 +++ COPYRIGHT | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5d86a51ab9..a67af884fb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.2.2 - 2012-05-07 +* Bug fixes (see mercurial logs for details) + Version 2.2.1 - 2011-12-26 * Bug fixes (see mercurial logs for details) diff --git a/COPYRIGHT b/COPYRIGHT index 9636f7aac5..5db854264a 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,7 +1,7 @@ -Copyright (C) 2010-2011 Nicolas Évrard. -Copyright (C) 2007-2011 Cédric Krier. +Copyright (C) 2010-2012 Nicolas Évrard. +Copyright (C) 2007-2012 Cédric Krier. Copyright (C) 2007-2011 Bertrand Chenal. -Copyright (C) 2008-2011 B2CK SPRL. +Copyright (C) 2008-2012 B2CK SPRL. Copyright (C) 2008-2011 Udo Spallek. Copyright (C) 2008-2011 virtual things - Preisler & Spallek GbR. Copyright (C) 2007-2009 Lorenzo Gil Sanchez. From 6333c6765b56074520b95b8ef37302892e9f2bc9 Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 7 May 2012 11:10:32 +0200 Subject: [PATCH 057/122] Added tag 2.2.2 for changeset 2503e2efa07f --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 0118ac4448..4f24481386 100644 --- a/.hgtags +++ b/.hgtags @@ -6,3 +6,4 @@ de84c1443d4bad908eabb99c381578b988c2117f 1.4.0 1876747b3f963ba6011b4bcf6968e681624c6e24 2.0.0 5364f8ca6cd2cccfb5f7f39c69bb20bae2b5f495 2.2.0 3fdf4ae699be5abbf9ebbb83fea5678e7f370179 2.2.1 +2503e2efa07fa5cb2ebbe743213f8d21fab54d15 2.2.2 From 74ee39e7bb0c6a56eae29e9f8e8b4266cd223e00 Mon Sep 17 00:00:00 2001 From: Mathias Behrle Date: Mon, 7 May 2012 11:11:01 +0200 Subject: [PATCH 058/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index 3b71650e0b..b409f6a09f 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.2" +VERSION = "2.2.3" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 6bb98a32e6cc03c3c4233c7ca762188cc91b9147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 12 May 2012 16:48:17 +0200 Subject: [PATCH 059/122] Fix domain_inversion for comparison of datetime with None review359002 (transplanted from 49609073c798e7b019a5d2dc28dcebb627ad10dd) --- tryton/common/domain_inversion.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tryton/common/domain_inversion.py b/tryton/common/domain_inversion.py index 8da0a6aa2a..335eee831a 100644 --- a/tryton/common/domain_inversion.py +++ b/tryton/common/domain_inversion.py @@ -3,6 +3,7 @@ import operator import types +import datetime def in_(a, b): if isinstance(a, (list, tuple)): @@ -52,7 +53,18 @@ def eval_leaf(part, context, boolop=operator.and_): # We should consider that other domain inversion will set a correct # value to this field return True - return OPERATORS[operand](context[field], value) + context_field = context[field] + if isinstance(context_field, datetime.date) and not value: + if isinstance(context_field, datetime.datetime): + value = datetime.datetime.min + else: + value = datetime.date.min + if isinstance(value, datetime.date) and not context_field: + if isinstance(value, datetime.datetime): + context_field = datetime.datetime.min + else: + context_field = datetime.date.min + return OPERATORS[operand](context_field, value) def inverse_leaf(domain): if domain in ('AND', 'OR'): @@ -396,6 +408,15 @@ def test_evaldomain(): assert eval_domain(domain, {'x': 6}) assert not eval_domain(domain, {'x': 4}) + domain = [['x', '>', None]] + assert eval_domain(domain, {'x': datetime.date.today()}) + assert eval_domain(domain, {'x': datetime.datetime.now()}) + + domain = [['x', '<', datetime.date.today()]] + assert eval_domain(domain, {'x': None}) + domain = [['x', '<', datetime.datetime.now()]] + assert eval_domain(domain, {'x': None}) + domain = [['x', 'in', [3, 5]]] assert eval_domain(domain, {'x': 3}) assert not eval_domain(domain, {'x': 4}) From 0767f2ac8520f449241599b850931d34d9e55fad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 14 May 2012 00:09:17 +0200 Subject: [PATCH 060/122] Activate form buttons only when they are sensitive issue2601 (transplanted from 4d6c095c984165c19ae61a45a7a82d4c706e4693) --- tryton/gui/window/form.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tryton/gui/window/form.py b/tryton/gui/window/form.py index 7e46d07cfa..2f351c9ba8 100644 --- a/tryton/gui/window/form.py +++ b/tryton/gui/window/form.py @@ -406,19 +406,24 @@ class Form(SignalEvent, TabContent): return True def sig_action(self, widget): - self.buttons['action'].props.active = True + if self.buttons['action'].props.sensitive: + self.buttons['action'].props.active = True def sig_print(self, widget): - self.buttons['print'].props.active = True + if self.buttons['print'].props.sensitive: + self.buttons['print'].props.active = True def sig_print_open(self, widget): - self.buttons['open'].props.active = True + if self.buttons['open'].props.sensitive: + self.buttons['open'].props.active = True def sig_print_email(self, widget): - self.buttons['email'].props.active = True + if self.buttons['email'].props.sensitive: + self.buttons['email'].props.active = True def sig_relate(self, widget): - self.buttons['relate'].props.active = True + if self.buttons['relate'].props.sensitive: + self.buttons['relate'].props.active = True def action_popup(self, widget): button, = widget.get_children() From c6200b2ef8c65f28276887e5eb6bbf695e0ef562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 22 Jun 2012 17:53:35 +0200 Subject: [PATCH 061/122] Fix name of fields loaded from predefined export issue2648 review404001 (transplanted from 481bf839727a0a1afff30fb963e46afa368b4306) --- tryton/gui/window/win_export.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tryton/gui/window/win_export.py b/tryton/gui/window/win_export.py index 79dae47296..43f2c9689e 100644 --- a/tryton/gui/window/win_export.py +++ b/tryton/gui/window/win_export.py @@ -246,7 +246,8 @@ class WinExport(object): child = self.model1.iter_children(iter) if self.model1.get_value(child, 0) is None: prefix_field = self.model1.get_value(iter, 1) - name, model = self.fields[prefix_field] + _, model = self.fields[prefix_field] + name = self.fields_data[prefix_field]['string'] self.model_populate(self._get_fields(model), iter, prefix_field + '/', name + '/') self.model1.remove(child) From 7e2aa8cb32c35cb85dd8f18d7b92aafcc61d8d08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 28 Jun 2012 15:11:17 +0200 Subject: [PATCH 062/122] set_value of M2O must simulate a focus-out in case it did not yet occur issue2624 review408001 (transplanted from a07d90df4d9e6b98778260ec684b6f1317a4cb8b) --- tryton/gui/window/view_form/view/form_gtk/many2one.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tryton/gui/window/view_form/view/form_gtk/many2one.py b/tryton/gui/window/view_form/view/form_gtk/many2one.py index 81d8bf5d85..85d5b87588 100644 --- a/tryton/gui/window/view_form/view/form_gtk/many2one.py +++ b/tryton/gui/window/view_form/view/form_gtk/many2one.py @@ -83,7 +83,7 @@ class Many2One(WidgetInterface): def _color_widget(self): return self.wid_text - def sig_activate(self, widget, event=None, key_press=False): + def sig_activate(self, widget=None, event=None, key_press=False): if not self.focus_out: return if not self.field: @@ -93,7 +93,7 @@ class Many2One(WidgetInterface): self.focus_out = False if not value: - if not key_press and not event: + if not key_press and not event and widget: widget.emit_stop_by_name('activate') if not self._readonly and (self.wid_text.get_text() or \ (self.field.get_state_attrs( @@ -243,7 +243,8 @@ class Many2One(WidgetInterface): return False def set_value(self, record, field): - pass # No update of the model, the model is updated in real time ! + # Simulate a focus-out + self.sig_activate() def display(self, record, field): self.changed = False From fbc0074c5ac01da772adaa289d473360f8bebd48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 19 Jul 2012 09:45:58 +0200 Subject: [PATCH 063/122] get_toplevel_window should return only gtk.WINDOW_TOPLEVEL issue2707 review410003 (transplanted from a10ed833b61119c2c169356a493023f892e2526b) --- tryton/common/common.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tryton/common/common.py b/tryton/common/common.py index 83cb472a5b..6bffd9fed4 100644 --- a/tryton/common/common.py +++ b/tryton/common/common.py @@ -243,7 +243,8 @@ def request_server(server_widget): def get_toplevel_window(): windows = [x for x in gtk.window_list_toplevels() - if x.window and x.props.visible] + if x.window and x.props.visible + and x.get_window_type() == gtk.WINDOW_TOPLEVEL] trans2windows = dict((x.get_transient_for(), x) for x in windows) for window in set(windows) - set(trans2windows.iterkeys()): return window From 86b97558ceacd4f9e790f55339050c1e89f55b4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 25 Jul 2012 20:31:56 +0200 Subject: [PATCH 064/122] Fix test on legend graph attribute review421001 (transplanted from 883480d210a7b3361afc69df26e766c62a4e76dc) --- tryton/gui/window/view_form/view/graph_gtk/graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/view/graph_gtk/graph.py b/tryton/gui/window/view_form/view/graph_gtk/graph.py index 854c1007be..695bcecf7b 100644 --- a/tryton/gui/window/view_form/view/graph_gtk/graph.py +++ b/tryton/gui/window/view_form/view/graph_gtk/graph.py @@ -276,7 +276,7 @@ class Graph(gtk.DrawingArea): cr.restore() def drawLegend(self, cr, width, height): - if not self.attrs.get('legend', True): + if not int(self.attrs.get('legend', 1)): return padding = 4 From 2a8fa4fe683c172acc965f66b2ea0e7cdb4b7268 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bonicoli Date: Tue, 14 Aug 2012 17:52:52 +0200 Subject: [PATCH 065/122] Use repr for faultCode in Fault.__repr__ issue2742 review467002 (transplanted from 56c1da6e515b54c3148c772ccc950fd051286de3) --- tryton/jsonrpc.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tryton/jsonrpc.py b/tryton/jsonrpc.py index a4c1c1767c..cda04d61a2 100644 --- a/tryton/jsonrpc.py +++ b/tryton/jsonrpc.py @@ -32,6 +32,11 @@ class Fault(xmlrpclib.Fault): super(Fault, self).__init__(faultCode, faultString, **extra) self.args = faultString + def __repr__(self): + return ( + "" % + (repr(self.faultCode), repr(self.faultString)) + ) class ProtocolError(xmlrpclib.ProtocolError): pass From 3d1c8dd658350bfdd87dc1771d0a201b48b907b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 16 Aug 2012 16:00:21 +0200 Subject: [PATCH 066/122] Fix wrong sorting to get lazy first review461001 (transplanted from 32492bf6244d7f1e93570e3ad8136488e1b981e4) --- tryton/gui/window/view_form/view/form.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/view/form.py b/tryton/gui/window/view_form/view/form.py index 6e05a63af8..d25e566ac5 100644 --- a/tryton/gui/window/view_form/view/form.py +++ b/tryton/gui/window/view_form/view/form.py @@ -106,7 +106,7 @@ class ViewForm(ParserView): # Get first the lazy one to reduce number of requests fields = [(name, field.attrs.get('loading', 'eager')) for name, field in record.group.fields.iteritems()] - fields.sort(key=operator.itemgetter(1)) + fields.sort(key=operator.itemgetter(1), reverse=True) for field, _ in fields: record[field].get(record, check_load=False) for name, widgets in self.widgets.iteritems(): From b3c4a62aaede2210a34b7bf8fc80b7dabaffc4c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 1 Sep 2012 18:55:57 +0200 Subject: [PATCH 067/122] Prepare release 2.2.3 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index a67af884fb..f97db531e5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.2.3 - 2012-09-01 +* Bug fixes (see mercurial logs for details) + Version 2.2.2 - 2012-05-07 * Bug fixes (see mercurial logs for details) From 81aaf0bf9a8c7c2cc28b6e59d29a4489ed78ee75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 1 Sep 2012 18:55:58 +0200 Subject: [PATCH 068/122] Added tag 2.2.3 for changeset e3af51f4f68b --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 4f24481386..c9e5c9f284 100644 --- a/.hgtags +++ b/.hgtags @@ -7,3 +7,4 @@ de84c1443d4bad908eabb99c381578b988c2117f 1.4.0 5364f8ca6cd2cccfb5f7f39c69bb20bae2b5f495 2.2.0 3fdf4ae699be5abbf9ebbb83fea5678e7f370179 2.2.1 2503e2efa07fa5cb2ebbe743213f8d21fab54d15 2.2.2 +e3af51f4f68b6b2c9b46e03aaa0a1c0c26214c0c 2.2.3 From 42e4b5b054d54065b5174fe261e97d7ce73e5b3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 1 Sep 2012 18:56:30 +0200 Subject: [PATCH 069/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index b409f6a09f..96907533a3 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.3" +VERSION = "2.2.4" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 01d624129ee188614501dddc05e2ec0c18bf1783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 10 Sep 2012 13:24:02 +0200 Subject: [PATCH 070/122] Replace Window.get_window_type by the property Window.get_window_type is only available since PyGTK 2.22 issue2743 review501008 (transplanted from b035296eecf53b535d420355c002ee7cc3e7c2f3) --- tryton/common/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/common/common.py b/tryton/common/common.py index 6bffd9fed4..00ad4bd7d2 100644 --- a/tryton/common/common.py +++ b/tryton/common/common.py @@ -244,7 +244,7 @@ def request_server(server_widget): def get_toplevel_window(): windows = [x for x in gtk.window_list_toplevels() if x.window and x.props.visible - and x.get_window_type() == gtk.WINDOW_TOPLEVEL] + and x.props.type == gtk.WINDOW_TOPLEVEL] trans2windows = dict((x.get_transient_for(), x) for x in windows) for window in set(windows) - set(trans2windows.iterkeys()): return window From 829e0b79d7d56d28f46b495ba4ca906b60bf11da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 1 Oct 2012 16:07:19 +0200 Subject: [PATCH 071/122] Don't store interger as current record Use inline if/else instead of and issue2701 (transplanted from 33f9f70a701fb253463297e173345e8d08cc58f3) --- tryton/gui/window/view_form/screen/screen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index 3ff1368102..9196b33b13 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -706,7 +706,7 @@ class Screen(SignalEvent): break self.current_record = record else: - self.current_record = len(self.group) and self.group[0] + self.current_record = self.group[0] if len(self.group) else None view.set_cursor(reset_view=False) view.display() @@ -738,7 +738,7 @@ class Screen(SignalEvent): record = parent self.current_record = record else: - self.current_record = len(self.group) and self.group[-1] + self.current_record = self.group[-1] if len(self.group) else None view.set_cursor(reset_view=False) view.display() From 3ece20aac92cf61ef64d041309915cb26d71c9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 6 Oct 2012 17:11:18 +0200 Subject: [PATCH 072/122] Use the same pattern for move_into than _move to prevent concurrency (transplanted from f57702fc015c87566146ee11623d8481ff2388c8) --- tryton/gui/window/view_form/view/list.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index 69d93e7d10..1efca225ea 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -126,6 +126,10 @@ class AdaptModelGroup(gtk.GenericTreeModel): group = parent.children_group(self.children_field, check_load=True) if group is not record.group: record.group.remove(record, remove=True, force_remove=True) + # Don't remove record from previous group + # as the new parent will change the parent + # This prevents concurrency conflict + record.group.record_removed.remove(record) group.add(record) record.modified_fields.setdefault(record.parent_name or 'id') group.move(record, 0) From 7639299500595920268fa682872aab6aadad04fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 8 Oct 2012 21:07:31 +0200 Subject: [PATCH 073/122] Delete the children before the parent records review553002 (transplanted from 735011602235036618d293eabc3991f06c602a4b) --- tryton/gui/window/view_form/model/record.py | 9 +++++++++ tryton/gui/window/view_form/screen/screen.py | 2 ++ 2 files changed, 11 insertions(+) diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py index b459869846..926540a1b3 100644 --- a/tryton/gui/window/view_form/model/record.py +++ b/tryton/gui/window/view_form/model/record.py @@ -115,6 +115,15 @@ class Record(SignalEvent): def parent_name(self): return self.group.parent_name + @property + def depth(self): + parent = self.parent + i = 0 + while parent: + i += 1 + parent = parent.parent + return i + def set_modified(self, value): if value: self.signal('record-modified') diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index 9196b33b13..48edcc20c6 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -548,6 +548,8 @@ class Screen(SignalEvent): if not records: return if delete: + # Must delete children records before parent + records.sort(key=lambda r: r.depth, reverse=True) if not self.group.delete(records): return False From 3fde2b64e4c39f91e9cc73e2add8bf410c961256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 9 Oct 2012 17:18:35 +0200 Subject: [PATCH 074/122] Fix next/previous in form view when there is no current record issue2788 review548003 (transplanted from bd5d0d004c19cd4fe33f3263b065d3fdba630130) --- tryton/gui/window/view_form/screen/screen.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tryton/gui/window/view_form/screen/screen.py b/tryton/gui/window/view_form/screen/screen.py index 48edcc20c6..4c5d40e6f1 100644 --- a/tryton/gui/window/view_form/screen/screen.py +++ b/tryton/gui/window/view_form/screen/screen.py @@ -681,7 +681,9 @@ class Screen(SignalEvent): store = view.store iter_ = store.get_iter(end) self.current_record = store.get_value(iter_, 0) - elif view.view_type == 'form' and self.current_record.group: + elif (view.view_type == 'form' + and self.current_record + and self.current_record.group): group = self.current_record.group record = self.current_record while group: @@ -723,7 +725,9 @@ class Screen(SignalEvent): store = view.store iter_ = store.get_iter(start) self.current_record = store.get_value(iter_, 0) - elif view.view_type == 'form' and self.current_record.group: + elif (view.view_type == 'form' + and self.current_record + and self.current_record.group): group = self.current_record.group record = self.current_record idx = group.index(record) - 1 From 3760846c54943cd920a4926762445fa80f4f109e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 10 Oct 2012 17:49:02 +0200 Subject: [PATCH 075/122] Prevent closing non-sensitive tabs review555002 (transplanted from 5f8ba9d5cb9c84c4d118f0de07acc16abbec512a) --- tryton/gui/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tryton/gui/main.py b/tryton/gui/main.py index 17a6ad5bbd..41a66ab327 100644 --- a/tryton/gui/main.py +++ b/tryton/gui/main.py @@ -1201,6 +1201,8 @@ class Main(object): def _sig_remove_book(self, widget, page_widget): for page in self.pages: if page.widget == page_widget: + if not page.widget.props.sensitive: + return page_num = self.notebook.page_num(page.widget) self.notebook.set_current_page(page_num) res = page.sig_close() From 1b14a23213b368e3e009899dcc15938e030e3366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 17 Oct 2012 21:19:22 +0200 Subject: [PATCH 076/122] Fix calls to sig_db_dump/restore issue2814 (transplanted from 2105a3798a43a68f2813a0258597c20d653c87a0) --- tryton/gui/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tryton/gui/main.py b/tryton/gui/main.py index 41a66ab327..6b41eabf2e 100644 --- a/tryton/gui/main.py +++ b/tryton/gui/main.py @@ -1320,7 +1320,7 @@ class Main(object): self.refresh_ssl() common.message(_("Database dropped successfully!")) - def sig_db_restore(self, widget): + def sig_db_restore(self, widget=None): if not self.sig_logout(widget): return False filename = common.file_selection(_('Open Backup File to Restore...'), @@ -1362,7 +1362,7 @@ class Main(object): else: common.message(_('Database restore failed!')) - def sig_db_dump(self, widget): + def sig_db_dump(self, widget=None): if not self.sig_logout(widget): return False dialog = DBBackupDrop(function='backup') From 77928d5f0ed34814de399714783565c3c777d8d0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bonicoli Date: Sat, 20 Oct 2012 13:46:07 +0200 Subject: [PATCH 077/122] avoid markup on unknown strings issue2843 review576002 (transplanted from ee1eeb93e98c8a82678b6cf37fa44fbc1b41fd55) --- tryton/gui/window/win_form.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tryton/gui/window/win_form.py b/tryton/gui/window/win_form.py index da34c31041..76d7690bfc 100644 --- a/tryton/gui/window/win_form.py +++ b/tryton/gui/window/win_form.py @@ -75,9 +75,8 @@ class WinForm(NoModal): self.win.set_title(self.screen.current_view.title) title = gtk.Label() - title.set_use_markup(True) - title.modify_font(pango.FontDescription("12")) - title.set_label('' + self.screen.current_view.title + '') + title.modify_font(pango.FontDescription("bold 12")) + title.set_label(self.screen.current_view.title) title.set_padding(20, 3) title.set_alignment(0.0, 0.5) title.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000")) From c91cd3415ab337f22cbd0493691663c4651e19fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 5 Nov 2012 17:32:08 +0100 Subject: [PATCH 078/122] Prepare release 2.2.4 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index f97db531e5..9ce8cd0f53 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.2.4 - 2012-11-05 +* Bug fixes (see mercurial logs for details) + Version 2.2.3 - 2012-09-01 * Bug fixes (see mercurial logs for details) From 397125f28a75948089947ce4f50f05bc5b4c590e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 5 Nov 2012 17:32:09 +0100 Subject: [PATCH 079/122] Added tag 2.2.4 for changeset 4b58bf988af7 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index c9e5c9f284..2ba8d8eb68 100644 --- a/.hgtags +++ b/.hgtags @@ -8,3 +8,4 @@ de84c1443d4bad908eabb99c381578b988c2117f 1.4.0 3fdf4ae699be5abbf9ebbb83fea5678e7f370179 2.2.1 2503e2efa07fa5cb2ebbe743213f8d21fab54d15 2.2.2 e3af51f4f68b6b2c9b46e03aaa0a1c0c26214c0c 2.2.3 +4b58bf988af7c5068f419bfce0a4912584d65d4c 2.2.4 From e774971f6581df27942235682f99adc6898b50b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 5 Nov 2012 17:32:47 +0100 Subject: [PATCH 080/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index 96907533a3..fa988ef1bc 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.4" +VERSION = "2.2.5" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 5949d928c44ff9e6d82a0bb62ccf1c5eb920477f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 15 Nov 2012 18:50:16 +0100 Subject: [PATCH 081/122] Record.get_eval must return only loaded values and validate only fields Domain inversion should not have fields that are not loaded otherwise the inversion could be wrong. issue2865 review583003 (transplanted from 4d2bd7127a51862ab1293e8cdc4cf9f8bf217945) --- tryton/common/domain_inversion.py | 4 ++-- tryton/gui/window/view_form/model/record.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tryton/common/domain_inversion.py b/tryton/common/domain_inversion.py index 335eee831a..15c3b58183 100644 --- a/tryton/common/domain_inversion.py +++ b/tryton/common/domain_inversion.py @@ -49,11 +49,11 @@ def eval_leaf(part, context, boolop=operator.and_): # In the case where the leaf concerns a m2o then having a value in the # evaluation context is deemed suffisant return bool(context.get(field.split('.')[0])) - if operand == '=' and not context[field] and boolop == operator.and_: + if operand == '=' and not context.get(field) and boolop == operator.and_: # We should consider that other domain inversion will set a correct # value to this field return True - context_field = context[field] + context_field = context.get(field) if isinstance(context_field, datetime.date) and not value: if isinstance(context_field, datetime.datetime): value = datetime.datetime.min diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py index 926540a1b3..c64ea8458b 100644 --- a/tryton/gui/window/view_form/model/record.py +++ b/tryton/gui/window/view_form/model/record.py @@ -224,6 +224,8 @@ class Record(SignalEvent): self._check_load() value = {} for name, field in self.group.fields.iteritems(): + if name not in self._loaded and self.id >= 0: + continue value[name] = field.get_eval(self, check_load=check_load) value['id'] = self.id return value @@ -442,7 +444,7 @@ class Record(SignalEvent): else: for field in fields: self[field] - self.validate([]) + self.validate(fields or []) def expr_eval(self, expr, check_load=False): if not isinstance(expr, basestring): From 02a0b7198336e56582baab063167c5f8f97ef9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 9 Dec 2012 00:11:55 +0100 Subject: [PATCH 082/122] Add missing parenthesis on test in O2M.set_on_change issue2917 (transplanted from b76788d09e04a0a80f5fccb26d5a505bdeb35c7d) --- tryton/gui/window/view_form/model/field.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index 6aa65306b7..d63d7e1dc6 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -631,7 +631,7 @@ class O2MField(CharField): record.value[self.name].remove(record2, signal=False, force_remove=True) - if value and value.get('add') or value.get('update', []): + if value and (value.get('add') or value.get('update', [])): record.value[self.name].add_fields(fields, signal=False) for vals in value.get('add', []): new_record = record.value[self.name].new(default=False, From 4590160869c872f0d1db173972b7282a63852cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 13 Dec 2012 19:06:01 +0100 Subject: [PATCH 083/122] Copy also tryton locale on win32 as directory is clean before issue2921 review597006 (transplanted from e5cdaf0a7ba1fd96593138d905bebe50de6c5663) --- setup.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/setup.py b/setup.py index 817acea543..833e10506e 100644 --- a/setup.py +++ b/setup.py @@ -233,6 +233,11 @@ if os.name == 'nt': shutil.rmtree(os.path.join(dist_dir, 'share', 'locale', lang)) shutil.copytree(os.path.join(gtk_dir, 'share', 'locale', lang), os.path.join(dist_dir, 'share', 'locale', lang)) + if os.path.isdir(os.path.join(os.path.dirname(__file__), + 'share', 'locale', lang)): + shutil.copytree(os.path.join(os.path.dirname(__file__), + 'share', 'locale', lang), + os.path.join(dist_dir, 'share', 'locale', lang)) if os.path.isdir(os.path.join(dist_dir, 'share', 'themes', 'MS-Windows')): shutil.rmtree(os.path.join(dist_dir, 'share', 'themes', 'MS-Windows')) @@ -331,6 +336,11 @@ elif sys.platform == 'darwin': shutil.rmtree(os.path.join(resources_dir, 'share', 'locale', lang)) shutil.copytree(os.path.join(gtk_dir, 'share', 'locale', lang), os.path.join(resources_dir, 'share', 'locale', lang)) + if os.path.isdir(os.path.join(os.path.dirname(__file__), + 'share', 'locale', lang)): + shutil.copytree(os.path.join(os.path.dirname(__file__), + 'share', 'locale', lang), + os.path.join(resources_dir, 'share', 'locale', lang)) # fix pathes within shared libraries for library in chain( From 1fddc0ae3daf6ca81e88ab493a7ac7f970d02b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 23 Dec 2012 16:56:31 +0100 Subject: [PATCH 084/122] Prepare release 2.2.5 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 9ce8cd0f53..6373ef79dc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.2.5 - 2012-12-23 +* Bug fixes (see mercurial logs for details) + Version 2.2.4 - 2012-11-05 * Bug fixes (see mercurial logs for details) From 83bebc86d5efe46beb1ebdd8300dfff08d8f7554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 23 Dec 2012 16:56:32 +0100 Subject: [PATCH 085/122] Added tag 2.2.5 for changeset 52abc37b8413 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 2ba8d8eb68..a37417fc4e 100644 --- a/.hgtags +++ b/.hgtags @@ -9,3 +9,4 @@ de84c1443d4bad908eabb99c381578b988c2117f 1.4.0 2503e2efa07fa5cb2ebbe743213f8d21fab54d15 2.2.2 e3af51f4f68b6b2c9b46e03aaa0a1c0c26214c0c 2.2.3 4b58bf988af7c5068f419bfce0a4912584d65d4c 2.2.4 +52abc37b8413843ff1253b66b089412af9815db5 2.2.5 From c9cf835f4de074813797bccc2398bc1c4bf1b7d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 23 Dec 2012 16:57:00 +0100 Subject: [PATCH 086/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index fa988ef1bc..8c0fe7e8d3 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.5" +VERSION = "2.2.6" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From f55bd2e88247513f7195334a4c47df10ceaecb0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 26 Jan 2013 15:07:23 +0100 Subject: [PATCH 087/122] Validate non-loaded O2M record when new and pass missing softvalidation issue2968 review637003 (transplanted from f753403e8ebc0455c691361f2c5e9a36be771006) --- tryton/gui/window/view_form/model/field.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index d63d7e1dc6..1ebde126f9 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -660,9 +660,9 @@ class O2MField(CharField): return True res = True for record2 in record.value.get(self.name, []): - if not record2.loaded: + if not record2.loaded and record2.id >= 0: continue - if not record2.validate(): + if not record2.validate(softvalidation=softvalidation): if not record2.modified: record.value[self.name].remove(record2) else: From 3043022f6e97cb978d715408916fc295b75821fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 12 Feb 2013 18:01:55 +0100 Subject: [PATCH 088/122] Prepare release 2.2.6 --- CHANGELOG | 3 +++ COPYRIGHT | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 6373ef79dc..69a750af5a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.2.6 - 2013-02-12 +* Bug fixes (see mercurial logs for details) + Version 2.2.5 - 2012-12-23 * Bug fixes (see mercurial logs for details) diff --git a/COPYRIGHT b/COPYRIGHT index 5db854264a..49c6ef7021 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,7 +1,7 @@ Copyright (C) 2010-2012 Nicolas Évrard. -Copyright (C) 2007-2012 Cédric Krier. +Copyright (C) 2007-2013 Cédric Krier. Copyright (C) 2007-2011 Bertrand Chenal. -Copyright (C) 2008-2012 B2CK SPRL. +Copyright (C) 2008-2013 B2CK SPRL. Copyright (C) 2008-2011 Udo Spallek. Copyright (C) 2008-2011 virtual things - Preisler & Spallek GbR. Copyright (C) 2007-2009 Lorenzo Gil Sanchez. From 8ac61325cc7c8bbad87dec1fb0f2365018654924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 12 Feb 2013 18:01:56 +0100 Subject: [PATCH 089/122] Added tag 2.2.6 for changeset 276bfe1927e6 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index a37417fc4e..dbea4011a2 100644 --- a/.hgtags +++ b/.hgtags @@ -10,3 +10,4 @@ de84c1443d4bad908eabb99c381578b988c2117f 1.4.0 e3af51f4f68b6b2c9b46e03aaa0a1c0c26214c0c 2.2.3 4b58bf988af7c5068f419bfce0a4912584d65d4c 2.2.4 52abc37b8413843ff1253b66b089412af9815db5 2.2.5 +276bfe1927e6162aa27801d4d09e5d06a8332421 2.2.6 From b738414e14cf5e490892dee28a41fa2b094f4a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 12 Feb 2013 18:02:31 +0100 Subject: [PATCH 090/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index 8c0fe7e8d3..7a5d714dca 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.6" +VERSION = "2.2.7" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From cf7a91d0050f4cdd3a90924217c698e60f1dbbae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 15 Apr 2012 17:03:34 +0200 Subject: [PATCH 091/122] Fix set value of many2one when text is empty many2one must have None value if text is empty. (transplanted from 3db19d8ba8a921ce550ad093529f6d5ae23e8ff9) --- tryton/gui/window/view_form/view/list_gtk/parser.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) 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 080ba54db4..b77abb5bbb 100644 --- a/tryton/gui/window/view_form/view/list_gtk/parser.py +++ b/tryton/gui/window/view_form/view/list_gtk/parser.py @@ -518,8 +518,8 @@ class M2O(Char): def value_from_text(self, record, text, callback=None): field = record.group.fields[self.field_name] - if not text and not field.get_state_attrs( - record)['required']: + if not text: + field.set_client(record, (False, '')) if callback: callback() return False @@ -527,11 +527,7 @@ class M2O(Char): relation = record[self.field_name].attrs['relation'] domain = record[self.field_name].domain_get(record) context = record[self.field_name].context_get(record) - if text: - dom = [('rec_name', 'ilike', '%' + text + '%'), - domain] - else: - dom = domain + dom = [('rec_name', 'ilike', '%' + text + '%'), domain] args = ('model', relation, 'search', dom, 0, None, None, context) try: @@ -539,7 +535,7 @@ class M2O(Char): except TrytonServerError, exception: ids = common.process_exception(exception, *args) if not ids: - field.set_client(record, '???') + field.set_client(record, (False, '')) if callback: callback() return From 88bd22379434260ad646e1a8a35d34f3e423a8a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20=C3=89vrard?= Date: Mon, 11 Feb 2013 09:38:40 +0100 Subject: [PATCH 092/122] Correctly parse the URL review621003 (transplanted from f690b98c1a382fd36a43ba90c0272adaf6cba370) --- tryton/gui/main.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tryton/gui/main.py b/tryton/gui/main.py index 6b41eabf2e..9d5b687c43 100644 --- a/tryton/gui/main.py +++ b/tryton/gui/main.py @@ -5,7 +5,7 @@ import os import sys import socket import gettext -from urlparse import urlparse +from urlparse import urlparse, parse_qsl import urllib import gobject import gtk @@ -1412,14 +1412,14 @@ class Main(object): Main.get_main().refresh_ssl() def _open_url(self, url): - url = urllib.unquote(url) urlp = urlparse(url) if not urlp.scheme == 'tryton': return urlp = urlparse('http' + url[6:]) - hostname, port = (urlp.netloc.split(':', 1) - + [CONFIG.defaults['login.port']])[:2] - database, path = (urlp.path[1:].split('/', 1) + [None])[:2] + hostname, port = map(urllib.unquote, + (urlp.netloc.split(':', 1) + [CONFIG.defaults['login.port']])[:2]) + database, path = map(urllib.unquote, + (urlp.path[1:].split('/', 1) + [None])[:2]) if (not path or hostname != rpc._HOST or int(port) != rpc._PORT or @@ -1429,8 +1429,8 @@ class Main(object): params = {} if urlp.params: try: - params = dict(param.split('=', 1) - for param in urlp.params.split('&')) + params.update(dict(parse_qsl(urlp.params, + strict_parsing=True))) except ValueError: return From e6e456b74f68a6cf11ccc1e9704e39bfa9c8ed2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 27 Mar 2013 22:50:08 +0100 Subject: [PATCH 093/122] Fix group loading when using '*' Prevent to load unnecessary records due to wrong loaded matching. issue3069 review744003 (transplanted from 0371410177db3ab0a3721486c1f83444ba549fa8) --- tryton/gui/window/view_form/model/record.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py index c64ea8458b..2b6bb189cf 100644 --- a/tryton/gui/window/view_form/model/record.py +++ b/tryton/gui/window/view_form/model/record.py @@ -46,6 +46,11 @@ class Record(SignalEvent): (field.attrs.get('loading', 'eager') for field in self.group.fields.itervalues()), 'eager') + # Set a valid name for next loaded check + for fname, field in self.group.fields.iteritems(): + if field.attrs.get('loading', 'eager') == loading: + name = fname + break else: loading = self.group.fields[name].attrs.get('loading', 'eager') if self in self.group and loading == 'eager': From 5c95d11a36ea4063ca1dc34274382baa3f1a14c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 27 Mar 2013 22:52:48 +0100 Subject: [PATCH 094/122] Add missing initialization of bars in Bar issue3073 review730002 (transplanted from 4ce2f0028aa8ac17114588eacf668de236f9d25a) --- tryton/gui/window/view_form/view/graph_gtk/bar.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tryton/gui/window/view_form/view/graph_gtk/bar.py b/tryton/gui/window/view_form/view/graph_gtk/bar.py index 73b248a003..26f54316eb 100644 --- a/tryton/gui/window/view_form/view/graph_gtk/bar.py +++ b/tryton/gui/window/view_form/view/graph_gtk/bar.py @@ -11,6 +11,10 @@ import tryton.rpc as rpc class Bar(Graph): + def __init__(self, *args, **kwargs): + super(Bar, self).__init__(*args, **kwargs) + self.bars = [] + def drawGraph(self, cr, width, height): def drawBar(bar): From 308abf9b93aba4077d3e59e5308548f0d28298b8 Mon Sep 17 00:00:00 2001 From: Ralf Peschke Date: Fri, 29 Mar 2013 08:28:27 +0100 Subject: [PATCH 095/122] Prevent o2m-records to be deleted on client-side When I delete some records of an one2many-field in an on-change-Event, the deleted records are sent to the client and the client hides them in the list. Pressing the save button the record loads again including the deleted o2m-records. The reason is the force_remove-flag. This will delete the record on the client-side and therefore this change will not be reflected on the server side. issue3091 review744002 (transplanted from e40190b28b312f3dd63bceb167698a885826ea0e) --- tryton/gui/window/view_form/model/field.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index 1ebde126f9..7b6ba2dd7a 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -629,7 +629,7 @@ class O2MField(CharField): to_remove.append(record2) for record2 in to_remove: record.value[self.name].remove(record2, signal=False, - force_remove=True) + force_remove=False) if value and (value.get('add') or value.get('update', [])): record.value[self.name].add_fields(fields, signal=False) From ac5a057dbdc31c85ad0058c32f50c9334a7ce118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 2 May 2013 09:31:15 +0200 Subject: [PATCH 096/122] Prepare release 2.2.7 --- CHANGELOG | 3 +++ COPYRIGHT | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 69a750af5a..3933461a56 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.2.7 - 2013-05-02 +* Bug fixes (see mercurial logs for details) + Version 2.2.6 - 2013-02-12 * Bug fixes (see mercurial logs for details) diff --git a/COPYRIGHT b/COPYRIGHT index 49c6ef7021..d30cab46fa 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,4 +1,4 @@ -Copyright (C) 2010-2012 Nicolas Évrard. +Copyright (C) 2010-2013 Nicolas Évrard. Copyright (C) 2007-2013 Cédric Krier. Copyright (C) 2007-2011 Bertrand Chenal. Copyright (C) 2008-2013 B2CK SPRL. From 841b433eea4b797c7f7c91b6c815610ed35ca2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 2 May 2013 09:31:16 +0200 Subject: [PATCH 097/122] Added tag 2.2.7 for changeset 86fee7a37404 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index dbea4011a2..83eacd4e70 100644 --- a/.hgtags +++ b/.hgtags @@ -11,3 +11,4 @@ e3af51f4f68b6b2c9b46e03aaa0a1c0c26214c0c 2.2.3 4b58bf988af7c5068f419bfce0a4912584d65d4c 2.2.4 52abc37b8413843ff1253b66b089412af9815db5 2.2.5 276bfe1927e6162aa27801d4d09e5d06a8332421 2.2.6 +86fee7a374049264042402c50a65dee4676c8d10 2.2.7 From 84bb940a2b79fef185422a4a9940adedb9e31eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 2 May 2013 09:31:35 +0200 Subject: [PATCH 098/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index 7a5d714dca..6435eba0bb 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.7" +VERSION = "2.2.8" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 85f3198a0056ffea58d396ec072d6af7389090ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 24 May 2013 12:40:34 +0200 Subject: [PATCH 099/122] Use jsonrpc object_hook to load json from URL (transplanted from ead6182dfa926891e9a429363c23466de561b5f0) --- tryton/gui/main.py | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tryton/gui/main.py b/tryton/gui/main.py index 9d5b687c43..02611bf9b9 100644 --- a/tryton/gui/main.py +++ b/tryton/gui/main.py @@ -18,6 +18,7 @@ import tryton.rpc as rpc from tryton.config import CONFIG, TRYTON_ICON, PIXMAPS_DIR, DATA_DIR, \ get_config_dir import tryton.common as common +from tryton.jsonrpc import object_hook from tryton.action import Action from tryton.exceptions import TrytonServerError, TrytonError from tryton.gui.window import Window @@ -1445,9 +1446,12 @@ class Main(object): limit = json.loads(params.get('limit', 'null')) auto_refresh = json.loads(params.get('auto_refresh', 'false')) name = json.loads(params.get('window_name', 'false')) - search_value = json.loads(params.get('search_value', '{}')) - domain = json.loads(params.get('domain', '[]')) - context = json.loads(params.get('context', '{}')) + search_value = json.loads(params.get('search_value', '{}'), + object_hook=object_hook) + domain = json.loads(params.get('domain', '[]'), + object_hook=object_hook) + context = json.loads(params.get('context', '{}'), + object_hook=object_hook) except ValueError: return if path: @@ -1468,13 +1472,15 @@ class Main(object): if not wizard: return try: - data = json.loads(params.get('data', '{}')) + data = json.loads(params.get('data', '{}'), + object_hook=object_hook) direct_print = json.loads(params.get('direct_print', 'false')) email_print = json.loads(params.get('email_print', 'false')) email = json.loads(params.get('email', 'null')) name = json.loads(params.get('name', 'false')) window = json.loads(params.get('window', 'false')) - context = json.loads(params.get('context', '{}')) + context = json.loads(params.get('context', '{}'), + object_hook=object_hook) except ValueError: return try: @@ -1489,12 +1495,13 @@ class Main(object): if not report: return try: - data = json.loads(params.get('data')) + data = json.loads(params.get('data'), object_hook=object_hook) direct_print = json.loads(params.get('direct_print', 'false')) email_print = json.loads(params.get('email_print', 'false')) email = json.loads(params.get('email', 'null')) name = json.loads(params.get('name', 'false')) - context = json.loads(params.get('context', '{}')) + context = json.loads(params.get('context', '{}'), + object_hook=object_hook) except ValueError: return try: From 38b0dd65fd4a76dfbad8867404a7d0e4b7ec121d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 9 Jun 2013 22:30:22 +0200 Subject: [PATCH 100/122] Prepare release 2.2.8 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 3933461a56..22700ebb2c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.2.8 - 2013-06-09 +* Bug fixes (see mercurial logs for details) + Version 2.2.7 - 2013-05-02 * Bug fixes (see mercurial logs for details) From cbee40502f88f3fefc1a7f2f484636aaf9f73dc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 9 Jun 2013 22:30:23 +0200 Subject: [PATCH 101/122] Added tag 2.2.8 for changeset db52ed9989e4 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 83eacd4e70..bb01200d1a 100644 --- a/.hgtags +++ b/.hgtags @@ -12,3 +12,4 @@ e3af51f4f68b6b2c9b46e03aaa0a1c0c26214c0c 2.2.3 52abc37b8413843ff1253b66b089412af9815db5 2.2.5 276bfe1927e6162aa27801d4d09e5d06a8332421 2.2.6 86fee7a374049264042402c50a65dee4676c8d10 2.2.7 +db52ed9989e42416ac6c0959e1a0650f5effea86 2.2.8 From ed1af04f7c4bd063780c4a0d4c7d8c9207ab3dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 9 Jun 2013 22:30:41 +0200 Subject: [PATCH 102/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index 6435eba0bb..6b2b241ea7 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.8" +VERSION = "2.2.9" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From bab88c0a15a16e44caa65e6228e785432ba5adf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 7 Jun 2013 19:28:16 +0200 Subject: [PATCH 103/122] del editabletree_entry on remove-widget instead of quit_cell issue3245 review918002 (transplanted from bc89814018e620da9d507688c1ba7047addcc39b) --- tryton/gui/window/view_form/view/list_gtk/editabletree.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tryton/gui/window/view_form/view/list_gtk/editabletree.py b/tryton/gui/window/view_form/view/list_gtk/editabletree.py index 3c79a7b592..701898fd40 100644 --- a/tryton/gui/window/view_form/view/list_gtk/editabletree.py +++ b/tryton/gui/window/view_form/view/list_gtk/editabletree.py @@ -22,8 +22,6 @@ class EditableTreeView(gtk.TreeView): def on_quit_cell(self, current_record, fieldname, value, callback=None): field = current_record[fieldname] - if hasattr(field, 'editabletree_entry'): - del field.editabletree_entry cell = self.cells[fieldname] # The value has not changed and is valid ... do nothing. @@ -234,6 +232,11 @@ class EditableTreeView(gtk.TreeView): entry.set_max_length(int(field.attrs.get('size', 0))) # store in the record the entry widget to get the value in set_value field.editabletree_entry = entry + + def remove_widget(cell): + if hasattr(field, 'editabletree_entry'): + del field.editabletree_entry + entry.connect('remove-widget', remove_widget) record.modified_fields.setdefault(column.name) return False From 0ddaf58507f23bc5bbebfe92d625c2e7be7ca2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 22 Jul 2013 11:38:57 +0200 Subject: [PATCH 104/122] Prepare release 2.2.9 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 22700ebb2c..7068b22f07 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.2.9 - 2013-07-22 +* Bug fixes (see mercurial logs for details) + Version 2.2.8 - 2013-06-09 * Bug fixes (see mercurial logs for details) From c1306df192f2d961671745468d55dcd624199757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 22 Jul 2013 11:38:58 +0200 Subject: [PATCH 105/122] Added tag 2.2.9 for changeset 5598a586bd06 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index bb01200d1a..bd84c1b2ca 100644 --- a/.hgtags +++ b/.hgtags @@ -13,3 +13,4 @@ e3af51f4f68b6b2c9b46e03aaa0a1c0c26214c0c 2.2.3 276bfe1927e6162aa27801d4d09e5d06a8332421 2.2.6 86fee7a374049264042402c50a65dee4676c8d10 2.2.7 db52ed9989e42416ac6c0959e1a0650f5effea86 2.2.8 +5598a586bd06dbd7a841bc96cd3b9b946b94530e 2.2.9 From a016b7311fd7a9052b95cc3fa31b90ef755bd021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 22 Jul 2013 11:39:32 +0200 Subject: [PATCH 106/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index 6b2b241ea7..fdefcfd205 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.9" +VERSION = "2.2.10" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 2f81c3d94c2b0cef5cab205b61e7556ea62f57c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Mon, 22 Jul 2013 14:43:55 +0200 Subject: [PATCH 107/122] Fix domain composition between screen and attribute domains domains can not be summed because they can be of 'OR' type review985002 (transplanted from ba60f315fc3e9346c438edd10cdcc2470abd1317) --- tryton/gui/window/view_form/model/field.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py index 7b6ba2dd7a..598b108150 100644 --- a/tryton/gui/window/view_form/model/field.py +++ b/tryton/gui/window/view_form/model/field.py @@ -55,13 +55,13 @@ class CharField(object): def domain_get(self, record): screen_domain, attr_domain = self.domains_get(record) - return localize_domain(screen_domain) + attr_domain + return [localize_domain(screen_domain), attr_domain] def validation_domains(self, record): screen_domain, attr_domain = self.domains_get(record) if attr_domain: - return screen_domain, screen_domain + unlocalize_domain(attr_domain, - self.name) + return (screen_domain, [screen_domain, + unlocalize_domain(attr_domain, self.name)]) else: return screen_domain, screen_domain @@ -394,7 +394,8 @@ class M2OField(CharField): def domain_get(self, record): screen_domain, attr_domain = self.domains_get(record) - return localize_domain(inverse_leaf(screen_domain), self.name) + attr_domain + return [localize_domain(inverse_leaf(screen_domain), self.name), + attr_domain] def get_state_attrs(self, record): result = super(M2OField, self).get_state_attrs(record) @@ -685,7 +686,7 @@ class O2MField(CharField): def domain_get(self, record): screen_domain, attr_domain = self.domains_get(record) - return localize_domain(inverse_leaf(screen_domain)) + attr_domain + return [localize_domain(inverse_leaf(screen_domain)), attr_domain] class M2MField(O2MField): From 6e0f331f39d28abed598370a3def9a492d25f7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 10 Oct 2013 23:24:12 +0200 Subject: [PATCH 108/122] Prepare release 2.2.10 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 7068b22f07..91c3772a02 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.2.10 - 2013-10-10 +* Bug fixes (see mercurial logs for details) + Version 2.2.9 - 2013-07-22 * Bug fixes (see mercurial logs for details) From e7d22df7b7091d0550a49f91adb170540edfcafd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 10 Oct 2013 23:24:13 +0200 Subject: [PATCH 109/122] Added tag 2.2.10 for changeset 20d44dc5b881 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index bd84c1b2ca..07a82b990e 100644 --- a/.hgtags +++ b/.hgtags @@ -14,3 +14,4 @@ e3af51f4f68b6b2c9b46e03aaa0a1c0c26214c0c 2.2.3 86fee7a374049264042402c50a65dee4676c8d10 2.2.7 db52ed9989e42416ac6c0959e1a0650f5effea86 2.2.8 5598a586bd06dbd7a841bc96cd3b9b946b94530e 2.2.9 +20d44dc5b8812ff437402e4cbc5695f8f7e9f3b2 2.2.10 From 4251b7d87974002d7e0476f16264c3389ec873cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 10 Oct 2013 23:24:37 +0200 Subject: [PATCH 110/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index fdefcfd205..ae1e1c585e 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.10" +VERSION = "2.2.11" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 6e0170ccc740f07ec74218bcd7d2fd3aa8d074b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 2 Oct 2013 21:16:47 +0200 Subject: [PATCH 111/122] Don't extend domain but wrap into a new list review1106002 (transplanted from e4a2d43ad02e5c5d3ddd4c22a3c2a0890afff0aa) --- tryton/gui/window/view_form/view/form_gtk/one2many.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tryton/gui/window/view_form/view/form_gtk/one2many.py b/tryton/gui/window/view_form/view/form_gtk/one2many.py index 21ae30c37b..99eeebca5c 100644 --- a/tryton/gui/window/view_form/view/form_gtk/one2many.py +++ b/tryton/gui/window/view_form/view/form_gtk/one2many.py @@ -297,9 +297,8 @@ class One2Many(WidgetInterface): domain = self.field.domain_get(self.record) context = rpc.CONTEXT.copy() context.update(self.field.context_get(self.record)) - domain = domain[:] - domain.extend(self.record.expr_eval(self.attrs.get('add_remove'), - context)) + domain = [domain, self.record.expr_eval(self.attrs.get('add_remove'), + context)] removed_ids = self.field.get_removed_ids(self.record) try: From 1a68134ea0b1a62d0659cae84cc3359288224add Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 2 Oct 2013 21:17:30 +0200 Subject: [PATCH 112/122] Fix move_into when record is not saved review1107002 (transplanted from d4d4ec2782007eab231325592e4885da76ce1381) --- tryton/gui/window/view_form/view/list.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py index 1efca225ea..7c263765b7 100644 --- a/tryton/gui/window/view_form/view/list.py +++ b/tryton/gui/window/view_form/view/list.py @@ -129,7 +129,8 @@ class AdaptModelGroup(gtk.GenericTreeModel): # Don't remove record from previous group # as the new parent will change the parent # This prevents concurrency conflict - record.group.record_removed.remove(record) + if record in record.group.record_removed: + record.group.record_removed.remove(record) group.add(record) record.modified_fields.setdefault(record.parent_name or 'id') group.move(record, 0) From 92f018c4fee28810afdac2d79437a4c9da065662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 9 Oct 2013 18:19:26 +0200 Subject: [PATCH 113/122] Fix restore predefined export with more than 2 levels depth issue3402 review1124003 (transplanted from 30b291e0bf4f17a0219b4572cee67e8fcc07acc7) --- tryton/gui/window/win_export.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/gui/window/win_export.py b/tryton/gui/window/win_export.py index 43f2c9689e..107956e3c2 100644 --- a/tryton/gui/window/win_export.py +++ b/tryton/gui/window/win_export.py @@ -370,7 +370,7 @@ class WinExport(object): self.on_row_expanded(self.view1, iter, self.model1.get_path(iter)) iter = self.model1.iter_children(iter) - prefix = parent + '/' + prefix += parent + '/' break else: iter = self.model1.iter_next(iter) From a5735e098d56658bd24148ae29075d717e3b87ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 3 Nov 2013 18:41:31 +0100 Subject: [PATCH 114/122] Sanitize report file extension issue3446 (transplanted from 357d0a4d9cb8b3f0f4192cb87996a5720bf1cb37) --- CHANGELOG | 2 ++ tryton/action/main.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 91c3772a02..002f286639 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Sanitize report file extension + Version 2.2.10 - 2013-10-10 * Bug fixes (see mercurial logs for details) diff --git a/tryton/action/main.py b/tryton/action/main.py index 3c8117061b..d5df3e89bc 100644 --- a/tryton/action/main.py +++ b/tryton/action/main.py @@ -59,7 +59,8 @@ class Action(object): dtemp = tempfile.mkdtemp(prefix='tryton_') fp_name = os.path.join(dtemp, name.replace(os.sep, '_').replace(os.altsep or os.sep, '_') \ - + os.extsep + type) + + os.extsep + + type.replace(os.sep, '_').replace(os.altsep or os.sep, '_')) with open(fp_name, 'wb') as file_d: file_d.write(data) if email_print: From d765fb50685ef76afd79855a721f77b7d2e40400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 3 Nov 2013 18:52:40 +0100 Subject: [PATCH 115/122] Prepare release 2.2.11 --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 002f286639..f13ed5195e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +Version 2.2.11 - 2013-11-03 +* Bug fixes (see mercurial logs for details) * Sanitize report file extension Version 2.2.10 - 2013-10-10 From 919412a3ffb0407a60ba96fd06a0a974d3f5b135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 3 Nov 2013 18:52:41 +0100 Subject: [PATCH 116/122] Added tag 2.2.11 for changeset aecdbc9aefbe --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 07a82b990e..f687249799 100644 --- a/.hgtags +++ b/.hgtags @@ -15,3 +15,4 @@ e3af51f4f68b6b2c9b46e03aaa0a1c0c26214c0c 2.2.3 db52ed9989e42416ac6c0959e1a0650f5effea86 2.2.8 5598a586bd06dbd7a841bc96cd3b9b946b94530e 2.2.9 20d44dc5b8812ff437402e4cbc5695f8f7e9f3b2 2.2.10 +aecdbc9aefbee7d6cdb2a72e573befeaed5eda5d 2.2.11 From 67d7807c587da0578f7026c1f506a806e91d041e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sun, 3 Nov 2013 18:53:02 +0100 Subject: [PATCH 117/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index ae1e1c585e..a886797380 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.11" +VERSION = "2.2.12" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From cd3989b59bf156569b383bec0393de882b7f3f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 18 Oct 2013 22:25:45 +0200 Subject: [PATCH 118/122] Quote user and password in the roundup XML-RPC URL review1143002 (transplanted from 8d9757fd30187f3bb35287b10020dd04e320f8d6) --- tryton/common/common.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tryton/common/common.py b/tryton/common/common.py index 00ad4bd7d2..16dd909bf0 100644 --- a/tryton/common/common.py +++ b/tryton/common/common.py @@ -9,6 +9,7 @@ import gettext import os import re import logging +from functools import partial from tryton.config import CONFIG from tryton.config import TRYTON_ICON, PIXMAPS_DIR, DATA_DIR import time @@ -912,8 +913,9 @@ def send_bugtracker(msg): protocol = 'http' if ssl or hasattr(socket, 'ssl'): protocol = 'https' + quote = partial(urllib.quote, safe="!$&'()*+,;=:") server = xmlrpclib.Server(('%s://%s:%s@' + CONFIG['roundup.xmlrpc']) - % (protocol, user, password), allow_none=True) + % (protocol, quote(user), quote(password)), allow_none=True) if hashlib: msg_md5 = hashlib.md5(msg).hexdigest() else: From 5c3fb5cbfa8e8478c78fa0a3f553cc0e7e673767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 4 Dec 2013 18:33:59 +0100 Subject: [PATCH 119/122] Prepare release 2.2.12 --- CHANGELOG | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index f13ed5195e..d0edb8cc43 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +Version 2.2.12 - 2013-12-04 +* Bug fixes (see mercurial logs for details) + Version 2.2.11 - 2013-11-03 * Bug fixes (see mercurial logs for details) * Sanitize report file extension From 83efaca488576197d1e027c7bed4b14ffd624be3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 4 Dec 2013 18:34:00 +0100 Subject: [PATCH 120/122] Added tag 2.2.12 for changeset bdc89dbdc16a --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index f687249799..6f2276df54 100644 --- a/.hgtags +++ b/.hgtags @@ -16,3 +16,4 @@ db52ed9989e42416ac6c0959e1a0650f5effea86 2.2.8 5598a586bd06dbd7a841bc96cd3b9b946b94530e 2.2.9 20d44dc5b8812ff437402e4cbc5695f8f7e9f3b2 2.2.10 aecdbc9aefbee7d6cdb2a72e573befeaed5eda5d 2.2.11 +bdc89dbdc16a2fa82b807af30c503c285f99f6bc 2.2.12 From 4bb41b7abac5d99e66b4d24512c88061a1183e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 4 Dec 2013 18:34:22 +0100 Subject: [PATCH 121/122] Increase version number --- tryton/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tryton/version.py b/tryton/version.py index a886797380..2c7b5af4ed 100644 --- a/tryton/version.py +++ b/tryton/version.py @@ -1,7 +1,7 @@ #This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. PACKAGE = "tryton" -VERSION = "2.2.12" +VERSION = "2.2.13" LICENSE = "GPL-3" WEBSITE = "http://www.tryton.org/" From 4584290436dccad4a8e4aa1f2a41896d628dfb03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 6 Feb 2014 22:36:44 +0100 Subject: [PATCH 122/122] Fix find button in search window It should use the text filled in the search entry. And it should not close the window if nothing is found. review3101003 (transplanted from 8b22f7366f7caeb7ecbe86c28b8b4f8f3bf32627) --- tryton/gui/window/win_search.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tryton/gui/window/win_search.py b/tryton/gui/window/win_search.py index 8495aa7891..ea19fd1963 100644 --- a/tryton/gui/window/win_search.py +++ b/tryton/gui/window/win_search.py @@ -109,10 +109,8 @@ class WinSearch(NoModal): if response_id == gtk.RESPONSE_OK: res = self.screen.sel_ids_get() elif response_id == gtk.RESPONSE_APPLY: - if not self.screen.search_filter(): - res = self.screen.sel_ids_get() - else: - return + self.screen.search_filter(self.screen.screen_container.get_text()) + return elif response_id == gtk.RESPONSE_ACCEPT: screen = Screen(self.model_name, domain=self.domain, context=self.context, mode=['form'])