tksheet 7.4.8__py3-none-any.whl → 7.4.10__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 +24 -21
- tksheet/functions.py +18 -15
- tksheet/main_table.py +179 -153
- tksheet/row_index.py +292 -137
- tksheet/sheet.py +251 -300
- tksheet/sorting.py +61 -50
- tksheet/tksheet_types.py +0 -3
- {tksheet-7.4.8.dist-info → tksheet-7.4.10.dist-info}/METADATA +1 -1
- tksheet-7.4.10.dist-info/RECORD +22 -0
- tksheet-7.4.8.dist-info/RECORD +0 -22
- {tksheet-7.4.8.dist-info → tksheet-7.4.10.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.4.8.dist-info → tksheet-7.4.10.dist-info}/WHEEL +0 -0
- {tksheet-7.4.8.dist-info → tksheet-7.4.10.dist-info}/top_level.txt +0 -0
tksheet/__init__.py
CHANGED
tksheet/column_headers.py
CHANGED
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import tkinter as tk
|
4
4
|
from collections import defaultdict
|
5
|
-
from collections.abc import Callable, Hashable, Sequence
|
5
|
+
from collections.abc import Callable, Hashable, Iterator, Sequence
|
6
6
|
from functools import partial
|
7
7
|
from itertools import cycle, islice, repeat
|
8
8
|
from math import ceil, floor
|
@@ -37,9 +37,8 @@ from .functions import (
|
|
37
37
|
)
|
38
38
|
from .other_classes import DotDict, DraggedRowColumn, DropdownStorage, EventDataDict, TextEditorStorage
|
39
39
|
from .row_index import RowIndex
|
40
|
-
from .sorting import sort_column, sort_rows_by_column,
|
40
|
+
from .sorting import sort_column, sort_rows_by_column, sort_tree_rows_by_column
|
41
41
|
from .text_editor import TextEditor
|
42
|
-
from .tksheet_types import AnyIter
|
43
42
|
|
44
43
|
|
45
44
|
class ColumnHeaders(tk.Canvas):
|
@@ -861,7 +860,7 @@ class ColumnHeaders(tk.Canvas):
|
|
861
860
|
def _sort_columns(
|
862
861
|
self,
|
863
862
|
event: tk.Event | None = None,
|
864
|
-
columns:
|
863
|
+
columns: Iterator[int] | None = None,
|
865
864
|
reverse: bool = False,
|
866
865
|
validation: bool = True,
|
867
866
|
key: Callable | None = None,
|
@@ -923,26 +922,30 @@ class ColumnHeaders(tk.Canvas):
|
|
923
922
|
if column is None:
|
924
923
|
if not self.MT.selected:
|
925
924
|
return event_data
|
926
|
-
column = self.MT.selected.column
|
925
|
+
column = self.MT.datacn(self.MT.selected.column)
|
927
926
|
if try_binding(self.ch_extra_begin_sort_rows_func, event_data, "begin_move_rows"):
|
928
927
|
if key is None:
|
929
928
|
key = self.PAR.ops.sort_key
|
930
929
|
disp_new_idxs, disp_row_ctr = {}, 0
|
931
930
|
if self.ops.treeview:
|
932
|
-
new_nodes_order, data_new_idxs =
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
931
|
+
new_nodes_order, data_new_idxs = sort_tree_rows_by_column(
|
932
|
+
data=self.MT.data,
|
933
|
+
column=column,
|
934
|
+
index=self.MT._row_index,
|
935
|
+
rns=self.RI.rns,
|
937
936
|
reverse=reverse,
|
937
|
+
key=key,
|
938
938
|
)
|
939
939
|
for node in new_nodes_order:
|
940
|
-
if (idx := try_b_index(self.MT.displayed_rows, self.RI.
|
940
|
+
if (idx := try_b_index(self.MT.displayed_rows, self.RI.rns[node.iid])) is not None:
|
941
941
|
disp_new_idxs[idx] = disp_row_ctr
|
942
942
|
disp_row_ctr += 1
|
943
943
|
else:
|
944
944
|
new_rows_order, data_new_idxs = sort_rows_by_column(
|
945
|
-
self.MT.data,
|
945
|
+
self.MT.data,
|
946
|
+
column=column,
|
947
|
+
reverse=reverse,
|
948
|
+
key=key,
|
946
949
|
)
|
947
950
|
if self.MT.all_rows_displayed:
|
948
951
|
disp_new_idxs = data_new_idxs
|
@@ -1013,7 +1016,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1013
1016
|
|
1014
1017
|
def select_col(
|
1015
1018
|
self,
|
1016
|
-
c: int |
|
1019
|
+
c: int | Iterator[int],
|
1017
1020
|
redraw: bool = False,
|
1018
1021
|
run_binding_func: bool = True,
|
1019
1022
|
ext: bool = False,
|
@@ -1094,7 +1097,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1094
1097
|
self.itemconfig(item, state="hidden")
|
1095
1098
|
|
1096
1099
|
def get_cell_dimensions(self, datacn: int) -> tuple[int, int]:
|
1097
|
-
txt = self.
|
1100
|
+
txt = self.cell_str(datacn, fix=False)
|
1098
1101
|
if txt:
|
1099
1102
|
self.MT.txt_measure_canvas.itemconfig(
|
1100
1103
|
self.MT.txt_measure_canvas_text,
|
@@ -1150,7 +1153,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1150
1153
|
elif isinstance(self.MT._headers, int):
|
1151
1154
|
datarn = self.MT._headers
|
1152
1155
|
for datacn in iterable:
|
1153
|
-
if txt := self.MT.
|
1156
|
+
if txt := self.MT.cell_str(datarn, datacn, get_displayed=True):
|
1154
1157
|
qconf(qtxtm, text=txt, font=qfont)
|
1155
1158
|
b = qbbox(qtxtm)
|
1156
1159
|
th = b[3] - b[1] + 5
|
@@ -1197,7 +1200,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1197
1200
|
qtxth = self.MT.table_txt_height
|
1198
1201
|
qfont = self.ops.table_font
|
1199
1202
|
for datarn in iterable:
|
1200
|
-
if txt := self.MT.
|
1203
|
+
if txt := self.MT.cell_str(datarn, datacn, get_displayed=True):
|
1201
1204
|
qconf(qtxtm, text=txt, font=qfont)
|
1202
1205
|
b = qbbox(qtxtm)
|
1203
1206
|
if (
|
@@ -1629,7 +1632,7 @@ class ColumnHeaders(tk.Canvas):
|
|
1629
1632
|
or (align.endswith("n") and cleftgridln + 5 > scrollpos_right)
|
1630
1633
|
):
|
1631
1634
|
continue
|
1632
|
-
text = self.
|
1635
|
+
text = self.cell_str(datacn, fix=False)
|
1633
1636
|
if not text:
|
1634
1637
|
continue
|
1635
1638
|
max_lines = int((self.current_height - top - 2) / txt_h)
|
@@ -2223,7 +2226,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2223
2226
|
edited = True
|
2224
2227
|
if edited and cell_resize and self.ops.cell_auto_resize_enabled:
|
2225
2228
|
if self.height_resizing_enabled:
|
2226
|
-
self.set_height_of_header_to_text(self.
|
2229
|
+
self.set_height_of_header_to_text(self.cell_str(datacn, fix=False))
|
2227
2230
|
self.set_col_width_run_binding(c)
|
2228
2231
|
if redraw:
|
2229
2232
|
self.MT.refresh()
|
@@ -2270,7 +2273,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2270
2273
|
redirect_int: bool = False,
|
2271
2274
|
) -> Any:
|
2272
2275
|
if get_displayed:
|
2273
|
-
return self.
|
2276
|
+
return self.cell_str(datacn, fix=False)
|
2274
2277
|
if redirect_int and isinstance(self.MT._headers, int): # internal use
|
2275
2278
|
return self.MT.get_cell_data(self.MT._headers, datacn, none_to_empty_str=True)
|
2276
2279
|
if (
|
@@ -2282,7 +2285,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2282
2285
|
return ""
|
2283
2286
|
return self.MT._headers[datacn]
|
2284
2287
|
|
2285
|
-
def
|
2288
|
+
def cell_str(self, datacn: int, fix: bool = True) -> str:
|
2286
2289
|
kwargs = self.get_cell_kwargs(datacn, key="dropdown")
|
2287
2290
|
if kwargs:
|
2288
2291
|
if kwargs["text"] is not None:
|
@@ -2292,7 +2295,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2292
2295
|
if kwargs:
|
2293
2296
|
return f"{kwargs['text']}"
|
2294
2297
|
if isinstance(self.MT._headers, int):
|
2295
|
-
return self.MT.
|
2298
|
+
return self.MT.cell_str(self.MT._headers, datacn, get_displayed=True)
|
2296
2299
|
if fix:
|
2297
2300
|
self.fix_header(datacn)
|
2298
2301
|
try:
|
tksheet/functions.py
CHANGED
@@ -16,7 +16,6 @@ from .colors import color_map
|
|
16
16
|
from .constants import align_value_error, symbols_set
|
17
17
|
from .formatters import to_bool
|
18
18
|
from .other_classes import DotDict, EventDataDict, Highlight, Loc, Span
|
19
|
-
from .tksheet_types import AnyIter
|
20
19
|
|
21
20
|
unpickle_obj = pickle.loads
|
22
21
|
lines_re = re.compile(r"[^\n]+")
|
@@ -356,6 +355,8 @@ def event_dict(
|
|
356
355
|
sheet_state=DotDict() if sheet_state is None else sheet_state,
|
357
356
|
treeview=DotDict(
|
358
357
|
nodes={},
|
358
|
+
renamed={},
|
359
|
+
text={},
|
359
360
|
)
|
360
361
|
if treeview is None
|
361
362
|
else treeview,
|
@@ -511,19 +512,19 @@ def is_iterable(o: Any) -> bool:
|
|
511
512
|
return False
|
512
513
|
|
513
514
|
|
514
|
-
def int_x_iter(i:
|
515
|
+
def int_x_iter(i: Iterator[int] | int) -> Iterator[int]:
|
515
516
|
if isinstance(i, int):
|
516
517
|
return (i,)
|
517
518
|
return i
|
518
519
|
|
519
520
|
|
520
|
-
def int_x_tuple(i:
|
521
|
+
def int_x_tuple(i: Iterator[int] | int) -> tuple[int]:
|
521
522
|
if isinstance(i, int):
|
522
523
|
return (i,)
|
523
524
|
return tuple(i)
|
524
525
|
|
525
526
|
|
526
|
-
def unpack(t: tuple[Any] | tuple[
|
527
|
+
def unpack(t: tuple[Any] | tuple[Iterator[Any]]) -> tuple[Any]:
|
527
528
|
if not len(t):
|
528
529
|
return t
|
529
530
|
if is_iterable(t[0]) and len(t) == 1:
|
@@ -725,7 +726,7 @@ def cell_right_within_box(
|
|
725
726
|
|
726
727
|
|
727
728
|
def get_last(
|
728
|
-
it:
|
729
|
+
it: Iterator[Any],
|
729
730
|
) -> Any:
|
730
731
|
if hasattr(it, "__reversed__"):
|
731
732
|
try:
|
@@ -748,8 +749,8 @@ def index_exists(seq: Sequence[Any], index: int) -> bool:
|
|
748
749
|
|
749
750
|
|
750
751
|
def add_to_displayed(displayed: list[int], to_add: Iterable[int]) -> list[int]:
|
751
|
-
# assumes to_add is sorted
|
752
|
-
for i in
|
752
|
+
# assumes to_add is sorted
|
753
|
+
for i in to_add:
|
753
754
|
ins = bisect_left(displayed, i)
|
754
755
|
displayed[ins:] = [i] + [e + 1 for e in islice(displayed, ins, None)]
|
755
756
|
return displayed
|
@@ -820,13 +821,13 @@ def insert_items(
|
|
820
821
|
) -> list[Any]:
|
821
822
|
"""
|
822
823
|
seq: list[Any]
|
823
|
-
to_insert: keys are ints sorted
|
824
|
+
to_insert: keys are ints sorted, representing list indexes to insert items.
|
824
825
|
Values are any, e.g. {1: 200, 0: 200}
|
825
826
|
"""
|
826
827
|
if to_insert:
|
827
|
-
if seq_len_func and next(
|
828
|
-
seq_len_func(next(
|
829
|
-
for idx, v in
|
828
|
+
if seq_len_func and next(reversed(to_insert)) >= len(seq) + len(to_insert):
|
829
|
+
seq_len_func(next(reversed(to_insert)) - len(to_insert))
|
830
|
+
for idx, v in to_insert.items():
|
830
831
|
seq[idx:idx] = [v]
|
831
832
|
return seq
|
832
833
|
|
@@ -1040,7 +1041,7 @@ def is_last_cell(
|
|
1040
1041
|
return row == end_row - 1 and col == end_col - 1
|
1041
1042
|
|
1042
1043
|
|
1043
|
-
def zip_fill_2nd_value(x:
|
1044
|
+
def zip_fill_2nd_value(x: Iterator[Any], o: Any) -> Generator[Any, Any]:
|
1044
1045
|
return zip(x, repeat(o))
|
1045
1046
|
|
1046
1047
|
|
@@ -1465,13 +1466,15 @@ def span_froms(
|
|
1465
1466
|
return from_r, from_c
|
1466
1467
|
|
1467
1468
|
|
1468
|
-
def del_named_span_options(options: dict, itr:
|
1469
|
+
def del_named_span_options(options: dict, itr: Iterator[Hashable], type_: str) -> None:
|
1469
1470
|
for k in itr:
|
1470
1471
|
if k in options and type_ in options[k]:
|
1471
1472
|
del options[k][type_]
|
1472
1473
|
|
1473
1474
|
|
1474
|
-
def del_named_span_options_nested(
|
1475
|
+
def del_named_span_options_nested(
|
1476
|
+
options: dict, itr1: Iterator[Hashable], itr2: Iterator[Hashable], type_: str
|
1477
|
+
) -> None:
|
1475
1478
|
for k1 in itr1:
|
1476
1479
|
for k2 in itr2:
|
1477
1480
|
k = (k1, k2)
|
@@ -1552,7 +1555,7 @@ def set_align(
|
|
1552
1555
|
def del_from_options(
|
1553
1556
|
options: dict,
|
1554
1557
|
key: str,
|
1555
|
-
coords: int |
|
1558
|
+
coords: int | Iterator[int | tuple[int, int]] | None = None,
|
1556
1559
|
) -> dict:
|
1557
1560
|
if isinstance(coords, int):
|
1558
1561
|
if coords in options and key in options[coords]:
|