tryton 7.0.7__py3-none-any.whl → 7.4.4__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.
- tryton/__init__.py +1 -1
- tryton/cache.py +34 -0
- tryton/common/common.py +149 -73
- tryton/common/completion.py +2 -2
- tryton/common/datetime_.py +3 -1
- tryton/common/domain_inversion.py +2 -1
- tryton/common/domain_parser.py +22 -11
- tryton/common/popup_menu.py +1 -1
- tryton/common/selection.py +6 -3
- tryton/common/tempfile.py +34 -0
- tryton/config.py +4 -5
- tryton/data/locale/bg/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/bg/LC_MESSAGES/tryton.po +69 -20
- tryton/data/locale/ca/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/ca/LC_MESSAGES/tryton.po +70 -25
- tryton/data/locale/cs/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/cs/LC_MESSAGES/tryton.po +68 -21
- tryton/data/locale/de/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/de/LC_MESSAGES/tryton.po +71 -26
- tryton/data/locale/es/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/es/LC_MESSAGES/tryton.po +68 -23
- tryton/data/locale/es_419/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/es_419/LC_MESSAGES/tryton.po +72 -22
- tryton/data/locale/et/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/et/LC_MESSAGES/tryton.po +73 -23
- tryton/data/locale/fa/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/fa/LC_MESSAGES/tryton.po +74 -25
- tryton/data/locale/fi/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/fi/LC_MESSAGES/tryton.po +63 -20
- tryton/data/locale/fr/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/fr/LC_MESSAGES/tryton.po +73 -28
- tryton/data/locale/hu/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/hu/LC_MESSAGES/tryton.po +75 -23
- tryton/data/locale/id/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/id/LC_MESSAGES/tryton.po +72 -23
- tryton/data/locale/it/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/it/LC_MESSAGES/tryton.po +73 -24
- tryton/data/locale/ja_JP/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/lo/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/lo/LC_MESSAGES/tryton.po +74 -25
- tryton/data/locale/lt/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/lt/LC_MESSAGES/tryton.po +73 -23
- tryton/data/locale/nl/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/nl/LC_MESSAGES/tryton.po +72 -27
- tryton/data/locale/pl/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/pl/LC_MESSAGES/tryton.po +113 -78
- tryton/data/locale/pt/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/pt/LC_MESSAGES/tryton.po +73 -24
- tryton/data/locale/ro/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/ro/LC_MESSAGES/tryton.po +87 -36
- tryton/data/locale/ru/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/ru/LC_MESSAGES/tryton.po +72 -25
- tryton/data/locale/sl/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/sl/LC_MESSAGES/tryton.po +77 -26
- tryton/data/locale/tr/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/tr/LC_MESSAGES/tryton.po +64 -20
- tryton/data/locale/uk/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/uk/LC_MESSAGES/tryton.po +75 -23
- tryton/data/locale/zh_CN/LC_MESSAGES/tryton.mo +0 -0
- tryton/data/locale/zh_CN/LC_MESSAGES/tryton.po +76 -24
- tryton/device_cookie.py +1 -1
- tryton/gui/main.py +14 -12
- tryton/gui/window/about.py +1 -1
- tryton/gui/window/dblogin.py +2 -2
- tryton/gui/window/email_.py +2 -2
- tryton/gui/window/form.py +10 -5
- tryton/gui/window/log.py +24 -2
- tryton/gui/window/tabcontent.py +2 -2
- tryton/gui/window/view_form/model/field.py +84 -34
- tryton/gui/window/view_form/model/group.py +7 -2
- tryton/gui/window/view_form/model/record.py +70 -31
- tryton/gui/window/view_form/screen/screen.py +98 -47
- tryton/gui/window/view_form/view/calendar_gtk/calendar_.py +15 -9
- tryton/gui/window/view_form/view/form.py +6 -12
- tryton/gui/window/view_form/view/form_gtk/char.py +5 -6
- tryton/gui/window/view_form/view/form_gtk/dictionary.py +49 -29
- tryton/gui/window/view_form/view/form_gtk/document.py +15 -10
- tryton/gui/window/view_form/view/form_gtk/many2many.py +49 -7
- tryton/gui/window/view_form/view/form_gtk/many2one.py +21 -13
- tryton/gui/window/view_form/view/form_gtk/multiselection.py +15 -5
- tryton/gui/window/view_form/view/form_gtk/one2many.py +42 -10
- tryton/gui/window/view_form/view/form_gtk/state_widget.py +6 -2
- tryton/gui/window/view_form/view/form_gtk/url.py +8 -4
- tryton/gui/window/view_form/view/graph_gtk/graph.py +3 -1
- tryton/gui/window/view_form/view/list.py +116 -48
- tryton/gui/window/view_form/view/list_gtk/editabletree.py +2 -1
- tryton/gui/window/view_form/view/list_gtk/widget.py +58 -23
- tryton/gui/window/view_form/view/screen_container.py +3 -5
- tryton/gui/window/win_csv.py +6 -12
- tryton/gui/window/win_export.py +49 -26
- tryton/gui/window/win_form.py +9 -7
- tryton/gui/window/win_import.py +45 -15
- tryton/gui/window/wizard.py +13 -10
- tryton/jsonrpc.py +75 -34
- tryton/plugins/__init__.py +5 -3
- tryton/pyson.py +57 -6
- tryton/rpc.py +18 -0
- tryton/tests/test_common_domain_parser.py +31 -2
- tryton/translate.py +5 -2
- {tryton-7.0.7.data → tryton-7.4.4.data}/scripts/tryton +8 -7
- {tryton-7.0.7.dist-info → tryton-7.4.4.dist-info}/METADATA +6 -6
- {tryton-7.0.7.dist-info → tryton-7.4.4.dist-info}/RECORD +105 -103
- {tryton-7.0.7.dist-info → tryton-7.4.4.dist-info}/WHEEL +1 -1
- {tryton-7.0.7.dist-info → tryton-7.4.4.dist-info}/LICENSE +0 -0
- {tryton-7.0.7.dist-info → tryton-7.4.4.dist-info}/top_level.txt +0 -0
|
@@ -75,7 +75,8 @@ class Screen:
|
|
|
75
75
|
self.__current_record = None
|
|
76
76
|
self.new_group(context or {})
|
|
77
77
|
self.current_record = None
|
|
78
|
-
self.screen_container = ScreenContainer(
|
|
78
|
+
self.screen_container = ScreenContainer(
|
|
79
|
+
self, attributes.get('tab_domain'))
|
|
79
80
|
self.screen_container.alternate_view = attributes.get(
|
|
80
81
|
'alternate_view', False)
|
|
81
82
|
self.widget = self.screen_container.widget_get()
|
|
@@ -116,11 +117,10 @@ class Screen:
|
|
|
116
117
|
return child
|
|
117
118
|
|
|
118
119
|
# Remove first level Viewport and ScrolledWindow to fill the Vbox
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
]
|
|
123
|
-
remove_bin(widget)
|
|
120
|
+
remove_bin(self.context_screen.screen_container.viewport)
|
|
121
|
+
if self.context_screen.current_view:
|
|
122
|
+
remove_bin(
|
|
123
|
+
self.context_screen.current_view.widget.get_children()[0])
|
|
124
124
|
|
|
125
125
|
self.screen_container.filter_vbox.pack_start(
|
|
126
126
|
context_widget, expand=False, fill=True, padding=0)
|
|
@@ -164,7 +164,6 @@ class Screen:
|
|
|
164
164
|
|
|
165
165
|
def search_active(self, active=True):
|
|
166
166
|
if active and not self.parent:
|
|
167
|
-
self.screen_container.set_screen(self)
|
|
168
167
|
self.screen_container.show_filter()
|
|
169
168
|
else:
|
|
170
169
|
self.screen_container.hide_filter()
|
|
@@ -308,7 +307,8 @@ class Screen:
|
|
|
308
307
|
try:
|
|
309
308
|
self.search_count = RPCExecute(
|
|
310
309
|
'model', self.model_name, 'search_count',
|
|
311
|
-
domain, 0, self.count_limit, context=context
|
|
310
|
+
domain, 0, self.count_limit, context=context,
|
|
311
|
+
process_exception=False)
|
|
312
312
|
except RPCException:
|
|
313
313
|
self.search_count = 0
|
|
314
314
|
else:
|
|
@@ -323,6 +323,7 @@ class Screen:
|
|
|
323
323
|
if only_ids:
|
|
324
324
|
return ids
|
|
325
325
|
self.clear()
|
|
326
|
+
GLib.idle_add(self.screen_container.search_entry.grab_focus)
|
|
326
327
|
self.load(ids)
|
|
327
328
|
self.count_tab_domain()
|
|
328
329
|
return bool(ids)
|
|
@@ -520,7 +521,8 @@ class Screen:
|
|
|
520
521
|
self.group.destroy()
|
|
521
522
|
|
|
522
523
|
def default_row_activate(self):
|
|
523
|
-
if (self.current_view
|
|
524
|
+
if (self.current_view
|
|
525
|
+
and self.current_view.view_type == 'tree'
|
|
524
526
|
and int(self.current_view.attributes.get('keyword_open', 0))):
|
|
525
527
|
return Action.exec_keyword('tree_open', {
|
|
526
528
|
'model': self.model_name,
|
|
@@ -536,6 +538,19 @@ class Screen:
|
|
|
536
538
|
def number_of_views(self):
|
|
537
539
|
return len(self.views) + len(self.view_to_load)
|
|
538
540
|
|
|
541
|
+
@property
|
|
542
|
+
def view_index(self):
|
|
543
|
+
return self.__current_view
|
|
544
|
+
|
|
545
|
+
@property
|
|
546
|
+
def next_view_type(self):
|
|
547
|
+
views = self.views + self.view_to_load
|
|
548
|
+
next_view_index = (self.view_index + 1) % len(views)
|
|
549
|
+
next_view = views[next_view_index]
|
|
550
|
+
if next_view and not isinstance(next_view, str):
|
|
551
|
+
next_view = next_view.view_type
|
|
552
|
+
return next_view
|
|
553
|
+
|
|
539
554
|
def switch_view(
|
|
540
555
|
self, view_type=None, view_id=None, creatable=None, display=True):
|
|
541
556
|
if view_id is not None:
|
|
@@ -642,7 +657,7 @@ class Screen:
|
|
|
642
657
|
|
|
643
658
|
def new(self, default=True, defaults=None):
|
|
644
659
|
previous_view = self.current_view
|
|
645
|
-
if self.current_view.view_type == 'calendar':
|
|
660
|
+
if self.current_view and self.current_view.view_type == 'calendar':
|
|
646
661
|
selected_date = self.current_view.get_selected_date()
|
|
647
662
|
if self.current_view and not self.current_view.creatable:
|
|
648
663
|
self.switch_view(creatable=True)
|
|
@@ -695,16 +710,19 @@ class Screen:
|
|
|
695
710
|
|
|
696
711
|
def save_current(self):
|
|
697
712
|
if not self.current_record:
|
|
698
|
-
if self.current_view
|
|
713
|
+
if (self.current_view
|
|
714
|
+
and self.current_view.view_type == 'tree'
|
|
715
|
+
and len(self.group)):
|
|
699
716
|
self.current_record = self.group[0]
|
|
700
717
|
else:
|
|
701
718
|
return True
|
|
702
|
-
self.current_view.set_value()
|
|
703
719
|
saved = False
|
|
704
720
|
record_id = None
|
|
705
|
-
|
|
721
|
+
if self.current_view:
|
|
722
|
+
self.current_view.set_value()
|
|
723
|
+
fields = self.current_view.get_fields()
|
|
706
724
|
path = self.current_record.get_path(self.group)
|
|
707
|
-
if self.current_view.view_type == 'tree':
|
|
725
|
+
if self.current_view and self.current_view.view_type == 'tree':
|
|
708
726
|
# False value must be not saved
|
|
709
727
|
saved = all((
|
|
710
728
|
x is not False and x >= 0
|
|
@@ -714,7 +732,7 @@ class Screen:
|
|
|
714
732
|
record_id = self.current_record.save(force_reload=True)
|
|
715
733
|
# False value must be not saved
|
|
716
734
|
saved = record_id is not False and record_id >= 0
|
|
717
|
-
|
|
735
|
+
elif self.current_view:
|
|
718
736
|
self.set_cursor()
|
|
719
737
|
self.current_view.display()
|
|
720
738
|
return False
|
|
@@ -742,17 +760,19 @@ class Screen:
|
|
|
742
760
|
def get(self):
|
|
743
761
|
if not self.current_record:
|
|
744
762
|
return None
|
|
745
|
-
self.current_view
|
|
763
|
+
if self.current_view:
|
|
764
|
+
self.current_view.set_value()
|
|
746
765
|
return self.current_record.get()
|
|
747
766
|
|
|
748
767
|
def get_on_change_value(self):
|
|
749
768
|
if not self.current_record:
|
|
750
769
|
return None
|
|
751
|
-
self.current_view
|
|
770
|
+
if self.current_view:
|
|
771
|
+
self.current_view.set_value()
|
|
752
772
|
return self.current_record.get_on_change_value()
|
|
753
773
|
|
|
754
774
|
def modified(self):
|
|
755
|
-
if self.current_view.view_type != 'tree':
|
|
775
|
+
if self.current_view and self.current_view.view_type != 'tree':
|
|
756
776
|
if self.current_record:
|
|
757
777
|
if self.current_record.modified or self.current_record.id < 0:
|
|
758
778
|
return True
|
|
@@ -760,7 +780,7 @@ class Screen:
|
|
|
760
780
|
for record in self.group:
|
|
761
781
|
if record.modified or record.id < 0:
|
|
762
782
|
return True
|
|
763
|
-
if self.current_view.modified:
|
|
783
|
+
if self.current_view and self.current_view.modified:
|
|
764
784
|
return True
|
|
765
785
|
return False
|
|
766
786
|
|
|
@@ -782,6 +802,7 @@ class Screen:
|
|
|
782
802
|
records = records or self.selected_records
|
|
783
803
|
if not records:
|
|
784
804
|
return
|
|
805
|
+
current_record = self.current_record
|
|
785
806
|
if delete:
|
|
786
807
|
# Must delete children records before parent
|
|
787
808
|
records.sort(key=lambda r: r.depth, reverse=True)
|
|
@@ -795,6 +816,9 @@ class Screen:
|
|
|
795
816
|
record.group.remove(
|
|
796
817
|
record, remove=remove, modified=False,
|
|
797
818
|
force_remove=force_remove)
|
|
819
|
+
# set current_record to None to prevent __select_changed
|
|
820
|
+
# to set deleted record as current_record
|
|
821
|
+
self.current_record = None
|
|
798
822
|
# call only once
|
|
799
823
|
record.set_modified()
|
|
800
824
|
|
|
@@ -809,7 +833,10 @@ class Screen:
|
|
|
809
833
|
record.parent.save(force_reload=False)
|
|
810
834
|
record.destroy()
|
|
811
835
|
|
|
812
|
-
|
|
836
|
+
if current_record and not current_record.destroyed:
|
|
837
|
+
self.current_record = current_record
|
|
838
|
+
else:
|
|
839
|
+
self.current_record = None
|
|
813
840
|
self.set_cursor()
|
|
814
841
|
self.display()
|
|
815
842
|
return True
|
|
@@ -821,11 +848,16 @@ class Screen:
|
|
|
821
848
|
context=self.context)
|
|
822
849
|
except RPCException:
|
|
823
850
|
return False
|
|
824
|
-
self.load(new_ids, position=self.new_position)
|
|
851
|
+
self.group.load(new_ids, position=self.new_position)
|
|
852
|
+
if new_ids:
|
|
853
|
+
self.current_record = self.group.get(new_ids[0])
|
|
854
|
+
self.display(set_cursor=True)
|
|
825
855
|
return True
|
|
826
856
|
|
|
827
857
|
def set_tree_state(self):
|
|
828
858
|
view = self.current_view
|
|
859
|
+
if not view:
|
|
860
|
+
return
|
|
829
861
|
if view.view_type not in {'tree', 'form', 'list-form'}:
|
|
830
862
|
return
|
|
831
863
|
if id(view) in self.tree_states_done:
|
|
@@ -920,7 +952,7 @@ class Screen:
|
|
|
920
952
|
json_paths, json_selected_path,
|
|
921
953
|
process_exception=False)
|
|
922
954
|
clear_cache('model.ir.ui.view_tree_state.get')
|
|
923
|
-
except
|
|
955
|
+
except RPCException:
|
|
924
956
|
logger.warn(
|
|
925
957
|
_('Unable to set view tree state'), exc_info=True)
|
|
926
958
|
|
|
@@ -935,12 +967,13 @@ class Screen:
|
|
|
935
967
|
|
|
936
968
|
def load(self, ids, set_cursor=True, modified=False, position=-1):
|
|
937
969
|
self.group.load(ids, modified=modified, position=position)
|
|
938
|
-
self.current_view
|
|
970
|
+
if self.current_view:
|
|
971
|
+
self.current_view.reset()
|
|
939
972
|
self.current_record = None
|
|
940
973
|
self.display(set_cursor=set_cursor)
|
|
941
974
|
|
|
942
975
|
def display(self, set_cursor=False):
|
|
943
|
-
if self.views:
|
|
976
|
+
if self.views and self.current_view:
|
|
944
977
|
self.search_active(self.current_view.view_type
|
|
945
978
|
in ('tree', 'graph', 'calendar'))
|
|
946
979
|
for view in self.views:
|
|
@@ -972,7 +1005,8 @@ class Screen:
|
|
|
972
1005
|
|
|
973
1006
|
def _get_next_record(self, test=False):
|
|
974
1007
|
view = self.current_view
|
|
975
|
-
if (view
|
|
1008
|
+
if (view
|
|
1009
|
+
and view.view_type in {'tree', 'form'}
|
|
976
1010
|
and self.current_record
|
|
977
1011
|
and self.current_record.group):
|
|
978
1012
|
group = self.current_record.group
|
|
@@ -1000,12 +1034,14 @@ class Screen:
|
|
|
1000
1034
|
record = next
|
|
1001
1035
|
break
|
|
1002
1036
|
return record
|
|
1003
|
-
elif (view
|
|
1037
|
+
elif (view
|
|
1038
|
+
and view.view_type == 'list-form'
|
|
1039
|
+
and len(self.group)
|
|
1004
1040
|
and self.current_record in self.group):
|
|
1005
1041
|
idx = self.group.index(self.current_record)
|
|
1006
1042
|
if 0 <= idx < len(self.group) - 1:
|
|
1007
1043
|
return self.group[idx + 1]
|
|
1008
|
-
elif view.view_type == 'calendar':
|
|
1044
|
+
elif view and view.view_type == 'calendar':
|
|
1009
1045
|
record = self.current_record
|
|
1010
1046
|
goocalendar = view.widgets.get('goocalendar')
|
|
1011
1047
|
if goocalendar:
|
|
@@ -1039,15 +1075,18 @@ class Screen:
|
|
|
1039
1075
|
|
|
1040
1076
|
def display_next(self):
|
|
1041
1077
|
view = self.current_view
|
|
1042
|
-
view
|
|
1078
|
+
if view:
|
|
1079
|
+
view.set_value()
|
|
1043
1080
|
self.set_cursor(reset_view=False)
|
|
1044
1081
|
self.current_record = self._get_next_record()
|
|
1045
1082
|
self.set_cursor(reset_view=False)
|
|
1046
|
-
view
|
|
1083
|
+
if view:
|
|
1084
|
+
view.display()
|
|
1047
1085
|
|
|
1048
1086
|
def _get_prev_record(self, test=False):
|
|
1049
1087
|
view = self.current_view
|
|
1050
|
-
if (view
|
|
1088
|
+
if (view
|
|
1089
|
+
and view.view_type in {'tree', 'form'}
|
|
1051
1090
|
and self.current_record
|
|
1052
1091
|
and self.current_record.group):
|
|
1053
1092
|
group = self.current_record.group
|
|
@@ -1065,7 +1104,7 @@ class Screen:
|
|
|
1065
1104
|
if parent and record.model_name == parent.model_name:
|
|
1066
1105
|
record = parent
|
|
1067
1106
|
return record
|
|
1068
|
-
elif view.view_type == 'calendar':
|
|
1107
|
+
elif view and view.view_type == 'calendar':
|
|
1069
1108
|
record = self.current_record
|
|
1070
1109
|
goocalendar = view.widgets.get('goocalendar')
|
|
1071
1110
|
if goocalendar:
|
|
@@ -1090,7 +1129,9 @@ class Screen:
|
|
|
1090
1129
|
if prev_id >= 0:
|
|
1091
1130
|
return events[prev_id].record
|
|
1092
1131
|
break
|
|
1093
|
-
elif (view
|
|
1132
|
+
elif (view
|
|
1133
|
+
and view.view_type == 'list-form'
|
|
1134
|
+
and len(self.group)
|
|
1094
1135
|
and self.current_record in self.group):
|
|
1095
1136
|
idx = self.group.index(self.current_record)
|
|
1096
1137
|
if 0 < idx <= len(self.group) - 1:
|
|
@@ -1104,11 +1145,13 @@ class Screen:
|
|
|
1104
1145
|
|
|
1105
1146
|
def display_prev(self):
|
|
1106
1147
|
view = self.current_view
|
|
1107
|
-
view
|
|
1148
|
+
if view:
|
|
1149
|
+
view.set_value()
|
|
1108
1150
|
self.set_cursor(reset_view=False)
|
|
1109
1151
|
self.current_record = self._get_prev_record()
|
|
1110
1152
|
self.set_cursor(reset_view=False)
|
|
1111
|
-
view
|
|
1153
|
+
if view:
|
|
1154
|
+
view.display()
|
|
1112
1155
|
|
|
1113
1156
|
def invalid_message(self, record=None):
|
|
1114
1157
|
if record is None:
|
|
@@ -1142,6 +1185,8 @@ class Screen:
|
|
|
1142
1185
|
def selected_paths(self):
|
|
1143
1186
|
if self.current_view and self.current_view.view_type == 'tree':
|
|
1144
1187
|
return self.current_view.get_selected_paths()
|
|
1188
|
+
else:
|
|
1189
|
+
return []
|
|
1145
1190
|
|
|
1146
1191
|
@property
|
|
1147
1192
|
def listed_records(self):
|
|
@@ -1181,7 +1226,7 @@ class Screen:
|
|
|
1181
1226
|
if not self.selected_records:
|
|
1182
1227
|
return []
|
|
1183
1228
|
|
|
1184
|
-
buttons = self.current_view.get_buttons()
|
|
1229
|
+
buttons = self.current_view.get_buttons() if self.current_view else []
|
|
1185
1230
|
|
|
1186
1231
|
for record in self.selected_records:
|
|
1187
1232
|
buttons = [b for b in buttons if is_active(record, b)]
|
|
@@ -1191,8 +1236,9 @@ class Screen:
|
|
|
1191
1236
|
|
|
1192
1237
|
def button(self, button):
|
|
1193
1238
|
'Execute button on the selected records'
|
|
1194
|
-
self.current_view
|
|
1195
|
-
|
|
1239
|
+
if self.current_view:
|
|
1240
|
+
self.current_view.set_value()
|
|
1241
|
+
fields = self.current_view.get_fields()
|
|
1196
1242
|
for record in self.selected_records:
|
|
1197
1243
|
domain = record.expr_eval(
|
|
1198
1244
|
button.get('states', {})).get('pre_validate', [])
|
|
@@ -1206,9 +1252,9 @@ class Screen:
|
|
|
1206
1252
|
if button.get('confirm', False) and not sur(button['confirm']):
|
|
1207
1253
|
return
|
|
1208
1254
|
if button.get('type', 'class') == 'class':
|
|
1209
|
-
|
|
1255
|
+
record_id = self.current_record.save(force_reload=False)
|
|
1256
|
+
if record_id is False or record_id < 0:
|
|
1210
1257
|
return
|
|
1211
|
-
if button.get('type', 'class') == 'class':
|
|
1212
1258
|
self._button_class(button)
|
|
1213
1259
|
else:
|
|
1214
1260
|
self._button_instance(button)
|
|
@@ -1217,6 +1263,7 @@ class Screen:
|
|
|
1217
1263
|
record = self.current_record
|
|
1218
1264
|
args = record.expr_eval(button.get('change', []))
|
|
1219
1265
|
values = record._get_on_change_args(args)
|
|
1266
|
+
values['id'] = record.id
|
|
1220
1267
|
try:
|
|
1221
1268
|
changes = RPCExecute('model', self.model_name, button['name'],
|
|
1222
1269
|
values, context=self.context)
|
|
@@ -1237,6 +1284,7 @@ class Screen:
|
|
|
1237
1284
|
except RPCException:
|
|
1238
1285
|
action = None
|
|
1239
1286
|
self.reload(ids, written=True)
|
|
1287
|
+
self.record_saved()
|
|
1240
1288
|
if isinstance(action, str):
|
|
1241
1289
|
self.client_action(action)
|
|
1242
1290
|
elif action:
|
|
@@ -1273,7 +1321,9 @@ class Screen:
|
|
|
1273
1321
|
elif action.startswith('switch'):
|
|
1274
1322
|
self.switch_view(*action.split(None, 2)[1:])
|
|
1275
1323
|
elif action == 'reload':
|
|
1276
|
-
if (self.current_view
|
|
1324
|
+
if (self.current_view
|
|
1325
|
+
and self.current_view.view_type in [
|
|
1326
|
+
'tree', 'graph', 'calendar']
|
|
1277
1327
|
and not self.parent):
|
|
1278
1328
|
self.search_filter()
|
|
1279
1329
|
elif action == 'reload menu':
|
|
@@ -1297,13 +1347,13 @@ class Screen:
|
|
|
1297
1347
|
if name:
|
|
1298
1348
|
query_string.append(
|
|
1299
1349
|
('name', json.dumps(name, separators=(',', ':'))))
|
|
1300
|
-
if self.screen_container.tab_domain:
|
|
1301
|
-
query_string.append(('tab_domain', json.dumps(
|
|
1302
|
-
self.screen_container.tab_domain,
|
|
1303
|
-
cls=JSONEncoder, separators=(',', ':'))))
|
|
1304
1350
|
path = [CONFIG['login.db'], 'model', self.model_name]
|
|
1305
1351
|
view_ids = [v.view_id for v in self.views] + self.view_ids
|
|
1306
|
-
if self.current_view.view_type != 'form':
|
|
1352
|
+
if self.current_view and self.current_view.view_type != 'form':
|
|
1353
|
+
if self.screen_container.tab_domain:
|
|
1354
|
+
query_string.append(('tab_domain', json.dumps(
|
|
1355
|
+
self.screen_container.tab_domain,
|
|
1356
|
+
cls=JSONEncoder, separators=(',', ':'))))
|
|
1307
1357
|
if self.search_value:
|
|
1308
1358
|
search_value = self.search_value
|
|
1309
1359
|
else:
|
|
@@ -1315,8 +1365,9 @@ class Screen:
|
|
|
1315
1365
|
separators=(',', ':'))))
|
|
1316
1366
|
elif self.current_record and self.current_record.id > -1:
|
|
1317
1367
|
path.append(str(self.current_record.id))
|
|
1318
|
-
|
|
1319
|
-
|
|
1368
|
+
if self.current_view:
|
|
1369
|
+
i = view_ids.index(self.current_view.view_id)
|
|
1370
|
+
view_ids = view_ids[i:] + view_ids[:i]
|
|
1320
1371
|
if view_ids:
|
|
1321
1372
|
query_string.append(('views', json.dumps(
|
|
1322
1373
|
view_ids, separators=(',', ':'))))
|
|
@@ -63,17 +63,23 @@ class Calendar_(goocalendar.Calendar):
|
|
|
63
63
|
return False
|
|
64
64
|
|
|
65
65
|
def current_domain(self):
|
|
66
|
-
|
|
67
|
-
self.current_domain_period.get_dates(True)
|
|
66
|
+
start, end = self.current_domain_period.get_dates(True)
|
|
68
67
|
dtstart = self.attrs['dtstart']
|
|
69
68
|
dtend = self.attrs.get('dtend') or dtstart
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
fields = self.view_calendar.screen.group.fields
|
|
70
|
+
if fields[dtstart].attrs['type'] == 'date':
|
|
71
|
+
start = start.date()
|
|
72
|
+
if fields[dtend].attrs['type'] == 'date':
|
|
73
|
+
end = end.date()
|
|
74
|
+
domain = [
|
|
75
|
+
(dtstart, '!=', None),
|
|
76
|
+
(dtend, '!=', None),
|
|
77
|
+
['OR',
|
|
78
|
+
['AND', (dtstart, '>=', start), (dtstart, '<', end)],
|
|
79
|
+
['AND', (dtend, '>=', start), (dtend, '<', end)],
|
|
80
|
+
['AND', (dtstart, '<', start), (dtend, '>', end)],
|
|
81
|
+
],
|
|
82
|
+
]
|
|
77
83
|
return domain
|
|
78
84
|
|
|
79
85
|
def get_colors(self, record):
|
|
@@ -230,6 +230,9 @@ class FormXMLViewParser(XMLViewParser):
|
|
|
230
230
|
self.container.add(None, attributes)
|
|
231
231
|
return
|
|
232
232
|
|
|
233
|
+
if int(attributes.get('visible', 0)):
|
|
234
|
+
self.field_attrs[name]['visible'] = True
|
|
235
|
+
|
|
233
236
|
widget = self.WIDGETS[attributes['widget']](self.view, attributes)
|
|
234
237
|
self.view.widgets[name].append(widget)
|
|
235
238
|
|
|
@@ -340,18 +343,7 @@ class FormXMLViewParser(XMLViewParser):
|
|
|
340
343
|
int(attributes.get('width', -1)),
|
|
341
344
|
int(attributes.get('height', -1)))
|
|
342
345
|
|
|
343
|
-
# Force to display the first time it switches on a page
|
|
344
|
-
# This avoids glitch in position of widgets
|
|
345
|
-
def switch(notebook, page, page_num):
|
|
346
|
-
if not self.view.widget:
|
|
347
|
-
# Not yet finish to parse
|
|
348
|
-
return
|
|
349
|
-
notebook.grab_focus()
|
|
350
|
-
self.view.display()
|
|
351
|
-
notebook.disconnect(handler_id)
|
|
352
|
-
handler_id = notebook.connect('switch-page', switch)
|
|
353
346
|
self.view.state_widgets.append(notebook)
|
|
354
|
-
|
|
355
347
|
self.view.notebooks.append(notebook)
|
|
356
348
|
self.container.add(notebook, attributes)
|
|
357
349
|
self.parse_child(node, notebook)
|
|
@@ -390,7 +382,6 @@ class FormXMLViewParser(XMLViewParser):
|
|
|
390
382
|
group = Container.constructor(
|
|
391
383
|
int(attributes.get('col', 4)),
|
|
392
384
|
attributes.get('homogeneous', False))
|
|
393
|
-
self.parse_child(node, group)
|
|
394
385
|
|
|
395
386
|
if 'name' in attributes and attributes['name'] == self.exclude_field:
|
|
396
387
|
self.container.add(None, attributes)
|
|
@@ -414,6 +405,9 @@ class FormXMLViewParser(XMLViewParser):
|
|
|
414
405
|
bool(attributes.get('yexpand'))))
|
|
415
406
|
self.view.state_widgets.append(widget)
|
|
416
407
|
self.container.add(widget, attributes)
|
|
408
|
+
# Parse the children at the end to preserve the order of the state
|
|
409
|
+
# widgets
|
|
410
|
+
self.parse_child(node, group)
|
|
417
411
|
|
|
418
412
|
def _parse_hpaned(self, node, attributes):
|
|
419
413
|
self._parse_paned(node, attributes, Gtk.HPaned)
|
|
@@ -171,10 +171,9 @@ class Password(Char):
|
|
|
171
171
|
self.widget.pack_start(
|
|
172
172
|
self.visibility_checkbox, expand=False, fill=True, padding=0)
|
|
173
173
|
|
|
174
|
-
def _readonly_set(self, value):
|
|
175
|
-
super(Char, self)._readonly_set(value)
|
|
176
|
-
self.entry.set_editable(not value)
|
|
177
|
-
self.visibility_checkbox.props.visible = not value
|
|
178
|
-
|
|
179
174
|
def toggle_visibility(self, button):
|
|
180
|
-
|
|
175
|
+
if self.autocomplete:
|
|
176
|
+
entry = self.entry.get_child()
|
|
177
|
+
else:
|
|
178
|
+
entry = self.entry
|
|
179
|
+
entry.props.visibility = not self.entry.props.visibility
|