[tryton-debian-vcs] tryton-client branch upstream updated. upstream/3.0.2-1-gad63d59

Mathias Behrle tryton-debian-vcs at alioth.debian.org
Wed Apr 16 16:10:54 UTC 2014


The following commit has been merged in the upstream branch:
https://alioth.debian.org/plugins/scmgit/cgi-bin/gitweb.cgi/?p=tryton/tryton-client.git;a=commitdiff;h=upstream/3.0.2-1-gad63d59

commit ad63d594c6d12fd0145f43c494bc7ca70fe68df2
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Wed Apr 16 14:48:40 2014 +0200

    Adding upstream version 3.0.3.

diff --git a/CHANGELOG b/CHANGELOG
index 85ce572..c47ee1f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+Version 3.0.3 - 2014-04-07
+* Bug fixes (see mercurial logs for details)
+
 Version 3.0.2 - 2013-12-04
 * Bug fixes (see mercurial logs for details)
 
diff --git a/COPYRIGHT b/COPYRIGHT
index 8121458..c952d2e 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -1,8 +1,8 @@
 Copyright (C) 2012-2013 Antoine Smolders.
-Copyright (C) 2010-2013 Nicolas Évrard.
-Copyright (C) 2007-2013 Cédric Krier.
+Copyright (C) 2010-2014 Nicolas Évrard.
+Copyright (C) 2007-2014 Cédric Krier.
 Copyright (C) 2007-2013 Bertrand Chenal.
-Copyright (C) 2008-2013 B2CK SPRL.
+Copyright (C) 2008-2014 B2CK SPRL.
 Copyright (C) 2008-2011 Udo Spallek.
 Copyright (C) 2008-2011 virtual things - Preisler & Spallek GbR.
 Copyright (C) 2011-2012 Rodrigo Hübner.
diff --git a/PKG-INFO b/PKG-INFO
index 1ffc501..6c6833d 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: tryton
-Version: 3.0.2
+Version: 3.0.3
 Summary: Tryton client
 Home-page: http://www.tryton.org/
 Author: Tryton
diff --git a/tryton.egg-info/PKG-INFO b/tryton.egg-info/PKG-INFO
index 1ffc501..6c6833d 100644
--- a/tryton.egg-info/PKG-INFO
+++ b/tryton.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: tryton
-Version: 3.0.2
+Version: 3.0.3
 Summary: Tryton client
 Home-page: http://www.tryton.org/
 Author: Tryton
diff --git a/tryton/common/domain_parser.py b/tryton/common/domain_parser.py
index e17be8d..3fbccd6 100644
--- a/tryton/common/domain_parser.py
+++ b/tryton/common/domain_parser.py
@@ -184,7 +184,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)
diff --git a/tryton/common/selection.py b/tryton/common/selection.py
index e7b7947..88fd848 100644
--- a/tryton/common/selection.py
+++ b/tryton/common/selection.py
@@ -24,7 +24,7 @@ class SelectionMixin(object):
         if (not isinstance(selection, (list, tuple))
                 and key not in self._values2selection):
             try:
-                if key:
+                if self.attrs.get('selection_change_with'):
                     selection = RPCExecute('model', self.model_name, selection,
                         dict(key))
                 else:
diff --git a/tryton/gui/window/view_form/model/field.py b/tryton/gui/window/view_form/model/field.py
index c4a7a2e..e83543f 100644
--- a/tryton/gui/window/view_form/model/field.py
+++ b/tryton/gui/window/view_form/model/field.py
@@ -488,25 +488,29 @@ class O2MField(CharField):
             return
         record.parent.signal('record-modified')
 
-    def _set_default_value(self, record):
+    def _set_default_value(self, record, fields=None):
         if record.value.get(self.name) is not None:
             return
         from group import Group
         parent_name = self.attrs.get('relation_field', '')
