tryton 7.4.10__py3-none-any.whl → 7.6.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tryton might be problematic. Click here for more details.

Files changed (122) hide show
  1. tryton/__init__.py +1 -1
  2. tryton/bus.py +113 -69
  3. tryton/chat.py +179 -0
  4. tryton/client.py +7 -0
  5. tryton/common/__init__.py +15 -11
  6. tryton/common/button.py +1 -1
  7. tryton/common/cellrendererfloat.py +1 -1
  8. tryton/common/cellrenderertext.py +2 -2
  9. tryton/common/common.py +91 -19
  10. tryton/common/environment.py +2 -2
  11. tryton/common/number_entry.py +12 -6
  12. tryton/common/selection.py +1 -1
  13. tryton/data/locale/bg/LC_MESSAGES/tryton.mo +0 -0
  14. tryton/data/locale/bg/LC_MESSAGES/tryton.po +26 -16
  15. tryton/data/locale/ca/LC_MESSAGES/tryton.mo +0 -0
  16. tryton/data/locale/ca/LC_MESSAGES/tryton.po +29 -18
  17. tryton/data/locale/cs/LC_MESSAGES/tryton.mo +0 -0
  18. tryton/data/locale/cs/LC_MESSAGES/tryton.po +28 -16
  19. tryton/data/locale/de/LC_MESSAGES/tryton.mo +0 -0
  20. tryton/data/locale/de/LC_MESSAGES/tryton.po +27 -18
  21. tryton/data/locale/es/LC_MESSAGES/tryton.mo +0 -0
  22. tryton/data/locale/es/LC_MESSAGES/tryton.po +25 -16
  23. tryton/data/locale/es_419/LC_MESSAGES/tryton.mo +0 -0
  24. tryton/data/locale/es_419/LC_MESSAGES/tryton.po +26 -16
  25. tryton/data/locale/et/LC_MESSAGES/tryton.mo +0 -0
  26. tryton/data/locale/et/LC_MESSAGES/tryton.po +28 -18
  27. tryton/data/locale/fa/LC_MESSAGES/tryton.mo +0 -0
  28. tryton/data/locale/fa/LC_MESSAGES/tryton.po +28 -18
  29. tryton/data/locale/fi/LC_MESSAGES/tryton.mo +0 -0
  30. tryton/data/locale/fi/LC_MESSAGES/tryton.po +25 -16
  31. tryton/data/locale/fr/LC_MESSAGES/tryton.mo +0 -0
  32. tryton/data/locale/fr/LC_MESSAGES/tryton.po +25 -16
  33. tryton/data/locale/hu/LC_MESSAGES/tryton.mo +0 -0
  34. tryton/data/locale/hu/LC_MESSAGES/tryton.po +28 -18
  35. tryton/data/locale/id/LC_MESSAGES/tryton.mo +0 -0
  36. tryton/data/locale/id/LC_MESSAGES/tryton.po +23 -16
  37. tryton/data/locale/it/LC_MESSAGES/tryton.mo +0 -0
  38. tryton/data/locale/it/LC_MESSAGES/tryton.po +29 -18
  39. tryton/data/locale/ja_JP/LC_MESSAGES/tryton.mo +0 -0
  40. tryton/data/locale/lo/LC_MESSAGES/tryton.mo +0 -0
  41. tryton/data/locale/lo/LC_MESSAGES/tryton.po +26 -18
  42. tryton/data/locale/lt/LC_MESSAGES/tryton.mo +0 -0
  43. tryton/data/locale/lt/LC_MESSAGES/tryton.po +30 -18
  44. tryton/data/locale/nl/LC_MESSAGES/tryton.mo +0 -0
  45. tryton/data/locale/nl/LC_MESSAGES/tryton.po +25 -16
  46. tryton/data/locale/pl/LC_MESSAGES/tryton.mo +0 -0
  47. tryton/data/locale/pl/LC_MESSAGES/tryton.po +31 -18
  48. tryton/data/locale/pt/LC_MESSAGES/tryton.mo +0 -0
  49. tryton/data/locale/pt/LC_MESSAGES/tryton.po +148 -177
  50. tryton/data/locale/ro/LC_MESSAGES/tryton.mo +0 -0
  51. tryton/data/locale/ro/LC_MESSAGES/tryton.po +32 -19
  52. tryton/data/locale/ru/LC_MESSAGES/tryton.mo +0 -0
  53. tryton/data/locale/ru/LC_MESSAGES/tryton.po +28 -16
  54. tryton/data/locale/sl/LC_MESSAGES/tryton.mo +0 -0
  55. tryton/data/locale/sl/LC_MESSAGES/tryton.po +33 -18
  56. tryton/data/locale/tr/LC_MESSAGES/tryton.mo +0 -0
  57. tryton/data/locale/tr/LC_MESSAGES/tryton.po +25 -16
  58. tryton/data/locale/uk/LC_MESSAGES/tryton.mo +0 -0
  59. tryton/data/locale/uk/LC_MESSAGES/tryton.po +31 -18
  60. tryton/data/locale/zh_CN/LC_MESSAGES/tryton.mo +0 -0
  61. tryton/data/locale/zh_CN/LC_MESSAGES/tryton.po +27 -18
  62. tryton/data/pixmaps/tryton/tryton-chat.svg +1 -0
  63. tryton/data/pixmaps/tryton/tryton-note.svg +1 -4
  64. tryton/gui/window/attachment.py +2 -2
  65. tryton/gui/window/board.py +1 -1
  66. tryton/gui/window/form.py +57 -10
  67. tryton/gui/window/note.py +2 -2
  68. tryton/gui/window/tabcontent.py +8 -1
  69. tryton/gui/window/view_board/action.py +1 -1
  70. tryton/gui/window/view_form/model/field.py +34 -28
  71. tryton/gui/window/view_form/model/group.py +4 -4
  72. tryton/gui/window/view_form/model/record.py +19 -4
  73. tryton/gui/window/view_form/screen/screen.py +24 -4
  74. tryton/gui/window/view_form/view/calendar_gtk/calendar_.py +1 -1
  75. tryton/gui/window/view_form/view/calendar_gtk/toolbar.py +1 -1
  76. tryton/gui/window/view_form/view/form.py +2 -1
  77. tryton/gui/window/view_form/view/form_gtk/binary.py +3 -3
  78. tryton/gui/window/view_form/view/form_gtk/calendar_.py +4 -4
  79. tryton/gui/window/view_form/view/form_gtk/char.py +42 -5
  80. tryton/gui/window/view_form/view/form_gtk/checkbox.py +3 -3
  81. tryton/gui/window/view_form/view/form_gtk/dictionary.py +53 -15
  82. tryton/gui/window/view_form/view/form_gtk/float.py +3 -7
  83. tryton/gui/window/view_form/view/form_gtk/image.py +4 -4
  84. tryton/gui/window/view_form/view/form_gtk/integer.py +1 -1
  85. tryton/gui/window/view_form/view/form_gtk/many2many.py +3 -4
  86. tryton/gui/window/view_form/view/form_gtk/many2one.py +2 -2
  87. tryton/gui/window/view_form/view/form_gtk/multiselection.py +3 -3
  88. tryton/gui/window/view_form/view/form_gtk/one2many.py +11 -8
  89. tryton/gui/window/view_form/view/form_gtk/progressbar.py +2 -2
  90. tryton/gui/window/view_form/view/form_gtk/pyson.py +3 -3
  91. tryton/gui/window/view_form/view/form_gtk/reference.py +4 -4
  92. tryton/gui/window/view_form/view/form_gtk/richtextbox.py +5 -5
  93. tryton/gui/window/view_form/view/form_gtk/selection.py +3 -3
  94. tryton/gui/window/view_form/view/form_gtk/state_widget.py +8 -6
  95. tryton/gui/window/view_form/view/form_gtk/textbox.py +4 -4
  96. tryton/gui/window/view_form/view/form_gtk/timedelta.py +3 -3
  97. tryton/gui/window/view_form/view/form_gtk/url.py +2 -2
  98. tryton/gui/window/view_form/view/form_gtk/widget.py +1 -1
  99. tryton/gui/window/view_form/view/graph_gtk/bar.py +7 -7
  100. tryton/gui/window/view_form/view/graph_gtk/graph.py +2 -2
  101. tryton/gui/window/view_form/view/graph_gtk/line.py +5 -5
  102. tryton/gui/window/view_form/view/graph_gtk/pie.py +2 -2
  103. tryton/gui/window/view_form/view/list.py +107 -52
  104. tryton/gui/window/view_form/view/list_gtk/editabletree.py +2 -2
  105. tryton/gui/window/view_form/view/list_gtk/widget.py +22 -20
  106. tryton/gui/window/view_form/view/screen_container.py +13 -1
  107. tryton/gui/window/win_csv.py +2 -2
  108. tryton/gui/window/win_export.py +9 -7
  109. tryton/gui/window/win_form.py +74 -39
  110. tryton/gui/window/win_import.py +5 -6
  111. tryton/gui/window/wizard.py +11 -11
  112. tryton/jsonrpc.py +2 -2
  113. tryton/plugins/__init__.py +0 -1
  114. tryton/pyson.py +18 -18
  115. tryton/rpc.py +7 -5
  116. {tryton-7.4.10.dist-info → tryton-7.6.1.dist-info}/METADATA +5 -5
  117. {tryton-7.4.10.dist-info → tryton-7.6.1.dist-info}/RECORD +121 -120
  118. tryton/gui/window/view_form/view/list_gtk/generictreemodel.py +0 -426
  119. {tryton-7.4.10.data → tryton-7.6.1.data}/scripts/tryton +0 -0
  120. {tryton-7.4.10.dist-info → tryton-7.6.1.dist-info}/WHEEL +0 -0
  121. {tryton-7.4.10.dist-info → tryton-7.6.1.dist-info}/licenses/LICENSE +0 -0
  122. {tryton-7.4.10.dist-info → tryton-7.6.1.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,7 @@ class StateMixin(object):
14
14
 
15
15
  def __init__(self, *args, **kwargs):
16
16
  self.attrs = kwargs.pop('attrs')
17
- super(StateMixin, self).__init__(*args, **kwargs)
17
+ super().__init__(*args, **kwargs)
18
18
 
19
19
  def state_set(self, record):
20
20
  if record:
@@ -30,7 +30,7 @@ class StateMixin(object):
30
30
  class Label(StateMixin, Gtk.Label):
31
31
 
32
32
  def state_set(self, record):
33
- super(Label, self).state_set(record)
33
+ super().state_set(record)
34
34
  if 'name' in self.attrs and record:
35
35
  field = record.group.fields[self.attrs['name']]
36
36
  else:
@@ -61,7 +61,7 @@ class VBox(StateMixin, Gtk.VBox):
61
61
  class Image(StateMixin, Gtk.Image):
62
62
 
63
63
  def state_set(self, record):
64
- super(Image, self).state_set(record)
64
+ super().state_set(record)
65
65
  if not record:
66
66
  return
67
67
  name = self.attrs['name']
@@ -72,6 +72,8 @@ class Image(StateMixin, Gtk.Image):
72
72
  if self.attrs.get('type') == 'url':
73
73
  pixbuf = common.IconFactory.get_pixbuf_url(
74
74
  name, size=size, size_param=self.attrs.get('url_size'))
75
+ elif self.attrs.get('type') == 'color':
76
+ pixbuf = common.SolidColorFactory.get_pixbuf(name, size, size)
75
77
  else:
76
78
  pixbuf = common.IconFactory.get_pixbuf(name, size)
77
79
  self.set_from_pixbuf(pixbuf)
@@ -82,7 +84,7 @@ class Frame(StateMixin, Gtk.Frame):
82
84
  def __init__(self, label=None, attrs=None):
83
85
  if not label: # label must be None to have no label widget
84
86
  label = None
85
- super(Frame, self).__init__(label=label, attrs=attrs)
87
+ super().__init__(label=label, attrs=attrs)
86
88
  if not label:
87
89
  self.set_shadow_type(Gtk.ShadowType.NONE)
88
90
  self.set_border_width(0)
@@ -93,7 +95,7 @@ class ScrolledWindow(StateMixin, Gtk.ScrolledWindow):
93
95
  def state_set(self, record):
94
96
  # Force to show first to ensure it is displayed in the Notebook
95
97
  self.show()
96
- super(ScrolledWindow, self).state_set(record)
98
+ super().state_set(record)
97
99
 
98
100
 
99
101
  class Notebook(StateMixin, Gtk.Notebook):
@@ -105,7 +107,7 @@ class Expander(StateMixin, Gtk.Expander):
105
107
  def __init__(self, label=None, attrs=None):
106
108
  if not label:
107
109
  label = None
108
- super(Expander, self).__init__(label=label, attrs=attrs)
110
+ super().__init__(label=label, attrs=attrs)
109
111
 
110
112
 
111
113
  class Link(StateMixin, Gtk.Button):
@@ -20,7 +20,7 @@ class TextBox(Widget, TranslateMixin):
20
20
  expand = True
21
21
 
22
22
  def __init__(self, view, attrs):
23
- super(TextBox, self).__init__(view, attrs)
23
+ super().__init__(view, attrs)
24
24
 
25
25
  self.widget = Gtk.VBox()
26
26
  self.scrolledwindow = Gtk.ScrolledWindow()
@@ -92,7 +92,7 @@ class TextBox(Widget, TranslateMixin):
92
92
  textview.props.sensitive = not value
93
93
 
94
94
  def _readonly_set(self, value):
95
- super(TextBox, self)._readonly_set(value)
95
+ super()._readonly_set(value)
96
96
  self.textview.set_editable(not value)
97
97
 
98
98
  @property
@@ -120,7 +120,7 @@ class TextBox(Widget, TranslateMixin):
120
120
  return buf.get_text(iter_start, iter_end, False)
121
121
 
122
122
  def display(self):
123
- super(TextBox, self).display()
123
+ super().display()
124
124
  value = self.field and self.field.get(self.record)
125
125
  if not value:
126
126
  value = ''
@@ -153,7 +153,7 @@ class TextBufferLimitSize(Gtk.TextBuffer):
153
153
  }
