tksheet 7.1.6__tar.gz → 7.1.7__tar.gz

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.
Files changed (25) hide show
  1. {tksheet-7.1.6/tksheet.egg-info → tksheet-7.1.7}/PKG-INFO +1 -1
  2. {tksheet-7.1.6 → tksheet-7.1.7}/pyproject.toml +35 -35
  3. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/__init__.py +99 -96
  4. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/column_headers.py +37 -24
  5. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/functions.py +5 -5
  6. tksheet-7.1.7/tksheet/listbox.py +19 -0
  7. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/main_table.py +299 -266
  8. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/row_index.py +46 -26
  9. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/sheet.py +56 -83
  10. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/sheet_options.py +3 -1
  11. {tksheet-7.1.6 → tksheet-7.1.7/tksheet.egg-info}/PKG-INFO +1 -1
  12. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet.egg-info/SOURCES.txt +1 -0
  13. {tksheet-7.1.6 → tksheet-7.1.7}/LICENSE.txt +0 -0
  14. {tksheet-7.1.6 → tksheet-7.1.7}/README.md +0 -0
  15. {tksheet-7.1.6 → tksheet-7.1.7}/setup.cfg +0 -0
  16. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/colors.py +0 -0
  17. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/formatters.py +0 -0
  18. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/other_classes.py +0 -0
  19. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/text_editor.py +0 -0
  20. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/themes.py +0 -0
  21. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/top_left_rectangle.py +0 -0
  22. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/types.py +0 -0
  23. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet/vars.py +0 -0
  24. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet.egg-info/dependency_links.txt +0 -0
  25. {tksheet-7.1.6 → tksheet-7.1.7}/tksheet.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tksheet
3
- Version: 7.1.6
3
+ Version: 7.1.7
4
4
  Summary: Tkinter table / sheet widget
5
5
  Author-email: ragardner <github@ragardner.simplelogin.com>
6
6
  License: Copyright (c) 2019 ragardner and open source contributors