-        group = Group(self.attrs['relation'], {},
+        fields = fields or {}
+        group = Group(self.attrs['relation'], fields,
                 parent=record,
                 parent_name=parent_name,
                 child_name=self.name,
                 context=self.context,
                 parent_datetime_field=self.attrs.get('datetime_field'))
-        if record.model_name == self.attrs['relation']:
+        if not fields and record.model_name == self.attrs['relation']:
             group.fields = record.group.fields
+        record.value[self.name] = group
+        self._connect_value(group)
+
+    def _connect_value(self, group):
         group.signal_connect(group, 'group-changed', self._group_changed)
         group.signal_connect(group, 'group-list-changed',
             self._group_list_changed)
         group.signal_connect(group, 'group-cleared', self._group_cleared)
         group.signal_connect(group, 'record-modified', self._record_modified)
-        record.value[self.name] = group
 
     def get_client(self, record):
         self._set_default_value(record)
@@ -572,44 +576,29 @@ class O2MField(CharField):
         return result
 
     def _set_value(self, record, value, default=False):
-        from group import Group
-
+        self._set_default_value(record)
+        group = record.value[self.name]
         if not value or (len(value) and isinstance(value[0], (int, long))):
             mode = 'list ids'
         else:
             mode = 'list values'
 
-        group = record.value.get(self.name)
-        fields = {}
-        if group is not None:
-            fields = group.fields.copy()
-            # Unconnect to prevent infinite loop
-            group.signal_unconnect(group)
-            group.destroy()
-        elif record.model_name == self.attrs['relation']:
-            fields = record.group.fields
-        if fields:
-            fields = dict((fname, field.attrs)
-                for fname, field in fields.iteritems())
         if mode == 'list values' and len(value):
             context = self.context_get(record)
-            field_names = set(f for v in value for f in v if f not in fields)
+            field_names = set(f for v in value for f in v
+                if f not in group.fields)
             if field_names:
                 try:
-                    fields.update(RPCExecute('model', self.attrs['relation'],
-                            'fields_get', list(field_names),
-                            main_iteration=False, context=context))
+                    fields = RPCExecute('model', self.attrs['relation'],
+                        'fields_get', list(field_names),
+                        main_iteration=False, context=context)
                 except RPCException:
                     return
+                group.load_fields(fields)
 
-        parent_name = self.attrs.get('relation_field', '')
-        group = Group(self.attrs['relation'], fields,
-            parent=record, parent_name=parent_name,
-            child_name=self.name,
-            context=self.context,
-            parent_datetime_field=self.attrs.get('datetime_field'))
-        record.value[self.name] = group
         if mode == 'list ids':
+            for old_record in group:
+                group.remove(old_record, remove=True, signal=False)
             group.load(value)
         else:
             for vals in value:
@@ -621,30 +610,37 @@ class O2MField(CharField):
                     new_record.id *= -1  # Don't consider record as unsaved
                     new_record.set(vals)
                     group.append(new_record)
-        group.signal_connect(group, 'group-changed', self._group_changed)
-        group.signal_connect(group, 'group-list-changed',
-            self._group_list_changed)
-        group.signal_connect(group, 'group-cleared', self._group_cleared)
-        group.signal_connect(group, 'record-modified', self._record_modified)
-        return group
 
-    def set(self, record, value):
-        self._set_value(record, value, default=False)
+    def set(self, record, value, _default=False):
+        group = record.value.get(self.name)
+        fields = {}
+        if group is not None:
+            fields = group.fields.copy()
+            # Unconnect to prevent infinite loop
+            group.signal_unconnect(group)
+            group.destroy()
+        elif record.model_name == self.attrs['relation']:
+            fields = record.group.fields
+        if fields:
+            fields = dict((fname, field.attrs)
+                for fname, field in fields.iteritems())
+
+        record.value[self.name] = None
+        self._set_default_value(record, fields=fields)
+        group = record.value[self.name]
+
+        group.signal_unconnect(group)
+        self._set_value(record, value, default=_default)
+        self._connect_value(group)
 
     def set_client(self, record, value, force_change=False):
         pass
 
     def set_default(self, record, value):
-        previous_group = record.value.get(self.name)
-        group = self._set_value(record, value, default=True)
-        if previous_group:
-            group.record_deleted.extend(x for x in previous_group if x.id >= 0)
-            group.record_deleted.extend(previous_group.record_deleted)
-            group.record_removed.extend(previous_group.record_removed)
+        self.set(record, value, _default=True)
         record.modified_fields.setdefault(self.name)
 
     def set_on_change(self, record, value):
-        self._set_default_value(record)
         if isinstance(value, (list, tuple)):
             self._set_value(record, value)
             record.modified_fields.setdefault(self.name)
@@ -732,36 +728,6 @@ class O2MField(CharField):
 
 class M2MField(O2MField):
 
-    def set(self, record, value):
-        from group import Group
-        group = record.value.get(self.name)
-        fields = {}
-        if group is not None:
-            fields = group.fields.copy()
-            # Unconnect to prevent infinite loop
-            group.signal_unconnect(group)
-            group.destroy()
-        elif record.model_name == self.attrs['relation']:
-            fields = record.group.fields
-        parent_name = self.attrs.get('relation_field', '')
-        group = Group(self.attrs['relation'], {},
-                parent=record, parent_name=parent_name,
-                child_name=self.name,
-                context=self.context,
-                parent_datetime_field=self.attrs.get('datetime_field'))
-        if record.value.get(self.name):
-            group.record_removed.extend(record.value[self.name])
-            group.record_deleted.extend(record.value[self.name].record_deleted)
-            group.record_removed.extend(record.value[self.name].record_removed)
-        record.value[self.name] = group
-        group.fields = fields
-        group.load(value)
-        group.signal_connect(group, 'group-changed', self._group_changed)
-        group.signal_connect(group, 'group-list-changed',
-            self._group_list_changed)
-        group.signal_connect(group, 'group-cleared', self._group_cleared)
-        group.signal_connect(group, 'record-modified', self._record_modified)
-
     def get_on_change_value(self, record):
         return self.get_eval(record)
 
@@ -779,6 +745,12 @@ class ReferenceField(CharField):
             return None
 
     def get(self, record):
+        if record.parent_name == self.name:
+            if record.parent:
+                return '%s,%s' % (record.group.parent.model_name,
+                    record.parent.id)
+            else:
+                return None
         if (record.value.get(self.name)
                 and record.value[self.name][0]
                 and record.value[self.name][1] >= -1):
diff --git a/tryton/gui/window/view_form/model/group.py b/tryton/gui/window/view_form/model/group.py
index 145e9f9..695513f 100644
--- a/tryton/gui/window/view_form/model/group.py
+++ b/tryton/gui/window/view_form/model/group.py
@@ -398,9 +398,6 @@ class Group(SignalEvent, list):
                     to_add.keys(), main_iteration=False, context=self.context)
             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)
 
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 55d9327..50fbad4 100644
--- a/tryton/gui/window/view_form/view/form_gtk/char.py
+++ b/tryton/gui/window/view_form/view/form_gtk/char.py
@@ -49,8 +49,10 @@ class Char(WidgetInterface, TranslateMixin):
     def translate_widget(self):
         entry = gtk.Entry()
         entry.set_property('activates_default', True)