154
154
 
155
155
  def __init__(self, max_length):
156
- super(TextBufferLimitSize, self).__init__()
156
+ super().__init__()
157
157
  self.max_length = max_length
158
158
 
159
159
  def do_insert_text(self, iter, text, length):
@@ -10,7 +10,7 @@ from .widget import Widget
10
10
  class TimeDelta(Widget):
11
11
 
12
12
  def __init__(self, view, attrs):
13
- super(TimeDelta, self).__init__(view, attrs)
13
+ super().__init__(view, attrs)
14
14
 
15
15
  self.widget = Gtk.HBox()
16
16
  self.entry = self.mnemonic_widget = Gtk.Entry()
@@ -37,7 +37,7 @@ class TimeDelta(Widget):
37
37
  return self.entry.get_text()
38
38
 
39
39
  def display(self):
40
- super(TimeDelta, self).display()
40
+ super().display()
41
41
  if not self.field:
42
42
  value = ''
43
43
  else:
@@ -46,5 +46,5 @@ class TimeDelta(Widget):
46
46
  reset_position(self.entry)
47
47
 
48
48
  def _readonly_set(self, value):
49
- super(TimeDelta, self)._readonly_set(value)
49
+ super()._readonly_set(value)
50
50
  self.entry.set_editable(not value)
