tksheet 7.1.21__py3-none-any.whl → 7.1.22__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.
tksheet/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
  tksheet - A Python tkinter table widget
5
5
  """
6
6
 
7
- __version__ = "7.1.21"
7
+ __version__ = "7.1.22"
8
8
 
9
9
  from .colors import (
10
10
  color_map,
@@ -32,6 +32,7 @@ from .formatters import (
32
32
  try_to_bool,
33
33
  )
34
34
  from .functions import (
35
+ add_highlight,
35
36
  alpha2idx,
36
37
  alpha2num,
37
38
  consecutive_chunks,
@@ -42,6 +43,7 @@ from .functions import (
42
43
  event_dict,
43
44
  get_checkbox_dict,
44
45
  get_checkbox_kwargs,
46
+ get_csv_str_dialect,
45
47
  get_data_from_clipboard,
46
48
  get_dropdown_dict,
47
49
  get_dropdown_kwargs,
@@ -54,6 +56,7 @@ from .functions import (
54
56
  is_iterable,
55
57
  move_elements_by_mapping,
56
58
  move_elements_to,
59
+ new_tk_event,
57
60
  num2alpha,
58
61
  rounded_box_coords,
59
62
  span_dict,
@@ -66,6 +69,7 @@ from .other_classes import (
66
69
  DrawnItem,
67
70
  EventDataDict,
68
71
  GeneratedMouseEvent,
72
+ Highlight,
69
73
  Selected,
70
74
  Span,
71
75
  SpanRange,
tksheet/column_headers.py CHANGED
@@ -25,6 +25,7 @@ from .functions import (
25
25
  event_dict,
26
26
  get_n2a,
27
27
  is_contiguous,
28
+ new_tk_event,
28
29
  pickled_event_dict,
29
30
  rounded_box_coords,
30
31
  try_binding,
@@ -42,6 +43,8 @@ from .vars import (
42
43
  USER_OS,
43
44
  rc_binding,
44
45
  symbols_set,
46
+ text_editor_close_bindings,
47
+ text_editor_newline_bindings,
45
48
  text_editor_to_unbind,
46
49
  )
47
50
 
@@ -124,6 +127,13 @@ class ColumnHeaders(tk.Canvas):
124
127
  self.align = kwargs["header_align"]
125
128
  self.basic_bindings()
126
129
 
130
+ def event_generate(self, *args, **kwargs) -> None:
131
+ for arg in args:
132
+ if self.MT and arg in self.MT.event_linker:
133
+ self.MT.event_linker[arg]()
134
+ else:
135
+ super().event_generate(*args, **kwargs)
136
+
127
137
  def basic_bindings(self, enable: bool = True):
128
138
  if enable:
129
139
  self.bind("<Motion>", self.mouse_motion)
@@ -833,6 +843,7 @@ class ColumnHeaders(tk.Canvas):
833
843
  event_data = event_dict(
834
844
  name="move_columns",
835
845
  sheet=self.PAR.name,
846
+ widget=self,
836
847
  boxes=self.MT.get_boxes(),
837
848
  selected=self.MT.selected,
838
849
  value=c,
@@ -844,6 +855,7 @@ class ColumnHeaders(tk.Canvas):
844
855
  to_move=self.dragged_col.to_move,
845
856
  ),
846
857
  move_data=self.PAR.ops.column_drag_and_drop_perform,
858
+ move_widths=self.PAR.ops.column_drag_and_drop_perform,
847
859
  event_data=event_data,
848
860
  )
849
861
  event_data["moved"]["columns"] = {
@@ -1730,21 +1742,16 @@ class ColumnHeaders(tk.Canvas):
1730
1742
  self.itemconfig(self.text_editor.canvas_id, state="normal")
1731
1743
  self.text_editor.open = True
1732
1744
  self.coords(self.text_editor.canvas_id, x, y)
1745
+ for b in text_editor_newline_bindings:
1746
+ self.text_editor.tktext.bind(b, self.text_editor_newline_binding)
1747
+ for b in text_editor_close_bindings:
1748
+ self.text_editor.tktext.bind(b, self.close_text_editor)
1733
1749
  if not dropdown:
1734
1750
  self.text_editor.tktext.focus_set()
1735
1751
  self.text_editor.window.scroll_to_bottom()
1736
- self.text_editor.tktext.bind("<Alt-Return>", lambda _x: self.text_editor_newline_binding(c=c))
1737
- self.text_editor.tktext.bind("<Alt-KP_Enter>", lambda _x: self.text_editor_newline_binding(c=c))
1738
- if USER_OS == "darwin":
1739
- self.text_editor.tktext.bind("<Option-Return>", lambda _x: self.text_editor_newline_binding(c=c))
1752
+ self.text_editor.tktext.bind("<FocusOut>", self.close_text_editor)
1740
1753
  for key, func in self.MT.text_editor_user_bound_keys.items():
1741
1754
  self.text_editor.tktext.bind(key, func)
1742
- self.text_editor.tktext.bind("<Tab>", lambda _x: self.close_text_editor((c, "Tab")))
1743
- self.text_editor.tktext.bind("<Return>", lambda _x: self.close_text_editor((c, "Return")))
1744
- self.text_editor.tktext.bind("<KP_Enter>", lambda _x: self.close_text_editor((c, "Return")))
1745
- if not dropdown:
1746
- self.text_editor.tktext.bind("<FocusOut>", lambda _x: self.close_text_editor((c, "FocusOut")))
1747
- self.text_editor.tktext.bind("<Escape>", lambda _x: self.close_text_editor((c, "Escape")))
1748
1755
  return True
1749
1756
 
1750
1757
  # displayed indexes #just here to receive text editor arg
@@ -1763,7 +1770,7 @@ class ColumnHeaders(tk.Canvas):
1763
1770
  self.coords(self.text_editor.canvas_id, self.MT.col_positions[c] + 1, 0)
1764
1771
 
1765
1772
  # displayed indexes
1766
- def text_editor_newline_binding(self, r=0, c=0, event: object = None, check_lines=True):
1773
+ def text_editor_newline_binding(self, event: object = None, check_lines=True):
1767
1774
  if not self.height_resizing_enabled:
1768
1775
  return
1769
1776
  curr_height = self.text_editor.window.winfo_height()
@@ -1777,6 +1784,7 @@ class ColumnHeaders(tk.Canvas):
1777
1784
  )
1778
1785
  > curr_height
1779
1786
  ):
1787
+ c = self.text_editor.column
1780
1788
  new_height = curr_height + self.MT.header_xtra_lines_increment
1781
1789
  space_bot = self.MT.get_space_bot(0)
1782
1790
  if new_height > space_bot:
@@ -1845,31 +1853,33 @@ class ColumnHeaders(tk.Canvas):
1845
1853
  self.focus_set()
1846
1854
 
1847
1855
  # c is displayed col
1848
- def close_text_editor(
1849
- self,
1850
- editor_info: tuple,
1851
- ):
1856
+ def close_text_editor(self, event: tk.Event) -> Literal["break"] | None:
1852
1857
  # checking if text editor should be closed or not
1853
- focused = self.focus_get()
1858
+ # errors if __tk_filedialog is open
1859
+ try:
1860
+ focused = self.focus_get()
1861
+ except Exception:
1862
+ focused = None
1854
1863
  try:
1855
1864
  if focused == self.text_editor.tktext.rc_popup_menu:
1856
1865
  return "break"
1857
1866
  except Exception:
1858
1867
  pass
1859
- if focused is None and editor_info:
1868
+ if focused is None:
1860
1869
  return "break"
1861
- if editor_info[1] == "Escape":
1870
+ if event.keysym == "Escape":
1862
1871
  self.hide_text_editor_and_dropdown()
1863
1872
  return
1864
1873
  # setting cell data with text editor value
1865
1874
  text_editor_value = self.text_editor.get()
1866
- c = editor_info[0]
1875
+ c = self.text_editor.column
1867
1876
  datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
1868
1877
  event_data = event_dict(
1869
1878
  name="end_edit_header",
1870
1879
  sheet=self.PAR.name,
1880
+ widget=self,
1871
1881
  cells_header={datacn: self.get_cell_data(datacn)},
1872
- key=editor_info[1] if len(editor_info) >= 2 else "FocusOut",
1882
+ key=event.keysym,
1873
1883
  value=text_editor_value,
1874
1884
  loc=c,
1875
1885
  column=c,
@@ -1893,7 +1903,7 @@ class ColumnHeaders(tk.Canvas):
1893
1903
  try_binding(self.extra_end_edit_cell_func, event_data)
1894
1904
  self.MT.recreate_all_selection_boxes()
1895
1905
  self.hide_text_editor_and_dropdown()
1896
- if editor_info[1] != "FocusOut":
1906
+ if event.keysym != "FocusOut":
1897
1907
  self.focus_set()
1898
1908
  return "break"
1899
1909
 
@@ -2014,6 +2024,7 @@ class ColumnHeaders(tk.Canvas):
2014
2024
  event_data = event_dict(
2015
2025
  name="end_edit_header",
2016
2026
  sheet=self.PAR.name,
2027
+ widget=self,
2017
2028
  cells_header={datacn: pre_edit_value},
2018
2029
  key="??",
2019
2030
  value=selection,
@@ -2045,7 +2056,7 @@ class ColumnHeaders(tk.Canvas):
2045
2056
  def mouseclick_outside_editor_or_dropdown(self, inside: bool = False):
2046
2057
  closed_dd_coords = self.dropdown.get_coords()
2047
2058
  if self.text_editor.open:
2048
- self.close_text_editor((self.text_editor.column, "ButtonPress-1"))
2059
+ self.close_text_editor(new_tk_event("ButtonPress-1"))
2049
2060
  if closed_dd_coords is not None:
2050
2061
  self.hide_dropdown_window()
2051
2062
  if inside:
@@ -2083,6 +2094,7 @@ class ColumnHeaders(tk.Canvas):
2083
2094
  event_data = event_dict(
2084
2095
  name="edit_header",
2085
2096
  sheet=self.PAR.name,
2097
+ widget=self,
2086
2098
  cells_header={datacn: self.get_cell_data(datacn)},
2087
2099
  boxes=self.MT.get_boxes(),
2088
2100
  selected=self.MT.selected,
@@ -2240,6 +2252,7 @@ class ColumnHeaders(tk.Canvas):
2240
2252
  event_data = event_dict(
2241
2253
  name="end_edit_header",
2242
2254
  sheet=self.PAR.name,
2255
+ widget=self,
2243
2256
  cells_header={datacn: pre_edit_value},
2244
2257
  key="??",
2245
2258
  value=value,
tksheet/functions.py CHANGED
@@ -17,6 +17,9 @@ from collections.abc import (
17
17
  from functools import partial
18
18
  from itertools import islice, repeat
19
19
 
20
+ from .formatters import (
21
+ to_bool,
22
+ )
20
23
  from .other_classes import (
21
24
  Box_nt,
22
25
  DotDict,
@@ -31,16 +34,20 @@ pickle_obj = partial(pickle.dumps, protocol=pickle.HIGHEST_PROTOCOL)
31
34
  unpickle_obj = pickle.loads
32
35
 
33
36
 
37
+ def get_csv_str_dialect(s: str, delimiters: str) -> csv.Dialect:
38
+ try:
39
+ return csv.Sniffer().sniff(s[:5000] if len(s) > 5000 else s, delimiters=delimiters)
40
+ except Exception:
41
+ return csv.excel_tab
42
+
43
+
34
44
  def get_data_from_clipboard(
35
45
  widget: tk.Misc,
36
46
  delimiters: str,
37
47
  lineterminator: str = "\n",
38
48
  ) -> list[list[str]]:
39
49
  data = widget.clipboard_get()
40
- try:
41
- dialect = csv.Sniffer().sniff(data, delimiters=delimiters)
42
- except Exception:
43
- dialect = csv.excel_tab
50
+ dialect = get_csv_str_dialect(data, delimiters=delimiters)
44
51
  if dialect.delimiter in data or lineterminator in data:
45
52
  return list(csv.reader(io.StringIO(data), dialect=dialect, skipinitialspace=True))
46
53
  return [[data]]
@@ -59,6 +66,12 @@ def tksheet_type_error(kwarg: str, valid_types: list[str], not_type: object) ->
59
66
  return f"Argument '{kwarg}' must be one of the following types: {valid_types}, " f"not {type(not_type)}."
60
67
 
61
68
 
69
+ def new_tk_event(keysym: str) -> tk.Event:
70
+ event = tk.Event()
71
+ event.keysym = keysym
72
+ return event
73
+
74
+
62
75
  def dropdown_search_function(
63
76
  search_for: object,
64
77
  data: Sequence[object],
@@ -112,6 +125,7 @@ def selection_box_tup_to_dict(box: tuple) -> dict:
112
125
  def event_dict(
113
126
  name: str = None,
114
127
  sheet: object = None,
128
+ widget: tk.Canvas | None = None,
115
129
  boxes: None | dict | tuple = None,
116
130
  cells_table: None | dict = None,
117
131
  cells_header: None | dict = None,
@@ -176,6 +190,7 @@ def event_dict(
176
190
  # "header": DotDict() if resized_header is None else resized_header,
177
191
  # "index": DotDict() if resized_index is None else resized_index,
178
192
  ),
193
+ widget=widget,
179
194
  )
180
195
 
181
196
 
@@ -184,7 +199,7 @@ def change_eventname(event_dict: EventDataDict, newname: str) -> EventDataDict:
184
199
 
185
200
 
186
201
  def pickled_event_dict(d: DotDict) -> DotDict:
187
- return DotDict(name=d["eventname"], data=pickle_compress(d))
202
+ return DotDict(name=d["eventname"], data=pickle_compress(DotDict({k: v for k, v in d.items() if k != "widget"})))
188
203
 
189
204
 
190
205
  def len_to_idx(n: int) -> int:
@@ -281,6 +296,13 @@ def is_type_int(o: object) -> bool:
281
296
  return isinstance(o, int) and not isinstance(o, bool)
282
297
 
283
298
 
299
+ def force_bool(o: object) -> bool:
300
+ try:
301
+ return to_bool(o)
302
+ except Exception:
303
+ return False
304
+
305
+
284
306
  def str_to_coords(s: str) -> None | tuple[int]:
285
307
  s = s.split(":")
286
308