tksheet 7.4.12__py3-none-any.whl → 7.4.13__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 +1 -1
- tksheet/column_headers.py +18 -18
- tksheet/functions.py +17 -5
- tksheet/main_table.py +132 -101
- tksheet/other_classes.py +1 -1
- tksheet/row_index.py +150 -112
- tksheet/sheet.py +16 -10
- {tksheet-7.4.12.dist-info → tksheet-7.4.13.dist-info}/METADATA +7 -7
- tksheet-7.4.13.dist-info/RECORD +22 -0
- tksheet-7.4.12.dist-info/RECORD +0 -22
- {tksheet-7.4.12.dist-info → tksheet-7.4.13.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.4.12.dist-info → tksheet-7.4.13.dist-info}/WHEEL +0 -0
- {tksheet-7.4.12.dist-info → tksheet-7.4.13.dist-info}/top_level.txt +0 -0
tksheet/__init__.py
CHANGED
tksheet/column_headers.py
CHANGED
@@ -5,7 +5,7 @@ from collections import defaultdict
|
|
5
5
|
from collections.abc import Callable, Hashable, Iterator, Sequence
|
6
6
|
from functools import partial
|
7
7
|
from itertools import cycle, islice, repeat
|
8
|
-
from math import ceil
|
8
|
+
from math import ceil
|
9
9
|
from operator import itemgetter
|
10
10
|
from typing import Any, Literal
|
11
11
|
|
@@ -741,7 +741,7 @@ class ColumnHeaders(tk.Canvas):
|
|
741
741
|
if size < self.ops.min_column_width:
|
742
742
|
new_col_pos = ceil(self.MT.col_positions[self.rsz_w - 1] + self.ops.min_column_width)
|
743
743
|
elif size > self.ops.max_column_width:
|
744
|
-
new_col_pos =
|
744
|
+
new_col_pos = int(self.MT.col_positions[self.rsz_w - 1] + self.ops.max_column_width)
|
745
745
|
increment = new_col_pos - self.MT.col_positions[self.rsz_w]
|
746
746
|
self.MT.col_positions[self.rsz_w + 1 :] = [
|
747
747
|
e + increment for e in islice(self.MT.col_positions, self.rsz_w + 1, None)
|
@@ -1373,7 +1373,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1373
1373
|
if draw_arrow:
|
1374
1374
|
mod = (self.MT.header_txt_height - 1) if self.MT.header_txt_height % 2 else self.MT.header_txt_height
|
1375
1375
|
small_mod = int(mod / 5)
|
1376
|
-
mid_y =
|
1376
|
+
mid_y = int(self.MT.min_header_height / 2)
|
1377
1377
|
if open_:
|
1378
1378
|
# up arrow
|
1379
1379
|
points = (
|
@@ -1552,13 +1552,13 @@ class ColumnHeaders(tk.Canvas):
|
|
1552
1552
|
else:
|
1553
1553
|
align = self.align
|
1554
1554
|
if kwargs:
|
1555
|
-
max_width = crightgridln - cleftgridln - txt_h -
|
1556
|
-
if align
|
1555
|
+
max_width = crightgridln - cleftgridln - txt_h - 5
|
1556
|
+
if align[-1] == "w":
|
1557
1557
|
draw_x = cleftgridln + 2
|
1558
|
-
elif align
|
1558
|
+
elif align[-1] == "e":
|
1559
1559
|
draw_x = crightgridln - 5 - txt_h
|
1560
|
-
elif align
|
1561
|
-
draw_x = cleftgridln +
|
1560
|
+
elif align[-1] == "n":
|
1561
|
+
draw_x = cleftgridln + (crightgridln - cleftgridln - txt_h) / 2
|
1562
1562
|
self.redraw_dropdown(
|
1563
1563
|
cleftgridln,
|
1564
1564
|
0,
|
@@ -1573,18 +1573,18 @@ class ColumnHeaders(tk.Canvas):
|
|
1573
1573
|
)
|
1574
1574
|
else:
|
1575
1575
|
max_width = crightgridln - cleftgridln - 2
|
1576
|
-
if align
|
1576
|
+
if align[-1] == "w":
|
1577
1577
|
draw_x = cleftgridln + 2
|
1578
|
-
elif align
|
1578
|
+
elif align[-1] == "e":
|
1579
1579
|
draw_x = crightgridln - 2
|
1580
|
-
elif align
|
1581
|
-
draw_x = cleftgridln +
|
1580
|
+
elif align[-1] == "n":
|
1581
|
+
draw_x = cleftgridln + (crightgridln - cleftgridln) / 2
|
1582
1582
|
if (kwargs := self.get_cell_kwargs(datacn, key="checkbox")) and max_width > txt_h + 1:
|
1583
1583
|
box_w = txt_h + 1
|
1584
|
-
if align
|
1584
|
+
if align[-1] == "w":
|
1585
1585
|
draw_x += box_w + 3
|
1586
|
-
elif align
|
1587
|
-
draw_x +=
|
1586
|
+
elif align[-1] == "n":
|
1587
|
+
draw_x += box_w / 2 + 1
|
1588
1588
|
max_width -= box_w + 4
|
1589
1589
|
try:
|
1590
1590
|
draw_check = (
|
@@ -1606,9 +1606,9 @@ class ColumnHeaders(tk.Canvas):
|
|
1606
1606
|
)
|
1607
1607
|
if (
|
1608
1608
|
max_width < self.MT.header_txt_width
|
1609
|
-
or (align
|
1610
|
-
or (align
|
1611
|
-
or (align
|
1609
|
+
or (align[-1] == "w" and draw_x > scrollpos_right)
|
1610
|
+
or (align[-1] == "e" and cleftgridln + 5 > scrollpos_right)
|
1611
|
+
or (align[-1] == "n" and cleftgridln + 5 > scrollpos_right)
|
1612
1612
|
):
|
1613
1613
|
continue
|
1614
1614
|
text = self.cell_str(datacn, fix=False)
|
tksheet/functions.py
CHANGED
@@ -793,6 +793,11 @@ def move_elements_by_mapping_gen(
|
|
793
793
|
return (seq[old_idxs[i]] if i in old_idxs else next(remaining_values) for i in range(len(seq)))
|
794
794
|
|
795
795
|
|
796
|
+
def move_fast(seq: list[Any], new_idxs: dict[int, int], old_idxs: dict[int, int]) -> list[Any]:
|
797
|
+
remaining_values = (e for i, e in enumerate(seq) if i not in new_idxs)
|
798
|
+
return [seq[old_idxs[i]] if i in old_idxs else next(remaining_values) for i in range(len(seq))]
|
799
|
+
|
800
|
+
|
796
801
|
def move_elements_to(
|
797
802
|
seq: list[Any],
|
798
803
|
move_to: int,
|
@@ -819,10 +824,17 @@ def get_new_indexes(
|
|
819
824
|
returns {old idx: new idx, ...}
|
820
825
|
"""
|
821
826
|
offset = sum(1 for i in to_move if i < move_to)
|
822
|
-
|
823
|
-
if get_inverse:
|
824
|
-
return
|
825
|
-
|
827
|
+
correct_move_to = move_to - offset
|
828
|
+
if not get_inverse:
|
829
|
+
return {elem: correct_move_to + i for i, elem in enumerate(to_move)}
|
830
|
+
else:
|
831
|
+
new_idxs = {}
|
832
|
+
old_idxs = {}
|
833
|
+
for i, elem in enumerate(to_move):
|
834
|
+
value = correct_move_to + i
|
835
|
+
new_idxs[elem] = value
|
836
|
+
old_idxs[value] = elem
|
837
|
+
return new_idxs, old_idxs
|
826
838
|
|
827
839
|
|
828
840
|
def insert_items(
|
@@ -833,7 +845,7 @@ def insert_items(
|
|
833
845
|
"""
|
834
846
|
seq: list[Any]
|
835
847
|
to_insert: keys are ints sorted, representing list indexes to insert items.
|
836
|
-
Values are any, e.g. {
|
848
|
+
Values are any, e.g. {0: 200, 1: 200}
|
837
849
|
"""
|
838
850
|
if to_insert:
|
839
851
|
if seq_len_func and next(reversed(to_insert)) >= len(seq) + len(to_insert):
|
tksheet/main_table.py
CHANGED
@@ -8,7 +8,6 @@ from collections import defaultdict, deque
|
|
8
8
|
from collections.abc import Callable, Generator, Hashable, Iterator, Sequence
|
9
9
|
from functools import partial
|
10
10
|
from itertools import accumulate, chain, cycle, filterfalse, islice, repeat
|
11
|
-
from math import ceil, floor
|
12
11
|
from operator import itemgetter
|
13
12
|
from re import IGNORECASE, escape, sub
|
14
13
|
from tkinter import TclError
|
@@ -75,8 +74,8 @@ from .functions import (
|
|
75
74
|
mod_event_val,
|
76
75
|
mod_span,
|
77
76
|
mod_span_widget,
|
78
|
-
move_elements_by_mapping,
|
79
77
|
move_elements_by_mapping_gen,
|
78
|
+
move_fast,
|
80
79
|
new_tk_event,
|
81
80
|
next_cell,
|
82
81
|
push_n,
|
@@ -323,7 +322,7 @@ class MainTable(tk.Canvas):
|
|
323
322
|
and kwargs["total_rows"] > 0
|
324
323
|
and kwargs["total_cols"] > 0
|
325
324
|
):
|
326
|
-
self.data = [list(repeat("", kwargs["total_cols"])) for
|
325
|
+
self.data = [list(repeat("", kwargs["total_cols"])) for _ in range(kwargs["total_rows"])]
|
327
326
|
_header = kwargs["header"] if kwargs["header"] is not None else kwargs["headers"]
|
328
327
|
if isinstance(_header, int):
|
329
328
|
self._headers = _header
|
@@ -1498,11 +1497,6 @@ class MainTable(tk.Canvas):
|
|
1498
1497
|
event_data: EventDataDict | None = None,
|
1499
1498
|
) -> tuple[dict[int, int], dict[int, int], EventDataDict]:
|
1500
1499
|
self.saved_column_widths = {}
|
1501
|
-
if not isinstance(totalcols, int):
|
1502
|
-
totalcols = max(data_new_idxs.values(), default=0)
|
1503
|
-
if totalcols:
|
1504
|
-
totalcols += 1
|
1505
|
-
totalcols = self.equalize_data_row_lengths(at_least_cols=totalcols)
|
1506
1500
|
if not event_data:
|
1507
1501
|
event_data = self.new_event_dict("move_columns", state=True)
|
1508
1502
|
if not event_data["moved"]["columns"]:
|
@@ -1539,26 +1533,26 @@ class MainTable(tk.Canvas):
|
|
1539
1533
|
)
|
1540
1534
|
else:
|
1541
1535
|
self.recreate_all_selection_boxes()
|
1536
|
+
|
1542
1537
|
if move_data:
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
)
|
1538
|
+
if not isinstance(totalcols, int):
|
1539
|
+
totalcols = max(data_new_idxs.values(), default=0)
|
1540
|
+
if totalcols:
|
1541
|
+
totalcols += 1
|
1542
|
+
totalcols = self.equalize_data_row_lengths(at_least_cols=totalcols)
|
1543
|
+
|
1544
|
+
self.data = [move_fast(k, data_new_idxs, data_old_idxs) for k in self.data]
|
1551
1545
|
maxidx = len_to_idx(totalcols)
|
1552
1546
|
self.CH.fix_header(maxidx)
|
1553
1547
|
if isinstance(self._headers, list) and self._headers:
|
1554
|
-
self._headers =
|
1548
|
+
self._headers = move_fast(self._headers, data_new_idxs, data_old_idxs)
|
1555
1549
|
maxidx = self.get_max_column_idx(maxidx)
|
1556
|
-
full_new_idxs = self.get_full_new_idxs(
|
1550
|
+
full_new_idxs, full_old_idxs = self.get_full_new_idxs(
|
1557
1551
|
max_idx=maxidx,
|
1558
1552
|
new_idxs=data_new_idxs,
|
1559
1553
|
old_idxs=data_old_idxs,
|
1554
|
+
get_inverse=True,
|
1560
1555
|
)
|
1561
|
-
full_old_idxs = dict(zip(full_new_idxs.values(), full_new_idxs))
|
1562
1556
|
self.tagged_cells = {
|
1563
1557
|
tags: {(k[0], full_new_idxs[k[1]]) for k in tagged} for tags, tagged in self.tagged_cells.items()
|
1564
1558
|
}
|
@@ -1731,14 +1725,14 @@ class MainTable(tk.Canvas):
|
|
1731
1725
|
data_old_idxs: dict[int, int],
|
1732
1726
|
maxidx: int,
|
1733
1727
|
) -> None:
|
1734
|
-
self.data =
|
1728
|
+
self.data = move_fast(
|
1735
1729
|
self.data,
|
1736
1730
|
data_new_idxs,
|
1737
1731
|
data_old_idxs,
|
1738
1732
|
)
|
1739
1733
|
self.RI.fix_index(maxidx)
|
1740
1734
|
if isinstance(self._row_index, list) and self._row_index:
|
1741
|
-
self._row_index =
|
1735
|
+
self._row_index = move_fast(self._row_index, data_new_idxs, data_old_idxs)
|
1742
1736
|
|
1743
1737
|
def move_rows_adjust_options_dict(
|
1744
1738
|
self,
|
@@ -1790,12 +1784,12 @@ class MainTable(tk.Canvas):
|
|
1790
1784
|
else:
|
1791
1785
|
self.move_rows_data(data_new_idxs, data_old_idxs, maxidx)
|
1792
1786
|
maxidx = self.get_max_row_idx(maxidx)
|
1793
|
-
full_new_idxs = self.get_full_new_idxs(
|
1787
|
+
full_new_idxs, full_old_idxs = self.get_full_new_idxs(
|
1794
1788
|
max_idx=maxidx,
|
1795
1789
|
new_idxs=data_new_idxs,
|
1796
1790
|
old_idxs=data_old_idxs,
|
1791
|
+
get_inverse=True,
|
1797
1792
|
)
|
1798
|
-
full_old_idxs = dict(zip(full_new_idxs.values(), full_new_idxs))
|
1799
1793
|
self.tagged_cells = {
|
1800
1794
|
tags: {(full_new_idxs[k[0]], k[1]) for k in tagged} for tags, tagged in self.tagged_cells.items()
|
1801
1795
|
}
|
@@ -1956,6 +1950,7 @@ class MainTable(tk.Canvas):
|
|
1956
1950
|
max_idx: int,
|
1957
1951
|
new_idxs: dict[int, int],
|
1958
1952
|
old_idxs: None | dict[int, int] = None,
|
1953
|
+
get_inverse: bool = False,
|
1959
1954
|
) -> dict[int, int]:
|
1960
1955
|
# return a dict of all row or column indexes
|
1961
1956
|
# old indexes and new indexes, not just the
|
@@ -1963,13 +1958,18 @@ class MainTable(tk.Canvas):
|
|
1963
1958
|
# {old index: new index, ...}
|
1964
1959
|
# all the way from 0 to max_idx
|
1965
1960
|
if old_idxs is None:
|
1966
|
-
old_idxs =
|
1967
|
-
|
1968
|
-
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1961
|
+
old_idxs = {v: k for k, v in new_idxs.items()}
|
1962
|
+
if get_inverse:
|
1963
|
+
d = {}
|
1964
|
+
d_in = {}
|
1965
|
+
for v, k in enumerate(move_elements_by_mapping_gen(tuple(range(max_idx + 1)), new_idxs, old_idxs)):
|
1966
|
+
d[k] = v
|
1967
|
+
d_in[v] = k
|
1968
|
+
return d, d_in
|
1969
|
+
else:
|
1970
|
+
return {
|
1971
|
+
k: v for v, k in enumerate(move_elements_by_mapping_gen(tuple(range(max_idx + 1)), new_idxs, old_idxs))
|
1972
|
+
}
|
1973
1973
|
|
1974
1974
|
def undo(self, event: Any = None) -> None | EventDataDict:
|
1975
1975
|
if not self.undo_stack:
|
@@ -4047,7 +4047,7 @@ class MainTable(tk.Canvas):
|
|
4047
4047
|
self.yview_scroll(-1, "units")
|
4048
4048
|
self.RI.yview_scroll(-1, "units")
|
4049
4049
|
self.y_move_synced_scrolls("moveto", self.yview()[0])
|
4050
|
-
self.main_table_redraw_grid_and_text(redraw_header=
|
4050
|
+
self.main_table_redraw_grid_and_text(redraw_header=False, redraw_row_index=True)
|
4051
4051
|
|
4052
4052
|
def shift_mousewheel(self, event: Any) -> None:
|
4053
4053
|
if event.delta < 0 or event.num == 5:
|
@@ -4060,7 +4060,7 @@ class MainTable(tk.Canvas):
|
|
4060
4060
|
self.xview_scroll(-1, "units")
|
4061
4061
|
self.CH.xview_scroll(-1, "units")
|
4062
4062
|
self.x_move_synced_scrolls("moveto", self.xview()[0])
|
4063
|
-
self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=
|
4063
|
+
self.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=False)
|
4064
4064
|
|
4065
4065
|
def ctrl_mousewheel(self, event: Any) -> None:
|
4066
4066
|
if event.delta < 0 or event.num == 5:
|
@@ -4441,7 +4441,7 @@ class MainTable(tk.Canvas):
|
|
4441
4441
|
self.cells_cache = self._redraw_precache_cells(disprn, disprn + 1, 0, len(self.col_positions) - 1)
|
4442
4442
|
if not (align := self.get_cell_kwargs(datarn, datacn, key="align")):
|
4443
4443
|
align = self.align
|
4444
|
-
if align
|
4444
|
+
if align[-1] == "w":
|
4445
4445
|
max_width += sum(
|
4446
4446
|
self._overflow(
|
4447
4447
|
self.cells_cache,
|
@@ -4449,7 +4449,7 @@ class MainTable(tk.Canvas):
|
|
4449
4449
|
datarn,
|
4450
4450
|
)
|
4451
4451
|
)
|
4452
|
-
elif align
|
4452
|
+
elif align[-1] == "e":
|
4453
4453
|
max_width += sum(
|
4454
4454
|
self._overflow(
|
4455
4455
|
self.cells_cache,
|
@@ -4768,6 +4768,7 @@ class MainTable(tk.Canvas):
|
|
4768
4768
|
self,
|
4769
4769
|
rows: list[int] | tuple[int],
|
4770
4770
|
create_ops: bool = True,
|
4771
|
+
tree: bool = True,
|
4771
4772
|
) -> None:
|
4772
4773
|
self.tagged_cells = {
|
4773
4774
|
tags: {(push_n(r, rows), c) for (r, c) in tagged} for tags, tagged in self.tagged_cells.items()
|
@@ -4777,7 +4778,8 @@ class MainTable(tk.Canvas):
|
|
4777
4778
|
self.tagged_rows = {tags: {push_n(r, rows) for r in tagged} for tags, tagged in self.tagged_rows.items()}
|
4778
4779
|
self.row_options = {push_n(r, rows): v for r, v in self.row_options.items()}
|
4779
4780
|
self.RI.cell_options = {push_n(r, rows): v for r, v in self.RI.cell_options.items()}
|
4780
|
-
|
4781
|
+
if tree:
|
4782
|
+
self.RI.rns = {k: push_n(r, rows) for k, r in self.RI.rns.items()}
|
4781
4783
|
# if there are named spans where rows were added
|
4782
4784
|
# add options to gap which was created by adding rows
|
4783
4785
|
totalcols = None
|
@@ -5044,7 +5046,7 @@ class MainTable(tk.Canvas):
|
|
5044
5046
|
event_data["added"]["rows"] = {
|
5045
5047
|
"table": {},
|
5046
5048
|
"index": {},
|
5047
|
-
"row_heights":
|
5049
|
+
"row_heights": dict.fromkeys(range(len(self.row_positions) - 1, maxrn + 1), default_height),
|
5048
5050
|
}
|
5049
5051
|
if not from_undo:
|
5050
5052
|
self.set_row_positions(
|
@@ -5168,7 +5170,7 @@ class MainTable(tk.Canvas):
|
|
5168
5170
|
event_data["added"]["columns"] = {
|
5169
5171
|
"table": {},
|
5170
5172
|
"header": {},
|
5171
|
-
"column_widths":
|
5173
|
+
"column_widths": dict.fromkeys(range(len(self.col_positions) - 1, maxcn + 1), default_width),
|
5172
5174
|
}
|
5173
5175
|
if not from_undo:
|
5174
5176
|
self.set_col_positions(
|
@@ -5181,6 +5183,7 @@ class MainTable(tk.Canvas):
|
|
5181
5183
|
self.adjust_options_post_add_rows(
|
5182
5184
|
rows=tuple(rows),
|
5183
5185
|
create_ops=create_ops,
|
5186
|
+
tree=tree,
|
5184
5187
|
)
|
5185
5188
|
event_data["added"]["rows"] = {
|
5186
5189
|
"table": rows,
|
@@ -6084,7 +6087,7 @@ class MainTable(tk.Canvas):
|
|
6084
6087
|
if draw_arrow:
|
6085
6088
|
mod = (self.table_txt_height - 1) if self.table_txt_height % 2 else self.table_txt_height
|
6086
6089
|
small_mod = int(mod / 5)
|
6087
|
-
mid_y =
|
6090
|
+
mid_y = int(self.min_row_height / 2)
|
6088
6091
|
if open_:
|
6089
6092
|
# up arrow
|
6090
6093
|
points = (
|
@@ -6283,19 +6286,25 @@ class MainTable(tk.Canvas):
|
|
6283
6286
|
# self.get_cell_kwargs not used here to boost performance
|
6284
6287
|
if t in self.cell_options and "dropdown" in self.cell_options[t]:
|
6285
6288
|
cells["dropdown"][t] = self.cell_options[t]["dropdown"]
|
6289
|
+
|
6286
6290
|
elif datarn in self.row_options and "dropdown" in self.row_options[datarn]:
|
6287
6291
|
cells["dropdown"][t] = self.row_options[datarn]["dropdown"]
|
6292
|
+
|
6288
6293
|
elif datacn in self.col_options and "dropdown" in self.col_options[datacn]:
|
6289
6294
|
cells["dropdown"][t] = self.col_options[datacn]["dropdown"]
|
6295
|
+
|
6290
6296
|
else:
|
6291
6297
|
if t in self.cell_options and "checkbox" in self.cell_options[t]:
|
6292
6298
|
cells["checkbox"][t] = self.cell_options[t]["checkbox"]
|
6299
|
+
|
6293
6300
|
elif datarn in self.row_options and "checkbox" in self.row_options[datarn]:
|
6294
6301
|
cells["checkbox"][t] = self.row_options[datarn]["checkbox"]
|
6302
|
+
|
6295
6303
|
elif datacn in self.col_options and "checkbox" in self.col_options[datacn]:
|
6296
6304
|
cells["checkbox"][t] = self.col_options[datacn]["checkbox"]
|
6297
6305
|
|
6298
6306
|
cells[t] = self.cell_str(datarn, datacn, get_displayed=True)
|
6307
|
+
|
6299
6308
|
return cells
|
6300
6309
|
|
6301
6310
|
def wrap_get_char_w(self, c: str) -> int:
|
@@ -6380,6 +6389,7 @@ class MainTable(tk.Canvas):
|
|
6380
6389
|
if changed_w:
|
6381
6390
|
for widget in (self, self.RI, self.CH, self.TL):
|
6382
6391
|
widget.update_idletasks()
|
6392
|
+
return
|
6383
6393
|
# important vars
|
6384
6394
|
x_stop = min(last_col_line_pos, scrollpos_right)
|
6385
6395
|
y_stop = min(last_row_line_pos, scrollpos_bot)
|
@@ -6452,14 +6462,14 @@ class MainTable(tk.Canvas):
|
|
6452
6462
|
else:
|
6453
6463
|
alternate_color = None
|
6454
6464
|
dont_blend = ()
|
6455
|
-
if
|
6465
|
+
if self.PAR.ops.show_selected_cells_border:
|
6466
|
+
override = ()
|
6467
|
+
else:
|
6456
6468
|
override = (
|
6457
6469
|
color_tup(self.PAR.ops.table_selected_cells_fg),
|
6458
6470
|
color_tup(self.PAR.ops.table_selected_columns_fg),
|
6459
6471
|
color_tup(self.PAR.ops.table_selected_rows_fg),
|
6460
6472
|
)
|
6461
|
-
else:
|
6462
|
-
override = ()
|
6463
6473
|
allow_overflow = self.PAR.ops.allow_cell_overflow
|
6464
6474
|
wrap = self.PAR.ops.table_wrap
|
6465
6475
|
cells = self._redraw_precache_cells(
|
@@ -6509,12 +6519,12 @@ class MainTable(tk.Canvas):
|
|
6509
6519
|
kws = cells["dropdown"][t] if t in cells["dropdown"] else None # noqa: SIM401
|
6510
6520
|
if kws:
|
6511
6521
|
max_width = crightgridln - cleftgridln - self.table_txt_height - 5
|
6512
|
-
if align
|
6522
|
+
if align[-1] == "w":
|
6513
6523
|
draw_x = cleftgridln + 2
|
6514
|
-
elif align
|
6524
|
+
elif align[-1] == "e":
|
6515
6525
|
draw_x = crightgridln - 5 - self.table_txt_height
|
6516
|
-
elif align
|
6517
|
-
draw_x = cleftgridln +
|
6526
|
+
elif align[-1] == "n":
|
6527
|
+
draw_x = cleftgridln + (crightgridln - cleftgridln - self.table_txt_height) / 2
|
6518
6528
|
self.redraw_dropdown(
|
6519
6529
|
cleftgridln,
|
6520
6530
|
rtopgridln,
|
@@ -6528,49 +6538,43 @@ class MainTable(tk.Canvas):
|
|
6528
6538
|
)
|
6529
6539
|
else:
|
6530
6540
|
max_width = crightgridln - cleftgridln - 2
|
6531
|
-
if align
|
6541
|
+
if align[-1] == "w":
|
6532
6542
|
draw_x = cleftgridln + 2
|
6533
|
-
elif align
|
6543
|
+
elif align[-1] == "e":
|
6534
6544
|
draw_x = crightgridln - 2
|
6535
|
-
elif align
|
6536
|
-
draw_x = cleftgridln +
|
6537
|
-
|
6538
|
-
|
6539
|
-
|
6540
|
-
|
6541
|
-
|
6542
|
-
|
6543
|
-
|
6544
|
-
|
6545
|
-
|
6546
|
-
|
6547
|
-
|
6548
|
-
|
6549
|
-
|
6550
|
-
|
6551
|
-
|
6552
|
-
|
6553
|
-
|
6554
|
-
|
6555
|
-
|
6556
|
-
|
6557
|
-
|
6558
|
-
|
6545
|
+
elif align[-1] == "n":
|
6546
|
+
draw_x = cleftgridln + (crightgridln - cleftgridln) / 2
|
6547
|
+
|
6548
|
+
if t in cells["checkbox"]:
|
6549
|
+
kws = cells["checkbox"][t]
|
6550
|
+
if max_width > self.table_txt_height + 1:
|
6551
|
+
box_w = self.table_txt_height + 1
|
6552
|
+
if align[-1] == "w":
|
6553
|
+
draw_x += box_w + 3
|
6554
|
+
elif align[-1] == "n":
|
6555
|
+
draw_x += box_w / 2 + 1
|
6556
|
+
max_width -= box_w + 4
|
6557
|
+
try:
|
6558
|
+
draw_check = bool(self.data[datarn][datacn])
|
6559
|
+
except Exception:
|
6560
|
+
draw_check = False
|
6561
|
+
self.redraw_checkbox(
|
6562
|
+
cleftgridln + 2,
|
6563
|
+
rtopgridln + 2,
|
6564
|
+
cleftgridln + self.table_txt_height + 3,
|
6565
|
+
rtopgridln + self.table_txt_height + 3,
|
6566
|
+
fill=fill if kws["state"] == "normal" else self.PAR.ops.table_grid_fg,
|
6567
|
+
outline="",
|
6568
|
+
draw_check=draw_check,
|
6569
|
+
)
|
6559
6570
|
text = cells[t]
|
6560
|
-
if (
|
6561
|
-
not text
|
6562
|
-
or (align.endswith("w") and draw_x > scrollpos_right)
|
6563
|
-
or (align.endswith("e") and cleftgridln + 5 > scrollpos_right)
|
6564
|
-
or (align.endswith("n") and cleftgridln + 5 > scrollpos_right)
|
6565
|
-
):
|
6571
|
+
if not text or (align[-1] == "w" and draw_x > scrollpos_right) or cleftgridln + 5 > scrollpos_right:
|
6566
6572
|
continue
|
6567
6573
|
if allow_overflow and not kws:
|
6568
|
-
if align
|
6574
|
+
if align[-1] == "w":
|
6569
6575
|
max_width += sum(self._overflow(cells, range(c + 1, text_end_col), datarn))
|
6570
|
-
elif align
|
6576
|
+
elif align[-1] == "e":
|
6571
6577
|
max_width += sum(self._overflow(cells, reversed(range(text_start_col, c)), datarn))
|
6572
|
-
elif align.endswith("n"):
|
6573
|
-
...
|
6574
6578
|
if max_width <= 1:
|
6575
6579
|
continue
|
6576
6580
|
start_line = max(0, int((scrollpos_top - rtopgridln) / self.table_txt_height))
|
@@ -6584,7 +6588,7 @@ class MainTable(tk.Canvas):
|
|
6584
6588
|
wrap=wrap,
|
6585
6589
|
start_line=start_line,
|
6586
6590
|
)
|
6587
|
-
if align
|
6591
|
+
if align[-1] == "w" or align[-1] == "e":
|
6588
6592
|
if self.hidd_text:
|
6589
6593
|
iid, showing = self.hidd_text.popitem()
|
6590
6594
|
self.coords(iid, draw_x, draw_y)
|
@@ -6617,15 +6621,15 @@ class MainTable(tk.Canvas):
|
|
6617
6621
|
)
|
6618
6622
|
self.disp_text[iid] = True
|
6619
6623
|
|
6620
|
-
elif align
|
6621
|
-
for
|
6624
|
+
elif align[-1] == "n":
|
6625
|
+
for t in gen_lines:
|
6622
6626
|
if self.hidd_text:
|
6623
6627
|
iid, showing = self.hidd_text.popitem()
|
6624
6628
|
self.coords(iid, draw_x, draw_y)
|
6625
6629
|
if showing:
|
6626
6630
|
self.itemconfig(
|
6627
6631
|
iid,
|
6628
|
-
text=
|
6632
|
+
text=t,
|
6629
6633
|
fill=fill,
|
6630
6634
|
font=font,
|
6631
6635
|
anchor=align,
|
@@ -6633,7 +6637,7 @@ class MainTable(tk.Canvas):
|
|
6633
6637
|
else:
|
6634
6638
|
self.itemconfig(
|
6635
6639
|
iid,
|
6636
|
-
text=
|
6640
|
+
text=t,
|
6637
6641
|
fill=fill,
|
6638
6642
|
font=font,
|
6639
6643
|
anchor=align,
|
@@ -6643,7 +6647,7 @@ class MainTable(tk.Canvas):
|
|
6643
6647
|
iid = self.create_text(
|
6644
6648
|
draw_x,
|
6645
6649
|
draw_y,
|
6646
|
-
text=
|
6650
|
+
text=t,
|
6647
6651
|
fill=fill,
|
6648
6652
|
font=font,
|
6649
6653
|
anchor=align,
|
@@ -6668,11 +6672,11 @@ class MainTable(tk.Canvas):
|
|
6668
6672
|
self.tag_raise(box.bd_iid)
|
6669
6673
|
if self.selected:
|
6670
6674
|
self.tag_raise(self.selected.iid)
|
6671
|
-
self.tag_raise("t")
|
6672
6675
|
if self.RI.disp_resize_lines:
|
6673
6676
|
self.tag_raise("rh")
|
6674
6677
|
if self.CH.disp_resize_lines:
|
6675
6678
|
self.tag_raise("rw")
|
6679
|
+
self.tag_raise("t")
|
6676
6680
|
if redraw_header and self.show_header:
|
6677
6681
|
self.CH.redraw_grid_and_text(
|
6678
6682
|
last_col_line_pos=last_col_line_pos,
|
@@ -6781,7 +6785,7 @@ class MainTable(tk.Canvas):
|
|
6781
6785
|
box = next(iter(reversed(self.selection_boxes.values())))
|
6782
6786
|
r1, c1, r2, c2 = box.coords
|
6783
6787
|
if r2 - r1 == 1 and c2 - c1 == 1:
|
6784
|
-
|
6788
|
+
box.state = "hidden"
|
6785
6789
|
self.set_currently_selected(item=box.fill_iid)
|
6786
6790
|
|
6787
6791
|
def coords_and_type(self, item: int) -> tuple:
|
@@ -7117,9 +7121,10 @@ class MainTable(tk.Canvas):
|
|
7117
7121
|
|
7118
7122
|
def get_redraw_selections(self, startr: int, endr: int, startc: int, endc: int) -> dict:
|
7119
7123
|
d = defaultdict(set)
|
7124
|
+
ignore_hidd_current = not self.PAR.ops.show_selected_cells_border
|
7120
7125
|
for _, box in self.get_selection_items():
|
7121
7126
|
r1, c1, r2, c2 = box.coords
|
7122
|
-
if box.state == "normal":
|
7127
|
+
if box.state == "normal" or ignore_hidd_current:
|
7123
7128
|
if box.type_ == "cells":
|
7124
7129
|
for r in range(startr, endr):
|
7125
7130
|
for c in range(startc, endc):
|
@@ -8081,23 +8086,49 @@ class MainTable(tk.Canvas):
|
|
8081
8086
|
cell value is not in datatypes kwarg
|
8082
8087
|
if get displayed is true then Nones are replaced by
|
8083
8088
|
"""
|
8084
|
-
kwargs = self.get_cell_kwargs(datarn, datacn, key=None)
|
8085
8089
|
if get_displayed:
|
8086
|
-
|
8087
|
-
|
8088
|
-
|
8089
|
-
elif
|
8090
|
-
|
8090
|
+
# check for dropdown
|
8091
|
+
if (datarn, datacn) in self.cell_options and "dropdown" in self.cell_options[(datarn, datacn)]:
|
8092
|
+
kws = self.cell_options[(datarn, datacn)]["dropdown"]
|
8093
|
+
elif datarn in self.row_options and "dropdown" in self.row_options[datarn]:
|
8094
|
+
kws = self.row_options[datarn]["dropdown"]
|
8095
|
+
elif datacn in self.col_options and "dropdown" in self.col_options[datacn]:
|
8096
|
+
kws = self.col_options[datacn]["dropdown"]
|
8097
|
+
else:
|
8098
|
+
kws = None
|
8099
|
+
if kws and kws["text"] is not None:
|
8100
|
+
return f"{kws['text']}"
|
8101
|
+
|
8102
|
+
# check for checkbox
|
8103
|
+
if (datarn, datacn) in self.cell_options and "checkbox" in self.cell_options[(datarn, datacn)]:
|
8104
|
+
kws = self.cell_options[(datarn, datacn)]["checkbox"]
|
8105
|
+
elif datarn in self.row_options and "checkbox" in self.row_options[datarn]:
|
8106
|
+
kws = self.row_options[datarn]["checkbox"]
|
8107
|
+
elif datacn in self.col_options and "checkbox" in self.col_options[datacn]:
|
8108
|
+
kws = self.col_options[datacn]["checkbox"]
|
8109
|
+
else:
|
8110
|
+
kws = None
|
8111
|
+
if kws:
|
8112
|
+
return f"{kws['text']}"
|
8091
8113
|
try:
|
8092
8114
|
value = self.data[datarn][datacn]
|
8093
8115
|
except Exception:
|
8094
8116
|
value = ""
|
8095
|
-
|
8096
|
-
|
8117
|
+
# check for format
|
8118
|
+
if (datarn, datacn) in self.cell_options and "format" in self.cell_options[(datarn, datacn)]:
|
8119
|
+
kws = self.cell_options[(datarn, datacn)]["format"]
|
8120
|
+
elif datarn in self.row_options and "format" in self.row_options[datarn]:
|
8121
|
+
kws = self.row_options[datarn]["format"]
|
8122
|
+
elif datacn in self.col_options and "format" in self.col_options[datacn]:
|
8123
|
+
kws = self.col_options[datacn]["format"]
|
8124
|
+
else:
|
8125
|
+
kws = None
|
8126
|
+
if kws:
|
8127
|
+
if kws["formatter"] is None:
|
8097
8128
|
if get_displayed:
|
8098
|
-
return data_to_str(value, **
|
8129
|
+
return data_to_str(value, **kws)
|
8099
8130
|
else:
|
8100
|
-
return f"{get_data_with_valid_check(value, **
|
8131
|
+
return f"{get_data_with_valid_check(value, **kws)}"
|
8101
8132
|
else:
|
8102
8133
|
if get_displayed:
|
8103
8134
|
# assumed given formatter class has __str__()
|
@@ -8106,7 +8137,7 @@ class MainTable(tk.Canvas):
|
|
8106
8137
|
# assumed given formatter class has get_data_with_valid_check()
|
8107
8138
|
return f"{value.get_data_with_valid_check()}"
|
8108
8139
|
else:
|
8109
|
-
return "" if value is None else
|
8140
|
+
return "" if value is None else str(value)
|
8110
8141
|
|
8111
8142
|
def get_cell_data(
|
8112
8143
|
self,
|
tksheet/other_classes.py
CHANGED
tksheet/row_index.py
CHANGED
@@ -3,9 +3,10 @@ from __future__ import annotations
|
|
3
3
|
import tkinter as tk
|
4
4
|
from collections import defaultdict
|
5
5
|
from collections.abc import Callable, Generator, Hashable, Iterator, Sequence
|
6
|
+
from contextlib import suppress
|
6
7
|
from functools import partial
|
7
|
-
from itertools import
|
8
|
-
from math import ceil
|
8
|
+
from itertools import cycle, islice, repeat
|
9
|
+
from math import ceil
|
9
10
|
from operator import itemgetter
|
10
11
|
from typing import Any, Literal
|
11
12
|
|
@@ -758,7 +759,7 @@ class RowIndex(tk.Canvas):
|
|
758
759
|
if size < self.MT.min_row_height:
|
759
760
|
new_row_pos = ceil(self.MT.row_positions[self.rsz_h - 1] + self.MT.min_row_height)
|
760
761
|
elif size > self.ops.max_row_height:
|
761
|
-
new_row_pos =
|
762
|
+
new_row_pos = int(self.MT.row_positions[self.rsz_h - 1] + self.ops.max_row_height)
|
762
763
|
increment = new_row_pos - self.MT.row_positions[self.rsz_h]
|
763
764
|
self.MT.row_positions[self.rsz_h + 1 :] = [
|
764
765
|
e + increment for e in islice(self.MT.row_positions, self.rsz_h + 1, None)
|
@@ -1071,7 +1072,7 @@ class RowIndex(tk.Canvas):
|
|
1071
1072
|
align = self.cell_options[datarn]["align"]
|
1072
1073
|
else:
|
1073
1074
|
align = self.align
|
1074
|
-
if align
|
1075
|
+
if align[-1] == "w":
|
1075
1076
|
w += self.MT.index_txt_height
|
1076
1077
|
w += self.get_iid_indent(self.MT._row_index[datarn].iid) + 10
|
1077
1078
|
return w, h
|
@@ -1245,7 +1246,7 @@ class RowIndex(tk.Canvas):
|
|
1245
1246
|
new_w = self.get_index_text_width(only_rows=only_rows)
|
1246
1247
|
else:
|
1247
1248
|
new_w = None
|
1248
|
-
if new_w is not None and (sheet_w_x :=
|
1249
|
+
if new_w is not None and (sheet_w_x := int(self.PAR.winfo_width() * 0.7)) < new_w:
|
1249
1250
|
new_w = sheet_w_x
|
1250
1251
|
if new_w and (self.current_width - new_w > 20 or new_w - self.current_width > 3):
|
1251
1252
|
if self.MT.find_window.open:
|
@@ -1394,7 +1395,7 @@ class RowIndex(tk.Canvas):
|
|
1394
1395
|
) -> None:
|
1395
1396
|
mod = (self.MT.index_txt_height - 1) if self.MT.index_txt_height % 2 else self.MT.index_txt_height
|
1396
1397
|
small_mod = int(mod / 5)
|
1397
|
-
mid_y =
|
1398
|
+
mid_y = int(self.MT.min_row_height / 2)
|
1398
1399
|
if has_children:
|
1399
1400
|
# up arrow
|
1400
1401
|
if open_:
|
@@ -1490,7 +1491,7 @@ class RowIndex(tk.Canvas):
|
|
1490
1491
|
if draw_arrow:
|
1491
1492
|
mod = (self.MT.index_txt_height - 1) if self.MT.index_txt_height % 2 else self.MT.index_txt_height
|
1492
1493
|
small_mod = int(mod / 5)
|
1493
|
-
mid_y =
|
1494
|
+
mid_y = int(self.MT.min_row_height / 2)
|
1494
1495
|
if open_:
|
1495
1496
|
# up arrow
|
1496
1497
|
points = (
|
@@ -1673,13 +1674,13 @@ class RowIndex(tk.Canvas):
|
|
1673
1674
|
else:
|
1674
1675
|
align = self.align
|
1675
1676
|
if dropdown_kwargs:
|
1676
|
-
max_width = self.current_width - self.MT.index_txt_height -
|
1677
|
-
if align
|
1677
|
+
max_width = self.current_width - self.MT.index_txt_height - 5
|
1678
|
+
if align[-1] == "w":
|
1678
1679
|
draw_x = 3
|
1679
|
-
elif align
|
1680
|
+
elif align[-1] == "e":
|
1680
1681
|
draw_x = self.current_width - 5 - self.MT.index_txt_height
|
1681
|
-
elif align
|
1682
|
-
draw_x =
|
1682
|
+
elif align[-1] == "n":
|
1683
|
+
draw_x = (self.current_width - self.MT.index_txt_height) / 2
|
1683
1684
|
self.redraw_dropdown(
|
1684
1685
|
0,
|
1685
1686
|
rtopgridln,
|
@@ -1694,22 +1695,22 @@ class RowIndex(tk.Canvas):
|
|
1694
1695
|
)
|
1695
1696
|
else:
|
1696
1697
|
max_width = self.current_width - 2
|
1697
|
-
if align
|
1698
|
+
if align[-1] == "w":
|
1698
1699
|
draw_x = 3
|
1699
|
-
elif align
|
1700
|
+
elif align[-1] == "e":
|
1700
1701
|
draw_x = self.current_width - 3
|
1701
|
-
elif align
|
1702
|
-
draw_x =
|
1702
|
+
elif align[-1] == "n":
|
1703
|
+
draw_x = self.current_width / 2
|
1703
1704
|
if (
|
1704
1705
|
(checkbox_kwargs := self.get_cell_kwargs(datarn, key="checkbox"))
|
1705
1706
|
and not dropdown_kwargs
|
1706
1707
|
and max_width > self.MT.index_txt_height + 1
|
1707
1708
|
):
|
1708
1709
|
box_w = self.MT.index_txt_height + 1
|
1709
|
-
if align
|
1710
|
+
if align[-1] == "w":
|
1710
1711
|
draw_x += box_w + 3
|
1711
|
-
elif align
|
1712
|
-
draw_x +=
|
1712
|
+
elif align[-1] == "n":
|
1713
|
+
draw_x += box_w / 2 + 1
|
1713
1714
|
max_width -= box_w + 4
|
1714
1715
|
try:
|
1715
1716
|
draw_check = (
|
@@ -1732,7 +1733,7 @@ class RowIndex(tk.Canvas):
|
|
1732
1733
|
if treeview and isinstance(self.MT._row_index, list) and len(self.MT._row_index) > datarn:
|
1733
1734
|
iid = self.MT._row_index[datarn].iid
|
1734
1735
|
max_width -= self.MT.index_txt_height
|
1735
|
-
if align
|
1736
|
+
if align[-1] == "w":
|
1736
1737
|
draw_x += self.MT.index_txt_height + 3
|
1737
1738
|
level, indent = self.get_iid_level_indent(iid)
|
1738
1739
|
draw_x += indent + 5
|
@@ -2729,16 +2730,17 @@ class RowIndex(tk.Canvas):
|
|
2729
2730
|
)
|
2730
2731
|
# deal with displayed mapping
|
2731
2732
|
event_data["moved"]["rows"]["displayed"] = {}
|
2732
|
-
|
2733
|
-
if
|
2734
|
-
if
|
2735
|
-
|
2733
|
+
with suppress(Exception):
|
2734
|
+
if new_loc_is_displayed:
|
2735
|
+
if disp_insert_row is None:
|
2736
|
+
if new_parent or insert_row > move_to_row:
|
2737
|
+
disp_insert_row = self.MT.disprn(self.rns[move_to_iid]) + 1
|
2738
|
+
else:
|
2739
|
+
disp_insert_row = self.MT.disprn(self.rns[move_to_iid])
|
2740
|
+
if (disp_from_row := self.MT.try_disprn(self.rns[item])) is not None:
|
2741
|
+
event_data["moved"]["rows"]["displayed"] = {disp_from_row: disp_insert_row}
|
2736
2742
|
else:
|
2737
|
-
|
2738
|
-
if (disp_from_row := self.MT.try_disprn(self.rns[item])) is not None:
|
2739
|
-
event_data["moved"]["rows"]["displayed"] = {disp_from_row: disp_insert_row}
|
2740
|
-
else:
|
2741
|
-
event_data["moved"]["rows"]["displayed"] = {(): disp_insert_row}
|
2743
|
+
event_data["moved"]["rows"]["displayed"] = {(): disp_insert_row}
|
2742
2744
|
|
2743
2745
|
if any(self.move_pid_causes_recursive_loop(self.MT._row_index[r].iid, new_parent) for r in moved_rows):
|
2744
2746
|
event_data["moved"]["rows"] = {}
|
@@ -2759,7 +2761,7 @@ class RowIndex(tk.Canvas):
|
|
2759
2761
|
event_data["moved"]["rows"]["data"],
|
2760
2762
|
)
|
2761
2763
|
data_new_idxs = event_data["moved"]["rows"]["data"]
|
2762
|
-
data_old_idxs =
|
2764
|
+
data_old_idxs = {v: k for k, v in data_new_idxs.items()}
|
2763
2765
|
|
2764
2766
|
if () in event_data["moved"]["rows"]["displayed"]:
|
2765
2767
|
del event_data["moved"]["rows"]["displayed"][()]
|
@@ -2988,15 +2990,6 @@ class RowIndex(tk.Canvas):
|
|
2988
2990
|
if not parent_node.children:
|
2989
2991
|
self.tree_open_ids.discard(parent_node.iid)
|
2990
2992
|
|
2991
|
-
def build_pid_causes_recursive_loop(self, iid: str, pid: str) -> bool:
|
2992
|
-
return any(
|
2993
|
-
i == pid
|
2994
|
-
for i in chain(
|
2995
|
-
self.get_iid_descendants(iid),
|
2996
|
-
islice(self.get_iid_ancestors(iid), 1, None),
|
2997
|
-
)
|
2998
|
-
)
|
2999
|
-
|
3000
2993
|
def move_pid_causes_recursive_loop(self, to_move_iid: str, move_to_parent: str) -> bool:
|
3001
2994
|
# if the parent the item is being moved under is one of the item's descendants
|
3002
2995
|
# then it is a recursive loop
|
@@ -3017,8 +3010,8 @@ class RowIndex(tk.Canvas):
|
|
3017
3010
|
include_parent_column: bool = True,
|
3018
3011
|
include_text_column: bool = True,
|
3019
3012
|
) -> None:
|
3020
|
-
index = self.MT._row_index
|
3021
3013
|
data_rns = {}
|
3014
|
+
tree = {}
|
3022
3015
|
if text_column is None:
|
3023
3016
|
text_column = iid_column
|
3024
3017
|
if not isinstance(ncols, int):
|
@@ -3030,33 +3023,27 @@ class RowIndex(tk.Canvas):
|
|
3030
3023
|
else:
|
3031
3024
|
iid = row[iid_column]
|
3032
3025
|
pid = row[parent_column]
|
3033
|
-
if iid in
|
3034
|
-
|
3026
|
+
if iid in tree:
|
3027
|
+
tree[iid].text = row[text_column] if isinstance(text_column, int) else text_column[rn]
|
3035
3028
|
else:
|
3036
|
-
|
3037
|
-
|
3038
|
-
|
3039
|
-
|
3040
|
-
parent="",
|
3041
|
-
)
|
3029
|
+
tree[iid] = Node(
|
3030
|
+
text=row[text_column] if isinstance(text_column, int) else text_column[rn],
|
3031
|
+
iid=iid,
|
3032
|
+
parent="",
|
3042
3033
|
)
|
3043
|
-
self.rns[iid] = len(index) - 1
|
3044
3034
|
data_rns[iid] = rn
|
3045
3035
|
if pid:
|
3046
|
-
if pid in
|
3047
|
-
|
3036
|
+
if pid in tree:
|
3037
|
+
tree[pid].children.append(iid)
|
3048
3038
|
else:
|
3049
|
-
|
3050
|
-
|
3051
|
-
|
3052
|
-
|
3053
|
-
children=[iid],
|
3054
|
-
)
|
3039
|
+
tree[pid] = Node(
|
3040
|
+
text=pid,
|
3041
|
+
iid=pid,
|
3042
|
+
children=[iid],
|
3055
3043
|
)
|
3056
|
-
|
3057
|
-
index[self.rns[iid]].parent = pid
|
3044
|
+
tree[iid].parent = pid
|
3058
3045
|
else:
|
3059
|
-
|
3046
|
+
tree[iid].parent = ""
|
3060
3047
|
exclude = set()
|
3061
3048
|
if not include_iid_column:
|
3062
3049
|
exclude.add(iid_column)
|
@@ -3065,18 +3052,35 @@ class RowIndex(tk.Canvas):
|
|
3065
3052
|
if isinstance(text_column, int) and not include_text_column:
|
3066
3053
|
exclude.add(text_column)
|
3067
3054
|
rows = []
|
3055
|
+
ctr = 0
|
3068
3056
|
if exclude:
|
3069
|
-
for iid in
|
3070
|
-
|
3071
|
-
|
3072
|
-
|
3057
|
+
for iid, node in tree.items():
|
3058
|
+
if node.parent == "":
|
3059
|
+
row = [tree[iid]]
|
3060
|
+
row.extend(e for i, e in enumerate(data[data_rns[iid]]) if i not in exclude)
|
3061
|
+
rows.append(row)
|
3062
|
+
self.rns[iid] = ctr
|
3063
|
+
ctr += 1
|
3064
|
+
for diid in self._build_get_descendants(iid, tree):
|
3065
|
+
row = [tree[diid]]
|
3066
|
+
row.extend(e for i, e in enumerate(data[data_rns[diid]]) if i not in exclude)
|
3067
|
+
rows.append(row)
|
3068
|
+
self.rns[diid] = ctr
|
3069
|
+
ctr += 1
|
3073
3070
|
else:
|
3074
|
-
for iid in
|
3075
|
-
|
3076
|
-
|
3077
|
-
|
3078
|
-
|
3079
|
-
|
3071
|
+
for iid, node in tree.items():
|
3072
|
+
if node.parent == "":
|
3073
|
+
row = [tree[iid]]
|
3074
|
+
row.extend(data[data_rns[iid]])
|
3075
|
+
rows.append(row)
|
3076
|
+
self.rns[iid] = ctr
|
3077
|
+
ctr += 1
|
3078
|
+
for diid in self._build_get_descendants(iid, tree):
|
3079
|
+
row = [tree[diid]]
|
3080
|
+
row.extend(data[data_rns[diid]])
|
3081
|
+
rows.append(row)
|
3082
|
+
self.rns[diid] = ctr
|
3083
|
+
ctr += 1
|
3080
3084
|
self.PAR.insert_rows(
|
3081
3085
|
rows=rows,
|
3082
3086
|
idx=0,
|
@@ -3091,7 +3095,6 @@ class RowIndex(tk.Canvas):
|
|
3091
3095
|
)
|
3092
3096
|
self.MT.all_rows_displayed = False
|
3093
3097
|
self.MT.displayed_rows = list(range(len(self.MT._row_index)))
|
3094
|
-
self.rns = {n.iid: i for i, n in enumerate(self.MT._row_index)}
|
3095
3098
|
if open_ids:
|
3096
3099
|
self.PAR.tree_set_open(open_ids=open_ids)
|
3097
3100
|
else:
|
@@ -3118,8 +3121,8 @@ class RowIndex(tk.Canvas):
|
|
3118
3121
|
include_parent_column: bool = True,
|
3119
3122
|
include_text_column: bool = True,
|
3120
3123
|
) -> None:
|
3121
|
-
index = self.MT._row_index
|
3122
3124
|
data_rns = {}
|
3125
|
+
tree = {}
|
3123
3126
|
iids_missing_rows = set()
|
3124
3127
|
if text_column is None:
|
3125
3128
|
text_column = iid_column
|
@@ -3146,43 +3149,36 @@ class RowIndex(tk.Canvas):
|
|
3146
3149
|
x += 1
|
3147
3150
|
tally_of_ids[iid] += 1
|
3148
3151
|
row[iid_column] = new
|
3149
|
-
if iid in
|
3150
|
-
|
3152
|
+
if iid in tree:
|
3153
|
+
tree[iid].text = row[text_column] if isinstance(text_column, int) else text_column[rn]
|
3151
3154
|
else:
|
3152
|
-
|
3153
|
-
|
3154
|
-
|
3155
|
-
|
3156
|
-
parent="",
|
3157
|
-
)
|
3155
|
+
tree[iid] = Node(
|
3156
|
+
text=row[text_column] if isinstance(text_column, int) else text_column[rn],
|
3157
|
+
iid=iid,
|
3158
|
+
parent="",
|
3158
3159
|
)
|
3159
|
-
self.rns[iid] = len(index) - 1
|
3160
3160
|
if iid in iids_missing_rows:
|
3161
3161
|
iids_missing_rows.discard(iid)
|
3162
3162
|
data_rns[iid] = rn
|
3163
|
-
if iid == pid or self.build_pid_causes_recursive_loop(iid, pid):
|
3163
|
+
if iid == pid or self.build_pid_causes_recursive_loop(iid, pid, tree):
|
3164
3164
|
row[parent_column] = ""
|
3165
3165
|
pid = ""
|
3166
3166
|
if pid:
|
3167
|
-
if pid in
|
3168
|
-
|
3167
|
+
if pid in tree:
|
3168
|
+
tree[pid].children.append(iid)
|
3169
3169
|
else:
|
3170
|
-
|
3171
|
-
|
3172
|
-
|
3173
|
-
|
3174
|
-
children=[iid],
|
3175
|
-
)
|
3170
|
+
tree[pid] = Node(
|
3171
|
+
text=pid,
|
3172
|
+
iid=pid,
|
3173
|
+
children=[iid],
|
3176
3174
|
)
|
3177
3175
|
iids_missing_rows.add(pid)
|
3178
|
-
|
3179
|
-
index[self.rns[iid]].parent = pid
|
3176
|
+
tree[iid].parent = pid
|
3180
3177
|
else:
|
3181
|
-
|
3178
|
+
tree[iid].parent = ""
|
3182
3179
|
empty_rows = {}
|
3183
3180
|
for iid in iids_missing_rows:
|
3184
|
-
node =
|
3185
|
-
node.parent = ""
|
3181
|
+
node = tree[iid]
|
3186
3182
|
newrow = self.MT.get_empty_row_seq(len(data), ncols)
|
3187
3183
|
newrow[iid_column] = node.iid
|
3188
3184
|
empty_rows[node.iid] = newrow
|
@@ -3194,24 +3190,41 @@ class RowIndex(tk.Canvas):
|
|
3194
3190
|
if isinstance(text_column, int) and not include_text_column:
|
3195
3191
|
exclude.add(text_column)
|
3196
3192
|
rows = []
|
3193
|
+
ctr = 0
|
3197
3194
|
if exclude:
|
3198
|
-
for iid in
|
3199
|
-
|
3200
|
-
|
3201
|
-
|
3202
|
-
|
3203
|
-
|
3204
|
-
|
3195
|
+
for iid, node in tree.items():
|
3196
|
+
if node.parent == "":
|
3197
|
+
row = [tree[iid]]
|
3198
|
+
if iid in empty_rows:
|
3199
|
+
row.extend(e for i, e in enumerate(empty_rows[iid]) if i not in exclude)
|
3200
|
+
else:
|
3201
|
+
row.extend(e for i, e in enumerate(data[data_rns[iid]]) if i not in exclude)
|
3202
|
+
rows.append(row)
|
3203
|
+
self.rns[iid] = ctr
|
3204
|
+
ctr += 1
|
3205
|
+
for diid in self._build_get_descendants(iid, tree):
|
3206
|
+
row = [tree[diid]]
|
3207
|
+
row.extend(e for i, e in enumerate(data[data_rns[diid]]) if i not in exclude)
|
3208
|
+
rows.append(row)
|
3209
|
+
self.rns[diid] = ctr
|
3210
|
+
ctr += 1
|
3205
3211
|
else:
|
3206
|
-
for iid in
|
3207
|
-
|
3208
|
-
|
3209
|
-
|
3210
|
-
|
3211
|
-
|
3212
|
-
|
3213
|
-
|
3214
|
-
|
3212
|
+
for iid, node in tree.items():
|
3213
|
+
if node.parent == "":
|
3214
|
+
row = [tree[iid]]
|
3215
|
+
if iid in empty_rows:
|
3216
|
+
row.extend(empty_rows[iid])
|
3217
|
+
else:
|
3218
|
+
row.extend(data[data_rns[iid]])
|
3219
|
+
rows.append(row)
|
3220
|
+
self.rns[iid] = ctr
|
3221
|
+
ctr += 1
|
3222
|
+
for diid in self._build_get_descendants(iid, tree):
|
3223
|
+
row = [tree[diid]]
|
3224
|
+
row.extend(data[data_rns[diid]])
|
3225
|
+
rows.append(row)
|
3226
|
+
self.rns[diid] = ctr
|
3227
|
+
ctr += 1
|
3215
3228
|
self.PAR.insert_rows(
|
3216
3229
|
rows=rows,
|
3217
3230
|
idx=0,
|
@@ -3226,7 +3239,6 @@ class RowIndex(tk.Canvas):
|
|
3226
3239
|
)
|
3227
3240
|
self.MT.all_rows_displayed = False
|
3228
3241
|
self.MT.displayed_rows = list(range(len(self.MT._row_index)))
|
3229
|
-
self.rns = {n.iid: i for i, n in enumerate(self.MT._row_index)}
|
3230
3242
|
if open_ids:
|
3231
3243
|
self.PAR.tree_set_open(open_ids=open_ids)
|
3232
3244
|
else:
|
@@ -3237,3 +3249,29 @@ class RowIndex(tk.Canvas):
|
|
3237
3249
|
data_indexes=True,
|
3238
3250
|
row_heights=row_heights is not False,
|
3239
3251
|
)
|
3252
|
+
|
3253
|
+
def _build_get_descendants(self, iid: str, tree: dict[str, Node]) -> Generator[str]:
|
3254
|
+
stack = [iter(tree[iid].children)]
|
3255
|
+
while stack:
|
3256
|
+
top_iterator = stack[-1]
|
3257
|
+
try:
|
3258
|
+
ciid = next(top_iterator)
|
3259
|
+
yield ciid
|
3260
|
+
if tree[ciid].children:
|
3261
|
+
stack.append(iter(tree[ciid].children))
|
3262
|
+
except StopIteration:
|
3263
|
+
stack.pop()
|
3264
|
+
|
3265
|
+
def build_pid_causes_recursive_loop(self, iid: str, pid: str, tree: dict[str, Node]) -> bool:
|
3266
|
+
# check descendants
|
3267
|
+
for diid in self._build_get_descendants(iid, tree):
|
3268
|
+
if diid == pid:
|
3269
|
+
return True
|
3270
|
+
# check ancestors
|
3271
|
+
current_iid = iid
|
3272
|
+
while tree[current_iid].parent:
|
3273
|
+
parent_iid = tree[current_iid].parent
|
3274
|
+
if parent_iid == pid:
|
3275
|
+
return True
|
3276
|
+
current_iid = parent_iid
|
3277
|
+
return False
|
tksheet/sheet.py
CHANGED
@@ -127,7 +127,7 @@ class Sheet(tk.Frame):
|
|
127
127
|
max_row_height: float = float("inf"),
|
128
128
|
max_header_height: float = float("inf"),
|
129
129
|
max_index_width: float = float("inf"),
|
130
|
-
after_redraw_time_ms: int =
|
130
|
+
after_redraw_time_ms: int = 16,
|
131
131
|
set_all_heights_and_widths: bool = False,
|
132
132
|
zoom: int = 100,
|
133
133
|
align: str = "nw",
|
@@ -4647,10 +4647,9 @@ class Sheet(tk.Frame):
|
|
4647
4647
|
if index[rns[item]].children:
|
4648
4648
|
open_ids.add(item)
|
4649
4649
|
if rns[item] in disp_set:
|
4650
|
-
|
4651
|
-
|
4652
|
-
|
4653
|
-
to_open.extend(to_disp)
|
4650
|
+
for did in descendants(item, check_open=True):
|
4651
|
+
disp_set.add(rns[did])
|
4652
|
+
to_open.append(rns[did])
|
4654
4653
|
return to_open
|
4655
4654
|
|
4656
4655
|
def tree_open(self, *items, redraw: bool = True) -> Sheet:
|
@@ -4924,7 +4923,7 @@ class Sheet(tk.Frame):
|
|
4924
4923
|
"""
|
4925
4924
|
Also deletes all descendants of items
|
4926
4925
|
"""
|
4927
|
-
rows = list(map(self.RI.rns.
|
4926
|
+
rows = list(map(self.RI.rns.__getitem__, filter(self.exists, unpack(items))))
|
4928
4927
|
if rows:
|
4929
4928
|
self.del_rows(rows, data_indexes=True, undo=undo)
|
4930
4929
|
return self.set_refresh_timer(rows)
|
@@ -5138,13 +5137,20 @@ class Sheet(tk.Frame):
|
|
5138
5137
|
for func in self.bound_events[event]:
|
5139
5138
|
func(data)
|
5140
5139
|
|
5141
|
-
def set_refresh_timer(
|
5140
|
+
def set_refresh_timer(
|
5141
|
+
self,
|
5142
|
+
redraw: bool = True,
|
5143
|
+
index: bool = True,
|
5144
|
+
header: bool = True,
|
5145
|
+
) -> Sheet:
|
5142
5146
|
if redraw and self.after_redraw_id is None:
|
5143
|
-
self.after_redraw_id = self.after(
|
5147
|
+
self.after_redraw_id = self.after(
|
5148
|
+
self.after_redraw_time_ms, lambda: self.after_redraw(index=index, header=header)
|
5149
|
+
)
|
5144
5150
|
return self
|
5145
5151
|
|
5146
|
-
def after_redraw(self) -> None:
|
5147
|
-
self.MT.main_table_redraw_grid_and_text(redraw_header=
|
5152
|
+
def after_redraw(self, index: bool = True, header: bool = True) -> None:
|
5153
|
+
self.MT.main_table_redraw_grid_and_text(redraw_header=header, redraw_row_index=index)
|
5148
5154
|
self.after_redraw_id = None
|
5149
5155
|
|
5150
5156
|
def del_options_using_span(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: tksheet
|
3
|
-
Version: 7.4.
|
3
|
+
Version: 7.4.13
|
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,23 +63,23 @@ 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</a></td>
|
66
|
+
<td><a href="https://github.com/ragardner/tksheet/wiki/Version-6" target="_blank">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://ragardner.github.io/tksheet/DOCUMENTATION.html">Documentation</a></td>
|
70
|
+
<td><a href="https://ragardner.github.io/tksheet/DOCUMENTATION.html" target="_blank">Documentation</a></td>
|
71
71
|
</tr>
|
72
72
|
<tr>
|
73
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md">Changelog</a></td>
|
73
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md" target="_blank">Changelog</a></td>
|
74
74
|
</tr>
|
75
75
|
<tr>
|
76
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#asking-questions">Questions</a></td>
|
76
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#asking-questions" target="_blank">Questions</a></td>
|
77
77
|
</tr>
|
78
78
|
<tr>
|
79
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#issues">Issues</a></td>
|
79
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#issues" target="_blank">Issues</a></td>
|
80
80
|
</tr>
|
81
81
|
<tr>
|
82
|
-
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#enhancements-or-suggestions">Suggestions and Contributors</a></td>
|
82
|
+
<td align="right" colspan="2"><a href="https://github.com/ragardner/tksheet/wiki/Version-7#enhancements-or-suggestions" target="_blank">Suggestions and Contributors</a></td>
|
83
83
|
</tr>
|
84
84
|
</tbody>
|
85
85
|
</table>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
tksheet/__init__.py,sha256=CdTPPFo67goThv2unHBQc8yvXaJncIkDk6fZVh6jpEk,2327
|
2
|
+
tksheet/colors.py,sha256=dHhmdFuQDlwohDHsAfT9VdrKoSl_R33L72a3HCin5zo,51591
|
3
|
+
tksheet/column_headers.py,sha256=Ztr5QvTo3u9ANbZXheECMzRwZ9KvYnQQu-fncOJfNGg,102657
|
4
|
+
tksheet/constants.py,sha256=aiDvUSaPtl_TSNtRRJ_p87c9iTBz9ksMd5IsSXzz4Hk,13316
|
5
|
+
tksheet/find_window.py,sha256=TvbSqO42cw1o1AO0tQ0Q1iZogouNr4ObMo7JfkZCxgA,19877
|
6
|
+
tksheet/formatters.py,sha256=DGcRiMsDJnySNpQcjfiX84oJ7TmOSMdU6u9injIhA4g,10095
|
7
|
+
tksheet/functions.py,sha256=qks2dLqBE9GMAuEXaA4qiU-rrL-dzmz4-tkmkp6_ETk,53037
|
8
|
+
tksheet/main_table.py,sha256=rm1ZeVRXTv-CwxKirFrssjIz4fvrxNH7pw0JAwUOcH4,364840
|
9
|
+
tksheet/other_classes.py,sha256=B2SrUAviztDUOPGoWkcu-AixqAaKwItshoVZPGe1_Tc,16662
|
10
|
+
tksheet/row_index.py,sha256=aQOQh6d4x6bGeu4Kn1KMKU5F9hwSFFinAsh5hddC3Ho,141241
|
11
|
+
tksheet/sheet.py,sha256=6XOlCb6uhofSwylInVHk2UYufZn4sHXFsQggJ40uAaE,269689
|
12
|
+
tksheet/sheet_options.py,sha256=ob-XYgGfBoi2TaFAvUUmlWUkw9xB-yXmJw17gu9__Lw,9948
|
13
|
+
tksheet/sorting.py,sha256=zcZPpRtP1h_xJGtGkG3E43H7deKQFnh9cMwZ1B2-aGc,17502
|
14
|
+
tksheet/text_editor.py,sha256=rU8Fz0-ltkM63W9io2DoZJPyzUGzCc9Z0qBtc4D1H40,7404
|
15
|
+
tksheet/themes.py,sha256=AoNAxibnQi04MN0Zpbn9-kyDnkiiV8TDNWP9FYjpuf0,18473
|
16
|
+
tksheet/tksheet_types.py,sha256=1MjXR34EmvP1KfHlLTvKKVnf0VMz_LU_WOM2q4o5hfI,4598
|
17
|
+
tksheet/top_left_rectangle.py,sha256=M52IrPIeMoYE3jSpooZmqw_0W5Fz_R-Yu1ZqA685EZ8,8557
|
18
|
+
tksheet-7.4.13.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
|
19
|
+
tksheet-7.4.13.dist-info/METADATA,sha256=ch2OK72gHX9RudQZpnF4JuYDE3KyR0OQTvl3WYtJpsw,8095
|
20
|
+
tksheet-7.4.13.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
21
|
+
tksheet-7.4.13.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
|
22
|
+
tksheet-7.4.13.dist-info/RECORD,,
|
tksheet-7.4.12.dist-info/RECORD
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
tksheet/__init__.py,sha256=6B6RTt5-41j4-VcGxzbvcO6Ggfd56Ooy0GwxL_kfLhI,2327
|
2
|
-
tksheet/colors.py,sha256=dHhmdFuQDlwohDHsAfT9VdrKoSl_R33L72a3HCin5zo,51591
|
3
|
-
tksheet/column_headers.py,sha256=CIQwGNY0PSWb8q3Yl5lOBCGckZ83BDefFH1e4qKoLfs,102720
|
4
|
-
tksheet/constants.py,sha256=aiDvUSaPtl_TSNtRRJ_p87c9iTBz9ksMd5IsSXzz4Hk,13316
|
5
|
-
tksheet/find_window.py,sha256=TvbSqO42cw1o1AO0tQ0Q1iZogouNr4ObMo7JfkZCxgA,19877
|
6
|
-
tksheet/formatters.py,sha256=DGcRiMsDJnySNpQcjfiX84oJ7TmOSMdU6u9injIhA4g,10095
|
7
|
-
tksheet/functions.py,sha256=Ffw6yDHj83oubcp4P9VCQhTRWtGkMI2CBob4JFld91E,52567
|
8
|
-
tksheet/main_table.py,sha256=40MAVfBxQ6FycJcuqm9ZsMOjVYKWhISjht3FFZ-UQOI,363608
|
9
|
-
tksheet/other_classes.py,sha256=g6LYYHXO9RMy2mN_e-HmGa3Wuzhdxt5voO8-Ug19_Ag,16671
|
10
|
-
tksheet/row_index.py,sha256=2aiADtsPskfHZeU0JK7fD4kZm-25ooSjO3mguG9vTM4,139671
|
11
|
-
tksheet/sheet.py,sha256=ZgryLoqfkm2vtJDIVhXAvSUQ8G7TXztiID8Ftt3V2qo,269531
|
12
|
-
tksheet/sheet_options.py,sha256=ob-XYgGfBoi2TaFAvUUmlWUkw9xB-yXmJw17gu9__Lw,9948
|
13
|
-
tksheet/sorting.py,sha256=zcZPpRtP1h_xJGtGkG3E43H7deKQFnh9cMwZ1B2-aGc,17502
|
14
|
-
tksheet/text_editor.py,sha256=rU8Fz0-ltkM63W9io2DoZJPyzUGzCc9Z0qBtc4D1H40,7404
|
15
|
-
tksheet/themes.py,sha256=AoNAxibnQi04MN0Zpbn9-kyDnkiiV8TDNWP9FYjpuf0,18473
|
16
|
-
tksheet/tksheet_types.py,sha256=1MjXR34EmvP1KfHlLTvKKVnf0VMz_LU_WOM2q4o5hfI,4598
|
17
|
-
tksheet/top_left_rectangle.py,sha256=M52IrPIeMoYE3jSpooZmqw_0W5Fz_R-Yu1ZqA685EZ8,8557
|
18
|
-
tksheet-7.4.12.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
|
19
|
-
tksheet-7.4.12.dist-info/METADATA,sha256=0WsLK9P5f8h788tKDhCSQjtYad1UD9mDmIOuFz7eNjE,7999
|
20
|
-
tksheet-7.4.12.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
21
|
-
tksheet-7.4.12.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
|
22
|
-
tksheet-7.4.12.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|