@@ -22,7 +22,7 @@ class URL(Char):
22
22
  "url"
23
23
 
24
24
  def __init__(self, view, attrs):
25
- super(URL, self).__init__(view, attrs)
25
+ super().__init__(view, attrs)
26
26
 
27
27
  self.tooltips = common.Tooltips()
28
28
  self.button = Gtk.Button()
@@ -34,7 +34,7 @@ class URL(Char):
34
34
  self.button, expand=False, fill=False, padding=0)
35
35
 
36
36
  def display(self):
37
- super(URL, self).display()
37
+ super().display()
38
38
  self.set_tooltips()
39
39
  if self.record and 'icon' in self.attrs:
40
40
  icon = self.attrs['icon']
@@ -19,7 +19,7 @@ class Widget(object):
19
19
  default_width_chars = 8
20
20
 
21
21
  def __init__(self, view, attrs):
22
- super(Widget, self).__init__()
22
+ super().__init__()
23
23
  self.view = view
24
24
  self.attrs = attrs
25
25
  self.widget = None
@@ -17,7 +17,7 @@ from .graph import Graph
17
17
  class Bar(Graph):
18
18
 
19
19
  def __init__(self, *args, **kwargs):
20
- super(Bar, self).__init__(*args, **kwargs)
20
+ super().__init__(*args, **kwargs)
21
21
  self.bars = []