-        entry.set_width_chars(int(self.attrs.get('size', -1)))
-        entry.set_max_length(int(self.attrs.get('size', 0)))
+        if self.record:
+            field_size = self.record.expr_eval(self.attrs.get('size'))
+            entry.set_width_chars(field_size or -1)
+            entry.set_max_length(field_size or 0)
         return entry
 
     @staticmethod
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 8abebb5..0d99af6 100644
--- a/tryton/gui/window/view_form/view/graph_gtk/bar.py
+++ b/tryton/gui/window/view_form/view/graph_gtk/bar.py
@@ -65,6 +65,9 @@ class Bar(Graph):
     def motion(self, widget, event):
         super(Bar, self).motion(widget, event)
 
+        if not getattr(self, 'area', None):
+            return
+
         def intersect(bar, event):
             x = self.area.w * bar.x + self.area.x
             y = self.area.h * bar.y + self.area.y
diff --git a/tryton/gui/window/view_form/view/graph_gtk/line.py b/tryton/gui/window/view_form/view/graph_gtk/line.py
index bd05f53..13868f4 100644
--- a/tryton/gui/window/view_form/view/graph_gtk/line.py
+++ b/tryton/gui/window/view_form/view/graph_gtk/line.py
@@ -154,6 +154,9 @@ class Line(Graph):
         cr.restore()
 
     def motion(self, widget, event):
+        if not getattr(self, 'area', None):
+            return
+
         nearest = None
         for point in self.points:
             x = point.x * self.area.w + self.area.x
