tksheet 7.4.4__py3-none-any.whl → 7.4.6__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 +84 -86
- tksheet/constants.py +4 -3
- tksheet/find_window.py +8 -8
- tksheet/formatters.py +58 -74
- tksheet/functions.py +65 -79
- tksheet/main_table.py +330 -448
- tksheet/other_classes.py +19 -25
- tksheet/row_index.py +114 -92
- tksheet/sheet.py +191 -208
- tksheet/sorting.py +23 -22
- tksheet/text_editor.py +18 -12
- tksheet/tksheet_types.py +187 -0
- tksheet/top_left_rectangle.py +18 -18
- {tksheet-7.4.4.dist-info → tksheet-7.4.6.dist-info}/METADATA +4 -2
- tksheet-7.4.6.dist-info/RECORD +22 -0
- {tksheet-7.4.4.dist-info → tksheet-7.4.6.dist-info}/WHEEL +1 -1
- tksheet-7.4.4.dist-info/RECORD +0 -22
- {tksheet-7.4.4.dist-info → tksheet-7.4.6.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.4.4.dist-info → tksheet-7.4.6.dist-info}/top_level.txt +0 -0
tksheet/other_classes.py
CHANGED
@@ -5,7 +5,7 @@ import tkinter as tk
|
|
5
5
|
from collections import namedtuple
|
6
6
|
from collections.abc import Callable, Hashable, Iterator
|
7
7
|
from functools import partial
|
8
|
-
from typing import Literal
|
8
|
+
from typing import Any, Literal
|
9
9
|
|
10
10
|
pickle_obj = partial(pickle.dumps, protocol=pickle.HIGHEST_PROTOCOL)
|
11
11
|
|
@@ -105,9 +105,7 @@ class SpanRange:
|
|
105
105
|
return reversed(range(self.from_, self.upto_))
|
106
106
|
|
107
107
|
def __contains__(self, n: int) -> bool:
|
108
|
-
|
109
|
-
return True
|
110
|
-
return False
|
108
|
+
return n >= self.from_ and n < self.upto_
|
111
109
|
|
112
110
|
def __eq__(self, v: SpanRange) -> bool:
|
113
111
|
return self.from_ == v.from_ and self.upto_ == v.upto_
|
@@ -133,7 +131,7 @@ class DotDict(dict):
|
|
133
131
|
def __setstate__(self, state: DotDict) -> None:
|
134
132
|
self.update(state)
|
135
133
|
|
136
|
-
def __setitem__(self, key: Hashable, item:
|
134
|
+
def __setitem__(self, key: Hashable, item: Any) -> None:
|
137
135
|
if type(item) is dict: # noqa: E721
|
138
136
|
super().__setitem__(key, DotDict(item))
|
139
137
|
else:
|
@@ -167,13 +165,13 @@ class Span(dict):
|
|
167
165
|
def __setstate__(self, state: Span) -> None:
|
168
166
|
self.update(state)
|
169
167
|
|
170
|
-
def __getitem__(self, key: Hashable) ->
|
168
|
+
def __getitem__(self, key: Hashable) -> Any:
|
171
169
|
if key == "data" or key == "value":
|
172
170
|
return self["widget"].get_data(self)
|
173
171
|
else:
|
174
172
|
return super().__getitem__(key)
|
175
173
|
|
176
|
-
def __setitem__(self, key: Hashable, item:
|
174
|
+
def __setitem__(self, key: Hashable, item: Any) -> None:
|
177
175
|
if key == "data" or key == "value":
|
178
176
|
self["widget"].set_data(self, data=item)
|
179
177
|
elif key == "bg":
|
@@ -189,11 +187,13 @@ class Span(dict):
|
|
189
187
|
|
190
188
|
def format(
|
191
189
|
self,
|
192
|
-
formatter_options: dict =
|
193
|
-
formatter_class:
|
190
|
+
formatter_options: dict | None = None,
|
191
|
+
formatter_class: Any = None,
|
194
192
|
redraw: bool = True,
|
195
193
|
**kwargs,
|
196
194
|
) -> Span:
|
195
|
+
if formatter_options is None:
|
196
|
+
formatter_options = {}
|
197
197
|
return self["widget"].format(
|
198
198
|
self,
|
199
199
|
formatter_options={"formatter": formatter_class, **formatter_options, **kwargs},
|
@@ -232,10 +232,10 @@ class Span(dict):
|
|
232
232
|
|
233
233
|
def dropdown(
|
234
234
|
self,
|
235
|
-
values: list =
|
235
|
+
values: list[Any] | None = None,
|
236
236
|
edit_data: bool = True,
|
237
|
-
set_values: dict[tuple[int, int],
|
238
|
-
set_value:
|
237
|
+
set_values: dict[tuple[int, int], Any] | None = None,
|
238
|
+
set_value: Any = None,
|
239
239
|
state: str = "normal",
|
240
240
|
redraw: bool = True,
|
241
241
|
selection_function: Callable | None = None,
|
@@ -246,9 +246,9 @@ class Span(dict):
|
|
246
246
|
) -> Span:
|
247
247
|
return self["widget"].dropdown(
|
248
248
|
self,
|
249
|
-
values=values,
|
249
|
+
values=[] if values is None else values,
|
250
250
|
edit_data=edit_data,
|
251
|
-
set_values=set_values,
|
251
|
+
set_values={} if set_values is None else set_values,
|
252
252
|
set_value=set_value,
|
253
253
|
state=state,
|
254
254
|
redraw=redraw,
|
@@ -327,7 +327,7 @@ class Span(dict):
|
|
327
327
|
convert: Callable | None = None,
|
328
328
|
undo: bool | None = None,
|
329
329
|
emit_event: bool | None = None,
|
330
|
-
widget:
|
330
|
+
widget: Any = None,
|
331
331
|
expand: str | None = None,
|
332
332
|
formatter_options: dict | None = None,
|
333
333
|
**kwargs,
|
@@ -406,19 +406,13 @@ class Span(dict):
|
|
406
406
|
@property
|
407
407
|
def rows(self) -> SpanRange:
|
408
408
|
rng_from_r = 0 if self["from_r"] is None else self["from_r"]
|
409
|
-
if self["upto_r"] is None
|
410
|
-
rng_upto_r = self["widget"].total_rows()
|
411
|
-
else:
|
412
|
-
rng_upto_r = self["upto_r"]
|
409
|
+
rng_upto_r = self["widget"].total_rows() if self["upto_r"] is None else self["upto_r"]
|
413
410
|
return SpanRange(rng_from_r, rng_upto_r)
|
414
411
|
|
415
412
|
@property
|
416
413
|
def columns(self) -> SpanRange:
|
417
414
|
rng_from_c = 0 if self["from_c"] is None else self["from_c"]
|
418
|
-
if self["upto_c"] is None
|
419
|
-
rng_upto_c = self["widget"].total_columns()
|
420
|
-
else:
|
421
|
-
rng_upto_c = self["upto_c"]
|
415
|
+
rng_upto_c = self["widget"].total_columns() if self["upto_c"] is None else self["upto_c"]
|
422
416
|
return SpanRange(rng_from_c, rng_upto_c)
|
423
417
|
|
424
418
|
@property
|
@@ -510,7 +504,7 @@ class EditorStorageBase(StorageBase):
|
|
510
504
|
self.highlight_from(index, line, column)
|
511
505
|
|
512
506
|
@property
|
513
|
-
def tktext(self) ->
|
507
|
+
def tktext(self) -> Any:
|
514
508
|
if self.window:
|
515
509
|
return self.window.tktext
|
516
510
|
return self.window
|
@@ -543,7 +537,7 @@ class ProgressBar:
|
|
543
537
|
def __len__(self):
|
544
538
|
return 2
|
545
539
|
|
546
|
-
def __getitem__(self, key: Hashable) ->
|
540
|
+
def __getitem__(self, key: Hashable) -> Any:
|
547
541
|
if key == 0:
|
548
542
|
return self.bg
|
549
543
|
elif key == 1:
|
tksheet/row_index.py
CHANGED
@@ -7,7 +7,7 @@ from functools import partial
|
|
7
7
|
from itertools import chain, cycle, islice, repeat
|
8
8
|
from math import ceil, floor
|
9
9
|
from operator import itemgetter
|
10
|
-
from typing import Literal
|
10
|
+
from typing import Any, Literal
|
11
11
|
|
12
12
|
from .colors import color_map
|
13
13
|
from .constants import (
|
@@ -91,7 +91,7 @@ class RowIndex(tk.Canvas):
|
|
91
91
|
self.rc_delete_row_enabled = False
|
92
92
|
self.edit_cell_enabled = False
|
93
93
|
self.visible_row_dividers = {}
|
94
|
-
self.row_width_resize_bbox =
|
94
|
+
self.row_width_resize_bbox = ()
|
95
95
|
self.rsz_w = None
|
96
96
|
self.rsz_h = None
|
97
97
|
self.currently_resizing_width = False
|
@@ -160,7 +160,7 @@ class RowIndex(tk.Canvas):
|
|
160
160
|
self.MT.recreate_all_selection_boxes()
|
161
161
|
self.current_width = new_width
|
162
162
|
|
163
|
-
def rc(self, event:
|
163
|
+
def rc(self, event: Any) -> None:
|
164
164
|
self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
|
165
165
|
self.focus_set()
|
166
166
|
popup_menu = None
|
@@ -187,7 +187,7 @@ class RowIndex(tk.Canvas):
|
|
187
187
|
self.popup_menu_loc = r
|
188
188
|
popup_menu.tk_popup(event.x_root, event.y_root)
|
189
189
|
|
190
|
-
def ctrl_b1_press(self, event:
|
190
|
+
def ctrl_b1_press(self, event: Any) -> None:
|
191
191
|
self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
|
192
192
|
if (
|
193
193
|
(self.drag_and_drop_enabled or self.row_selection_enabled)
|
@@ -210,7 +210,7 @@ class RowIndex(tk.Canvas):
|
|
210
210
|
elif not self.MT.ctrl_select_enabled:
|
211
211
|
self.b1_press(event)
|
212
212
|
|
213
|
-
def ctrl_shift_b1_press(self, event:
|
213
|
+
def ctrl_shift_b1_press(self, event: Any) -> None:
|
214
214
|
self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
|
215
215
|
y = event.y
|
216
216
|
r = self.MT.identify_row(y=y)
|
@@ -246,31 +246,35 @@ class RowIndex(tk.Canvas):
|
|
246
246
|
elif not self.MT.ctrl_select_enabled:
|
247
247
|
self.shift_b1_press(event)
|
248
248
|
|
249
|
-
def shift_b1_press(self, event:
|
249
|
+
def shift_b1_press(self, event: Any) -> None:
|
250
250
|
self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
|
251
251
|
r = self.MT.identify_row(y=event.y)
|
252
|
-
if (
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
self.
|
265
|
-
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
266
|
-
sel_event = self.MT.get_select_event(being_drawn_item=self.being_drawn_item)
|
267
|
-
try_binding(self.shift_selection_binding_func, sel_event)
|
268
|
-
self.PAR.emit_event("<<SheetSelect>>", data=sel_event)
|
269
|
-
elif r_selected:
|
270
|
-
self.dragged_row = DraggedRowColumn(
|
271
|
-
dragged=r,
|
272
|
-
to_move=sorted(self.MT.get_selected_rows()),
|
252
|
+
if (
|
253
|
+
(self.drag_and_drop_enabled or self.row_selection_enabled)
|
254
|
+
and self.rsz_h is None
|
255
|
+
and self.rsz_w is None
|
256
|
+
and r < len(self.MT.row_positions) - 1
|
257
|
+
):
|
258
|
+
r_selected = self.MT.row_selected(r)
|
259
|
+
if not r_selected and self.row_selection_enabled:
|
260
|
+
if self.MT.selected and self.MT.selected.type_ == "rows":
|
261
|
+
r_to_sel, c_to_sel = self.MT.selected.row, self.MT.selected.column
|
262
|
+
self.MT.deselect("all", redraw=False)
|
263
|
+
self.being_drawn_item = self.MT.create_selection_box(
|
264
|
+
*self.get_shift_select_box(r, r_to_sel), "rows"
|
273
265
|
)
|
266
|
+
self.MT.set_currently_selected(r_to_sel, c_to_sel, self.being_drawn_item)
|
267
|
+
else:
|
268
|
+
self.being_drawn_item = self.select_row(r, run_binding_func=False)
|
269
|
+
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
270
|
+
sel_event = self.MT.get_select_event(being_drawn_item=self.being_drawn_item)
|
271
|
+
try_binding(self.shift_selection_binding_func, sel_event)
|
272
|
+
self.PAR.emit_event("<<SheetSelect>>", data=sel_event)
|
273
|
+
elif r_selected:
|
274
|
+
self.dragged_row = DraggedRowColumn(
|
275
|
+
dragged=r,
|
276
|
+
to_move=sorted(self.MT.get_selected_rows()),
|
277
|
+
)
|
274
278
|
|
275
279
|
def get_shift_select_box(self, r: int, min_r: int) -> tuple[int, int, int, int, str]:
|
276
280
|
if r >= min_r:
|
@@ -313,7 +317,7 @@ class RowIndex(tk.Canvas):
|
|
313
317
|
if x >= x1 and y >= y1 and x <= x2 and y <= y2:
|
314
318
|
return r
|
315
319
|
|
316
|
-
def mouse_motion(self, event:
|
320
|
+
def mouse_motion(self, event: Any) -> None:
|
317
321
|
if not self.currently_resizing_height and not self.currently_resizing_width:
|
318
322
|
x = self.canvasx(event.x)
|
319
323
|
y = self.canvasy(event.y)
|
@@ -354,17 +358,16 @@ class RowIndex(tk.Canvas):
|
|
354
358
|
self.rsz_w = None
|
355
359
|
except Exception:
|
356
360
|
self.rsz_w = None
|
357
|
-
if not mouse_over_resize:
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
self.MT.current_cursor = "hand2"
|
361
|
+
if not mouse_over_resize and self.MT.row_selected(self.MT.identify_row(event, allow_end=False)):
|
362
|
+
mouse_over_selected = True
|
363
|
+
if self.MT.current_cursor != "hand2":
|
364
|
+
self.config(cursor="hand2")
|
365
|
+
self.MT.current_cursor = "hand2"
|
363
366
|
if not mouse_over_resize and not mouse_over_selected:
|
364
367
|
self.MT.reset_mouse_motion_creations()
|
365
368
|
try_binding(self.extra_motion_func, event)
|
366
369
|
|
367
|
-
def double_b1(self, event:
|
370
|
+
def double_b1(self, event: Any):
|
368
371
|
self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
|
369
372
|
self.focus_set()
|
370
373
|
if (
|
@@ -410,7 +413,7 @@ class RowIndex(tk.Canvas):
|
|
410
413
|
self.mouse_motion(event)
|
411
414
|
try_binding(self.extra_double_b1_func, event)
|
412
415
|
|
413
|
-
def b1_press(self, event:
|
416
|
+
def b1_press(self, event: Any):
|
414
417
|
self.MT.unbind("<MouseWheel>")
|
415
418
|
self.focus_set()
|
416
419
|
self.closed_dropdown = self.mouseclick_outside_editor_or_dropdown_all_canvases(inside=True)
|
@@ -479,7 +482,7 @@ class RowIndex(tk.Canvas):
|
|
479
482
|
self.toggle_select_row(r, redraw=True)
|
480
483
|
try_binding(self.extra_b1_press_func, event)
|
481
484
|
|
482
|
-
def b1_motion(self, event:
|
485
|
+
def b1_motion(self, event: Any):
|
483
486
|
x1, y1, x2, y2 = self.MT.get_canvas_visible_area()
|
484
487
|
if self.height_resizing_enabled and self.rsz_h is not None and self.currently_resizing_height:
|
485
488
|
y = self.canvasy(event.y)
|
@@ -578,7 +581,7 @@ class RowIndex(tk.Canvas):
|
|
578
581
|
elif end_row < start_row:
|
579
582
|
return end_row, 0, start_row + 1, len(self.MT.col_positions) - 1, "rows"
|
580
583
|
|
581
|
-
def ctrl_b1_motion(self, event:
|
584
|
+
def ctrl_b1_motion(self, event: Any) -> None:
|
582
585
|
x1, y1, x2, y2 = self.MT.get_canvas_visible_area()
|
583
586
|
if (
|
584
587
|
self.drag_and_drop_enabled
|
@@ -632,7 +635,7 @@ class RowIndex(tk.Canvas):
|
|
632
635
|
elif not self.MT.ctrl_select_enabled:
|
633
636
|
self.b1_motion(event)
|
634
637
|
|
635
|
-
def drag_and_drop_motion(self, event:
|
638
|
+
def drag_and_drop_motion(self, event: Any) -> float:
|
636
639
|
y = event.y
|
637
640
|
hend = self.winfo_height()
|
638
641
|
ycheck = self.yview()
|
@@ -700,7 +703,7 @@ class RowIndex(tk.Canvas):
|
|
700
703
|
if ctrl_lines:
|
701
704
|
self.MT.delete_ctrl_outlines()
|
702
705
|
|
703
|
-
def scroll_if_event_offscreen(self, event:
|
706
|
+
def scroll_if_event_offscreen(self, event: Any) -> bool:
|
704
707
|
ycheck = self.yview()
|
705
708
|
need_redraw = False
|
706
709
|
if event.y > self.winfo_height() and len(ycheck) > 1 and ycheck[1] < 1:
|
@@ -730,14 +733,14 @@ class RowIndex(tk.Canvas):
|
|
730
733
|
if len(ycheck) > 1 and ycheck[1] > 1:
|
731
734
|
self.MT.set_yviews("moveto", 1)
|
732
735
|
|
733
|
-
def event_over_dropdown(self, r: int, datarn: int, event:
|
736
|
+
def event_over_dropdown(self, r: int, datarn: int, event: Any, canvasy: float) -> bool:
|
734
737
|
return (
|
735
738
|
canvasy < self.MT.row_positions[r] + self.MT.index_txt_height
|
736
739
|
and self.get_cell_kwargs(datarn, key="dropdown")
|
737
740
|
and event.x > self.current_width - self.MT.index_txt_height - 4
|
738
741
|
)
|
739
742
|
|
740
|
-
def event_over_checkbox(self, r: int, datarn: int, event:
|
743
|
+
def event_over_checkbox(self, r: int, datarn: int, event: Any, canvasy: float) -> bool:
|
741
744
|
return (
|
742
745
|
canvasy < self.MT.row_positions[r] + self.MT.index_txt_height
|
743
746
|
and self.get_cell_kwargs(datarn, key="checkbox")
|
@@ -774,7 +777,7 @@ class RowIndex(tk.Canvas):
|
|
774
777
|
)
|
775
778
|
)
|
776
779
|
|
777
|
-
def b1_release(self, event:
|
780
|
+
def b1_release(self, event: Any) -> None:
|
778
781
|
to_hide = self.being_drawn_item
|
779
782
|
if self.being_drawn_item is not None and (to_sel := self.MT.coords_and_type(self.being_drawn_item)):
|
780
783
|
r_to_sel, c_to_sel = self.MT.selected.row, self.MT.selected.column
|
@@ -1231,7 +1234,7 @@ class RowIndex(tk.Canvas):
|
|
1231
1234
|
def set_width_of_index_to_text(
|
1232
1235
|
self,
|
1233
1236
|
text: None | str = None,
|
1234
|
-
only_rows: list =
|
1237
|
+
only_rows: list[int] | None = None,
|
1235
1238
|
) -> int:
|
1236
1239
|
self.fix_index()
|
1237
1240
|
w = self.ops.default_row_index_width
|
@@ -1245,7 +1248,7 @@ class RowIndex(tk.Canvas):
|
|
1245
1248
|
if (tw := b[2] - b[0] + 10) > w:
|
1246
1249
|
w = tw
|
1247
1250
|
elif text is None:
|
1248
|
-
w = self.get_index_text_width(only_rows=only_rows)
|
1251
|
+
w = self.get_index_text_width(only_rows=[] if only_rows is None else only_rows)
|
1249
1252
|
if w > self.ops.max_index_width:
|
1250
1253
|
w = int(self.ops.max_index_width)
|
1251
1254
|
self.set_width(w, set_TL=True)
|
@@ -1641,9 +1644,8 @@ class RowIndex(tk.Canvas):
|
|
1641
1644
|
row_pos_exists: bool,
|
1642
1645
|
set_scrollregion: bool,
|
1643
1646
|
) -> bool:
|
1644
|
-
if set_scrollregion:
|
1645
|
-
|
1646
|
-
return False
|
1647
|
+
if set_scrollregion and not self.configure_scrollregion(last_row_line_pos=last_row_line_pos):
|
1648
|
+
return False
|
1647
1649
|
self.hidd_text.update(self.disp_text)
|
1648
1650
|
self.disp_text = {}
|
1649
1651
|
self.hidd_high.update(self.disp_high)
|
@@ -1910,7 +1912,7 @@ class RowIndex(tk.Canvas):
|
|
1910
1912
|
d[box.type_ if box.type_ != "columns" else "cells"].add(r)
|
1911
1913
|
return d
|
1912
1914
|
|
1913
|
-
def open_cell(self, event:
|
1915
|
+
def open_cell(self, event: Any = None, ignore_existing_editor: bool = False) -> None:
|
1914
1916
|
if not self.MT.anything_selected() or (not ignore_existing_editor and self.text_editor.open):
|
1915
1917
|
return
|
1916
1918
|
if not self.MT.selected:
|
@@ -1940,7 +1942,7 @@ class RowIndex(tk.Canvas):
|
|
1940
1942
|
# r is displayed row
|
1941
1943
|
def open_text_editor(
|
1942
1944
|
self,
|
1943
|
-
event:
|
1945
|
+
event: Any = None,
|
1944
1946
|
r: int = 0,
|
1945
1947
|
text: None | str = None,
|
1946
1948
|
state: str = "normal",
|
@@ -1983,7 +1985,7 @@ class RowIndex(tk.Canvas):
|
|
1983
1985
|
self.text_editor.set_text(self.text_editor.get() + "" if not isinstance(text, str) else text)
|
1984
1986
|
return False
|
1985
1987
|
self.hide_text_editor()
|
1986
|
-
if not self.MT.see(r
|
1988
|
+
if not self.MT.see(r, 0, keep_yscroll=True):
|
1987
1989
|
self.MT.main_table_redraw_grid_and_text(True, True)
|
1988
1990
|
x = 0
|
1989
1991
|
y = self.MT.row_positions[r]
|
@@ -2033,7 +2035,7 @@ class RowIndex(tk.Canvas):
|
|
2033
2035
|
self.text_editor.tktext.bind(key, func)
|
2034
2036
|
return True
|
2035
2037
|
|
2036
|
-
def text_editor_newline_binding(self, event:
|
2038
|
+
def text_editor_newline_binding(self, event: Any = None, check_lines: bool = True) -> None:
|
2037
2039
|
if not self.height_resizing_enabled:
|
2038
2040
|
return
|
2039
2041
|
curr_height = self.text_editor.window.winfo_height()
|
@@ -2230,7 +2232,7 @@ class RowIndex(tk.Canvas):
|
|
2230
2232
|
self.text_editor.autocomplete(self.dropdown.window.search_and_see(event_data))
|
2231
2233
|
return "break"
|
2232
2234
|
|
2233
|
-
def open_dropdown_window(self, r: int, event:
|
2235
|
+
def open_dropdown_window(self, r: int, event: Any = None) -> None:
|
2234
2236
|
self.hide_text_editor()
|
2235
2237
|
kwargs = self.get_cell_kwargs(self.MT.datarn(r), key="dropdown")
|
2236
2238
|
if kwargs["state"] == "disabled":
|
@@ -2308,7 +2310,7 @@ class RowIndex(tk.Canvas):
|
|
2308
2310
|
def close_dropdown_window(
|
2309
2311
|
self,
|
2310
2312
|
r: int | None = None,
|
2311
|
-
selection:
|
2313
|
+
selection: Any = None,
|
2312
2314
|
redraw: bool = True,
|
2313
2315
|
) -> None:
|
2314
2316
|
if r is not None and selection is not None:
|
@@ -2415,7 +2417,7 @@ class RowIndex(tk.Canvas):
|
|
2415
2417
|
self.MT.sheet_modified(event_data)
|
2416
2418
|
return edited
|
2417
2419
|
|
2418
|
-
def set_cell_data(self, datarn: int | None = None, value:
|
2420
|
+
def set_cell_data(self, datarn: int | None = None, value: Any = "") -> None:
|
2419
2421
|
if isinstance(self.MT._row_index, int):
|
2420
2422
|
self.MT.set_cell_data(datarn=datarn, datacn=self.MT._row_index, value=value)
|
2421
2423
|
else:
|
@@ -2427,20 +2429,21 @@ class RowIndex(tk.Canvas):
|
|
2427
2429
|
else:
|
2428
2430
|
self.MT._row_index[datarn] = value
|
2429
2431
|
|
2430
|
-
def input_valid_for_cell(self, datarn: int, value:
|
2432
|
+
def input_valid_for_cell(self, datarn: int, value: Any, check_readonly: bool = True) -> bool:
|
2431
2433
|
kwargs = self.get_cell_kwargs(datarn, key=None)
|
2432
2434
|
if check_readonly and "readonly" in kwargs:
|
2433
2435
|
return False
|
2434
2436
|
elif "checkbox" in kwargs:
|
2435
2437
|
return is_bool_like(value)
|
2436
|
-
elif self.cell_equal_to(datarn, value):
|
2437
|
-
return False
|
2438
|
-
elif (kwargs := kwargs.get("dropdown", {})) and kwargs["validate_input"] and value not in kwargs["values"]:
|
2439
|
-
return False
|
2440
2438
|
else:
|
2441
|
-
return
|
2439
|
+
return not (
|
2440
|
+
self.cell_equal_to(datarn, value)
|
2441
|
+
or (kwargs := kwargs.get("dropdown", {}))
|
2442
|
+
and kwargs["validate_input"]
|
2443
|
+
and value not in kwargs["values"]
|
2444
|
+
)
|
2442
2445
|
|
2443
|
-
def cell_equal_to(self, datarn: int, value:
|
2446
|
+
def cell_equal_to(self, datarn: int, value: Any) -> bool:
|
2444
2447
|
self.fix_index(datarn)
|
2445
2448
|
if isinstance(self.MT._row_index, list):
|
2446
2449
|
return self.MT._row_index[datarn] == value
|
@@ -2453,7 +2456,7 @@ class RowIndex(tk.Canvas):
|
|
2453
2456
|
get_displayed: bool = False,
|
2454
2457
|
none_to_empty_str: bool = False,
|
2455
2458
|
redirect_int: bool = False,
|
2456
|
-
) ->
|
2459
|
+
) -> Any:
|
2457
2460
|
if get_displayed:
|
2458
2461
|
return self.get_valid_cell_data_as_str(datarn, fix=False)
|
2459
2462
|
if redirect_int and isinstance(self.MT._row_index, int): # internal use
|
@@ -2496,7 +2499,7 @@ class RowIndex(tk.Canvas):
|
|
2496
2499
|
value = get_n2a(datarn, self.ops.default_row_index)
|
2497
2500
|
return value
|
2498
2501
|
|
2499
|
-
def get_value_for_empty_cell(self, datarn: int, r_ops: bool = True) ->
|
2502
|
+
def get_value_for_empty_cell(self, datarn: int, r_ops: bool = True) -> Any:
|
2500
2503
|
if self.ops.treeview:
|
2501
2504
|
iid = self.new_iid()
|
2502
2505
|
return Node(text=iid, iid=iid, parent=self.get_row_parent(datarn))
|
@@ -2508,7 +2511,7 @@ class RowIndex(tk.Canvas):
|
|
2508
2511
|
else:
|
2509
2512
|
return ""
|
2510
2513
|
|
2511
|
-
def get_empty_index_seq(self, end: int, start: int = 0, r_ops: bool = True) -> list[
|
2514
|
+
def get_empty_index_seq(self, end: int, start: int = 0, r_ops: bool = True) -> list[Any]:
|
2512
2515
|
return [self.get_value_for_empty_cell(datarn, r_ops=r_ops) for datarn in range(start, end)]
|
2513
2516
|
|
2514
2517
|
def fix_index(self, datarn: int | None = None) -> None:
|
@@ -2683,12 +2686,10 @@ class RowIndex(tk.Canvas):
|
|
2683
2686
|
else:
|
2684
2687
|
move_to_index = len(self.tree[new_parent].children)
|
2685
2688
|
move_to_row = self.tree_rns[new_parent]
|
2686
|
-
if new_parent == self.tree[item].parent
|
2687
|
-
|
2688
|
-
|
2689
|
-
|
2690
|
-
break
|
2691
|
-
move_to_row += sum(1 for _ in self.get_iid_descendants(ciid)) + 1
|
2689
|
+
_find = move_to_index + 1 if new_parent == self.tree[item].parent else move_to_index
|
2690
|
+
move_to_row += _find + sum(
|
2691
|
+
self.num_descendants(cid) for cid in islice(self.tree[new_parent].children, _find)
|
2692
|
+
)
|
2692
2693
|
insert_row = move_to_row + 1
|
2693
2694
|
else:
|
2694
2695
|
num_top_nodes = sum(1 for _ in self.gen_top_nodes())
|
@@ -2708,7 +2709,7 @@ class RowIndex(tk.Canvas):
|
|
2708
2709
|
disp_insert_row = None
|
2709
2710
|
|
2710
2711
|
else:
|
2711
|
-
iids =
|
2712
|
+
iids = {self.MT._row_index[r].iid for r in event_data["moved"]["rows"]["data"]}
|
2712
2713
|
iids_descendants = {iid: set(self.get_iid_descendants(iid)) for iid in iids}
|
2713
2714
|
|
2714
2715
|
# remove descendants in iids to move
|
@@ -2730,10 +2731,7 @@ class RowIndex(tk.Canvas):
|
|
2730
2731
|
# max_from = max(event_data.moved.rows)
|
2731
2732
|
min_to = min(event_data["moved"]["rows"]["data"].values())
|
2732
2733
|
max_to = max(event_data["moved"]["rows"]["data"].values())
|
2733
|
-
if min_from <= min_to
|
2734
|
-
insert_row = max_to
|
2735
|
-
else:
|
2736
|
-
insert_row = min_to
|
2734
|
+
insert_row = max_to if min_from <= min_to else min_to
|
2737
2735
|
move_to_iid = self.MT._row_index[insert_row].iid
|
2738
2736
|
|
2739
2737
|
move_to_index = self.PAR.index(move_to_iid)
|
@@ -2755,7 +2753,7 @@ class RowIndex(tk.Canvas):
|
|
2755
2753
|
if (disp_from_row := self.MT.try_disprn(self.tree_rns[item])) is not None:
|
2756
2754
|
event_data["moved"]["rows"]["displayed"] = {disp_from_row: disp_insert_row}
|
2757
2755
|
else:
|
2758
|
-
event_data["moved"]["rows"]["displayed"] = {
|
2756
|
+
event_data["moved"]["rows"]["displayed"] = {(): disp_insert_row}
|
2759
2757
|
|
2760
2758
|
if any(self.move_pid_causes_recursive_loop(self.MT._row_index[r].iid, new_parent) for r in moved_rows):
|
2761
2759
|
event_data["moved"]["rows"] = {}
|
@@ -2778,8 +2776,8 @@ class RowIndex(tk.Canvas):
|
|
2778
2776
|
data_new_idxs = event_data["moved"]["rows"]["data"]
|
2779
2777
|
data_old_idxs = dict(zip(data_new_idxs.values(), data_new_idxs))
|
2780
2778
|
|
2781
|
-
if
|
2782
|
-
del event_data["moved"]["rows"]["displayed"][
|
2779
|
+
if () in event_data["moved"]["rows"]["displayed"]:
|
2780
|
+
del event_data["moved"]["rows"]["displayed"][()]
|
2783
2781
|
|
2784
2782
|
if event_data["moved"]["rows"]["displayed"]:
|
2785
2783
|
event_data["moved"]["rows"]["displayed"] = get_new_indexes(
|
@@ -2848,7 +2846,7 @@ class RowIndex(tk.Canvas):
|
|
2848
2846
|
row_ctr = next(reversed(mapping.values())) + 1
|
2849
2847
|
|
2850
2848
|
if disp_mapping := event_data["moved"]["rows"]["displayed"]:
|
2851
|
-
if
|
2849
|
+
if () in disp_mapping:
|
2852
2850
|
disp_row_ctr = next(reversed(disp_mapping.values()))
|
2853
2851
|
else:
|
2854
2852
|
disp_row_ctr = next(reversed(disp_mapping.values())) + 1
|
@@ -2907,24 +2905,48 @@ class RowIndex(tk.Canvas):
|
|
2907
2905
|
|
2908
2906
|
def ancestors_all_open(self, iid: str, stop_at: str = "") -> bool:
|
2909
2907
|
if stop_at:
|
2910
|
-
for
|
2911
|
-
if
|
2908
|
+
for i in self.get_iid_ancestors(iid):
|
2909
|
+
if i == stop_at:
|
2912
2910
|
return True
|
2913
|
-
elif
|
2911
|
+
elif i not in self.tree_open_ids:
|
2914
2912
|
return False
|
2915
2913
|
return True
|
2916
2914
|
return all(map(self.tree_open_ids.__contains__, self.get_iid_ancestors(iid)))
|
2917
2915
|
|
2918
2916
|
def get_iid_ancestors(self, iid: str) -> Generator[str]:
|
2919
|
-
|
2920
|
-
|
2921
|
-
|
2917
|
+
current_iid = iid
|
2918
|
+
while self.tree[current_iid].parent:
|
2919
|
+
parent_iid = self.tree[current_iid].parent
|
2920
|
+
yield parent_iid
|
2921
|
+
current_iid = parent_iid
|
2922
2922
|
|
2923
2923
|
def get_iid_descendants(self, iid: str, check_open: bool = False) -> Generator[str]:
|
2924
|
-
|
2925
|
-
|
2926
|
-
|
2927
|
-
|
2924
|
+
tree = self.tree
|
2925
|
+
stack = [iter(tree[iid].children)]
|
2926
|
+
while stack:
|
2927
|
+
top_iterator = stack[-1]
|
2928
|
+
try:
|
2929
|
+
ciid = next(top_iterator)
|
2930
|
+
yield ciid
|
2931
|
+
if tree[ciid].children and (not check_open or ciid in self.tree_open_ids):
|
2932
|
+
stack.append(iter(tree[ciid].children))
|
2933
|
+
except StopIteration:
|
2934
|
+
stack.pop()
|
2935
|
+
|
2936
|
+
def num_descendants(self, iid: str) -> int:
|
2937
|
+
tree = self.tree
|
2938
|
+
stack = [iter(tree[iid].children)]
|
2939
|
+
num = 0
|
2940
|
+
while stack:
|
2941
|
+
top_iterator = stack[-1]
|
2942
|
+
try:
|
2943
|
+
ciid = next(top_iterator)
|
2944
|
+
num += 1
|
2945
|
+
if tree[ciid].children:
|
2946
|
+
stack.append(iter(tree[ciid].children))
|
2947
|
+
except StopIteration:
|
2948
|
+
stack.pop()
|
2949
|
+
return num
|
2928
2950
|
|
2929
2951
|
def items_parent(self, iid: str) -> str:
|
2930
2952
|
if self.tree[iid].parent:
|
@@ -2976,7 +2998,7 @@ class RowIndex(tk.Canvas):
|
|
2976
2998
|
|
2977
2999
|
def tree_build(
|
2978
3000
|
self,
|
2979
|
-
data: list[list[
|
3001
|
+
data: list[list[Any]],
|
2980
3002
|
iid_column: int,
|
2981
3003
|
parent_column: int,
|
2982
3004
|
text_column: None | int | list[str] = None,
|
@@ -3086,5 +3108,5 @@ class RowIndex(tk.Canvas):
|
|
3086
3108
|
{self.tree_rns[iid] for iid in self.PAR.get_children() if self.tree[iid].parent},
|
3087
3109
|
deselect_all=False,
|
3088
3110
|
data_indexes=True,
|
3089
|
-
row_heights=
|
3111
|
+
row_heights=row_heights is not False,
|
3090
3112
|
)
|