22
22
 
23
23
  def drawGraph(self, cr, width, height):
@@ -63,7 +63,7 @@ class Bar(Graph):
63
63
  return linear
64
64
 
65
65
  def motion(self, widget, event):
66
- super(Bar, self).motion(widget, event)
66
+ super().motion(widget, event)
67
67
 
68
68
  if not getattr(self, 'area', None):
69
69
  return
@@ -127,7 +127,7 @@ class Bar(Graph):
127
127
  maxx - minx + 2, maxy - miny + 2)
128
128
 
129
129
  def action(self):
130
- super(Bar, self).action()
130
+ super().action()
131
131
  for bar in self.bars:
132
132
  if bar.highlight:
133
133
  ids = self.ids[bar.xname]
@@ -171,11 +171,11 @@ class VerticalBar(Bar):
171
171
  i += 1
172
172
 
173
173
  def XLabels(self):
174
- xlabels = super(VerticalBar, self).XLabels()
174
+ xlabels = super().XLabels()
175
175
  return [(x[0] + (self.xscale / 2), x[1]) for x in xlabels]
176
176
 
177
177
  def YLabels(self):
178
- ylabels = super(VerticalBar, self).YLabels()
178
+ ylabels = super().YLabels()
179
179
  if all('timedelta' in f for f in self.yfields):
