tksheet 7.4.11__tar.gz → 7.4.12__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.
- {tksheet-7.4.11/tksheet.egg-info → tksheet-7.4.12}/PKG-INFO +3 -3
- {tksheet-7.4.11 → tksheet-7.4.12}/README.md +2 -2
- {tksheet-7.4.11 → tksheet-7.4.12}/pyproject.toml +1 -1
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/__init__.py +1 -1
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/column_headers.py +26 -47
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/functions.py +92 -33
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/main_table.py +198 -220
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/other_classes.py +3 -1
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/row_index.py +28 -56
- {tksheet-7.4.11 → tksheet-7.4.12/tksheet.egg-info}/PKG-INFO +3 -3
- {tksheet-7.4.11 → tksheet-7.4.12}/LICENSE.txt +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/setup.cfg +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/colors.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/constants.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/find_window.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/formatters.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/sheet.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/sheet_options.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/sorting.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/text_editor.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/themes.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/tksheet_types.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet/top_left_rectangle.py +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet.egg-info/SOURCES.txt +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet.egg-info/dependency_links.txt +0 -0
- {tksheet-7.4.11 → tksheet-7.4.12}/tksheet.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: tksheet
|
3
|
-
Version: 7.4.
|
3
|
+
Version: 7.4.12
|
4
4
|
Summary: Tkinter table / sheet and treeview widget
|
5
5
|
Author-email: ragardner <github@ragardner.simplelogin.com>
|
6
6
|
License: Copyright (c) 2019 ragardner and open source contributors
|
@@ -63,11 +63,11 @@ License-File: LICENSE.txt
|
|
63
63
|
<tbody>
|
64
64
|
<tr>
|
65
65
|
<td style="color: LightCoral">Versions 6.x.x →</td>
|
66
|
-
<td><a href="https://github.com/ragardner/tksheet/wiki/Version-6">Documentation
|
66
|
+
<td><a href="https://github.com/ragardner/tksheet/wiki/Version-6">Documentation</a></td>
|
67
67
|
</tr>
|
68
68
|
<tr>
|
69
69
|
<td style="color: lightgreen">Versions 7.x.x →</td>
|
70
|
-
<td><a href="https://github.
|
70
|
+
<td><a href="https://ragardner.github.io/tksheet/DOCUMENTATION.html">Documentation</a></td>
|
71
71
|
</tr>
|
72
72
|
<tr>
|
73
73
|
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md">Changelog</a></td>
|
@@ -18,11 +18,11 @@
|
|
18
18
|
<tbody>
|
19
19
|
<tr>
|
20
20
|
<td style="color: LightCoral">Versions 6.x.x →</td>
|
21
|
-
<td><a href="https://github.com/ragardner/tksheet/wiki/Version-6">Documentation
|
21
|
+
<td><a href="https://github.com/ragardner/tksheet/wiki/Version-6">Documentation</a></td>
|
22
22
|
</tr>
|
23
23
|
<tr>
|
24
24
|
<td style="color: lightgreen">Versions 7.x.x →</td>
|
25
|
-
<td><a href="https://github.
|
25
|
+
<td><a href="https://ragardner.github.io/tksheet/DOCUMENTATION.html">Documentation</a></td>
|
26
26
|
</tr>
|
27
27
|
<tr>
|
28
28
|
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md">Changelog</a></td>
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
6
6
|
name = "tksheet"
|
7
7
|
description = "Tkinter table / sheet and treeview widget"
|
8
8
|
readme = "README.md"
|
9
|
-
version = "7.4.
|
9
|
+
version = "7.4.12"
|
10
10
|
authors = [{ name = "ragardner", email = "github@ragardner.simplelogin.com" }]
|
11
11
|
requires-python = ">=3.8"
|
12
12
|
license = {file = "LICENSE.txt"}
|
@@ -1058,44 +1058,6 @@ class ColumnHeaders(tk.Canvas):
|
|
1058
1058
|
self.MT.run_selection_binding("columns")
|
1059
1059
|
return fill_iid
|
1060
1060
|
|
1061
|
-
def display_box(
|
1062
|
-
self,
|
1063
|
-
x1: int,
|
1064
|
-
y1: int,
|
1065
|
-
x2: int,
|
1066
|
-
y2: int,
|
1067
|
-
fill: str,
|
1068
|
-
outline: str,
|
1069
|
-
state: str,
|
1070
|
-
tags: str | tuple[str],
|
1071
|
-
iid: None | int = None,
|
1072
|
-
) -> int:
|
1073
|
-
coords = rounded_box_coords(
|
1074
|
-
x1,
|
1075
|
-
y1,
|
1076
|
-
x2,
|
1077
|
-
y2,
|
1078
|
-
radius=5 if self.ops.rounded_boxes else 0,
|
1079
|
-
)
|
1080
|
-
if isinstance(iid, int):
|
1081
|
-
self.coords(iid, coords)
|
1082
|
-
self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
|
1083
|
-
else:
|
1084
|
-
if self.hidd_boxes:
|
1085
|
-
iid = self.hidd_boxes.pop()
|
1086
|
-
self.coords(iid, coords)
|
1087
|
-
self.itemconfig(iid, fill=fill, outline=outline, state=state, tags=tags)
|
1088
|
-
else:
|
1089
|
-
iid = self.create_polygon(coords, fill=fill, outline=outline, state=state, tags=tags, smooth=True)
|
1090
|
-
self.disp_boxes.add(iid)
|
1091
|
-
return iid
|
1092
|
-
|
1093
|
-
def hide_box(self, item: int) -> None:
|
1094
|
-
if isinstance(item, int):
|
1095
|
-
self.disp_boxes.discard(item)
|
1096
|
-
self.hidd_boxes.add(item)
|
1097
|
-
self.itemconfig(item, state="hidden")
|
1098
|
-
|
1099
1061
|
def get_cell_dimensions(self, datacn: int) -> tuple[int, int]:
|
1100
1062
|
txt = self.cell_str(datacn, fix=False)
|
1101
1063
|
if txt:
|
@@ -1279,6 +1241,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1279
1241
|
sel_cols_bg: str,
|
1280
1242
|
selections: dict,
|
1281
1243
|
datacn: int,
|
1244
|
+
has_dd: bool,
|
1282
1245
|
) -> tuple[str, bool]:
|
1283
1246
|
redrawn = False
|
1284
1247
|
kwargs = self.get_cell_kwargs(datacn, key="highlight")
|
@@ -1319,18 +1282,32 @@ class ColumnHeaders(tk.Canvas):
|
|
1319
1282
|
sc,
|
1320
1283
|
self.current_height - 1,
|
1321
1284
|
fill=fill,
|
1322
|
-
outline=
|
1323
|
-
self.ops.header_fg
|
1324
|
-
if self.get_cell_kwargs(datacn, key="dropdown") and self.ops.show_dropdown_borders
|
1325
|
-
else ""
|
1326
|
-
),
|
1285
|
+
outline=self.ops.header_fg if has_dd and self.ops.show_dropdown_borders else "",
|
1327
1286
|
tag="hi",
|
1328
1287
|
)
|
1329
1288
|
elif not kwargs:
|
1330
1289
|
if "columns" in selections and c in selections["columns"]:
|
1331
1290
|
txtfg = self.ops.header_selected_columns_fg
|
1291
|
+
redrawn = self.redraw_highlight(
|
1292
|
+
fc + 1,
|
1293
|
+
0,
|
1294
|
+
sc,
|
1295
|
+
self.current_height - 1,
|
1296
|
+
fill=self.ops.header_selected_columns_bg,
|
1297
|
+
outline=self.ops.header_fg if has_dd and self.ops.show_dropdown_borders else "",
|
1298
|
+
tag="hi",
|
1299
|
+
)
|
1332
1300
|
elif "cells" in selections and c in selections["cells"]:
|
1333
1301
|
txtfg = self.ops.header_selected_cells_fg
|
1302
|
+
redrawn = self.redraw_highlight(
|
1303
|
+
fc + 1,
|
1304
|
+
0,
|
1305
|
+
sc,
|
1306
|
+
self.current_height - 1,
|
1307
|
+
fill=self.ops.header_selected_cells_bg,
|
1308
|
+
outline=self.ops.header_fg if has_dd and self.ops.show_dropdown_borders else "",
|
1309
|
+
tag="hi",
|
1310
|
+
)
|
1334
1311
|
else:
|
1335
1312
|
txtfg = self.ops.header_fg
|
1336
1313
|
return txtfg, redrawn
|
@@ -1559,6 +1536,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1559
1536
|
cleftgridln = self.MT.col_positions[c]
|
1560
1537
|
crightgridln = self.MT.col_positions[c + 1]
|
1561
1538
|
datacn = c if self.MT.all_columns_displayed else self.MT.displayed_columns[c]
|
1539
|
+
kwargs = self.get_cell_kwargs(datacn, key="dropdown")
|
1562
1540
|
fill, dd_drawn = self.redraw_highlight_get_text_fg(
|
1563
1541
|
fc=cleftgridln,
|
1564
1542
|
sc=crightgridln,
|
@@ -1567,12 +1545,13 @@ class ColumnHeaders(tk.Canvas):
|
|
1567
1545
|
sel_cols_bg=sel_cols_bg,
|
1568
1546
|
selections=selections,
|
1569
1547
|
datacn=datacn,
|
1548
|
+
has_dd=bool(kwargs),
|
1570
1549
|
)
|
1571
1550
|
if datacn in self.cell_options and "align" in self.cell_options[datacn]:
|
1572
1551
|
align = self.cell_options[datacn]["align"]
|
1573
1552
|
else:
|
1574
1553
|
align = self.align
|
1575
|
-
if kwargs
|
1554
|
+
if kwargs:
|
1576
1555
|
max_width = crightgridln - cleftgridln - txt_h - 2
|
1577
1556
|
if align.endswith("w"):
|
1578
1557
|
draw_x = cleftgridln + 2
|
@@ -1664,7 +1643,6 @@ class ColumnHeaders(tk.Canvas):
|
|
1664
1643
|
anchor=align,
|
1665
1644
|
state="normal",
|
1666
1645
|
)
|
1667
|
-
self.tag_raise(iid)
|
1668
1646
|
else:
|
1669
1647
|
iid = self.create_text(
|
1670
1648
|
draw_x,
|
@@ -1709,6 +1687,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1709
1687
|
if showing:
|
1710
1688
|
self.itemconfig(iid, state="hidden")
|
1711
1689
|
dct[iid] = False
|
1690
|
+
self.tag_raise("t")
|
1712
1691
|
if self.disp_resize_lines:
|
1713
1692
|
self.tag_raise("rw")
|
1714
1693
|
return True
|
@@ -2314,8 +2293,8 @@ class ColumnHeaders(tk.Canvas):
|
|
2314
2293
|
kwargs = self.get_cell_kwargs(datacn, key=None, cell=c_ops)
|
2315
2294
|
if "checkbox" in kwargs:
|
2316
2295
|
return False
|
2317
|
-
elif
|
2318
|
-
return kwargs["values"][0]
|
2296
|
+
elif "dropdown" in kwargs and kwargs["dropdown"]["validate_input"] and kwargs["dropdown"]["values"]:
|
2297
|
+
return kwargs["dropdown"]["values"][0]
|
2319
2298
|
else:
|
2320
2299
|
return ""
|
2321
2300
|
|
@@ -9,7 +9,7 @@ from bisect import bisect_left
|
|
9
9
|
from collections import deque
|
10
10
|
from collections.abc import Callable, Generator, Hashable, Iterable, Iterator, Sequence
|
11
11
|
from difflib import SequenceMatcher
|
12
|
-
from itertools import islice, repeat
|
12
|
+
from itertools import chain, islice, repeat
|
13
13
|
from typing import Any, Literal
|
14
14
|
|
15
15
|
from .colors import color_map
|
@@ -31,34 +31,16 @@ def wrap_text(
|
|
31
31
|
wrap: Literal["", "c", "w"] = "",
|
32
32
|
start_line: int = 0,
|
33
33
|
) -> Generator[str]:
|
34
|
-
lines = (match.group() for match in lines_re.finditer(text))
|
35
|
-
current_line = []
|
36
34
|
total_lines = 0
|
37
35
|
line_width = 0
|
38
|
-
|
39
|
-
|
40
|
-
for
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
if line_width >= max_width:
|
47
|
-
break
|
48
|
-
current_line.append(char)
|
49
|
-
|
50
|
-
if total_lines >= start_line:
|
51
|
-
yield "".join(current_line)
|
52
|
-
|
53
|
-
# Count the line whether it's empty or not
|
54
|
-
total_lines += 1
|
55
|
-
if total_lines >= max_lines:
|
56
|
-
return
|
57
|
-
|
58
|
-
elif wrap == "c":
|
59
|
-
for line in lines:
|
60
|
-
for char in line:
|
61
|
-
char_width = widths.get(char, char_width_fn(char))
|
36
|
+
if wrap == "c":
|
37
|
+
current_line = []
|
38
|
+
for match in lines_re.finditer(text):
|
39
|
+
for char in match.group():
|
40
|
+
try:
|
41
|
+
char_width = widths[char]
|
42
|
+
except KeyError:
|
43
|
+
char_width = char_width_fn(char)
|
62
44
|
|
63
45
|
# adding char to line would result in wrap
|
64
46
|
if line_width + char_width >= max_width:
|
@@ -89,11 +71,14 @@ def wrap_text(
|
|
89
71
|
line_width = 0
|
90
72
|
|
91
73
|
elif wrap == "w":
|
92
|
-
|
74
|
+
try:
|
75
|
+
space_width = widths[" "]
|
76
|
+
except KeyError:
|
77
|
+
space_width = char_width_fn(" ")
|
78
|
+
current_line = []
|
93
79
|
|
94
|
-
for
|
95
|
-
|
96
|
-
for i, word in enumerate(words):
|
80
|
+
for match in lines_re.finditer(text):
|
81
|
+
for i, word in enumerate(match.group().split()):
|
97
82
|
# if we're going to next word and
|
98
83
|
# if a space fits on the end of the current line we add one
|
99
84
|
if i and line_width + space_width < max_width:
|
@@ -104,8 +89,12 @@ def wrap_text(
|
|
104
89
|
word_width = 0
|
105
90
|
word_char_widths = []
|
106
91
|
for char in word:
|
107
|
-
|
108
|
-
|
92
|
+
try:
|
93
|
+
char_width = widths[char]
|
94
|
+
except KeyError:
|
95
|
+
char_width = char_width_fn(char)
|
96
|
+
word_char_widths.append(char_width)
|
97
|
+
word_width += char_width
|
109
98
|
|
110
99
|
# we only wrap by character if the whole word alone wont fit max width
|
111
100
|
# word won't fit at all we resort to char wrapping it
|
@@ -167,6 +156,28 @@ def wrap_text(
|
|
167
156
|
current_line = [] # Reset for next line
|
168
157
|
line_width = 0
|
169
158
|
|
159
|
+
else:
|
160
|
+
for match in lines_re.finditer(text):
|
161
|
+
line_width = 0
|
162
|
+
current_line = []
|
163
|
+
for char in match.group():
|
164
|
+
try:
|
165
|
+
char_width = widths[char]
|
166
|
+
except KeyError:
|
167
|
+
char_width = char_width_fn(char)
|
168
|
+
line_width += char_width
|
169
|
+
if line_width >= max_width:
|
170
|
+
break
|
171
|
+
current_line.append(char)
|
172
|
+
|
173
|
+
if total_lines >= start_line:
|
174
|
+
yield "".join(current_line)
|
175
|
+
|
176
|
+
# Count the line whether it's empty or not
|
177
|
+
total_lines += 1
|
178
|
+
if total_lines >= max_lines:
|
179
|
+
return
|
180
|
+
|
170
181
|
|
171
182
|
def get_csv_str_dialect(s: str, delimiters: str) -> csv.Dialect:
|
172
183
|
if len(s) > 6000:
|
@@ -1684,3 +1695,51 @@ def pop_positions(
|
|
1684
1695
|
save_to[to_pop[i]] = pos
|
1685
1696
|
else:
|
1686
1697
|
yield pos
|
1698
|
+
|
1699
|
+
|
1700
|
+
def get_horizontal_gridline_points(
|
1701
|
+
left: float,
|
1702
|
+
stop: float,
|
1703
|
+
positions: list[float],
|
1704
|
+
start: int,
|
1705
|
+
end: int,
|
1706
|
+
) -> list[int | float]:
|
1707
|
+
return list(
|
1708
|
+
chain.from_iterable(
|
1709
|
+
(
|
1710
|
+
left - 1,
|
1711
|
+
positions[r],
|
1712
|
+
stop,
|
1713
|
+
positions[r],
|
1714
|
+
left - 1,
|
1715
|
+
positions[r],
|
1716
|
+
left - 1,
|
1717
|
+
positions[r + 1] if len(positions) - 1 > r else positions[r],
|
1718
|
+
)
|
1719
|
+
for r in range(start, end)
|
1720
|
+
)
|
1721
|
+
)
|
1722
|
+
|
1723
|
+
|
1724
|
+
def get_vertical_gridline_points(
|
1725
|
+
top: float,
|
1726
|
+
stop: float,
|
1727
|
+
positions: list[float],
|
1728
|
+
start: int,
|
1729
|
+
end: int,
|
1730
|
+
) -> list[float]:
|
1731
|
+
return list(
|
1732
|
+
chain.from_iterable(
|
1733
|
+
(
|
1734
|
+
positions[c],
|
1735
|
+
top - 1,
|
1736
|
+
positions[c],
|
1737
|
+
stop,
|
1738
|
+
positions[c],
|
1739
|
+
top - 1,
|
1740
|
+
positions[c + 1] if len(positions) - 1 > c else positions[c],
|
1741
|
+
top - 1,
|
1742
|
+
)
|
1743
|
+
for c in range(start, end)
|
1744
|
+
)
|
1745
|
+
)
|