@@ -1,35 +1,35 @@
1
- [build-system]
2
- requires = ["setuptools"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- name = "tksheet"
7
- description = "Tkinter table / sheet widget"
8
- readme = "README.md"
9
- version = "7.1.6"
10
- authors = [{ name = "ragardner", email = "github@ragardner.simplelogin.com" }]
11
- requires-python = ">=3.8"
12
- license = {file = "LICENSE.txt"}
13
- keywords = ["tkinter", "table", "widget", "sheet", "grid", "tk"]
14
- classifiers = [
15
- "Development Status :: 5 - Production/Stable",
16
- "Intended Audience :: Developers",
17
- "Topic :: Software Development :: Libraries",
18
- "License :: OSI Approved :: MIT License",
19
- "Programming Language :: Python :: 3.8",
20
- "Programming Language :: Python :: 3.9",
21
- "Programming Language :: Python :: 3.10",
22
- "Programming Language :: Python :: 3.11",
23
- "Programming Language :: Python :: 3.12",
24
- ]
25
-
26
- [project.urls]
27
- "Homepage" = "https://github.com/ragardner/tksheet"
28
- "Bug Reports" = "https://github.com/ragardner/tksheet/issues"
29
- "Funding" = "https://github.com/ragardner"
30
-
31
- [tool.black]
32
- line-length = 120
33
-
34
- [tool.ruff]
35
- line-length = 120
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "tksheet"
7
+ description = "Tkinter table / sheet widget"
8
+ readme = "README.md"
9
+ version = "7.1.7"
10
+ authors = [{ name = "ragardner", email = "github@ragardner.simplelogin.com" }]
11
+ requires-python = ">=3.8"
12
+ license = {file = "LICENSE.txt"}
13
+ keywords = ["tkinter", "table", "widget", "sheet", "grid", "tk"]
14
+ classifiers = [
15
+ "Development Status :: 5 - Production/Stable",
16
+ "Intended Audience :: Developers",
17
+ "Topic :: Software Development :: Libraries",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3.8",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ ]
25
+
26
+ [project.urls]
27
+ "Homepage" = "https://github.com/ragardner/tksheet"
28
+ "Bug Reports" = "https://github.com/ragardner/tksheet/issues"
29
+ "Funding" = "https://github.com/ragardner"
30
+
31
+ [tool.black]
32
+ line-length = 120
33
+
34
+ [tool.ruff]
35
+ line-length = 120
@@ -1,96 +1,99 @@
1
- # ruff: noqa: F401
2
-
3
- """
4
- tksheet - A Python tkinter table widget
5
- """
6
-
7
- __version__ = "7.1.6"
8
-
9
- from .colors import (
10
- color_map,
11
- )
12
- from .column_headers import ColumnHeaders
13
- from .formatters import (
14
- Formatter,
15
- bool_formatter,
16
- data_to_str,
17
- float_formatter,
18
- float_to_str,
19
- format_data,
20
- formatter,
21
- get_clipboard_data,
22
- get_data_with_valid_check,
23
- int_formatter,
24
- is_bool_like,
25
- is_none_like,
26
- percentage_formatter,
27
- percentage_to_str,
28
- to_bool,
29
- to_float,
30
- to_int,
31
- to_str,
32
- try_to_bool,
33
- )
34
- from .functions import (
35
- alpha2idx,
36
- alpha2num,
37
- consecutive_chunks,
38
- data_to_displayed_idxs,
39
- displayed_to_data_idxs,
40
- dropdown_search_function,
41
- event_dict,
42
- get_checkbox_dict,
43
- get_checkbox_kwargs,
44
- get_checkbox_points,
45
- get_dropdown_dict,
46
- get_dropdown_kwargs,
47
- get_index_of_gap_in_sorted_integer_seq_forward,
48
- get_index_of_gap_in_sorted_integer_seq_reverse,
49
- get_n2a,
50
- get_new_indexes,
51
- get_seq_without_gaps_at_index,
52
- is_iterable,
53
- move_elements_by_mapping,
54
- move_elements_to,
55
- num2alpha,
56
- span_dict,
57
- tksheet_type_error,
58
- )
59
- from .main_table import MainTable
60
- from .other_classes import (
61
- DotDict,
62
- DraggedRowColumn,
63
- DrawnItem,
64
- EventDataDict,
65
- GeneratedMouseEvent,
66
- Selected,
67
- Span,
68
- SpanRange,
69
- TextCfg,
70
- )
71
- from .row_index import RowIndex
72
- from .sheet import Dropdown, Sheet
73
- from .sheet_options import new_sheet_options
74
- from .text_editor import (
75
- TextEditor,
76
- TextEditorTkText,
77
- )
78
- from .themes import (
79
- theme_black,
80
- theme_dark,
81
- theme_dark_blue,
82
- theme_dark_green,
83
- theme_light_blue,
84
- theme_light_green,
85
- )
86
- from .top_left_rectangle import TopLeftRectangle
87
- from .vars import (
88
- USER_OS,
89
- ctrl_key,
90
- emitted_events,
91
- falsy,
92
- nonelike,
93
- rc_binding,
94
- symbols_set,
95
- truthy,
96
- )
1
+ # ruff: noqa: F401
2
+
3
+ """
4
+ tksheet - A Python tkinter table widget
5
+ """
6
+
7
+ __version__ = "7.1.7"
8
+
9
+ from .colors import (
10
+ color_map,
11
+ )
12
+ from .column_headers import ColumnHeaders
13
+ from .formatters import (
14
+ Formatter,
15
+ bool_formatter,
16
+ data_to_str,
17
+ float_formatter,
18
+ float_to_str,
19
+ format_data,
20
+ formatter,
21
+ get_clipboard_data,
22
+ get_data_with_valid_check,
23
+ int_formatter,
24
+ is_bool_like,
25
+ is_none_like,
26
+ percentage_formatter,
27
+ percentage_to_str,
28
+ to_bool,
29
+ to_float,
30
+ to_int,
31
+ to_str,
32
+ try_to_bool,
33
+ )
34
+ from .functions import (
35
+ alpha2idx,
36
+ alpha2num,
37
+ consecutive_chunks,
38
+ data_to_displayed_idxs,
39
+ displayed_to_data_idxs,
40
+ dropdown_search_function,
41
+ event_dict,
42
+ get_checkbox_dict,
43
+ get_checkbox_kwargs,
44
+ rounded_box_coords,
45
+ get_dropdown_dict,
46
+ get_dropdown_kwargs,
47
+ get_index_of_gap_in_sorted_integer_seq_forward,
48
+ get_index_of_gap_in_sorted_integer_seq_reverse,
49
+ get_n2a,
50
+ get_new_indexes,
51
+ get_seq_without_gaps_at_index,
52
+ is_iterable,
53
+ move_elements_by_mapping,
54
+ move_elements_to,
55
+ num2alpha,
56
+ span_dict,
57
+ tksheet_type_error,
58
+ )
59
+ from .listbox import (
60
+ ListBox,
61
+ )
62
+ from .main_table import MainTable
63
+ from .other_classes import (
64
+ DotDict,
65
+ DraggedRowColumn,
66
+ DrawnItem,
67
+ EventDataDict,
68
+ GeneratedMouseEvent,
69
+ Selected,
70
+ Span,
71
+ SpanRange,
72
+ TextCfg,
73
+ )
74
+ from .row_index import RowIndex
75
+ from .sheet import Dropdown, Sheet
76
+ from .sheet_options import new_sheet_options
77
+ from .text_editor import (
78
+ TextEditor,
79
+ TextEditorTkText,
80
+ )
81
+ from .themes import (
82
+ theme_black,
83
+ theme_dark,
84
+ theme_dark_blue,
85
+ theme_dark_green,
86
+ theme_light_blue,
87
+ theme_light_green,
88
+ )
89
+ from .top_left_rectangle import TopLeftRectangle
90
+ from .vars import (
91
+ USER_OS,
92
+ ctrl_key,
93
+ emitted_events,
94
+ falsy,
95
+ nonelike,
96
+ rc_binding,
97
+ symbols_set,
98
+ truthy,
99
+ )
@@ -23,7 +23,7 @@ from .functions import (
23
23
  consecutive_ranges,
24
24
  ev_stack_dict,
25
25
  event_dict,
26
- get_checkbox_points,
26
+ rounded_box_coords,
27
27
  get_n2a,
28
28
  is_contiguous,
29
29
  try_binding,
@@ -935,14 +935,26 @@ class ColumnHeaders(tk.Canvas):
935
935
  outline: str,
936
936
  state: str,
937
937
  tags: str | tuple[str],
938
+ iid: None | int = None,
938
939
  ) -> int:
939
- if self.hidd_boxes:
940
- iid = self.hidd_boxes.pop()
941
- self.coords(iid, x1, y1, x2, y2)
940
+ coords = rounded_box_coords(
941
+ x1,
942
+ y1,
943
+ x2,
944
+ y2,
945
+ radius=9 if self.PAR.ops.rounded_boxes else 0,
946
+ )
947
+ if isinstance(iid, int):
948
+ self.coords(iid, coords)
942
949
  self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
943
950
  else:
944
- iid = self.create_rectangle(x1, y1, x2, y2, fill=fill, outline=outline, state=state, tags=tags)
945
- self.disp_boxes.add(iid)
951
+ if self.hidd_boxes:
952
+ iid = self.hidd_boxes.pop()
953
+ self.coords(iid, coords)
954
+ self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
955
+ else:
956
+ iid = self.create_polygon(coords, fill=fill, outline=outline, state=state, tags=tags, smooth=True)
957
+ self.disp_boxes.add(iid)
946
958
  return iid
947
959
 
948
960
  def hide_box(self, item: int) -> None:
@@ -1276,7 +1288,7 @@ class ColumnHeaders(tk.Canvas):
1276
1288
  self.disp_dropdown[t] = True
1277
1289
 
1278
1290
  def redraw_checkbox(self, x1, y1, x2, y2, fill, outline, tag, draw_check=False):
1279
- points = get_checkbox_points(x1, y1, x2, y2)
1291
+ points = rounded_box_coords(x1, y1, x2, y2)
1280
1292
  if self.hidd_checkbox:
1281
1293
  t, sh = self.hidd_checkbox.popitem()
1282
1294
  self.coords(t, points)
@@ -1294,7 +1306,7 @@ class ColumnHeaders(tk.Canvas):
1294
1306
  y1 = y1 + 4
1295
1307
  x2 = x2 - 3
1296
1308
  y2 = y2 - 3
1297
- points = get_checkbox_points(x1, y1, x2, y2, radius=4)
1309
+ points = rounded_box_coords(x1, y1, x2, y2, radius=4)
1298
1310
  if self.hidd_checkbox:
1299
1311
  t, sh = self.hidd_checkbox.popitem()
1300
1312
  self.coords(t, points)
@@ -1574,16 +1586,14 @@ class ColumnHeaders(tk.Canvas):
1574
1586
  dct[iid] = False
1575
1587
  return True
1576
1588
 
1577
- def get_redraw_selections(self, startc, endc):
1578
- d = defaultdict(list)
1589
+ def get_redraw_selections(self, startc: int, endc: int) -> dict[str, set[int]]:
1590
+ d = defaultdict(set)
1579
1591
  for item, box in self.MT.get_selection_items(rows=False):
1580
- d[box.type_].append(box.coords)
1581
- d2 = {}
1582
- if "cells" in d:
1583
- d2["cells"] = {c for c in range(startc, endc) for r1, c1, r2, c2 in d["cells"] if c1 <= c and c2 > c}
1584
- if "columns" in d:
1585
- d2["columns"] = {c for c in range(startc, endc) for r1, c1, r2, c2 in d["columns"] if c1 <= c and c2 > c}
1586
- return d2
1592
+ r1, c1, r2, c2 = box.coords
1593
+ for c in range(startc, endc):
1594
+ if c1 <= c and c2 > c:
1595
+ d[box.type_].add(c)
1596
+ return d
1587
1597
 
1588
1598
  def open_cell(self, event: object = None, ignore_existing_editor=False):
1589
1599
  if not self.MT.anything_selected() or (not ignore_existing_editor and self.text_editor.open):
@@ -1817,6 +1827,8 @@ class ColumnHeaders(tk.Canvas):
1817
1827
 
1818
1828
  def hide_text_editor(self, reason: None | str = None) -> None:
1819
1829
  if self.text_editor.open:
1830
+ for b in ("<Alt-Return>", "<Option-Return>", "<Tab>", "<Return>", "<FocusOut>", "<Escape>"):
1831
+ self.text_editor.tktext.unbind(b)
1820
1832
  self.itemconfig(self.text_editor.canvas_id, state="hidden")
1821
1833
  self.text_editor.open = False
1822
1834
  if reason == "Escape":
@@ -1840,7 +1852,7 @@ class ColumnHeaders(tk.Canvas):
1840
1852
  self.hide_text_editor_and_dropdown()
1841
1853
  return
1842
1854
  # setting cell data with text editor value
1843
- self.text_editor_value = self.text_editor.get()
1855
+ text_editor_value = self.text_editor.get()
1844
1856
  c = editor_info[0]
1845
1857
  datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
1846
1858
  event_data = event_dict(
@@ -1848,7 +1860,7 @@ class ColumnHeaders(tk.Canvas):
1848
1860
  sheet=self.PAR.name,
1849
1861
  cells_header={datacn: self.get_cell_data(datacn)},
1850
1862
  key=editor_info[1] if len(editor_info) >= 2 else "FocusOut",
1851
- value=self.text_editor_value,
1863
+ value=text_editor_value,
1852
1864
  loc=c,
1853
1865
  boxes=self.MT.get_boxes(),
1854
1866
  selected=self.MT.selected,
@@ -1861,11 +1873,11 @@ class ColumnHeaders(tk.Canvas):
1861
1873
  check_input_valid=False,
1862
1874
  )
1863
1875
  if self.MT.edit_validation_func:
1864
- self.text_editor_value = self.MT.edit_validation_func(event_data)
1865
- if self.text_editor_value is not None and self.input_valid_for_cell(datacn, self.text_editor_value):
1866
- edited = set_data(value=self.text_editor_value)
1867
- elif self.input_valid_for_cell(datacn, self.text_editor_value):
1868
- edited = set_data(value=self.text_editor_value)
1876
+ text_editor_value = self.MT.edit_validation_func(event_data)
1877
+ if text_editor_value is not None and self.input_valid_for_cell(datacn, text_editor_value):
1878
+ edited = set_data(value=text_editor_value)
1879
+ elif self.input_valid_for_cell(datacn, text_editor_value):
1880
+ edited = set_data(value=text_editor_value)
1869
1881
  if edited:
1870
1882
  try_binding(self.extra_end_edit_cell_func, event_data)
1871
1883
  self.MT.recreate_all_selection_boxes()
@@ -2037,6 +2049,7 @@ class ColumnHeaders(tk.Canvas):
2037
2049
 
2038
2050
  def hide_dropdown_window(self) -> None:
2039
2051
  if self.dropdown.open:
2052
+ self.dropdown.window.unbind("<FocusOut>")
2040
2053
  self.itemconfig(self.dropdown.canvas_id, state="hidden")
2041
2054
  self.dropdown.open = False
2042
2055
 
@@ -356,7 +356,7 @@ def consecutive_chunks(seq: list[int]) -> Generator[list[int]]:
356
356
  for index, value in enumerate(seq, 1):
357
357
  try:
358
358
  if seq[index] > value + 1:
359
- yield seq[start:(start := index)]
359
+ yield seq[start : (start := index)]
360
360
  except Exception:
361
361
  yield seq[start : len(seq)]
362
362
 
@@ -504,14 +504,14 @@ def displayed_to_data_idxs(
504
504
  return [displayed[e] for e in to_convert]
505
505
 
506
506
 
507
- def get_checkbox_points(
507
+ def rounded_box_coords(
508
508
  x1: float,
509
509
  y1: float,
510
510
  x2: float,
511
511
  y2: float,
512
512
  radius: int = 8,
513
- ) -> list[float]:
514
- return [
513
+ ) -> tuple[float]:
514
+ return (
515
515
  x1 + radius,
516
516
  y1,
517
517
  x1 + radius,
@@ -552,7 +552,7 @@ def get_checkbox_points(
552
552
  y1 + radius,
553
553
  x1,
554
554
  y1,
555
- ]
555
+ )
556
556
 
557
557
 
558
558
  def diff_list(seq: list[float]) -> list[int]:
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+ import tkinter as tk
3
+ # from collections.abc import Callable, Generator, Iterator, Sequence
4
+
5
+ from .sheet import (
6
+ Sheet,
7
+ )
8
+
9
+
10
+ class ListBox(Sheet):
11
+ def __init__(
12
+ self,
13
+ parent: tk.Misc,
14
+ ) -> None:
15
+ Sheet.__init__(
16
+ self,
17
+ parent=parent,
18
+ )
19
+ self.parent = parent