180
180
  converter = {f.get('timedelta') for f in self.yfields}
181
181
  if len(converter) == 1:
@@ -227,11 +227,11 @@ class HorizontalBar(Bar):
227
227
  i += 1
228
228
 
229
229
  def YLabels(self):
230
- xlabels = super(HorizontalBar, self).XLabels()
230
+ xlabels = super().XLabels()
231
231
  return [(1 - (x[0] + (self.xscale / 2)), x[1]) for x in xlabels]
232
232
 
233
233
  def XLabels(self):
234
- ylabels = super(HorizontalBar, self).YLabels()
234
+ ylabels = super().YLabels()
235
235
  if all('timedelta' in f for f in self.yfields):
236
236
  converter = {f.get('timedelta') for f in self.yfields}
237
237
  if len(converter) == 1:
@@ -75,7 +75,7 @@ class Graph(Gtk.DrawingArea):
75
75
  __gsignals__ = {"draw": "override"}
76
76
 
77
77
  def __init__(self, view, xfield, yfields):
78
- super(Graph, self).__init__()
78
+ super().__init__()
79
79
  self.view = view
80
80
  self.xfield = xfield
81
81
  self.yfields = yfields
@@ -99,7 +99,7 @@ class Graph(Gtk.DrawingArea):
99
99
 
100
100
  def destroy(self):
101
101
  self.popup.destroy()
102
- super(Graph, self).destroy()
102
+ super().destroy()
103
103
 
104
104
  def motion(self, widget, event):
105
105
  self.popup.set_position(self, event.x, event.y)
@@ -145,7 +145,7 @@ class Line(Graph):
145
145
  cr.restore()
146
146
 
147
147
  def drawLegend(self, cr, widht, height):
148
- super(Line, self).drawLegend(cr, widht, height)
148
+ super().drawLegend(cr, widht, height)
149
149
  cr.save()
150
150
  for point in self.points:
151
151
  if point.highlight:
@@ -237,7 +237,7 @@ class Line(Graph):
237
237
  int(maxx - minx + 1), int(maxy - miny + 1))
238
238
 
239
239
  def updateXY(self):
240
- super(Line, self).updateXY()
240
+ super().updateXY()
241
241
  if self.xrange != 0:
242
242
  self.xrange -= 1
243
243
  if self.xrange == 0:
@@ -246,18 +246,18 @@ class Line(Graph):
246
246
  self.xscale = 1.0 / self.xrange
247
247
 
248
248
  def drawAxis(self, cr, width, height):
249
- super(Line, self).drawAxis(cr, width, height)
249
+ super().drawAxis(cr, width, height)
250
250
  self.drawLine(cr, 1.0, 0)
251
251
 
252
252
  def action(self):
253
- super(Line, self).action()
253
+ super().action()
254
254
  for point in self.points:
255
255
  if point.highlight:
256
256
  ids = self.ids[point.xname]
257
257
  self.action_keyword(ids)
258
258
 
259
259
  def YLabels(self):
260
- ylabels = super(Line, self).YLabels()
260
+ ylabels = super().YLabels()
261
261
  if all('timedelta' in f for f in self.yfields):
262
262
  converter = {f.get('timedelta') for f in self.yfields}
263
263
  if len(converter) == 1:
