From 6be32b621623df6e66168bae5437661c0e1be7b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Tue, 24 Apr 2012 12:19:47 +0200
Subject: [PATCH 001/104] 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 df205c95e7..82ae4e3646 100644
--- a/tryton/version.py
+++ b/tryton/version.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.
PACKAGE = "tryton"
-VERSION = "2.4.0"
+VERSION = "2.4.1"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
From 9ab579e74fbafa85fcac272f14359531f78c7601 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 27 Apr 2012 13:36:02 +0200
Subject: [PATCH 002/104] Check if GTK locale directory exists before copying
it (transplanted from 7cebed85fb4e0fed16e31aec1c7dededd6bd5195)
---
setup.py | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/setup.py b/setup.py
index 2bac21704e..e93598de9a 100644
--- a/setup.py
+++ b/setup.py
@@ -247,8 +247,9 @@ if os.name == 'nt':
for lang in all_languages():
if os.path.isdir(os.path.join(dist_dir, 'share', 'locale', lang)):
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(gtk_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(dist_dir, 'share', 'themes',
'MS-Windows')):
@@ -361,8 +362,9 @@ elif sys.platform == 'darwin':
lang)):
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(gtk_dir, 'share', 'locale', lang)):
+ shutil.copytree(os.path.join(gtk_dir, 'share', 'locale', lang),
+ os.path.join(resources_dir, 'share', 'locale', lang))
# fix pathes within shared libraries
for library in chain(
From 40ef53347080df95a043b50f25d23e6a8ef56521 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 27 Apr 2012 13:36:22 +0200
Subject: [PATCH 003/104] Add missing Tryton icon to wizard dialog
(transplanted from 60449e5bfc90aaecb868fe91151a6eca945ae41d)
---
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 6b0c7de8ef..d57dc4d79b 100644
--- a/tryton/gui/window/wizard.py
+++ b/tryton/gui/window/wizard.py
@@ -13,7 +13,7 @@ from tryton.gui import Main
from tryton.exceptions import TrytonServerError, TrytonServerUnavailable
from tryton.gui.window.nomodal import NoModal
from tryton.common.button import Button
-from tryton.common import RPCExecute, RPCException
+from tryton.common import RPCExecute, RPCException, TRYTON_ICON
_ = gettext.gettext
@@ -293,6 +293,7 @@ class WizardDialog(Wizard, NoModal):
self.dia = gtk.Dialog(self.name, self.parent,
gtk.DIALOG_DESTROY_WITH_PARENT)
self.dia.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
+ self.dia.set_icon(TRYTON_ICON)
if hasattr(self.dia, 'set_deletable'):
self.dia.set_deletable(False)
self.dia.connect('close', self.close)
From 732ed37303cdf7f792caca0e82344d3bba0a6f21 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 27 Apr 2012 13:37:07 +0200
Subject: [PATCH 004/104] Stop wizard on TrytonServerError if there is no
screen
issue2569
review347001
(transplanted from f3efd9da7bb8145108e72d82d1d3afc41414fe45)
---
tryton/gui/window/wizard.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tryton/gui/window/wizard.py b/tryton/gui/window/wizard.py
index d57dc4d79b..b18a2e5666 100644
--- a/tryton/gui/window/wizard.py
+++ b/tryton/gui/window/wizard.py
@@ -82,8 +82,9 @@ class Wizard(object):
result = RPCExecute('wizard', self.action, 'execute',
self.session_id, data, self.state, context=ctx)
except RPCException, rpc_exception:
- if not isinstance(rpc_exception.exception,
- TrytonServerError):
+ if (not isinstance(rpc_exception.exception,
+ TrytonServerError)
+ or not self.screen):
self.state = self.end_state
break
From 3c324001a90cdb518a43790e9a116449b617bc74 Mon Sep 17 00:00:00 2001
From: Mathias Behrle
Date: Sat, 28 Apr 2012 11:45:30 +0200
Subject: [PATCH 005/104] Adding missing argument for string conversion.
issue2573
(transplanted from 1aa6aa450c48ba800a6a978a9f985dabd876b43e)
---
setup.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/setup.py b/setup.py
index e93598de9a..589880ebf1 100644
--- a/setup.py
+++ b/setup.py
@@ -62,7 +62,7 @@ data_files = [
for lang in languages:
data_files += [
('share/locale/%s/LC_MESSAGES' % lang,
- glob.glob('share/locale/%s/LC_MESSAGES/*.mo')),
+ glob.glob('share/locale/%s/LC_MESSAGES/*.mo' % lang)),
]
if os.name == 'nt':
From ec8a7f3e5122e832a6c370ed14cf68c6e8d376dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sat, 5 May 2012 09:30:41 +0200
Subject: [PATCH 006/104] Improve hack of glitch in position of widgets in
notebook
By calling display when switching tabs, it loose the value of focused widget
because value is reset before the focus-out is proceed.
issue2571
review353001
(transplanted from 9c863c7e1626ca96677d04de19ab59957f5d7253)
---
tryton/gui/window/view_form/view/form.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/tryton/gui/window/view_form/view/form.py b/tryton/gui/window/view_form/view/form.py
index 3ed74f4b18..5f5e69b584 100644
--- a/tryton/gui/window/view_form/view/form.py
+++ b/tryton/gui/window/view_form/view/form.py
@@ -30,6 +30,7 @@ class ViewForm(ParserView):
for notebook in notebooks:
def switch(notebook, page, page_num):
if page_num not in display_done.setdefault(notebook, []):
+ notebook.grab_focus()
display_done[notebook].append(page_num)
self.display()
notebook.connect('switch-page', switch)
From 0fbc23f54a44d7080cbd933f8e40b90dd85a952d 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 007/104] 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 5b7a125077..9c71e0d66f 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):
@@ -56,7 +57,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):
@@ -422,6 +434,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 fc0fc33900c52ee8399384fe211007adedbf094f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sat, 12 May 2012 17:26:43 +0200
Subject: [PATCH 008/104] Set None as value for empty reference field
issue2599
(transplanted from 11a133823558e92f8428d6405a5ea5bbbbfe2b8c)
---
tryton/gui/window/view_form/view/form_gtk/reference.py | 5 ++++-
1 file changed, 4 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 a610486c5d..651982afc6 100644
--- a/tryton/gui/window/view_form/view/form_gtk/reference.py
+++ b/tryton/gui/window/view_form/view/form_gtk/reference.py
@@ -116,7 +116,10 @@ class Reference(Many2One):
def set_value(self, record, field):
if not self.get_model():
value = self.wid_text.get_text()
- return field.set_client(record, ('', value))
+ if not value:
+ field.set_client(record, None)
+ else:
+ return field.set_client(record, ('', value))
return super(Reference, self).set_value(record, field)
def set_text(self, value):
From 9ed60d92adc9175ae8ae1a8cd92247a6478932bf 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 009/104] 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 fe4012f979..e28025ed15 100644
--- a/tryton/gui/window/form.py
+++ b/tryton/gui/window/form.py
@@ -395,19 +395,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 sig_search(self, widget):
search_container = self.screen.screen_container
From c22b7eb52a67a8437a0f814d955a3b6ed7e0dbd3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sat, 19 May 2012 15:37:35 +0200
Subject: [PATCH 010/104] Use one record pool per group
Having a global pool has some side effect between tabs.
So it is better to get read optimization only inside one tab by using a pool on
the main group.
issue2582
review370002
(transplanted from c025b45e7c70bc262ddab7bb680b4260725da966)
---
tryton/gui/window/view_form/model/group.py | 6 ++++++
tryton/gui/window/view_form/model/record.py | 23 ++++++++++++---------
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/tryton/gui/window/view_form/model/group.py b/tryton/gui/window/view_form/model/group.py
index dae254d2c2..089882af9b 100644
--- a/tryton/gui/window/view_form/model/group.py
+++ b/tryton/gui/window/view_form/model/group.py
@@ -1,5 +1,10 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
+try:
+ from weakref import WeakSet
+except ImportError:
+ from weakrefset import WeakSet
+
from record import Record
from field import Field, O2MField
from tryton.signal_event import SignalEvent
@@ -36,6 +41,7 @@ class Group(SignalEvent, list):
self.__id2record = {}
self.__field_childs = None
self.exclude_field = None
+ self.pool = WeakSet()
@property
def domain(self):
diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py
index 874615ed12..cf3458ce5a 100644
--- a/tryton/gui/window/view_form/model/record.py
+++ b/tryton/gui/window/view_form/model/record.py
@@ -1,10 +1,5 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
-try:
- from weakref import WeakSet
-except ImportError:
- from weakrefset import WeakSet
-from collections import defaultdict
import tryton.rpc as rpc
from tryton.signal_event import SignalEvent
import tryton.common as common
@@ -13,8 +8,6 @@ import field as fields
from functools import reduce
from tryton.common import RPCExecute, RPCException
-POOL = defaultdict(WeakSet)
-
class Record(SignalEvent):
@@ -42,7 +35,7 @@ class Record(SignalEvent):
self.autocompletion = {}
self.exception = False
self.destroyed = False
- POOL[model_name].add(self)
+ self.pool.add(self)
def __getitem__(self, name):
if name not in self._loaded and self.id >= 0:
@@ -74,7 +67,7 @@ class Record(SignalEvent):
n += 1
record_context = self.context_get()
if loading == 'eager' and len(id2record) < 80:
- for record in POOL[self.model_name]:
+ for record in self.pool:
if (name not in record._loaded
and record.id >= 0
and record.id not in id2record
@@ -131,6 +124,14 @@ class Record(SignalEvent):
def modified(self):
return bool(self.modified_fields)
+ @property
+ def pool(self):
+ group = self.group
+ while (group.parent is not None
+ and group.parent.model_name == self.model_name):
+ group = group.parent
+ return group.pool
+
@property
def parent(self):
return self.group.parent
@@ -576,6 +577,8 @@ class Record(SignalEvent):
return self.attachment_count
def destroy(self):
+ # Get reference to pool before unref group
+ pool = self.pool
for v in self.value.itervalues():
if hasattr(v, 'destroy'):
v.destroy()
@@ -584,4 +587,4 @@ class Record(SignalEvent):
self.value = None
self.next = None
self.destroyed = True
- POOL[self.model_name].remove(self)
+ pool.remove(self)
From f2160ea20ce6bcc85e848fc0147c2546688bc26a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sat, 19 May 2012 15:40:27 +0200
Subject: [PATCH 011/104] Retreive current record after saving
issue371001
(transplanted from 8a902d5ad123085bd9c2dda0203483295ee0a386)
---
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 5f5e69b584..af75da275d 100644
--- a/tryton/gui/window/view_form/view/form.py
+++ b/tryton/gui/window/view_form/view/form.py
@@ -166,8 +166,8 @@ class ViewForm(ParserView):
focus_widget.grab_focus()
def button_clicked(self, widget):
- record = self.screen.current_record
record_id = self.screen.save_current()
+ record = self.screen.current_record
attrs = widget.attrs
if record_id:
if not attrs.get('confirm', False) or \
From 7acf30e7557416a4e9286783b7e00e5c35f762df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Mon, 21 May 2012 12:40:10 +0200
Subject: [PATCH 012/104] Set record modified when setting list on O2M
issue2607
review375001
(transplanted from 209e5395d4076e182cf454c0ab868e02869c361e)
---
tryton/gui/window/view_form/model/field.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py
index b918d360d0..af88c6bffa 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -664,7 +664,10 @@ class O2MField(CharField):
def set_on_change(self, record, value):
self._set_default_value(record)
if isinstance(value, (list, tuple)):
- return self.set(record, value, modified=False)
+ self.set(record, value, modified=False)
+ record.modified_fields.setdefault(self.name)
+ record.signal('record-modified')
+ return True
if value and (value.get('add') or value.get('update')):
context = self.context_get(record)
From cdbe6850f4a91d4fefcca34a219a221dcbd6bdb5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 8 Jun 2012 19:22:05 +0200
Subject: [PATCH 013/104] Manage error when saving record from Many2One
The save of the current record must be done at the same level as the
validation.
issue2614
review393001
(transplanted from d284eb9d3405d49c09eb5e59d2bac4ce9b4b27bc)
---
tryton/gui/window/view_form/view/form_gtk/many2one.py | 11 ++++-------
tryton/gui/window/view_form/view/list_gtk/parser.py | 9 +++------
tryton/gui/window/win_form.py | 7 ++++++-
3 files changed, 13 insertions(+), 14 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 a8448d2439..82b647175a 100644
--- a/tryton/gui/window/view_form/view/form_gtk/many2one.py
+++ b/tryton/gui/window/view_form/view/form_gtk/many2one.py
@@ -177,13 +177,13 @@ class Many2One(WidgetInterface):
screen = self.get_screen()
def callback(result):
- if result and screen.save_current():
+ if result:
self.field.set_client(self.record,
self.value_from_id(screen.current_record.id,
screen.current_record.rec_name()))
self.display(self.record, self.field)
self.focus_out = True
- WinForm(screen, callback, new=True)
+ WinForm(screen, callback, new=True, save_current=True)
def sig_edit(self, widget):
if not self.focus_out or not self.field:
@@ -198,18 +198,15 @@ class Many2One(WidgetInterface):
screen.load([self.id_from_value(self.field.get(self.record))])
def callback(result):
- if result and screen.save_current():
+ if result:
self.field.set_client(self.record,
self.value_from_id(screen.current_record.id,
screen.current_record.rec_name()),
force_change=True)
- elif result:
- screen.display()
- return WinForm(screen, callback)
self.focus_out = True
self.display(self.record, self.field)
self.changed = True
- WinForm(screen, callback)
+ WinForm(screen, callback, save_current=True)
return
elif model and not self._readonly:
domain = self.field.domain_get(self.record)
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 335db528c3..b67cd6f30b 100644
--- a/tryton/gui/window/view_form/view/list_gtk/parser.py
+++ b/tryton/gui/window/view_form/view/list_gtk/parser.py
@@ -627,20 +627,17 @@ class M2O(Char):
mode=['form'])
def open_callback(result):
- if result and screen.save_current():
+ if result:
value = (screen.current_record.id,
screen.current_record.rec_name())
field.set_client(record, value, force_change=True)
- elif result:
- screen.display()
- return WinForm(screen, open_callback)
if callback:
callback()
if obj_id:
screen.load([obj_id])
- WinForm(screen, open_callback)
+ WinForm(screen, open_callback, save_current=True)
else:
- WinForm(screen, open_callback, new=True)
+ WinForm(screen, open_callback, new=True, save_current=True)
def search_remote(self, record, relation, ids=None, domain=None,
context=None, callback=None):
diff --git a/tryton/gui/window/win_form.py b/tryton/gui/window/win_form.py
index 9b27b928b9..f6536583d7 100644
--- a/tryton/gui/window/win_form.py
+++ b/tryton/gui/window/win_form.py
@@ -16,12 +16,14 @@ class WinForm(NoModal):
"Form window"
def __init__(self, screen, callback, view_type='form',
- new=False, many=False, domain=None, context=None):
+ new=False, many=False, domain=None, context=None,
+ save_current=False):
NoModal.__init__(self)
self.screen = screen
self.callback = callback
self.domain = domain
self.context = context
+ self.save_current = save_current
self.prev_view = self.screen.current_view
self.screen.screen_container.alternate_view = True
switch_new = False
@@ -366,6 +368,9 @@ class WinForm(NoModal):
and self.screen.current_record is not None):
validate = self.screen.current_record.validate(
self.screen.current_view.get_fields())
+ if validate and self.save_current:
+ if not self.screen.save_current():
+ validate = False
if not validate:
self.screen.set_cursor()
self.screen.display()
From 514f085711928dda1bfa6b694847b0c6aa08a988 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 8 Jun 2012 21:21:33 +0200
Subject: [PATCH 014/104] Update context before it could be overriden by field
name (transplanted from 62f249f7fd8511a3b7dcd4c008dadb163375c182)
---
tryton/gui/window/view_form/model/record.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py
index cf3458ce5a..4bbc56bb81 100644
--- a/tryton/gui/window/view_form/model/record.py
+++ b/tryton/gui/window/view_form/model/record.py
@@ -448,10 +448,10 @@ class Record(SignalEvent):
self._check_load()
ctx = rpc.CONTEXT.copy()
ctx['context'] = ctx.copy()
+ ctx['context'].update(self.context_get())
for name, field in self.group.fields.items():
ctx[name] = field.get_eval(self, check_load=check_load)
- ctx['context'].update(self.context_get())
ctx['active_id'] = self.id
ctx['id'] = self.id # Force local id
ctx['_user'] = rpc._USER
From 1bb9d7d370c2bb63e1f073a10c2e6e7efe2342ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Wed, 20 Jun 2012 10:54:07 +0200
Subject: [PATCH 015/104] Don't fail on unknow font family
issue2617
review399004
(transplanted from 03432c9a3c3db53087a8e83c5ca0da58069ab62a)
---
tryton/gui/window/view_form/view/form_gtk/richtextbox.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/tryton/gui/window/view_form/view/form_gtk/richtextbox.py b/tryton/gui/window/view_form/view/form_gtk/richtextbox.py
index 85c68d5e47..8325f6a5dd 100644
--- a/tryton/gui/window/view_form/view/form_gtk/richtextbox.py
+++ b/tryton/gui/window/view_form/view/form_gtk/richtextbox.py
@@ -145,8 +145,10 @@ class RichTextBox(TextBox):
}
self.tools['size'].child.set_active(self.sizes.index(
self.current_font_prop['size']))
- self.tools['font_family'].child.set_active(self.families.index(
- self.current_font_prop['font_family']))
+ font_family = self.current_font_prop['font_family']
+ if font_family in self.families:
+ self.tools['font_family'].child.set_active(self.families.index(
+ font_family))
self.start_tags = {}
self.end_tags = {}
# Connect events
From 38a0046efb07064d7758f8a9155e0a4c4b106d15 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 22 Jun 2012 17:51:38 +0200
Subject: [PATCH 016/104] Don't reload records when sorting if there are
unsaved records
issue2664
review403001
(transplanted from 696e37e43e038166ccf84050272397070e54251a)
---
tryton/gui/window/view_form/view/list_gtk/parser.py | 4 +---
1 file changed, 1 insertion(+), 3 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 b67cd6f30b..a423780cbb 100644
--- a/tryton/gui/window/view_form/view/list_gtk/parser.py
+++ b/tryton/gui/window/view_form/view/list_gtk/parser.py
@@ -64,13 +64,11 @@ def sort_model(column, treeview, screen):
store = treeview.get_model()
unsaved_records = [x for x in store.group if x.id < 0]
search_string = screen.screen_container.get_text() or None
- if screen.search_count == len(store):
+ if screen.search_count == len(store) or unsaved_records:
ids = screen.search_filter(search_string=search_string, only_ids=True)
store.sort(ids)
else:
screen.search_filter(search_string=search_string)
- for record in unsaved_records:
- store.group.append(record)
def realized(func):
From 1880b0ec6334ad065ffd6598026b74808058f55f 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 017/104] 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 1ea435db93..949d8d1ed9 100644
--- a/tryton/gui/window/win_export.py
+++ b/tryton/gui/window/win_export.py
@@ -242,7 +242,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 1702d2f4f180557912bacd9a9caf6ad130d29964 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 22 Jun 2012 17:56:23 +0200
Subject: [PATCH 018/104] Reset rec_name when setting just id of M2O or
Reference
issue2641
review406001
(transplanted from 6e702bc1759212191c72dfb480378c652b08886b)
---
tryton/gui/window/view_form/model/field.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py
index af88c6bffa..85e06d194a 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -389,7 +389,9 @@ class M2OField(CharField):
def set_client(self, record, value, force_change=False):
if isinstance(value, (tuple, list)):
value, rec_name = value
- record.value[self.name + '.rec_name'] = rec_name
+ else:
+ rec_name = ''
+ record.value[self.name + '.rec_name'] = rec_name
super(M2OField, self).set_client(record, value,
force_change=force_change)
@@ -806,7 +808,9 @@ class ReferenceField(CharField):
ref_model, ref_id = value
if isinstance(ref_id, (tuple, list)):
ref_id, rec_name = ref_id
- record.value[self.name + '.rec_name'] = rec_name
+ else:
+ rec_name = ''
+ record.value[self.name + '.rec_name'] = rec_name
value = (ref_model, ref_id)
super(ReferenceField, self).set_client(record, value,
force_change=force_change)
From 6f1cd98f759495de2081134b48d1b4d057b4a6aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 22 Jun 2012 17:58:23 +0200
Subject: [PATCH 019/104] Manage focus out event when adding in O2M
issue2640
review404002
(transplanted from ac56de2924712b7b0e36e7a788e199b237fe7b7d)
---
tryton/gui/window/view_form/view/form_gtk/one2many.py | 6 ++++++
1 file changed, 6 insertions(+)
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 3a4db78586..bf3ca67cd4 100644
--- a/tryton/gui/window/view_form/view/form_gtk/one2many.py
+++ b/tryton/gui/window/view_form/view/form_gtk/one2many.py
@@ -32,6 +32,7 @@ class One2Many(WidgetInterface):
tooltips = common.Tooltips()
+ self.focus_out = True
if attrs.get('add_remove'):
self.wid_text = gtk.Entry()
@@ -299,6 +300,8 @@ class One2Many(WidgetInterface):
self._sig_add()
def _sig_add(self, *args):
+ if not self.focus_out:
+ return
self.view.set_value()
domain = self.field.domain_get(self.record)
context = self.field.context_get(self.record)
@@ -306,6 +309,7 @@ class One2Many(WidgetInterface):
domain.extend(self.record.expr_eval(self.attrs.get('add_remove')))
removed_ids = self.field.get_removed_ids(self.record)
+ self.focus_out = False
try:
if self.wid_text.get_text():
dom = [('rec_name', 'ilike',
@@ -316,9 +320,11 @@ class One2Many(WidgetInterface):
ids = RPCExecute('model', self.attrs['relation'], 'search', dom,
0, CONFIG['client.limit'], None, context=context)
except RPCException:
+ self.focus_out = True
return False
def callback(result):
+ self.focus_out = True
if result:
ids = [x[0] for x in result]
self.screen.load(ids, modified=True)
From 1fee6f3058f77d740f259737ad7d3df7ae9371a2 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 020/104] 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 82b647175a..1b70515282 100644
--- a/tryton/gui/window/view_form/view/form_gtk/many2one.py
+++ b/tryton/gui/window/view_form/view/form_gtk/many2one.py
@@ -106,7 +106,7 @@ class Many2One(WidgetInterface):
def id_from_value(value):
return value
- 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 or not self.field:
return
self.changed = False
@@ -115,7 +115,7 @@ class Many2One(WidgetInterface):
self.focus_out = False
if model and not self.has_target(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()
@@ -276,7 +276,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 set_text(self, value):
if not value:
From 9b1441447c0df9e571caffe4d20390b876ebbc37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Tue, 10 Jul 2012 13:09:27 +0200
Subject: [PATCH 021/104] Delay the save of record and popup in treeview
The save and popup must be delayed because if it take too much time, the rpc
call will process events before the main event is finished.
issue2621
review412001
(transplanted from f2b19cdf0cf13c91d6b7f261a9a7838872f0e589)
---
.../view_form/view/form_gtk/many2one.py | 4 +-
tryton/gui/window/view_form/view/list.py | 84 +++++++++++--------
2 files changed, 51 insertions(+), 37 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 1b70515282..906b597018 100644
--- a/tryton/gui/window/view_form/view/form_gtk/many2one.py
+++ b/tryton/gui/window/view_form/view/form_gtk/many2one.py
@@ -308,5 +308,7 @@ class Many2One(WidgetInterface):
def _populate_popup(self, widget, menu):
value = self.field.get(self.record)
if self.has_target(value):
- populate(menu, self.get_model(), self.id_from_value(value))
+ # Delay filling of popup as it can take time
+ gobject.idle_add(populate, menu, self.get_model(),
+ self.id_from_value(value))
return True
diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py
index 6233da2051..285bd6c00a 100644
--- a/tryton/gui/window/view_form/view/list.py
+++ b/tryton/gui/window/view_form/view/list.py
@@ -549,38 +549,41 @@ class ViewList(ParserView):
return False
group = model.group
record = group[path[0][0]]
-
menu = gtk.Menu()
- copy_item = gtk.ImageMenuItem('gtk-copy')
- copy_item.connect('activate', lambda x: self.on_copy())
- menu.append(copy_item)
- # Don't activate actions if parent is modified
- parent = record.parent if record else None
- while parent:
- if parent.modified:
- record = None
- break
- parent = parent.parent
- populate(menu, group.model_name, record)
- for col in self.widget_tree.get_columns():
- if not col.get_visible() or not col.name:
- continue
- field = group.fields[col.name]
- model = None
- if field.attrs['type'] == 'many2one':
- model = field.attrs['relation']
- record_id = field.get(record)
- elif field.attrs['type'] == 'reference':
- value = field.get(record)
- if value:
- model, record_id = value.split(',')
- record_id = int(record_id)
- if not model:
- continue
- label = field.attrs['string']
- populate(menu, model, record_id, title=label)
- menu.show_all()
menu.popup(None, None, None, event.button, event.time)
+
+ def pop(menu, group, record):
+ copy_item = gtk.ImageMenuItem('gtk-copy')
+ copy_item.connect('activate', lambda x: self.on_copy())
+ menu.append(copy_item)
+ # Don't activate actions if parent is modified
+ parent = record.parent if record else None
+ while parent:
+ if parent.modified:
+ record = None
+ break
+ parent = parent.parent
+ populate(menu, group.model_name, record)
+ for col in self.widget_tree.get_columns():
+ if not col.get_visible() or not col.name:
+ continue
+ field = group.fields[col.name]
+ model = None
+ if field.attrs['type'] == 'many2one':
+ model = field.attrs['relation']
+ record_id = field.get(record)
+ elif field.attrs['type'] == 'reference':
+ value = field.get(record)
+ if value:
+ model, record_id = value.split(',')
+ record_id = int(record_id)
+ if not model:
+ continue
+ label = field.attrs['string']
+ populate(menu, model, record_id, title=label)
+ menu.show_all()
+ # Delay filling of popup as it can take time
+ gobject.idle_add(pop, menu, group, record)
elif event.button == 2:
event.button = 1
event.state |= gtk.gdk.MOD1_MASK
@@ -707,12 +710,21 @@ class ViewList(ParserView):
and self.widget_tree.editable \
and not self.screen.parent \
and previous_record != self.screen.current_record:
- if previous_record and \
- not (previous_record.validate(self.get_fields())
- and previous_record.save()):
- self.screen.current_record = previous_record
- self.set_cursor()
- return True
+ if previous_record:
+ def go_previous():
+ self.screen.current_record = previous_record
+ self.set_cursor()
+
+ def save():
+ if not previous_record.destroyed:
+ if not previous_record.save():
+ go_previous()
+
+ if not previous_record.validate(self.get_fields()):
+ go_previous()
+ return True
+ # Delay the save to let GTK process the current event
+ gobject.idle_add(save)
self.update_children()
def set_value(self):
From f55021fd57747bc2fb35ceda484a06f73587c638 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 022/104] 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 815f2ee685..0f4dd0c5d4 100644
--- a/tryton/common/common.py
+++ b/tryton/common/common.py
@@ -255,7 +255,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 a6a099be17de176e353a45f2d37bffef8d262398 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 023/104] 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 c90173ef85..77c464c9ff 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 c50ddfe8bc2d387a02ac4716050dbf9183f68208 Mon Sep 17 00:00:00 2001
From: Pierre-Louis Bonicoli
Date: Tue, 14 Aug 2012 17:52:52 +0200
Subject: [PATCH 024/104] 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 0b1daa1701..59d7eccb0b 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 f7e77afa19f72973c67aefb4cc43ee205dcae2a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Thu, 16 Aug 2012 14:57:00 +0200
Subject: [PATCH 025/104] Don't use Screen.save_current in button_clicked
Screen.save_current force the reload of the record before the call to the
Button RPC. So this could generate a race condition between the button call and
the reload of the record.
issue2739
review460001
(transplanted from dade8f50910b320f00618418a409f22f169b147a)
---
tryton/gui/window/view_form/view/form.py | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tryton/gui/window/view_form/view/form.py b/tryton/gui/window/view_form/view/form.py
index af75da275d..887c7af20d 100644
--- a/tryton/gui/window/view_form/view/form.py
+++ b/tryton/gui/window/view_form/view/form.py
@@ -166,10 +166,12 @@ class ViewForm(ParserView):
focus_widget.grab_focus()
def button_clicked(self, widget):
- record_id = self.screen.save_current()
record = self.screen.current_record
attrs = widget.attrs
- if record_id:
+ fields = self.get_fields()
+ if record.validate(fields):
+ # Don't reload as it will be done after the RPC call
+ record.save(force_reload=False)
if not attrs.get('confirm', False) or \
common.sur(attrs['confirm']):
button_type = attrs.get('type', 'object')
@@ -177,7 +179,7 @@ class ViewForm(ParserView):
if button_type == 'object':
try:
RPCExecute('model', self.screen.model_name,
- attrs['name'], [record_id], context=context)
+ attrs['name'], [record.id], context=context)
except RPCException:
pass
elif button_type == 'action':
@@ -191,8 +193,8 @@ class ViewForm(ParserView):
if action_id:
Action.execute(action_id, {
'model': self.screen.model_name,
- 'id': record_id,
- 'ids': [record_id],
+ 'id': record.id,
+ 'ids': [record.id],
}, context=context)
else:
raise Exception('Unallowed button type')
From a7a8816146d08137f171fceded620aeef3b0b080 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 026/104] 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 887c7af20d..ee09ff6163 100644
--- a/tryton/gui/window/view_form/view/form.py
+++ b/tryton/gui/window/view_form/view/form.py
@@ -122,7 +122,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 2dd3e1c5f358953083a0d1bb434494889a7dbeb6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sat, 25 Aug 2012 15:42:53 +0200
Subject: [PATCH 027/104] Fix missing on_change_with initialisation for
non-grouped calls
issue2759
review481004
(transplanted from 38340c974fc513f3e3800fa8c1a6db35e3c1d327)
---
tryton/gui/window/view_form/model/record.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py
index 4bbc56bb81..bf54c2f257 100644
--- a/tryton/gui/window/view_form/model/record.py
+++ b/tryton/gui/window/view_form/model/record.py
@@ -534,6 +534,8 @@ class Record(SignalEvent):
for fieldname, value in result.items():
self.group.fields[fieldname].set_on_change(self, value)
for fieldname in later:
+ on_change_with = self.group.fields[fieldname].attrs.get(
+ 'on_change_with')
values = self._get_on_change_args(on_change_with)
try:
result = RPCExecute('model', self.model_name,
From 8768ef541667a199efd9696eb4f308d98a6ad1b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sat, 1 Sep 2012 18:50:12 +0200
Subject: [PATCH 028/104] Prepare release 2.4.1
---
CHANGELOG | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 3ec662b48c..de75c733f2 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+Version 2.4.1 - 2012-09-01
+* Bug fixes (see mercurial logs for details)
+
Version 2.4.0 - 2012-04-23
* Bug fixes (see mercurial logs for details)
* Remove workflow
From 8626276ec4c2069bf43032349957bef40ac3d7f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sat, 1 Sep 2012 18:50:13 +0200
Subject: [PATCH 029/104] Added tag 2.4.1 for changeset 03f86ced937d
---
.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags b/.hgtags
index 0bfa039388..2661a07fe0 100644
--- a/.hgtags
+++ b/.hgtags
@@ -6,3 +6,4 @@ de84c1443d4bad908eabb99c381578b988c2117f 1.4.0
1876747b3f963ba6011b4bcf6968e681624c6e24 2.0.0
5364f8ca6cd2cccfb5f7f39c69bb20bae2b5f495 2.2.0
fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0
+03f86ced937d03bada5193526bf78655c0c489a5 2.4.1
From 48e3a11d57c357a0bbe1dc589e8630c97b68c253 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sat, 1 Sep 2012 18:52:28 +0200
Subject: [PATCH 030/104] 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 82ae4e3646..aa797078eb 100644
--- a/tryton/version.py
+++ b/tryton/version.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.
PACKAGE = "tryton"
-VERSION = "2.4.1"
+VERSION = "2.4.2"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
From 6650a4c01162b646ab2658e0811f95bf2fe959fa 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 031/104] 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 0f4dd0c5d4..fd3c32fa61 100644
--- a/tryton/common/common.py
+++ b/tryton/common/common.py
@@ -256,7 +256,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 f387e4d02fde8641f4076a531258c12ae595d9fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Tue, 18 Sep 2012 11:18:49 +0200
Subject: [PATCH 032/104] Fix closing tag in richtext box
review515002
(transplanted from 92a7806efe2da14abb429f86517176be9dbe7873)
---
.../view_form/view/form_gtk/richtextbox.py | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/tryton/gui/window/view_form/view/form_gtk/richtextbox.py b/tryton/gui/window/view_form/view/form_gtk/richtextbox.py
index 8325f6a5dd..6ccd9460dc 100644
--- a/tryton/gui/window/view_form/view/form_gtk/richtextbox.py
+++ b/tryton/gui/window/view_form/view/form_gtk/richtextbox.py
@@ -31,16 +31,16 @@ def formalize_text_markup(text):
occurrence = 0
i += 1
if stack:
- span_close = '<\\\span>' * stack[-1][2]
+ span_close = '' * stack[-1][2]
data = re.search('^' + span_close, text[i:])
if data and stack[-1][2] > 1:
span = stack.pop()
- text = re.sub(span_close, text[:i] + '<\\span>', text[i:], 1)
+ text = re.sub(span_close, text[:i] + '', text[i:], 1)
text = text[:span[0]] + re.sub('> tag
lines = text.split('\n')
align = "left"
@@ -53,12 +53,12 @@ def formalize_text_markup(text):
else:
break
actual_align = "" % align
- if re.search("(<\\\p>|<\\p>)", lines[i]):
+ if re.search("
", lines[i]):
align = 'left'
- lines[i] = re.sub('(<\\\p>|<\\p>)', '', lines[i])
+ lines[i] = re.sub('
', '', lines[i])
# If not exists any line add paragraph
if not re.search('^$', lines[i]):
- lines[i] = actual_align + lines[i] + "<\\p>"
+ lines[i] = actual_align + lines[i] + ""
return '\n'.join(lines)
@@ -258,7 +258,7 @@ class RichTextBox(TextBox):
locks[tag] = True
imark = text_buffer.get_iter_at_mark(end_mark)
if imark.ends_tag(self.text_tags[tag]) and locks[tag]:
- text_buffer.insert(imark, "<\\%s>" % tag[0])
+ text_buffer.insert(imark, "%s>" % tag[0])
locks[tag] = False
for tag in ('left', 'right', 'center', 'fill'):
imark = text_buffer.get_iter_at_mark(begin_mark)
@@ -267,7 +267,7 @@ class RichTextBox(TextBox):
locks[tag] = True
imark = text_buffer.get_iter_at_mark(end_mark)
if imark.ends_tag(self.text_tags[tag]) and locks[tag]:
- text_buffer.insert(imark, "<\\p>")
+ text_buffer.insert(imark, "")
locks[tag] = False
for tag in ('font_family', 'size', 'foreground', 'background'):
for name, prop in self.font_props[tag].items():
@@ -280,7 +280,7 @@ class RichTextBox(TextBox):
imark = text_buffer.get_iter_at_mark(end_mark)
if imark.ends_tag(prop) and locks['%s %s' % (tag, name)]:
locks['%s %s' % (tag, name)] = False
- text_buffer.insert(imark, "<\\span>")
+ text_buffer.insert(imark, "")
imark = text_buffer.get_iter_at_mark(end_mark)
if not imark.forward_to_tag_toggle(None):
break
@@ -311,7 +311,7 @@ class RichTextBox(TextBox):
text_buffer.delete(text_buffer.get_iter_at_offset(
data_open.start()), text_buffer.get_iter_at_offset(
data_open.end()))
- close_re = '<\\\%s>' % tag
+ close_re = '%s>' % tag
data_close = re.search(close_re, text)
if data_close:
text = re.sub(close_re, '', text, 1)
From 0082c5307cad7d94873a8fdc5e77ab09810a8282 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20=C3=89vrard?=
Date: Fri, 21 Sep 2012 15:46:10 +0200
Subject: [PATCH 033/104] call WinSearch callback even when WinForm do not
yield result
review529003
issue2782
(transplanted from 28fce397c4d151ba200d805422c84aabf6befc82)
---
tryton/gui/window/win_search.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tryton/gui/window/win_search.py b/tryton/gui/window/win_search.py
index 2de567f5ba..68ad5e9d55 100644
--- a/tryton/gui/window/win_search.py
+++ b/tryton/gui/window/win_search.py
@@ -116,6 +116,8 @@ class WinSearch(NoModal):
record = screen.current_record
res = [(record.id, record.value.get('rec_name', ''))]
self.callback(res)
+ else:
+ self.callback(None)
self.destroy()
WinForm(screen, callback, new=True)
return
From 4a5ae5d2e3c677a9388457b9d1897f89c238e785 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Thu, 27 Sep 2012 11:36:34 +0200
Subject: [PATCH 034/104] Allow to display time(0, 0) (transplanted from
11bfe50ebecf65ae3f44a4331f42d47898d34e71)
---
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 85e06d194a..d7627375c4 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -263,7 +263,7 @@ class TimeField(CharField):
def get_client(self, record):
value = super(TimeField, self).get_client(record)
- if value:
+ if value is not None:
return value.strftime(HM_FORMAT)
return ''
From 737a98a7650dd62ab52a40feeb5394d6c01f4fd9 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 035/104] 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 22d764f8e7..790aad9515 100644
--- a/tryton/gui/window/view_form/screen/screen.py
+++ b/tryton/gui/window/view_form/screen/screen.py
@@ -707,7 +707,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
self.set_cursor(reset_view=False)
view.display()
@@ -739,7 +739,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
self.set_cursor(reset_view=False)
view.display()
From ada2e694fc44060200619d0048c27f541c6bd766 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 5 Oct 2012 18:31:00 +0200
Subject: [PATCH 036/104] Restore Concurrency exception with RPCProgress
issue2789
review549003
(transplanted from 532d1c16e16b84f2bcf3f0f8299356c509cd85a8)
---
tryton/common/common.py | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/tryton/common/common.py b/tryton/common/common.py
index fd3c32fa61..c1f3d5a3da 100644
--- a/tryton/common/common.py
+++ b/tryton/common/common.py
@@ -952,6 +952,8 @@ PLOCK = Lock()
def process_exception(exception, *args, **kwargs):
+ rpc_execute = kwargs.get('rpc_execute', rpc.execute)
+
if isinstance(exception, TrytonError):
if exception.faultCode == 'BadFingerprint':
warning(
@@ -977,14 +979,15 @@ def process_exception(exception, *args, **kwargs):
'always': (res == 'always'),
}, rpc.CONTEXT)
try:
- rpc.execute(*args2)
+ rpc_execute(*args2)
except TrytonServerError, exception:
process_exception(exception, *args2)
if args:
try:
- return rpc.execute(*args)
+ return rpc_execute(*args)
except TrytonServerError, exception:
- return process_exception(exception, *args)
+ return process_exception(exception, *args,
+ rpc_execute=rpc_execute)
return True
return False
elif exception.faultCode == 'UserError':
@@ -997,9 +1000,10 @@ def process_exception(exception, *args, **kwargs):
if '_timestamp' in args[5]:
del args[5]['_timestamp']
try:
- return rpc.execute(*args)
+ return rpc_execute(*args)
except TrytonServerError, exception:
- return process_exception(exception, *args)
+ return process_exception(exception, *args,
+ rpc_execute=rpc_execute)
return False
else:
message(_('Concurrency Exception'), msg_type=gtk.MESSAGE_ERROR)
@@ -1027,9 +1031,10 @@ def process_exception(exception, *args, **kwargs):
continue
if args:
try:
- return rpc.execute(*args)
+ return rpc_execute(*args)
except TrytonServerError, exception:
- return process_exception(exception, *args)
+ return process_exception(exception, *args,
+ rpc_execute=rpc_execute)
return True
finally:
PLOCK.release()
@@ -1256,12 +1261,14 @@ class RPCProgress(object):
gtk.main_iteration()
if self.exception:
if process_exception_p:
- if process_exception(self.exception):
- self.res = None
- self.error = False
- self.exception = None
- return self.run(process_exception_p)
- raise RPCException(self.exception)
+ def rpc_execute(*args):
+ return RPCProgress('execute',
+ args).run(process_exception_p, main_iteration_p)
+ result = process_exception(self.exception, *self.args,
+ rpc_execute=rpc_execute)
+ if result is False:
+ raise RPCException(self.exception)
+ return result
else:
raise self.exception
return self.res
From e7735c88bdf560a656ae367308b410cb7a0f8b1d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sat, 6 Oct 2012 15:18:44 +0200
Subject: [PATCH 037/104] Don't register search_box if not on a page
issue2770
(transplanted from cda1bcf226dc18140e6fa6f9e884b9be2ea29c7a)
---
tryton/gui/window/view_form/view/screen_container.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tryton/gui/window/view_form/view/screen_container.py b/tryton/gui/window/view_form/view/screen_container.py
index 802abc19ef..b40130b1a1 100644
--- a/tryton/gui/window/view_form/view/screen_container.py
+++ b/tryton/gui/window/view_form/view/screen_container.py
@@ -331,10 +331,10 @@ class ScreenContainer(object):
from tryton.gui.main import Main
page = Main.get_main().get_page()
if button.get_active():
- if self.search_window not in page.dialogs:
+ if page and self.search_window not in page.dialogs:
page.dialogs.append(self.search_window)
self.search_window.show()
else:
self.search_window.hide()
- if self.search_window in page.dialogs:
+ if page and self.search_window in page.dialogs:
page.dialogs.remove(self.search_window)
From c4aff8dcf295ab98f03c2a49e42384065b3c27c5 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 038/104] 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 285bd6c00a..11a09f56b1 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 8087ee8275f887788601695116761cce5b156cfd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Mon, 8 Oct 2012 21:05:24 +0200
Subject: [PATCH 039/104] Remove row_has_child_toggled in removed
Calling get_iter force a reload of the records and break the clear of the
group.
issue2710
review552002
(transplanted from 35b8da5ce48822cd279e01d2f53ff1f064d5c269)
---
tryton/gui/window/view_form/view/list.py | 8 --------
1 file changed, 8 deletions(-)
diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py
index 11a09f56b1..4341382e6b 100644
--- a/tryton/gui/window/view_form/view/list.py
+++ b/tryton/gui/window/view_form/view/list.py
@@ -74,14 +74,6 @@ class AdaptModelGroup(gtk.GenericTreeModel):
or record.group.child_name == self.children_field)):
path = self.on_get_path(record)
self.row_deleted(path)
- if (record.parent and
- record.group != self.group and
- len(record.children_group(self.children_field)) <= 1):
- path = self.on_get_path(record.parent)
- iter_ = self.get_iter(path)
- self.__removed = record # XXX check for thread
- self.row_has_child_toggled(path, iter_)
- self.__removed = None
def append(self, model):
self.group.add(model)
From 5a51b0abbc0bb9790652a521cb8f08e09036cee0 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 040/104] 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 bf54c2f257..a75757bdda 100644
--- a/tryton/gui/window/view_form/model/record.py
+++ b/tryton/gui/window/view_form/model/record.py
@@ -140,6 +140,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 790aad9515..0585979a4a 100644
--- a/tryton/gui/window/view_form/screen/screen.py
+++ b/tryton/gui/window/view_form/screen/screen.py
@@ -542,6 +542,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 0f75b8138fb3dd70511b2de0fa75b480bdb6b5b0 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 041/104] 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 0585979a4a..08ab95ebe3 100644
--- a/tryton/gui/window/view_form/screen/screen.py
+++ b/tryton/gui/window/view_form/screen/screen.py
@@ -682,7 +682,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:
@@ -724,7 +726,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 1e452b1eea6568c5401443825eb9dd07d6401740 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 042/104] 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 0281966bd3..d68cc44218 100644
--- a/tryton/gui/main.py
+++ b/tryton/gui/main.py
@@ -1189,6 +1189,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 f4dbcd33da284d47dd519328a87521e183efeddf 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 043/104] 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 d68cc44218..fcdef8c463 100644
--- a/tryton/gui/main.py
+++ b/tryton/gui/main.py
@@ -1311,7 +1311,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...'),
@@ -1353,7 +1353,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 a5d70fc4ceda2dfdf64ec92d495cc37f1b41fce7 Mon Sep 17 00:00:00 2001
From: Pierre-Louis Bonicoli
Date: Sat, 20 Oct 2012 13:46:07 +0200
Subject: [PATCH 044/104] 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 f6536583d7..4c91fca280 100644
--- a/tryton/gui/window/win_form.py
+++ b/tryton/gui/window/win_form.py
@@ -77,9 +77,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 56d036c56abfe72589efd977efc4fc91fd2e0d7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Mon, 5 Nov 2012 17:30:19 +0100
Subject: [PATCH 045/104] Prepare release 2.4.2
---
CHANGELOG | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index de75c733f2..817e33203c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+Version 2.4.2 - 2012-11-05
+* Bug fixes (see mercurial logs for details)
+
Version 2.4.1 - 2012-09-01
* Bug fixes (see mercurial logs for details)
From 4d1cd77d16e914996c773417ef0b166fab046257 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Mon, 5 Nov 2012 17:30:20 +0100
Subject: [PATCH 046/104] Added tag 2.4.2 for changeset 733b3f702200
---
.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags b/.hgtags
index 2661a07fe0..a780ed8685 100644
--- a/.hgtags
+++ b/.hgtags
@@ -7,3 +7,4 @@ de84c1443d4bad908eabb99c381578b988c2117f 1.4.0
5364f8ca6cd2cccfb5f7f39c69bb20bae2b5f495 2.2.0
fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0
03f86ced937d03bada5193526bf78655c0c489a5 2.4.1
+733b3f7022001aad274cd502d7e34fc9231af8b6 2.4.2
From a51cfcdb272fa6ff4c0400fc65a03b69a8cc9c92 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Mon, 5 Nov 2012 17:31:08 +0100
Subject: [PATCH 047/104] 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 aa797078eb..607d4d92da 100644
--- a/tryton/version.py
+++ b/tryton/version.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.
PACKAGE = "tryton"
-VERSION = "2.4.2"
+VERSION = "2.4.3"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
From 58bac50f467dd2106b3ef1a0f159409f3b713fa5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Tue, 30 Oct 2012 13:04:27 +0100
Subject: [PATCH 048/104] Fix domain parser to not always strip default
operator
review585002
(transplanted from 548cb6aeab1f9cb6aa456a7221e79c53de6f6cbe)
---
tryton/common/domain_parser.py | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/tryton/common/domain_parser.py b/tryton/common/domain_parser.py
index 48338a85f4..ba02d80b37 100644
--- a/tryton/common/domain_parser.py
+++ b/tryton/common/domain_parser.py
@@ -715,7 +715,9 @@ class DomainParser(object):
operator = '!'
value = value.replace('%%', '%')
def_operator = default_operator(field)
- if def_operator in operator:
+ if (def_operator == operator.strip()
+ or (def_operator in operator
+ and 'not' in operator)):
operator = operator.rstrip(def_operator
).replace('not', '!').strip()
if operator.endswith('in'):
@@ -924,6 +926,10 @@ def test_string():
'string': '(Sur)Name',
'type': 'char',
},
+ 'date': {
+ 'string': 'Date',
+ 'type': 'date',
+ },
})
assert dom.string([('name', '=', 'Doe')]) == 'Name: =Doe'
assert dom.string([('name', 'ilike', '%Doe%')]) == 'Name: Doe'
@@ -951,6 +957,8 @@ def test_string():
'Name: Doe (Name: John or Name: Jane)'
assert dom.string([]) == ''
assert dom.string([('surname', 'ilike', '%Doe%')]) == '"(Sur)Name": Doe'
+ assert dom.string([('date', '>=', datetime.date(2012, 10, 24))]) == \
+ 'Date: >=10/24/2012'
def test_group():
From 3af52d79947a30bcfbff945075a5b573ee7dcf75 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 2 Nov 2012 16:19:00 +0100
Subject: [PATCH 049/104] Fix domain parser when value is a list
review591002
(transplanted from 61d834ed6a8c49c89c29b85b3134ae28112cb9ee)
---
tryton/common/domain_parser.py | 45 +++++++++++++++++++++++++++++++---
1 file changed, 42 insertions(+), 3 deletions(-)
diff --git a/tryton/common/domain_parser.py b/tryton/common/domain_parser.py
index ba02d80b37..11e50daec3 100644
--- a/tryton/common/domain_parser.py
+++ b/tryton/common/domain_parser.py
@@ -541,9 +541,15 @@ def complete_value(field, value):
yield True
def complete_selection():
+ test_value = value
+ if isinstance(value, list):
+ test_value = value[-1]
for svalue, test in field['selection']:
- if test.lower().startswith(value.lower()):
- yield svalue
+ if test.lower().startswith(test_value.lower()):
+ if test_value == value:
+ yield svalue
+ else:
+ yield value[:-1] + [svalue]
def complete_datetime():
yield datetime.date.today()
@@ -566,6 +572,23 @@ def complete_value(field, value):
return completes.get(field['type'], lambda: [])()
+def test_complete_selection():
+ field = {
+ 'type': 'selection',
+ 'selection': [
+ ('male', 'Male'),
+ ('female', 'Female'),
+ ],
+ }
+ for value, result in (
+ ('m', ['male']),
+ ('test', []),
+ ('', ['male', 'female']),
+ (['male', 'f'], [['male', 'female']]),
+ ):
+ assert list(complete_value(field, value)) == result
+
+
def parenthesize(tokens):
"Nest tokens according to parenthesis"
for token in tokens:
@@ -912,7 +935,10 @@ class DomainParser(object):
(field['name'], '<', rvalue),
])
continue
- value = convert_value(field, value)
+ if isinstance(value, list):
+ value = [convert_value(field, v) for v in value]
+ else:
+ value = convert_value(field, value)
yield field['name'], operator, value
@@ -1045,6 +1071,15 @@ def test_parse_clause():
'name': 'integer',
'type': 'integer',
},
+ 'selection': {
+ 'string': 'Selection',
+ 'name': 'selection',
+ 'type': 'selection',
+ 'selection': [
+ ('male', 'Male'),
+ ('female', 'Female'),
+ ],
+ },
})
assert rlist(dom.parse_clause([('John',)])) == [
('rec_name', 'ilike', '%John%')]
@@ -1058,6 +1093,10 @@ def test_parse_clause():
assert rlist(dom.parse_clause([('Name', '!', ['John', 'Jane'])])) == [
('name', 'not in', ['John', 'Jane']),
]
+ assert rlist(dom.parse_clause([('Selection', None, ['Male', 'Female'])])) \
+ == [
+ ('selection', 'in', ['male', 'female'])
+ ]
assert rlist(dom.parse_clause([('Integer', None, '3..5')])) == [[
('integer', '>=', 3),
('integer', '<', 5),
From 82dd460c543c4b7b21c07f30e8e5ca0995969a18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 2 Nov 2012 16:20:04 +0100
Subject: [PATCH 050/104] Fix Char.translate_widget_set when value is None
review587004
(transplanted from 4b45f57716e5a9576db6c02bc16a51e77daf6aef)
---
tryton/gui/window/view_form/view/form_gtk/char.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tryton/gui/window/view_form/view/form_gtk/char.py b/tryton/gui/window/view_form/view/form_gtk/char.py
index c999f2228a..b0e112a236 100644
--- a/tryton/gui/window/view_form/view/form_gtk/char.py
+++ b/tryton/gui/window/view_form/view/form_gtk/char.py
@@ -56,7 +56,7 @@ class Char(WidgetInterface, TranslateMixin):
@staticmethod
def translate_widget_set(widget, value):
- widget.set_text(value)
+ widget.set_text(value or '')
@staticmethod
def translate_widget_get(widget):
From 0501cf57e5fa7a295862ae49dccbf6a15e583ff3 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 051/104] 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 9c71e0d66f..db120c680f 100644
--- a/tryton/common/domain_inversion.py
+++ b/tryton/common/domain_inversion.py
@@ -53,11 +53,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 a75757bdda..3ef1c257d5 100644
--- a/tryton/gui/window/view_form/model/record.py
+++ b/tryton/gui/window/view_form/model/record.py
@@ -249,6 +249,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
@@ -448,7 +450,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 2b82b59650bdecb7038512c3009cb5c980ac2ea9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Thu, 15 Nov 2012 19:49:00 +0100
Subject: [PATCH 052/104] Don't untimezone fallback date for converting
datetime (transplanted from aa2764ccc856dd2c589caf1f02e957c32211c79a)
---
tryton/common/domain_parser.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tryton/common/domain_parser.py b/tryton/common/domain_parser.py
index 11e50daec3..d8873a0134 100644
--- a/tryton/common/domain_parser.py
+++ b/tryton/common/domain_parser.py
@@ -214,8 +214,8 @@ def convert_value(field, value):
date_format() + ' ' + HM_FORMAT)[:6]))
except ValueError:
try:
- return untimezoned_date(datetime.datetime(*time.strptime(value,
- date_format())[:6]))
+ return datetime.datetime(*time.strptime(value,
+ date_format())[:6])
except ValueError:
return
except TypeError:
From 11db41ec52fb59a540a85fa844013e3fc6f806ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Fri, 16 Nov 2012 11:03:43 +0100
Subject: [PATCH 053/104] Reset rec_name for on_change_with calls
issue2888
review594006
(transplanted from ea3353be76ad7370364874c1d08c767b15b49e8e)
---
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 3ef1c257d5..95e033a80a 100644
--- a/tryton/gui/window/view_form/model/record.py
+++ b/tryton/gui/window/view_form/model/record.py
@@ -536,6 +536,11 @@ class Record(SignalEvent):
continue
fieldnames.add(fieldname)
values.update(self._get_on_change_args(on_change_with))
+ if isinstance(self.group.fields[fieldname], (fields.M2OField,
+ fields.ReferenceField)):
+ field_rec_name = fieldname + '.rec_name'
+ if field_rec_name in self.value:
+ del self.value[field_rec_name]
if fieldnames:
try:
result = RPCExecute('model', self.model_name, 'on_change_with',
From 38ace29ddb5e16274469b09f2466b62869d385da 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 054/104] 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 d7627375c4..8ceb3fb45d 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -697,7 +697,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 fc142bdb4ce6ede004ff49123ef9acee14b7d59d 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 055/104] 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 589880ebf1..81319e72e2 100644
--- a/setup.py
+++ b/setup.py
@@ -250,6 +250,11 @@ if os.name == 'nt':
if os.path.isdir(os.path.join(gtk_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')):
@@ -365,6 +370,11 @@ elif sys.platform == 'darwin':
if os.path.isdir(os.path.join(gtk_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 982a34deb3c0fbfaf840678da4b2e1960f01e94b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 23 Dec 2012 16:47:59 +0100
Subject: [PATCH 056/104] Prepare release 2.4.3
---
CHANGELOG | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 817e33203c..250b9617d4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+Version 2.4.3 - 2012-12-23
+* Bug fixes (see mercurial logs for details)
+
Version 2.4.2 - 2012-11-05
* Bug fixes (see mercurial logs for details)
From 29c4341d7ce0f90b609f0630199530b4f7e81def Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 23 Dec 2012 16:48:00 +0100
Subject: [PATCH 057/104] Added tag 2.4.3 for changeset 0e4ac607e0a0
---
.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags b/.hgtags
index a780ed8685..89cf904ebf 100644
--- a/.hgtags
+++ b/.hgtags
@@ -8,3 +8,4 @@ de84c1443d4bad908eabb99c381578b988c2117f 1.4.0
fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0
03f86ced937d03bada5193526bf78655c0c489a5 2.4.1
733b3f7022001aad274cd502d7e34fc9231af8b6 2.4.2
+0e4ac607e0a048972a6b5c5f90651a25fae25c6e 2.4.3
From f8ce2af8525b0574add39f45b8488b76ba4b692c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 23 Dec 2012 16:48:32 +0100
Subject: [PATCH 058/104] 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 607d4d92da..6d44fae66d 100644
--- a/tryton/version.py
+++ b/tryton/version.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.
PACKAGE = "tryton"
-VERSION = "2.4.3"
+VERSION = "2.4.4"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
From f1d82ed859fa642d4b0f66bfa615dc32c3967f94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 23 Dec 2012 22:57:12 +0100
Subject: [PATCH 059/104] Disable main_iteration on RPC query from field
RPC query from field could happen during a GTK event.
review619002
(transplanted from db149f280d6053d50dd7dd230ce744d9ae397acd)
---
tryton/gui/window/view_form/model/field.py | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py
index 8ceb3fb45d..dcd4a51313 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -410,7 +410,7 @@ class M2OField(CharField):
if not rec_name and value >= 0:
try:
result = RPCExecute('model', self.attrs['relation'], 'read',
- value, ['rec_name'])
+ value, ['rec_name'], main_iteration=False)
except RPCException:
return False
rec_name = result['rec_name'] or ''
@@ -637,7 +637,8 @@ class O2MField(CharField):
if field_names:
try:
fields.update(RPCExecute('model', self.attrs['relation'],
- 'fields_get', field_names, context=context))
+ 'fields_get', field_names,
+ main_iteration=False, context=context))
except RPCException:
return False
@@ -680,7 +681,8 @@ class O2MField(CharField):
field_names.append(fieldname)
try:
fields = RPCExecute('model', self.attrs['relation'],
- 'fields_get', field_names, context=context)
+ 'fields_get', field_names, main_iteration=False,
+ context=context)
except RPCException:
return False
@@ -835,7 +837,7 @@ class ReferenceField(CharField):
if not rec_name and ref_id >= 0:
try:
result = RPCExecute('model', ref_model, 'read', ref_id,
- ['rec_name'])
+ ['rec_name'], main_iteration=False)
except RPCException:
return
rec_name = result['rec_name']
@@ -893,7 +895,8 @@ class BinaryField(CharField):
context = record.context_get()
try:
values = RPCExecute('model', record.model_name, 'read',
- record.id, [self.name], context=context)
+ record.id, [self.name], main_iteration=False,
+ context=context)
except RPCException:
return ''
_, filename = tempfile.mkstemp(prefix='tryton_')
From 3e34450de85862ce4300dfaa730a4b36a16f9499 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20=C3=89vrard?=
Date: Thu, 10 Jan 2013 11:37:17 +0100
Subject: [PATCH 060/104] Add missing _default for TimeField
issue2940
review631003
(transplanted from 034e965007685e470598698fec3a235d2df3bcb3)
---
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 dcd4a51313..eb25933dd0 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -252,6 +252,8 @@ class DateField(CharField):
class TimeField(CharField):
+ _default = None
+
def set_client(self, record, value, force_change=False):
if not isinstance(value, datetime.time):
try:
From e2210cd9b5f55d6d0a8d3fbbe1b243e991f7e2cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sat, 19 Jan 2013 17:13:44 +0100
Subject: [PATCH 061/104] Fix list popup when parent modified
issue2949
review635004
(transplanted from 97de060117ce1f39dfedb41efc02ef496d7e1979)
---
tryton/gui/window/view_form/view/list.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py
index 4341382e6b..ddb86e212d 100644
--- a/tryton/gui/window/view_form/view/list.py
+++ b/tryton/gui/window/view_form/view/list.py
@@ -556,10 +556,10 @@ class ViewList(ParserView):
parent = record.parent if record else None
while parent:
if parent.modified:
- record = None
break
parent = parent.parent
- populate(menu, group.model_name, record)
+ else:
+ populate(menu, group.model_name, record)
for col in self.widget_tree.get_columns():
if not col.get_visible() or not col.name:
continue
From 751e4d6cc16e77927e32e694433444cc993bd511 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 062/104] 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 eb25933dd0..1f1aa33e4b 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -725,9 +725,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 736f17b1d5a5b4adfda26b110cf0df04e2ceee61 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Tue, 12 Feb 2013 17:59:08 +0100
Subject: [PATCH 063/104] Prepare release 2.4.4
---
CHANGELOG | 3 +++
COPYRIGHT | 6 +++---
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 250b9617d4..80e703c066 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+Version 2.4.4 - 2013-02-12
+* Bug fixes (see mercurial logs for details)
+
Version 2.4.3 - 2012-12-23
* Bug fixes (see mercurial logs for details)
diff --git a/COPYRIGHT b/COPYRIGHT
index 55b3570380..3f60d5d9be 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -1,7 +1,7 @@
-Copyright (C) 2010-2012 Nicolas Évrard.
-Copyright (C) 2007-2012 Cédric Krier.
+Copyright (C) 2010-2013 Nicolas Évrard.
+Copyright (C) 2007-2013 Cédric Krier.
Copyright (C) 2007-2012 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) 2011-2012 Rodrigo Hübner.
From 82404c9737e1391f93d2950d33eda2a3a7c245f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Tue, 12 Feb 2013 17:59:09 +0100
Subject: [PATCH 064/104] Added tag 2.4.4 for changeset 4207622ad8b1
---
.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags b/.hgtags
index 89cf904ebf..9cb4d39d70 100644
--- a/.hgtags
+++ b/.hgtags
@@ -9,3 +9,4 @@ fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0
03f86ced937d03bada5193526bf78655c0c489a5 2.4.1
733b3f7022001aad274cd502d7e34fc9231af8b6 2.4.2
0e4ac607e0a048972a6b5c5f90651a25fae25c6e 2.4.3
+4207622ad8b1c6885e3e36265906035b950d7b89 2.4.4
From d04815b6e0141fcdbf594db37d2138b28f11eacb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Tue, 12 Feb 2013 17:59:42 +0100
Subject: [PATCH 065/104] 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 6d44fae66d..30c6cedbba 100644
--- a/tryton/version.py
+++ b/tryton/version.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.
PACKAGE = "tryton"
-VERSION = "2.4.4"
+VERSION = "2.4.5"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
From bc371869bb2b63ccdfcd5fce51bf0775decd0e04 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 066/104] 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 fcdef8c463..fcf35adb1e 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
@@ -1403,14 +1403,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
@@ -1420,8 +1420,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 86e5fdbfb4728ee2d0a51917c7ec42fac4ba7097 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Mon, 4 Mar 2013 22:21:52 +0100
Subject: [PATCH 067/104] Disable main iteration for all RPC request from
model/
We can not know if the request is fired during the process of a GTK event.
review686002
(transplanted from db672c4e45901a05ce23a669648daa25794c3e9b)
---
tryton/gui/window/view_form/model/group.py | 4 +--
tryton/gui/window/view_form/model/record.py | 27 +++++++++++++--------
2 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/tryton/gui/window/view_form/model/group.py b/tryton/gui/window/view_form/model/group.py
index 089882af9b..ab0a8b06a1 100644
--- a/tryton/gui/window/view_form/model/group.py
+++ b/tryton/gui/window/view_form/model/group.py
@@ -187,7 +187,7 @@ class Group(SignalEvent, list):
for fnct in self.on_write:
try:
res += RPCExecute('model', self.model_name, fnct, ids,
- context=self.context)
+ main_iteration=False, context=self.context)
except RPCException:
return []
return list({}.fromkeys(res))
@@ -376,7 +376,7 @@ class Group(SignalEvent, list):
ctx.update(self.context)
try:
values = RPCExecute('model', self.model_name, 'default_get',
- to_add.keys(), context=ctx)
+ to_add.keys(), main_iteration=False, context=ctx)
except RPCException:
return False
for name in to_add:
diff --git a/tryton/gui/window/view_form/model/record.py b/tryton/gui/window/view_form/model/record.py
index 95e033a80a..0ab86cd8d6 100644
--- a/tryton/gui/window/view_form/model/record.py
+++ b/tryton/gui/window/view_form/model/record.py
@@ -281,6 +281,7 @@ class Record(SignalEvent):
value = self.get(get_readonly=True)
try:
res = RPCExecute('model', self.model_name, 'create', value,
+ main_iteration=False,
context=self.context_get())
except RPCException:
return False
@@ -297,7 +298,8 @@ class Record(SignalEvent):
context['_timestamp'] = self.get_timestamp()
try:
if not RPCExecute('model', self.model_name, 'write',
- [self.id], value, context=context):
+ [self.id], value, main_iteration=False,
+ context=context):
return False
except RPCException:
return False
@@ -332,7 +334,7 @@ class Record(SignalEvent):
reload_ids = list(reload_ids)
try:
RPCExecute('model', record.model_name, 'delete', list(record_ids),
- context=ctx)
+ main_iteration=False, context=ctx)
except RPCException:
return False
if reload_ids:
@@ -343,7 +345,8 @@ class Record(SignalEvent):
if len(self.group.fields):
try:
vals = RPCExecute('model', self.model_name, 'default_get',
- self.group.fields.keys(), context=context)
+ self.group.fields.keys(), main_iteration=False,
+ context=context)
except RPCException:
return
if (self.parent
@@ -360,7 +363,8 @@ class Record(SignalEvent):
def rec_name(self):
try:
return RPCExecute('model', self.model_name, 'read', self.id,
- ['rec_name'], context=self.context_get())['rec_name']
+ ['rec_name'], main_iteration=False,
+ context=self.context_get())['rec_name']
except RPCException:
return ''
@@ -490,8 +494,9 @@ class Record(SignalEvent):
attr = PYSONDecoder().decode(attr)
args = self._get_on_change_args(attr)
try:
- res = RPCExecute('model', self.model_name,
- 'on_change_' + fieldname, args, context=self.context_get())
+ res = RPCExecute('model', self.model_name, 'on_change_' +
+ fieldname, args, main_iteration=False,
+ context=self.context_get())
except RPCException:
return
later = {}
@@ -544,7 +549,8 @@ class Record(SignalEvent):
if fieldnames:
try:
result = RPCExecute('model', self.model_name, 'on_change_with',
- list(fieldnames), values, context=self.context_get())
+ list(fieldnames), values, main_iteration=False,
+ context=self.context_get())
except RPCException:
return
for fieldname, value in result.items():
@@ -556,7 +562,7 @@ class Record(SignalEvent):
try:
result = RPCExecute('model', self.model_name,
'on_change_with_' + fieldname, values,
- context=self.context_get())
+ main_iteration=False, context=self.context_get())
except RPCException:
return
self.group.fields[fieldname].set_on_change(self, result)
@@ -574,7 +580,8 @@ class Record(SignalEvent):
args = self._get_on_change_args(autocomplete)
try:
res = RPCExecute('model', self.model_name, 'autocomplete_' +
- fieldname, args, context=self.context_get())
+ fieldname, args, main_iteration=False,
+ context=self.context_get())
except RPCException:
# ensure res is a list
res = []
@@ -589,7 +596,7 @@ class Record(SignalEvent):
'search_count', [
('resource', '=',
'%s,%s' % (self.model_name, self.id)),
- ])
+ ], main_iteration=False)
except RPCException:
return 0
return self.attachment_count
From 8611b523952a7eddb843c699bb10658c97143970 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 068/104] 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 0ab86cd8d6..b0fd90091b 100644
--- a/tryton/gui/window/view_form/model/record.py
+++ b/tryton/gui/window/view_form/model/record.py
@@ -48,6 +48,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 ad5090570c293e1455280f99c6d583bcbd3bd8ef 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 069/104] 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 493b65c594..6833a21cde 100644
--- a/tryton/gui/window/view_form/view/graph_gtk/bar.py
+++ b/tryton/gui/window/view_form/view/graph_gtk/bar.py
@@ -12,6 +12,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 dd5937abcb0dac187bb96adbe3767fbe1eedca08 Mon Sep 17 00:00:00 2001
From: Ralf Peschke
Date: Fri, 29 Mar 2013 08:28:27 +0100
Subject: [PATCH 070/104] 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 1f1aa33e4b..c71faa3aa1 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -699,7 +699,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 09a01dcb2fec1743970beb5baff1d629d56ac723 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Thu, 2 May 2013 09:30:28 +0200
Subject: [PATCH 071/104] Prepare release 2.4.5
---
CHANGELOG | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 80e703c066..436841cafa 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+Version 2.4.5 - 2013-05-02
+* Bug fixes (see mercurial logs for details)
+
Version 2.4.4 - 2013-02-12
* Bug fixes (see mercurial logs for details)
From 7c52804b343c1c644bcb5adc6872935149ac64e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Thu, 2 May 2013 09:30:29 +0200
Subject: [PATCH 072/104] Added tag 2.4.5 for changeset 50e628545fa3
---
.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags b/.hgtags
index 9cb4d39d70..90f047e74d 100644
--- a/.hgtags
+++ b/.hgtags
@@ -10,3 +10,4 @@ fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0
733b3f7022001aad274cd502d7e34fc9231af8b6 2.4.2
0e4ac607e0a048972a6b5c5f90651a25fae25c6e 2.4.3
4207622ad8b1c6885e3e36265906035b950d7b89 2.4.4
+50e628545fa3f690fc5cad5e572e95f8bfd21b75 2.4.5
From 93452f95b82ca3ea515b80ed41ed99b93dcb4f40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Thu, 2 May 2013 09:30:49 +0200
Subject: [PATCH 073/104] 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 30c6cedbba..809ded80da 100644
--- a/tryton/version.py
+++ b/tryton/version.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.
PACKAGE = "tryton"
-VERSION = "2.4.5"
+VERSION = "2.4.6"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
From 57646c7232d8e7805bcda098db13240a4b10ee3c 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 074/104] 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 fcf35adb1e..26a8e42e8e 100644
--- a/tryton/gui/main.py
+++ b/tryton/gui/main.py
@@ -19,6 +19,7 @@ from tryton.common import RPCExecute, RPCException
from tryton.config import CONFIG, TRYTON_ICON, get_config_dir
import tryton.common as common
from tryton.pyson import PYSONDecoder
+from tryton.jsonrpc import object_hook
from tryton.action import Action
from tryton.exceptions import TrytonServerError, TrytonError, \
TrytonServerUnavailable
@@ -1436,9 +1437,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:
@@ -1459,13 +1463,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:
@@ -1480,11 +1486,12 @@ 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'))
- context = json.loads(params.get('context', '{}'))
+ context = json.loads(params.get('context', '{}'),
+ object_hook=object_hook)
except ValueError:
return
try:
From 2c55b91e32acb58e3fc1cf00c51e520044cb182d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 9 Jun 2013 22:29:28 +0200
Subject: [PATCH 075/104] Prepare release 2.4.6
---
CHANGELOG | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 436841cafa..9e595fd001 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+Version 2.4.6 - 2013-06-09
+* Bug fixes (see mercurial logs for details)
+
Version 2.4.5 - 2013-05-02
* Bug fixes (see mercurial logs for details)
From a96f682a0acca6bca195c5b645c35e66a1419c9e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 9 Jun 2013 22:29:29 +0200
Subject: [PATCH 076/104] Added tag 2.4.6 for changeset 74255ad128ab
---
.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags b/.hgtags
index 90f047e74d..304dd8e886 100644
--- a/.hgtags
+++ b/.hgtags
@@ -11,3 +11,4 @@ fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0
0e4ac607e0a048972a6b5c5f90651a25fae25c6e 2.4.3
4207622ad8b1c6885e3e36265906035b950d7b89 2.4.4
50e628545fa3f690fc5cad5e572e95f8bfd21b75 2.4.5
+74255ad128ab5ce3792823e18982477192b5c6d9 2.4.6
From cff4c46d863d96808c8b1ae020eae0e8a20ee895 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 9 Jun 2013 22:29:53 +0200
Subject: [PATCH 077/104] 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 809ded80da..bd2fb07df7 100644
--- a/tryton/version.py
+++ b/tryton/version.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.
PACKAGE = "tryton"
-VERSION = "2.4.6"
+VERSION = "2.4.7"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
From a25a5296f55e42a1d6b21b4c8b3d3c3253a5ee6e 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 078/104] 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 3a0b2ba47a..8ce628fb34 100644
--- a/tryton/gui/window/view_form/view/list_gtk/editabletree.py
+++ b/tryton/gui/window/view_form/view/list_gtk/editabletree.py
@@ -24,8 +24,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.
@@ -233,6 +231,11 @@ class EditableTreeView(gtk.TreeView):
# 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 472f9cc0a5ab405107a36e7aba93b71faa1df6ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Mon, 22 Jul 2013 11:42:05 +0200
Subject: [PATCH 079/104] Prepare release 2.4.7
---
CHANGELOG | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 9e595fd001..b4dd532482 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+Version 2.4.7 - 2013-07-22
+* Bug fixes (see mercurial logs for details)
+
Version 2.4.6 - 2013-06-09
* Bug fixes (see mercurial logs for details)
From df0412a22f77177b490e33179eca80a14ef5dfe5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Mon, 22 Jul 2013 11:42:05 +0200
Subject: [PATCH 080/104] Added tag 2.4.7 for changeset b7f74f142071
---
.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags b/.hgtags
index 304dd8e886..ffd2ee20b2 100644
--- a/.hgtags
+++ b/.hgtags
@@ -12,3 +12,4 @@ fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0
4207622ad8b1c6885e3e36265906035b950d7b89 2.4.4
50e628545fa3f690fc5cad5e572e95f8bfd21b75 2.4.5
74255ad128ab5ce3792823e18982477192b5c6d9 2.4.6
+b7f74f142071f979d7f9747e9138427fc6e1d639 2.4.7
From cff26ed06cf36df281b571256900263afea5df3d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Mon, 22 Jul 2013 11:42:35 +0200
Subject: [PATCH 081/104] 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 bd2fb07df7..538a5a1ace 100644
--- a/tryton/version.py
+++ b/tryton/version.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.
PACKAGE = "tryton"
-VERSION = "2.4.7"
+VERSION = "2.4.8"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
From b5092645af73b2ca7ee91f591768b2724af02652 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 082/104] 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 | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py
index c71faa3aa1..32424b62bb 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -58,13 +58,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
@@ -442,8 +442,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)
@@ -750,7 +750,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 ac720ef80d0a2b96a205dcd1f8bb1cc685d7e72d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Thu, 1 Aug 2013 15:59:57 +0200
Subject: [PATCH 083/104] Fix fallback value of get_preferences (transplanted
from b70b126c0b22c7db6ad9aeb30a752b47eaeeeba2)
---
tryton/gui/main.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tryton/gui/main.py b/tryton/gui/main.py
index 26a8e42e8e..9d90cfecee 100644
--- a/tryton/gui/main.py
+++ b/tryton/gui/main.py
@@ -928,7 +928,7 @@ class Main(object):
prefs = RPCExecute('model', 'res.user', 'get_preferences',
False)
except RPCException:
- prefs = None
+ prefs = {}
common.ICONFACTORY.load_icons()
if prefs and 'language_direction' in prefs:
translate.set_language_direction(prefs['language_direction'])
From d1deab26bf319a9231bb22e18a51de0e45a5cbb5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Wed, 4 Sep 2013 10:41:21 +0200
Subject: [PATCH 084/104] Don't use field digits to format float/Decimal in
domain_parser
The conversion of a domain into string should keep the same significant digit,
which means to not use the field digits definition but significant digit of the
value.
issue3266
review1041002
(transplanted from add046625334e0237bc6fc9d684427e6de1b1903)
---
tryton/common/domain_parser.py | 30 ++++++++++++++++--------------
1 file changed, 16 insertions(+), 14 deletions(-)
diff --git a/tryton/common/domain_parser.py b/tryton/common/domain_parser.py
index d8873a0134..1ba888933d 100644
--- a/tryton/common/domain_parser.py
+++ b/tryton/common/domain_parser.py
@@ -378,10 +378,10 @@ def format_value(field, value):
and not isinstance(value, (float, Decimal))):
return ''
try:
- digit = int(field.get('digits', (16, 2))[1])
- except ValueError:
- digit = 2
- return locale.format('%.' + str(digit) + 'f', value or 0.0, True)
+ digit = len(str(value).split('.')[1])
+ except IndexError:
+ digit = 0
+ return locale.format('%.*f', (digit, value or 0), True)
def format_selection():
selections = dict(field['selection'])
@@ -447,13 +447,14 @@ def test_format_integer():
def test_format_float():
field = {
'type': 'float',
- 'digits': (16, 2),
}
for value, result in (
- (1, '1.00'),
- (1.5, '1.50'),
- (0, '0.00'),
- (0.0, '0.00'),
+ (1, '1'),
+ (1.5, '1.5'),
+ (1.50, '1.5'),
+ (150.79, '150.79'),
+ (0, '0'),
+ (0.0, '0.0'),
(False, ''),
(None, ''),
):
@@ -463,13 +464,14 @@ def test_format_float():
def test_format_numeric():
field = {
'type': 'numeric',
- 'digits': (16, 2),
}
for value, result in (
- (Decimal(1), '1.00'),
- (Decimal('1.5'), '1.50'),
- (Decimal(0), '0.00'),
- (Decimal('0.0'), '0.00'),
+ (Decimal(1), '1'),
+ (Decimal('1.5'), '1.5'),
+ (Decimal('1.50'), '1.50'),
+ (Decimal('150.79'), '150.79'),
+ (Decimal(0), '0'),
+ (Decimal('0.0'), '0.0'),
(False, ''),
(None, ''),
):
From c29651f993622f4da0ffe2d611624041b60505f8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Thu, 10 Oct 2013 23:23:06 +0200
Subject: [PATCH 085/104] Prepare release 2.4.8
---
CHANGELOG | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index b4dd532482..b9cd986ac8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+Version 2.4.8 - 2013-10-10
+* Bug fixes (see mercurial logs for details)
+
Version 2.4.7 - 2013-07-22
* Bug fixes (see mercurial logs for details)
From dc53f988d2e6e3f86651cdc84278b4ff3352242b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Thu, 10 Oct 2013 23:23:07 +0200
Subject: [PATCH 086/104] Added tag 2.4.8 for changeset 3c42199fdfdc
---
.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags b/.hgtags
index ffd2ee20b2..f3ca0ef43b 100644
--- a/.hgtags
+++ b/.hgtags
@@ -13,3 +13,4 @@ fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0
50e628545fa3f690fc5cad5e572e95f8bfd21b75 2.4.5
74255ad128ab5ce3792823e18982477192b5c6d9 2.4.6
b7f74f142071f979d7f9747e9138427fc6e1d639 2.4.7
+3c42199fdfdc35a1ec7c8b1e46a52cacf1c3d474 2.4.8
From c1013f281dabda46f983a3cadc8b1053130bd432 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Thu, 10 Oct 2013 23:23:31 +0200
Subject: [PATCH 087/104] 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 538a5a1ace..dece4337a4 100644
--- a/tryton/version.py
+++ b/tryton/version.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.
PACKAGE = "tryton"
-VERSION = "2.4.8"
+VERSION = "2.4.9"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
From ec8d0415632559f7c5b452c7cbe82814294bdd22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sat, 28 Sep 2013 14:56:27 +0200
Subject: [PATCH 088/104] Fix Reference widget when no model is selected, value
is just text
issue3352
review1090002
(transplanted from 5b7b2c1ba521565cb9e052c33f980a28589a47de)
---
tryton/gui/window/view_form/view/form_gtk/reference.py | 7 ++++++-
1 file changed, 6 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 651982afc6..b96a17d836 100644
--- a/tryton/gui/window/view_form/view/form_gtk/reference.py
+++ b/tryton/gui/window/view_form/view/form_gtk/reference.py
@@ -111,7 +111,12 @@ class Reference(Many2One):
return
self.wid_text.set_text('')
self.wid_text.set_position(0)
- self.field.set_client(self.record, (self.get_model(), (-1, '')))
+ model = self.get_model()
+ if model:
+ value = (model, (-1, ''))
+ else:
+ value = ('', '')
+ self.field.set_client(self.record, value)
def set_value(self, record, field):
if not self.get_model():
From 99e59d9e3ea835dbf10e067d6c29dea7ff12856e 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 089/104] Don't extend domain but wrap into a new list
review1106002
(transplanted from e4a2d43ad02e5c5d3ddd4c22a3c2a0890afff0aa)
---
tryton/gui/window/view_form/view/form_gtk/one2many.py | 3 +--
1 file changed, 1 insertion(+), 2 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 bf3ca67cd4..24c136e34e 100644
--- a/tryton/gui/window/view_form/view/form_gtk/one2many.py
+++ b/tryton/gui/window/view_form/view/form_gtk/one2many.py
@@ -305,8 +305,7 @@ class One2Many(WidgetInterface):
self.view.set_value()
domain = self.field.domain_get(self.record)
context = self.field.context_get(self.record)
- domain = domain[:]
- domain.extend(self.record.expr_eval(self.attrs.get('add_remove')))
+ domain = [domain, self.record.expr_eval(self.attrs.get('add_remove'))]
removed_ids = self.field.get_removed_ids(self.record)
self.focus_out = False
From fda5b0132ed4b4697e8e43488a3c7208d9bcb651 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 090/104] 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 ddb86e212d..f22d481f13 100644
--- a/tryton/gui/window/view_form/view/list.py
+++ b/tryton/gui/window/view_form/view/list.py
@@ -121,7 +121,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 bac5f4075624e95729a56c2a62dead4d1b3162bb 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 091/104] 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 949d8d1ed9..63748784d8 100644
--- a/tryton/gui/window/win_export.py
+++ b/tryton/gui/window/win_export.py
@@ -352,7 +352,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 bb89e16c54b47438c2bf02b71e97be80bb4c54f2 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 092/104] 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 b9cd986ac8..37c05d7bc6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,5 @@
+* Sanitize report file extension
+
Version 2.4.8 - 2013-10-10
* Bug fixes (see mercurial logs for details)
diff --git a/tryton/action/main.py b/tryton/action/main.py
index 88f1698c2f..d733ea1aaf 100644
--- a/tryton/action/main.py
+++ b/tryton/action/main.py
@@ -42,7 +42,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 6253bbb72fe7fc73ba957bfc4a5ebd9be65cc0c8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 3 Nov 2013 18:51:52 +0100
Subject: [PATCH 093/104] Prepare release 2.4.9
---
CHANGELOG | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 37c05d7bc6..04e4fce54a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,5 @@
+Version 2.4.9 - 2013-11-03
+* Bug fixes (see mercurial logs for details)
* Sanitize report file extension
Version 2.4.8 - 2013-10-10
From 5813f7c3a26ad3b1a70e71189db0cd466165a01f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 3 Nov 2013 18:51:53 +0100
Subject: [PATCH 094/104] Added tag 2.4.9 for changeset 675708fca92f
---
.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags b/.hgtags
index f3ca0ef43b..f7333626a6 100644
--- a/.hgtags
+++ b/.hgtags
@@ -14,3 +14,4 @@ fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0
74255ad128ab5ce3792823e18982477192b5c6d9 2.4.6
b7f74f142071f979d7f9747e9138427fc6e1d639 2.4.7
3c42199fdfdc35a1ec7c8b1e46a52cacf1c3d474 2.4.8
+675708fca92f27625e0619e9a5444e8abbc289d6 2.4.9
From 98796205ebbeb333f6f57726a776cb16ac4dbe5b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 3 Nov 2013 18:52:17 +0100
Subject: [PATCH 095/104] 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 dece4337a4..49b334890a 100644
--- a/tryton/version.py
+++ b/tryton/version.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.
PACKAGE = "tryton"
-VERSION = "2.4.9"
+VERSION = "2.4.10"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
From be45c1c050399ca43128c7293a5ecf4a6bf7b99c 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 096/104] 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 c1f3d5a3da..3b0cc6dd24 100644
--- a/tryton/common/common.py
+++ b/tryton/common/common.py
@@ -10,6 +10,7 @@ import os
import subprocess
import re
import logging
+from functools import partial
from tryton.config import CONFIG
from tryton.config import TRYTON_ICON, PIXMAPS_DIR
import time
@@ -897,9 +898,10 @@ def send_bugtracker(title, 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 + '\n' + title).hexdigest()
else:
From fcb547c1ead5ee4225d35816d37af4b63867f77c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 3 Nov 2013 20:42:34 +0100
Subject: [PATCH 097/104] Don't set image on button if it is still the same
It fixes also a strange behavior of GTK that doesn't display any images if the
icon is changed before it is realized.
issue3191
review1451002
(transplanted from 4bc44691dc89dfd7802c9d84bbb466f98038bb75)
---
tryton/common/button.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tryton/common/button.py b/tryton/common/button.py
index 2adae35ba6..5a695e8cc3 100644
--- a/tryton/common/button.py
+++ b/tryton/common/button.py
@@ -17,6 +17,11 @@ class Button(gtk.Button):
self._set_icon(attrs.get('icon'))
def _set_icon(self, stock):
+ image = self.get_image()
+ if not image and not stock:
+ return
+ elif image and image.get_stock()[0] == stock:
+ return
if not stock:
self.set_image(gtk.Image())
return
From f4f748ff045afc9b485c06c5366385b52b648554 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20=C3=89vrard?=
Date: Fri, 15 Nov 2013 15:03:00 +0100
Subject: [PATCH 098/104] Use get_eval for check_required computation
issue3473
review1561002
(transplanted from 4786286136344caf3e4bda27c23ac1ab911d9380)
---
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 32424b62bb..21eb409798 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -80,7 +80,7 @@ class CharField(object):
def check_required(self, record):
state_attrs = self.get_state_attrs(record)
if bool(int(state_attrs.get('required') or 0)):
- if (not self.get(record)
+ if (not self.get_eval(record)
and not bool(int(state_attrs.get('readonly') or 0))):
return False
return True
From 3d29bf47a25981c7c85fc5dbce216009befe71ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Wed, 4 Dec 2013 18:03:19 +0100
Subject: [PATCH 099/104] Prepare release 2.4.10
---
CHANGELOG | 3 +++
1 file changed, 3 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 04e4fce54a..5e97561920 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+Version 2.4.10 - 2013-12-04
+* Bug fixes (see mercurial logs for details)
+
Version 2.4.9 - 2013-11-03
* Bug fixes (see mercurial logs for details)
* Sanitize report file extension
From de4b7143eb26b568aa6e329e2d95ed0b1452b21d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Wed, 4 Dec 2013 18:03:20 +0100
Subject: [PATCH 100/104] Added tag 2.4.10 for changeset ccc098c7a309
---
.hgtags | 1 +
1 file changed, 1 insertion(+)
diff --git a/.hgtags b/.hgtags
index f7333626a6..c92a76ecdf 100644
--- a/.hgtags
+++ b/.hgtags
@@ -15,3 +15,4 @@ fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0
b7f74f142071f979d7f9747e9138427fc6e1d639 2.4.7
3c42199fdfdc35a1ec7c8b1e46a52cacf1c3d474 2.4.8
675708fca92f27625e0619e9a5444e8abbc289d6 2.4.9
+ccc098c7a309d87a968a5a43148627f311078260 2.4.10
From 5490d54f9a6e5d963f929fce0e98562de347d52c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Wed, 4 Dec 2013 18:04:11 +0100
Subject: [PATCH 101/104] 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 49b334890a..7b365ce19e 100644
--- a/tryton/version.py
+++ b/tryton/version.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.
PACKAGE = "tryton"
-VERSION = "2.4.10"
+VERSION = "2.4.11"
LICENSE = "GPL-3"
WEBSITE = "http://www.tryton.org/"
From 03a3d7097c39c1e02ba89c7f1c95a62a8f602835 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 26 Jan 2014 22:17:03 +0100
Subject: [PATCH 102/104] Encode gettext value to match with string value
issue3587
review2991002
(transplanted from 80a479e15e31f5a97eaf26ddbd3f9a89303c595e)
---
tryton/common/domain_parser.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tryton/common/domain_parser.py b/tryton/common/domain_parser.py
index 1ba888933d..a83c594850 100644
--- a/tryton/common/domain_parser.py
+++ b/tryton/common/domain_parser.py
@@ -178,7 +178,7 @@ def convert_value(field, value):
def convert_boolean():
if isinstance(value, basestring):
- return any(test.lower().startswith(value.lower())
+ return any(test.decode('utf-8').lower().startswith(value.lower())
for test in (_('y'), _('yes'), _('true'), _('t'), '1'))
else:
return bool(value)
From 47a89aa7b45d3b6697ca254efdd572c3a42111ea 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 103/104] 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 68ad5e9d55..53cc9f0ffe 100644
--- a/tryton/gui/window/win_search.py
+++ b/tryton/gui/window/win_search.py
@@ -103,10 +103,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'])
From 8217924234cba5669bd6fb0c28531ed990375af1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Krier?=
Date: Sun, 9 Feb 2014 23:54:56 +0100
Subject: [PATCH 104/104] Don't set missing default value to False
False is not always a good valid value for the field, so it is better to let the
field dealing with default value.
issue3643
review3281002
(transplanted from 9a16381241f48ca880e7544edeef54c255c99255)
---
tryton/gui/window/view_form/model/group.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/tryton/gui/window/view_form/model/group.py b/tryton/gui/window/view_form/model/group.py
index ab0a8b06a1..45dbefe58d 100644
--- a/tryton/gui/window/view_form/model/group.py
+++ b/tryton/gui/window/view_form/model/group.py
@@ -379,9 +379,6 @@ class Group(SignalEvent, list):
to_add.keys(), main_iteration=False, context=ctx)
except RPCException:
return False
- for name in to_add:
- if name not in values:
- values[name] = False
for record in new:
record.set_default(values, signal=signal)