diff --git a/tryton/gui/window/view_form/view/graph_gtk/pie.py b/tryton/gui/window/view_form/view/graph_gtk/pie.py
index 174ebf5..9018288 100644
--- a/tryton/gui/window/view_form/view/graph_gtk/pie.py
+++ b/tryton/gui/window/view_form/view/graph_gtk/pie.py
@@ -108,6 +108,9 @@ class Pie(Graph):
     def motion(self, widget, event):
         super(Pie, self).motion(widget, event)
 
+        if not getattr(self, 'area', None):
+            return
+
         d = (event.x - self.centerx) ** 2 + (event.y - self.centery) ** 2
         if d > self.radius ** 2:
             self.popup.hide()
diff --git a/tryton/gui/window/view_form/view/list.py b/tryton/gui/window/view_form/view/list.py
index d927d70..1b61eaf 100644
--- a/tryton/gui/window/view_form/view/list.py
+++ b/tryton/gui/window/view_form/view/list.py
@@ -588,16 +588,19 @@ class ViewList(ParserView):
 
     def __button_press(self, treeview, event):
         if event.button == 3:
-            path = treeview.get_path_at_pos(int(event.x), int(event.y))
+            try:
+                path, col, x, y = treeview.get_path_at_pos(
+                    int(event.x), int(event.y))
+            except TypeError:
+                # Outside row
+                return False
             selection = treeview.get_selection()
             if selection.get_mode() == gtk.SELECTION_SINGLE:
                 model = selection.get_selected()[0]
             elif selection.get_mode() == gtk.SELECTION_MULTIPLE:
                 model = selection.get_selected_rows()[0]
-            if (not path) or not path[0]:
-                return False
-            group = model.group
-            record = group[path[0][0]]
+            record = model.get_value(model.get_iter(path), 0)
+            group = record.group
             menu = gtk.Menu()
             menu.popup(None, None, None, event.button, event.time)
 
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 319fe6c..50b660c 100644
--- a/tryton/gui/window/view_form/view/list_gtk/editabletree.py
+++ b/tryton/gui/window/view_form/view/list_gtk/editabletree.py
@@ -21,7 +21,7 @@ class TreeView(gtk.TreeView):
     def next_column(self, path, column=None, editable=True, _sign=1):
         columns = self.get_columns()
         if column is None:
-            column = columns[-1 * _sign]
+            column = columns[-1 if _sign > 0 else 0]
         model = self.get_model()
         record = model.get_value(model.get_iter(path), 0)
         if _sign < 0:
diff --git a/tryton/gui/window/win_search.py b/tryton/gui/window/win_search.py
index 388b1e0..cc5e1cb 100644
--- a/tryton/gui/window/win_search.py
+++ b/tryton/gui/window/win_search.py
@@ -109,10 +109,8 @@ class WinSearch(NoModal):
         if response_id == gtk.RESPONSE_OK:
             res = self.screen.sel_ids_get()
         elif response_id == gtk.RESPONSE_APPLY:
-            if not self.screen.search_filter():
-                res = self.screen.sel_ids_get()
-            else:
-                return
+            self.screen.search_filter(self.screen.screen_container.get_text())
+            return
         elif response_id == gtk.RESPONSE_ACCEPT:
             screen = Screen(self.model_name, domain=self.domain,
                 context=self.context, mode=['form'])
diff --git a/tryton/gui/window/wizard.py b/tryton/gui/window/wizard.py
index a910de4..869ec06 100644
--- a/tryton/gui/window/wizard.py
+++ b/tryton/gui/window/wizard.py
@@ -350,9 +350,13 @@ class WizardDialog(Wizard, NoModal):
             dialog = self.page
         if (hasattr(dialog, 'screen')
                 and dialog.screen.current_record
-                and self.sensible_widget != main.window
-                and self.ids):
-            dialog.screen.reload(self.ids, written=True)
+                and self.sensible_widget != main.window):
+            if dialog.screen.model_name == self.model:
+                ids = self.ids
+            else:
+                # Wizard run from a children record so reload parent record
+                ids = [dialog.screen.current_record.id]
+            dialog.screen.reload(ids, written=True)
 
     def end(self):
         super(WizardDialog, self).end()
diff --git a/tryton/version.py b/tryton/version.py
index b21c548..0158ec3 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 = "3.0.2"
+VERSION = "3.0.3"
 LICENSE = "GPL-3"
 WEBSITE = "http://www.tryton.org/"
-- 
tryton-client



More information about the tryton-debian-vcs mailing list