@@ -110,7 +110,7 @@ class Pie(Graph):
110
110
  cr.restore()
111
111
 
112
112
  def motion(self, widget, event):
113
- super(Pie, self).motion(widget, event)
113
+ super().motion(widget, event)
114
114
 
115
115
  if not getattr(self, 'area', None):
116
116
  return
@@ -172,7 +172,7 @@ class Pie(Graph):
172
172
  self.queue_draw()
173
173
 
174
174
  def action(self):
175
- super(Pie, self).action()
175
+ super().action()
176
176
  for slice in self.slices:
177
177
  if slice.highlight:
178
178
  ids = self.ids[slice.xname]
@@ -8,13 +8,14 @@ import sys
8
8
  from collections import defaultdict
9
9
  from functools import wraps
10
10
  from io import StringIO
11
+ from weakref import WeakValueDictionary
11
12
 
12
13
  from gi.repository import Gdk, GLib, GObject, Gtk
13
14
 
14
15
  import tryton.common as common
15
16
  from tryton.common import (
16
- RPCException, RPCExecute, Tooltips, domain_inversion, node_attributes,
17
- simplify, unique_value)
17
+ RPCException, RPCExecute, Tooltips, domain_inversion, get_monitor_size,
18
+ node_attributes, simplify, unique_value)
18
19
  from tryton.common.cellrendererbutton import CellRendererButton
19
20
  from tryton.common.popup_menu import populate, popup
20
21
  from tryton.config import CONFIG
@@ -23,7 +24,6 @@ from tryton.pyson import PYSONDecoder
23
24
 
24
25
  from . import View, XMLViewParser
25
26
  from .list_gtk.editabletree import EditableTreeView, TreeView
26
- from .list_gtk.generictreemodel import GenericTreeModel
27
27
  from .list_gtk.widget import (
28
28
  M2M, M2O, O2M, O2O, URL, Affix, Binary, Boolean, Button, Char, Date, Dict,
29
29
  Float, Image, Int, MultiSelection, ProgressBar, Reference, Selection, Text,
@@ -63,15 +63,30 @@ def path_convert_id2pos(model, id_path):
63
63
  return tuple(indexes)
64
64
 
65
65
 
66
- class AdaptModelGroup(GenericTreeModel):
66
+ class ModelGroup(GObject.GObject, Gtk.TreeModel):
67
67
 
68
68
  def __init__(self, group, children_field=None):
69
- super(AdaptModelGroup, self).__init__()
69
+ super().__init__()
70
+ self._pool = WeakValueDictionary()
70
71
  self.group = group
71
- self.set_property('leak_references', False)
72
72
  self.children_field = children_field
73
73
  self.__removed = None # XXX dirty hack to allow update of has_child
74
74
 
75
+ def _get_user_data(self, iter):
76
+ return self._pool.get(iter.user_data)
77
+
78
+ def _set_user_data(self, iter, data):
79
+ if data is not None:
80
+ iter.user_data = id(data)
81
+ self._pool[iter.user_data] = data
82
+ else:
83
+ iter.user_data = None
84
+
85
+ def _create_tree_iter(self, data):
86
+ iter = Gtk.TreeIter()
87
+ self._set_user_data(iter, data)
88
+ return iter
89
+
75
90
  def added(self, group, record):
76
91
  if (group is self.group
77
92
  and (record.group is self.group
@@ -103,7 +118,6 @@ class AdaptModelGroup(GenericTreeModel):
103
118
  def remove(self, iter_):
104
119
  record = self.get_value(iter_, 0)
105
120
  record.group.remove(record)
106
- self.invalidate_iters()
107
121
 
108
122
  def __move(self, record, path, offset=0):
109
123
  iter_ = self.get_iter(path)
@@ -172,43 +186,51 @@ class AdaptModelGroup(GenericTreeModel):
172
186
  def __len__(self):
173
187
  return len(self.group)
174
188
 
175
- def on_get_flags(self):
189
+ def do_get_flags(self):
176
190
  if not self.children_field:
177
191
  return Gtk.TreeModelFlags.LIST_ONLY
178
192
  return 0
179
193
 
180
- def on_get_n_columns(self):
194
+ def do_get_n_columns(self):
181
195
  # XXX
182
196
  return 1
183
197
 
184
- def on_get_column_type(self, index):
198
+ def do_get_column_type(self, index):
185
199
  # XXX
186
200
  return GObject.TYPE_PYOBJECT
187
201
 
188
- def on_get_path(self, record):
189
- return record.get_index_path(self.group)
202
+ def do_get_path(self, iter):
203
+ record = self._get_user_data(iter)
204
+ path = record.get_index_path(self.group)
205
+ if path is None:
206
+ return None
207
+ else:
208
+ return Gtk.TreePath(path)
190
209
 
191
- def on_get_iter(self, path):
210
+ def do_get_iter(self, path):
192
211
  group = self.group
193
212
  record = None
194
213
  for i in path:
195
214
  if group is None or i >= len(group):
196
- return None
215
+ return (False, None)
197
216
  record = group[i]
198
217
  if not self.children_field:
199
218
  break
200
219
  group = record.children_group(self.children_field)
201
- return record
220
+ return (True, self._create_tree_iter(record))
202
221
 
203
- def on_get_value(self, record, column):
204
- return record
222
+ def do_get_value(self, iter, column):
223
+ return self._get_user_data(iter)
205
224
 
206
- def on_iter_next(self, record):
207
- if record is None:
208
- return None
209
- return record.next.get(id(record.group))
225
+ def do_iter_next(self, iter):
226
+ record = self._get_user_data(iter)
227
+ if record is not None:
228
+ record = record.next.get(id(record.group))
229
+ self._set_user_data(iter, record)
230
+ return record is not None
210
231
 
211
- def on_iter_has_child(self, record):
232
+ def do_iter_has_child(self, parent):
233
+ record = self._get_user_data(parent) if parent else None
212
234
  if record is None or not self.children_field:
213
235
  return False
214
236
  children = record.children_group(self.children_field)
@@ -219,40 +241,49 @@ class AdaptModelGroup(GenericTreeModel):
219
241
  length -= 1
220
242
  return bool(length)
221
243
 
222
- def on_iter_children(self, record):
244
+ def do_iter_children(self, parent):
245
+ record = self._get_user_data(parent) if parent else None
246
+ child = None
223
247
  if record is None:
224
248
  if self.group:
225
- return self.group[0]
226
- else:
227
- return None
228
- if self.children_field:
249
+ child = self.group[0]
250
+ elif self.children_field:
229
251
  children = record.children_group(self.children_field)
230
252
  if children:
231
- return children[0]
232
- return None
253
+ child = children[0]
254
+ if child:
255
+ return (True, self._create_tree_iter(child))
256
+ else:
257
+ return (False, None)
233
258
 
234
- def on_iter_n_children(self, record):
259
+ def do_iter_n_children(self, iter):
260
+ record = self._get_user_data(iter) if iter else None
235
261
  if record is None:
236
262
  return len(self.group)
237
263
  if not self.children_field:
238
264
  return 0
239
265
  return len(record.children_group(self.children_field))
240
266
 
241
- def on_iter_nth_child(self, record, nth):
267
+ def do_iter_nth_child(self, parent, n):
268
+ record = self._get_user_data(parent) if parent else None
269
+ child = None
242
270
  if record is None:
243
- if nth < len(self.group):
244
- return self.group[nth]
245
- return None
246
- if not self.children_field:
247
- return None
248
- if nth < len(record.children_group(self.children_field)):
249
- return record.children_group(self.children_field)[nth]
250
- return None
271
+ if n < len(self.group):
272
+ child = self.group[n]
273
+ elif self.children_field:
274
+ if n < len(record.children_group(self.children_field)):
275
+ child = record.children_group(self.children_field)[n]
276
+ if child:
277
+ return (True, self._create_tree_iter(child))
278
+ else:
279
+ return (False, None)
251
280
 
252
- def on_iter_parent(self, record):
253
- if record is None:
254
- return None
255
- return record.parent
281
+ def do_iter_parent(self, child):
282
+ record = self._get_user_data(child) if child else None
283
+ if record and record.parent:
284
+ return (True, self._create_tree_iter(record.parent))
285
+ else:
286
+ return (False, None)
256
287
 
257
288
 
258
289
  class TreeXMLViewParser(XMLViewParser):
@@ -407,19 +438,23 @@ class TreeXMLViewParser(XMLViewParser):
407
438
  'binary': 200,
408
439
  }
409
440
 
441
+ field_attrs = self.field_attrs.get(attributes['name'], {})
442
+ if field_attrs:
443
+ computed_width = default_width.get(field_attrs['type'], 100)
444
+ if attributes.get('symbol'):
445
+ computed_width += 20
446
+ else:
447
+ computed_width = 80
448
+
410
449
  screen = self.view.screen
411
450
  width = screen.tree_column_width[screen.model_name].get(column.name)
412
- field_attrs = self.field_attrs.get(attributes['name'], {})
413
451
  if not width:
414
452
  if 'width' in attributes:
415
- width = int(attributes['width'])
416
- elif field_attrs:
417
- width = default_width.get(field_attrs['type'], 100)
418
- if attributes.get('symbol'):
419
- width += 20
453
+ computed_width = width = int(attributes['width'])
420
454
  else:
421
- width = 80
455
+ width = computed_width
422
456
  column.width = width
457
+ column.computed_width = computed_width
423
458
  if width > 0:
424
459
  column.set_fixed_width(width)
425
460
  column.set_min_width(1)
@@ -537,6 +572,11 @@ class ViewTree(View):
537
572
  menuitem.set_active(visible)
538
573
  menuitem.connect('toggled', toggle, columns)
539
574
  menu.add(menuitem)
575
+ if self.optionals:
576
+ menu.add(Gtk.SeparatorMenuItem())
577
+ menuitem = Gtk.MenuItem(label=_("Reset Column Widths"))
578
+ menuitem.connect('activate', self.reset_width)
579
+ menu.add(menuitem)
540
580
  popup(menu, widget)
541
581
 
542
582
  def save_optional(self):
@@ -551,6 +591,20 @@ class ViewTree(View):
551
591
  pass
552
592
  self.screen.tree_column_optional[self.view_id] = fields
553
593
 
594
+ def reset_width(self, menuitem):
595
+ try:
596
+ screen_width, _ = get_monitor_size()
597
+ RPCExecute(
598
+ 'model', 'ir.ui.view_tree_width', 'reset_width',
599
+ self.screen.model_name, screen_width)
600
+ except RPCException:
601
+ pass
602
+ self.screen.tree_column_width.pop(self.screen.model_name, None)
603
+
604
+ for col in self.treeview.get_columns():
605
+ if col.name:
606
+ col.set_fixed_width(col.computed_width)
607
+
554
608
  def get_column_widget(self, column):
555
609
  'Return the widget of the column'
556
610
  idx = [c for c in self.treeview.get_columns()
@@ -1048,11 +1102,12 @@ class ViewTree(View):
1048
1102
  if last_col and last_col.name in fields:
1049
1103
  del fields[last_col.name]
1050
1104
 
1105
+ screen_width, _ = get_monitor_size()
1051
1106
  if fields and any(fields.values()):
1052
1107
  model_name = self.screen.model_name
1053
1108
  try:
1054
1109
  RPCExecute('model', 'ir.ui.view_tree_width', 'set_width',
1055
- model_name, fields)
1110
+ model_name, fields, screen_width)
1056
1111
  except RPCException:
1057
1112
  pass
1058
1113
  self.screen.tree_column_width[model_name].update(fields)
@@ -1149,7 +1204,7 @@ class ViewTree(View):
1149
1204
  if (force
1150
1205
  or not self.treeview.get_model()
1151
1206
  or self.group != self.treeview.get_model().group):
1152
- model = AdaptModelGroup(self.group, self.children_field)
1207
+ model = ModelGroup(self.group, self.children_field)
1153
1208
  self.treeview.set_model(model)
1154
1209
  # __select_changed resets current_record to None
1155
1210
  self.record = current_record
@@ -29,7 +29,7 @@ class TreeView(Gtk.TreeView):
29
29
  display_counter = 0
30
30
 
31
31
  def __init__(self, view):
32
- super(TreeView, self).__init__()
32
+ super().__init__()
33
33
  self.view = view
34
34
 
35
35
  def next_column(
@@ -153,7 +153,7 @@ class EditableTreeView(TreeView):
153
153
  if cell:
154
154
  self.set_cursor_on_cell(path, focus_column, cell, start_editing)
155
155
  else:
156
- super(EditableTreeView, self).set_cursor(
156
+ super().set_cursor(
157
157
  path, focus_column, start_editing)
158
158
 
159
159
  def set_value(self):