tksheet 7.1.12__tar.gz → 7.1.21__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.1.12/tksheet.egg-info → tksheet-7.1.21}/PKG-INFO +2 -2
- {tksheet-7.1.12 → tksheet-7.1.21}/README.md +1 -1
- {tksheet-7.1.12 → tksheet-7.1.21}/pyproject.toml +1 -1
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/__init__.py +2 -1
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/column_headers.py +10 -7
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/functions.py +28 -8
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/main_table.py +124 -95
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/row_index.py +110 -68
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/sheet.py +38 -34
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/sheet_options.py +3 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/themes.py +12 -0
- {tksheet-7.1.12 → tksheet-7.1.21/tksheet.egg-info}/PKG-INFO +2 -2
- {tksheet-7.1.12 → tksheet-7.1.21}/LICENSE.txt +0 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/setup.cfg +0 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/colors.py +0 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/formatters.py +0 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/other_classes.py +0 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/text_editor.py +0 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/top_left_rectangle.py +0 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/types.py +0 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet/vars.py +0 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet.egg-info/SOURCES.txt +0 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet.egg-info/dependency_links.txt +0 -0
- {tksheet-7.1.12 → tksheet-7.1.21}/tksheet.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: tksheet
|
3
|
-
Version: 7.1.
|
3
|
+
Version: 7.1.21
|
4
4
|
Summary: Tkinter table / sheet widget
|
5
5
|
Author-email: ragardner <github@ragardner.simplelogin.com>
|
6
6
|
License: Copyright (c) 2019 ragardner and open source contributors
|
@@ -42,7 +42,7 @@ License-File: LICENSE.txt
|
|
42
42
|
|
43
43
|
# tksheet
|
44
44
|
|
45
|
-
[](https://pypi.python.org/pypi/tksheet/) ](https://pypi.python.org/pypi/tksheet/)  [](https://github.com/ragardner/tksheet/blob/master/LICENSE.txt)
|
46
46
|
|
47
47
|
[](https://github.com/ragardner/tksheet/releases) [](https://pypi.org/project/tksheet/)
|
48
48
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# tksheet
|
2
2
|
|
3
|
-
[](https://pypi.python.org/pypi/tksheet/) ](https://pypi.python.org/pypi/tksheet/)  [](https://github.com/ragardner/tksheet/blob/master/LICENSE.txt)
|
4
4
|
|
5
5
|
[](https://github.com/ragardner/tksheet/releases) [](https://pypi.org/project/tksheet/)
|
6
6
|
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
6
6
|
name = "tksheet"
|
7
7
|
description = "Tkinter table / sheet widget"
|
8
8
|
readme = "README.md"
|
9
|
-
version = "7.1.
|
9
|
+
version = "7.1.21"
|
10
10
|
authors = [{ name = "ragardner", email = "github@ragardner.simplelogin.com" }]
|
11
11
|
requires-python = ">=3.8"
|
12
12
|
license = {file = "LICENSE.txt"}
|
@@ -4,7 +4,7 @@
|
|
4
4
|
tksheet - A Python tkinter table widget
|
5
5
|
"""
|
6
6
|
|
7
|
-
__version__ = "7.1.
|
7
|
+
__version__ = "7.1.21"
|
8
8
|
|
9
9
|
from .colors import (
|
10
10
|
color_map,
|
@@ -42,6 +42,7 @@ from .functions import (
|
|
42
42
|
event_dict,
|
43
43
|
get_checkbox_dict,
|
44
44
|
get_checkbox_kwargs,
|
45
|
+
get_data_from_clipboard,
|
45
46
|
get_dropdown_dict,
|
46
47
|
get_dropdown_kwargs,
|
47
48
|
get_index_of_gap_in_sorted_integer_seq_forward,
|
@@ -22,10 +22,10 @@ from .colors import (
|
|
22
22
|
from .formatters import is_bool_like, try_to_bool
|
23
23
|
from .functions import (
|
24
24
|
consecutive_ranges,
|
25
|
-
ev_stack_dict,
|
26
25
|
event_dict,
|
27
26
|
get_n2a,
|
28
27
|
is_contiguous,
|
28
|
+
pickled_event_dict,
|
29
29
|
rounded_box_coords,
|
30
30
|
try_binding,
|
31
31
|
)
|
@@ -133,6 +133,9 @@ class ColumnHeaders(tk.Canvas):
|
|
133
133
|
self.bind("<Double-Button-1>", self.double_b1)
|
134
134
|
self.bind(rc_binding, self.rc)
|
135
135
|
self.bind("<MouseWheel>", self.mousewheel)
|
136
|
+
if USER_OS == "linux":
|
137
|
+
self.bind("<Button-4>", self.mousewheel)
|
138
|
+
self.bind("<Button-5>", self.mousewheel)
|
136
139
|
else:
|
137
140
|
self.unbind("<Motion>")
|
138
141
|
self.unbind("<ButtonPress-1>")
|
@@ -141,6 +144,9 @@ class ColumnHeaders(tk.Canvas):
|
|
141
144
|
self.unbind("<Double-Button-1>")
|
142
145
|
self.unbind(rc_binding)
|
143
146
|
self.unbind("<MouseWheel>")
|
147
|
+
if USER_OS == "linux":
|
148
|
+
self.unbind("<Button-4>")
|
149
|
+
self.unbind("<Button-5>")
|
144
150
|
|
145
151
|
def mousewheel(self, event: object):
|
146
152
|
maxlines = 0
|
@@ -845,7 +851,7 @@ class ColumnHeaders(tk.Canvas):
|
|
845
851
|
"displayed": disp_new_idxs,
|
846
852
|
}
|
847
853
|
if self.MT.undo_enabled:
|
848
|
-
self.MT.undo_stack.append(
|
854
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
849
855
|
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
850
856
|
try_binding(self.ch_extra_end_drag_drop_func, event_data, "end_move_columns")
|
851
857
|
self.MT.sheet_modified(event_data)
|
@@ -1278,12 +1284,9 @@ class ColumnHeaders(tk.Canvas):
|
|
1278
1284
|
self.itemconfig(t, fill=fill, tag=tag, state="normal")
|
1279
1285
|
self.lift(t)
|
1280
1286
|
else:
|
1281
|
-
t = self.
|
1287
|
+
t = self.create_polygon(
|
1282
1288
|
points,
|
1283
1289
|
fill=fill,
|
1284
|
-
width=2,
|
1285
|
-
capstyle=tk.ROUND,
|
1286
|
-
joinstyle=tk.ROUND,
|
1287
1290
|
tag=tag,
|
1288
1291
|
)
|
1289
1292
|
self.disp_dropdown[t] = True
|
@@ -2091,7 +2094,7 @@ class ColumnHeaders(tk.Canvas):
|
|
2091
2094
|
self.fix_header(datacn)
|
2092
2095
|
if not check_input_valid or self.input_valid_for_cell(datacn, value):
|
2093
2096
|
if self.MT.undo_enabled and undo:
|
2094
|
-
self.MT.undo_stack.append(
|
2097
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
2095
2098
|
self.set_cell_data(datacn=datacn, value=value)
|
2096
2099
|
edited = True
|
2097
2100
|
if edited and cell_resize and self.PAR.ops.cell_auto_resize_enabled:
|
@@ -1,8 +1,11 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import bisect
|
4
|
+
import csv
|
5
|
+
import io
|
4
6
|
import pickle
|
5
7
|
import re
|
8
|
+
import tkinter as tk
|
6
9
|
import zlib
|
7
10
|
from collections import deque
|
8
11
|
from collections.abc import (
|
@@ -19,6 +22,7 @@ from .other_classes import (
|
|
19
22
|
DotDict,
|
20
23
|
EventDataDict,
|
21
24
|
Highlight,
|
25
|
+
Loc,
|
22
26
|
Span,
|
23
27
|
)
|
24
28
|
|
@@ -27,6 +31,21 @@ pickle_obj = partial(pickle.dumps, protocol=pickle.HIGHEST_PROTOCOL)
|
|
27
31
|
unpickle_obj = pickle.loads
|
28
32
|
|
29
33
|
|
34
|
+
def get_data_from_clipboard(
|
35
|
+
widget: tk.Misc,
|
36
|
+
delimiters: str,
|
37
|
+
lineterminator: str = "\n",
|
38
|
+
) -> list[list[str]]:
|
39
|
+
data = widget.clipboard_get()
|
40
|
+
try:
|
41
|
+
dialect = csv.Sniffer().sniff(data, delimiters=delimiters)
|
42
|
+
except Exception:
|
43
|
+
dialect = csv.excel_tab
|
44
|
+
if dialect.delimiter in data or lineterminator in data:
|
45
|
+
return list(csv.reader(io.StringIO(data), dialect=dialect, skipinitialspace=True))
|
46
|
+
return [[data]]
|
47
|
+
|
48
|
+
|
30
49
|
def pickle_compress(obj: object) -> bytes:
|
31
50
|
return compress(pickle_obj(obj))
|
32
51
|
|
@@ -164,11 +183,8 @@ def change_eventname(event_dict: EventDataDict, newname: str) -> EventDataDict:
|
|
164
183
|
return EventDataDict({**event_dict, **{"eventname": newname}})
|
165
184
|
|
166
185
|
|
167
|
-
def
|
168
|
-
return DotDict(
|
169
|
-
name=d["eventname"],
|
170
|
-
data=pickle_compress(d),
|
171
|
-
)
|
186
|
+
def pickled_event_dict(d: DotDict) -> DotDict:
|
187
|
+
return DotDict(name=d["eventname"], data=pickle_compress(d))
|
172
188
|
|
173
189
|
|
174
190
|
def len_to_idx(n: int) -> int:
|
@@ -406,11 +422,13 @@ def index_exists(seq: Sequence[object], index: int) -> bool:
|
|
406
422
|
def move_elements_by_mapping(
|
407
423
|
seq: list[object],
|
408
424
|
new_idxs: dict[int, int],
|
409
|
-
old_idxs: dict[int, int],
|
425
|
+
old_idxs: dict[int, int] | None = None,
|
410
426
|
) -> list[object]:
|
411
427
|
# move elements of a list around, displacing
|
412
428
|
# other elements based on mapping
|
413
429
|
# of {old index: new index, ...}
|
430
|
+
if old_idxs is None:
|
431
|
+
old_idxs = dict(zip(new_idxs.values(), new_idxs))
|
414
432
|
|
415
433
|
# create dummy list
|
416
434
|
res = [0] * len(seq)
|
@@ -1293,10 +1311,12 @@ def mod_span_widget(span: Span, widget: object) -> Span:
|
|
1293
1311
|
def mod_event_val(
|
1294
1312
|
event_data: EventDataDict,
|
1295
1313
|
val: object,
|
1296
|
-
loc:
|
1314
|
+
loc: Loc | int,
|
1297
1315
|
) -> EventDataDict:
|
1298
1316
|
event_data.value = val
|
1299
|
-
event_data.loc = loc
|
1317
|
+
event_data.loc = Loc(*loc)
|
1318
|
+
event_data.row = loc[0]
|
1319
|
+
event_data.column = loc[1]
|
1300
1320
|
return event_data
|
1301
1321
|
|
1302
1322
|
|
@@ -52,9 +52,9 @@ from .functions import (
|
|
52
52
|
decompress_load,
|
53
53
|
diff_gen,
|
54
54
|
diff_list,
|
55
|
-
ev_stack_dict,
|
56
55
|
event_dict,
|
57
56
|
gen_formatted,
|
57
|
+
get_data_from_clipboard,
|
58
58
|
get_new_indexes,
|
59
59
|
get_seq_without_gaps_at_index,
|
60
60
|
index_exists,
|
@@ -68,6 +68,7 @@ from .functions import (
|
|
68
68
|
mod_span_widget,
|
69
69
|
move_elements_by_mapping,
|
70
70
|
pickle_obj,
|
71
|
+
pickled_event_dict,
|
71
72
|
rounded_box_coords,
|
72
73
|
span_idxs_post_move,
|
73
74
|
try_binding,
|
@@ -363,10 +364,10 @@ class MainTable(tk.Canvas):
|
|
363
364
|
("<ButtonRelease-1>", self, self.b1_release),
|
364
365
|
("<Double-Button-1>", self, self.double_b1),
|
365
366
|
("<MouseWheel>", self, self.mousewheel),
|
367
|
+
("<MouseWheel>", self.RI, self.mousewheel),
|
366
368
|
("<Shift-ButtonPress-1>", self, self.shift_b1_press),
|
367
369
|
("<Shift-ButtonPress-1>", self.CH, self.CH.shift_b1_press),
|
368
370
|
("<Shift-ButtonPress-1>", self.RI, self.RI.shift_b1_press),
|
369
|
-
("<MouseWheel>", self.RI, self.mousewheel),
|
370
371
|
(rc_binding, self, self.rc),
|
371
372
|
(f"<{ctrl_key}-ButtonPress-1>", self, self.ctrl_b1_press),
|
372
373
|
(f"<{ctrl_key}-ButtonPress-1>", self.CH, self.CH.ctrl_b1_press),
|
@@ -385,9 +386,11 @@ class MainTable(tk.Canvas):
|
|
385
386
|
("<Control-equal>", self.zoom_in),
|
386
387
|
("<Control-minus>", self.zoom_out),
|
387
388
|
)
|
388
|
-
|
389
|
+
mt_ri_canvas_linux_bindings = {
|
389
390
|
("<Button-4>", self.mousewheel),
|
390
391
|
("<Button-5>", self.mousewheel),
|
392
|
+
}
|
393
|
+
all_canvas_linux_bindings = {
|
391
394
|
("<Shift-Button-4>", self.shift_mousewheel),
|
392
395
|
("<Shift-Button-5>", self.shift_mousewheel),
|
393
396
|
("<Control-Button-4>", self.ctrl_mousewheel),
|
@@ -400,6 +403,9 @@ class MainTable(tk.Canvas):
|
|
400
403
|
for canvas in (self, self.RI, self.CH):
|
401
404
|
canvas.bind(b[0], b[1])
|
402
405
|
if USER_OS == "linux":
|
406
|
+
for b in mt_ri_canvas_linux_bindings:
|
407
|
+
for canvas in (self, self.RI):
|
408
|
+
canvas.bind(b[0], b[1])
|
403
409
|
for b in all_canvas_linux_bindings:
|
404
410
|
for canvas in (self, self.RI, self.CH):
|
405
411
|
canvas.bind(b[0], b[1])
|
@@ -410,6 +416,9 @@ class MainTable(tk.Canvas):
|
|
410
416
|
for canvas in (self, self.RI, self.CH):
|
411
417
|
canvas.unbind(b[0])
|
412
418
|
if USER_OS == "linux":
|
419
|
+
for b in mt_ri_canvas_linux_bindings:
|
420
|
+
for canvas in (self, self.RI):
|
421
|
+
canvas.unbind(b[0])
|
413
422
|
for b in all_canvas_linux_bindings:
|
414
423
|
for canvas in (self, self.RI, self.CH):
|
415
424
|
canvas.unbind(b[0])
|
@@ -495,6 +504,8 @@ class MainTable(tk.Canvas):
|
|
495
504
|
def get_ctrl_x_c_boxes(self) -> tuple[dict[tuple[int, int, int, int], str], int]:
|
496
505
|
boxes = {}
|
497
506
|
maxrows = 0
|
507
|
+
if not self.selected:
|
508
|
+
return boxes, maxrows
|
498
509
|
if self.selected.type_ in ("cells", "columns"):
|
499
510
|
curr_box = self.selection_boxes[self.selected.fill_iid].coords
|
500
511
|
maxrows = curr_box[2] - curr_box[0]
|
@@ -517,7 +528,7 @@ class MainTable(tk.Canvas):
|
|
517
528
|
)
|
518
529
|
return s, writer
|
519
530
|
|
520
|
-
def ctrl_c(self, event=None) -> None:
|
531
|
+
def ctrl_c(self, event=None) -> None | EventDataDict:
|
521
532
|
if not self.selected:
|
522
533
|
return
|
523
534
|
event_data = event_dict(
|
@@ -555,14 +566,17 @@ class MainTable(tk.Canvas):
|
|
555
566
|
for r1, c1, r2, c2 in boxes:
|
556
567
|
self.show_ctrl_outline(canvas="table", start_cell=(c1, r1), end_cell=(c2, r2))
|
557
568
|
self.clipboard_clear()
|
558
|
-
if len(event_data["cells"]["table"]) == 1
|
569
|
+
if len(event_data["cells"]["table"]) == 1 and self.PAR.ops.to_clipboard_lineterminator not in next(
|
570
|
+
iter(event_data["cells"]["table"].values())
|
571
|
+
):
|
559
572
|
self.clipboard_append(next(iter(event_data["cells"]["table"].values())))
|
560
573
|
else:
|
561
574
|
self.clipboard_append(s.getvalue())
|
562
575
|
self.update_idletasks()
|
563
576
|
try_binding(self.extra_end_ctrl_c_func, event_data, "end_ctrl_c")
|
577
|
+
return event_data
|
564
578
|
|
565
|
-
def ctrl_x(self, event=None) -> None:
|
579
|
+
def ctrl_x(self, event=None, validation: bool = True) -> None | EventDataDict:
|
566
580
|
if not self.selected:
|
567
581
|
return
|
568
582
|
event_data = event_dict(
|
@@ -586,10 +600,14 @@ class MainTable(tk.Canvas):
|
|
586
600
|
datacn = self.datacn(c)
|
587
601
|
row.append(self.get_cell_clipboard(datarn, datacn))
|
588
602
|
val = self.get_value_for_empty_cell(datarn, datacn)
|
589
|
-
if
|
590
|
-
self.edit_validation_func
|
591
|
-
|
592
|
-
|
603
|
+
if (
|
604
|
+
not self.edit_validation_func
|
605
|
+
or not validation
|
606
|
+
or (
|
607
|
+
self.edit_validation_func
|
608
|
+
and (val := self.edit_validation_func(mod_event_val(event_data, val, (r1 + rn, c))))
|
609
|
+
is not None
|
610
|
+
)
|
593
611
|
):
|
594
612
|
event_data = self.event_data_set_cell(
|
595
613
|
datarn,
|
@@ -607,10 +625,14 @@ class MainTable(tk.Canvas):
|
|
607
625
|
datacn = self.datacn(c)
|
608
626
|
row.append(self.get_cell_clipboard(datarn, datacn))
|
609
627
|
val = self.get_value_for_empty_cell(datarn, datacn)
|
610
|
-
if
|
611
|
-
self.edit_validation_func
|
612
|
-
|
613
|
-
|
628
|
+
if (
|
629
|
+
not self.edit_validation_func
|
630
|
+
or not validation
|
631
|
+
or (
|
632
|
+
self.edit_validation_func
|
633
|
+
and (val := self.edit_validation_func(mod_event_val(event_data, val, (r1 + rn, c))))
|
634
|
+
is not None
|
635
|
+
)
|
614
636
|
):
|
615
637
|
event_data = self.event_data_set_cell(
|
616
638
|
datarn,
|
@@ -620,9 +642,11 @@ class MainTable(tk.Canvas):
|
|
620
642
|
)
|
621
643
|
writer.writerow(row)
|
622
644
|
if event_data["cells"]["table"]:
|
623
|
-
self.undo_stack.append(
|
645
|
+
self.undo_stack.append(pickled_event_dict(event_data))
|
624
646
|
self.clipboard_clear()
|
625
|
-
if len(event_data["cells"]["table"]) == 1
|
647
|
+
if len(event_data["cells"]["table"]) == 1 and self.PAR.ops.to_clipboard_lineterminator not in next(
|
648
|
+
iter(event_data["cells"]["table"].values())
|
649
|
+
):
|
626
650
|
self.clipboard_append(next(iter(event_data["cells"]["table"].values())))
|
627
651
|
else:
|
628
652
|
self.clipboard_append(s.getvalue())
|
@@ -633,8 +657,9 @@ class MainTable(tk.Canvas):
|
|
633
657
|
if event_data["cells"]["table"]:
|
634
658
|
try_binding(self.extra_end_ctrl_x_func, event_data, "end_ctrl_x")
|
635
659
|
self.sheet_modified(event_data)
|
660
|
+
return event_data
|
636
661
|
|
637
|
-
def ctrl_v(self, event: object = None) -> None:
|
662
|
+
def ctrl_v(self, event: object = None, validation: bool = True) -> None | EventDataDict:
|
638
663
|
if not self.PAR.ops.expand_sheet_if_paste_too_big and (
|
639
664
|
len(self.col_positions) == 1 or len(self.row_positions) == 1
|
640
665
|
):
|
@@ -660,18 +685,13 @@ class MainTable(tk.Canvas):
|
|
660
685
|
elif len(self.row_positions) > 1 and len(self.col_positions) > 1:
|
661
686
|
selected_c, selected_r = 0, len(self.row_positions) - 1
|
662
687
|
try:
|
663
|
-
data =
|
688
|
+
data = get_data_from_clipboard(
|
689
|
+
widget=self,
|
690
|
+
delimiters=self.PAR.ops.from_clipboard_delimiters,
|
691
|
+
lineterminator=self.PAR.ops.to_clipboard_lineterminator,
|
692
|
+
)
|
664
693
|
except Exception:
|
665
694
|
return
|
666
|
-
try:
|
667
|
-
dialect = csv.Sniffer().sniff(data, delimiters=self.PAR.ops.from_clipboard_delimiters)
|
668
|
-
except Exception:
|
669
|
-
dialect = csv.excel_tab
|
670
|
-
if dialect.delimiter in data:
|
671
|
-
if not (data := list(csv.reader(io.StringIO(data), dialect=dialect, skipinitialspace=True))):
|
672
|
-
return
|
673
|
-
else:
|
674
|
-
data = [[data]]
|
675
695
|
new_data_numcols = max(map(len, data))
|
676
696
|
new_data_numrows = len(data)
|
677
697
|
for rn, r in enumerate(data):
|
@@ -749,9 +769,13 @@ class MainTable(tk.Canvas):
|
|
749
769
|
for ndr, r in enumerate(range(selected_r, selected_r_adjusted_new_data_numrows)):
|
750
770
|
for ndc, c in enumerate(range(selected_c, selected_c_adjusted_new_data_numcols)):
|
751
771
|
val = data[ndr][ndc]
|
752
|
-
if
|
753
|
-
self.edit_validation_func
|
754
|
-
|
772
|
+
if (
|
773
|
+
not self.edit_validation_func
|
774
|
+
or not validation
|
775
|
+
or (
|
776
|
+
self.edit_validation_func
|
777
|
+
and (val := self.edit_validation_func(mod_event_val(event_data, val, (r, c)))) is not None
|
778
|
+
)
|
755
779
|
):
|
756
780
|
event_data = self.event_data_set_cell(
|
757
781
|
datarn=self.datarn(r),
|
@@ -785,10 +809,14 @@ class MainTable(tk.Canvas):
|
|
785
809
|
):
|
786
810
|
val = data[ndr][ndc]
|
787
811
|
datacn = self.datacn(c)
|
788
|
-
if
|
789
|
-
self.edit_validation_func
|
790
|
-
|
791
|
-
|
812
|
+
if (
|
813
|
+
not self.edit_validation_func
|
814
|
+
or not validation
|
815
|
+
or (
|
816
|
+
self.edit_validation_func
|
817
|
+
and (val := self.edit_validation_func(mod_event_val(event_data, val, (r, c)))) is not None
|
818
|
+
and self.input_valid_for_cell(r, datacn, val, ignore_empty=True)
|
819
|
+
)
|
792
820
|
):
|
793
821
|
rows[r][datacn] = val
|
794
822
|
ctr += 1
|
@@ -823,10 +851,14 @@ class MainTable(tk.Canvas):
|
|
823
851
|
):
|
824
852
|
val = data[ndr][ndc]
|
825
853
|
datarn = self.datarn(r)
|
826
|
-
if
|
827
|
-
self.edit_validation_func
|
828
|
-
|
829
|
-
|
854
|
+
if (
|
855
|
+
not self.edit_validation_func
|
856
|
+
or not validation
|
857
|
+
or (
|
858
|
+
self.edit_validation_func
|
859
|
+
and (val := self.edit_validation_func(mod_event_val(event_data, val, (r, c)))) is not None
|
860
|
+
and self.input_valid_for_cell(datarn, c, val, ignore_empty=True)
|
861
|
+
)
|
830
862
|
):
|
831
863
|
columns[c][datarn] = val
|
832
864
|
ctr += 1
|
@@ -839,7 +871,7 @@ class MainTable(tk.Canvas):
|
|
839
871
|
)
|
840
872
|
self.deselect("all", redraw=False)
|
841
873
|
if event_data["cells"]["table"] or event_data["added"]["rows"] or event_data["added"]["columns"]:
|
842
|
-
self.undo_stack.append(
|
874
|
+
self.undo_stack.append(pickled_event_dict(event_data))
|
843
875
|
self.create_selection_box(
|
844
876
|
selected_r,
|
845
877
|
selected_c,
|
@@ -861,8 +893,9 @@ class MainTable(tk.Canvas):
|
|
861
893
|
if event_data["cells"]["table"] or event_data["added"]["rows"] or event_data["added"]["columns"]:
|
862
894
|
try_binding(self.extra_end_ctrl_v_func, event_data, "end_ctrl_v")
|
863
895
|
self.sheet_modified(event_data)
|
896
|
+
return event_data
|
864
897
|
|
865
|
-
def delete_key(self, event: object = None) -> None:
|
898
|
+
def delete_key(self, event: object = None, validation: bool = True) -> None | EventDataDict:
|
866
899
|
if not self.selected:
|
867
900
|
return
|
868
901
|
event_data = event_dict(
|
@@ -879,9 +912,13 @@ class MainTable(tk.Canvas):
|
|
879
912
|
for c in range(c1, c2):
|
880
913
|
datarn, datacn = self.datarn(r), self.datacn(c)
|
881
914
|
val = self.get_value_for_empty_cell(datarn, datacn)
|
882
|
-
if
|
883
|
-
self.edit_validation_func
|
884
|
-
|
915
|
+
if (
|
916
|
+
not self.edit_validation_func
|
917
|
+
or not validation
|
918
|
+
or (
|
919
|
+
self.edit_validation_func
|
920
|
+
and (val := self.edit_validation_func(mod_event_val(event_data, val, (r, c)))) is not None
|
921
|
+
)
|
885
922
|
):
|
886
923
|
event_data = self.event_data_set_cell(
|
887
924
|
datarn,
|
@@ -890,10 +927,11 @@ class MainTable(tk.Canvas):
|
|
890
927
|
event_data,
|
891
928
|
)
|
892
929
|
if event_data["cells"]["table"]:
|
893
|
-
self.undo_stack.append(
|
930
|
+
self.undo_stack.append(pickled_event_dict(event_data))
|
894
931
|
try_binding(self.extra_end_delete_key_func, event_data, "end_delete")
|
895
932
|
self.refresh()
|
896
933
|
self.sheet_modified(event_data)
|
934
|
+
return event_data
|
897
935
|
|
898
936
|
def event_data_set_cell(self, datarn: int, datacn: int, value: object, event_data: dict) -> EventDataDict:
|
899
937
|
if self.input_valid_for_cell(datarn, datacn, value):
|
@@ -1370,39 +1408,36 @@ class MainTable(tk.Canvas):
|
|
1370
1408
|
# all the way from 0 to max_idx
|
1371
1409
|
if old_idxs is None:
|
1372
1410
|
old_idxs = dict(zip(new_idxs.values(), new_idxs))
|
1373
|
-
seq = tuple(range(max_idx + 1))
|
1374
1411
|
return dict(
|
1375
1412
|
zip(
|
1376
|
-
move_elements_by_mapping(
|
1377
|
-
|
1413
|
+
move_elements_by_mapping(tuple(range(max_idx + 1)), new_idxs, old_idxs),
|
1414
|
+
range(max_idx + 1),
|
1378
1415
|
)
|
1379
1416
|
)
|
1380
1417
|
|
1381
|
-
def undo(self, event: object = None) -> None:
|
1418
|
+
def undo(self, event: object = None) -> None | EventDataDict:
|
1382
1419
|
if not self.undo_stack:
|
1383
1420
|
return
|
1384
|
-
|
1385
|
-
modification = self.undo_stack[-1]["data"]
|
1386
|
-
else:
|
1387
|
-
modification = decompress_load(self.undo_stack[-1]["data"])
|
1421
|
+
modification = decompress_load(self.undo_stack[-1]["data"])
|
1388
1422
|
if not try_binding(self.extra_begin_ctrl_z_func, modification, "begin_undo"):
|
1389
1423
|
return
|
1390
|
-
self.
|
1424
|
+
event_data = self.undo_modification_invert_event(modification)
|
1425
|
+
self.redo_stack.append(pickled_event_dict(event_data))
|
1391
1426
|
self.undo_stack.pop()
|
1392
|
-
try_binding(self.extra_end_ctrl_z_func,
|
1427
|
+
try_binding(self.extra_end_ctrl_z_func, event_data, "end_undo")
|
1428
|
+
return event_data
|
1393
1429
|
|
1394
|
-
def redo(self, event: object = None) -> None:
|
1430
|
+
def redo(self, event: object = None) -> None | EventDataDict:
|
1395
1431
|
if not self.redo_stack:
|
1396
1432
|
return
|
1397
|
-
|
1398
|
-
modification = self.redo_stack[-1]["data"]
|
1399
|
-
else:
|
1400
|
-
modification = decompress_load(self.redo_stack[-1]["data"])
|
1433
|
+
modification = decompress_load(self.redo_stack[-1]["data"])
|
1401
1434
|
if not try_binding(self.extra_begin_ctrl_z_func, modification, "begin_redo"):
|
1402
1435
|
return
|
1403
|
-
self.
|
1436
|
+
event_data = self.undo_modification_invert_event(modification, name="redo")
|
1437
|
+
self.undo_stack.append(pickled_event_dict(event_data))
|
1404
1438
|
self.redo_stack.pop()
|
1405
|
-
try_binding(self.extra_end_ctrl_z_func,
|
1439
|
+
try_binding(self.extra_end_ctrl_z_func, event_data, "end_redo")
|
1440
|
+
return event_data
|
1406
1441
|
|
1407
1442
|
def sheet_modified(self, event_data: EventDataDict, purge_redo: bool = True) -> None:
|
1408
1443
|
self.PAR.emit_event("<<SheetModified>>", event_data)
|
@@ -1450,7 +1485,7 @@ class MainTable(tk.Canvas):
|
|
1450
1485
|
k: mod_span_widget(unpickle_obj(v), self.PAR) for k, v in modification["named_spans"].items()
|
1451
1486
|
}
|
1452
1487
|
|
1453
|
-
def undo_modification_invert_event(self, modification: EventDataDict, name: str = "undo") ->
|
1488
|
+
def undo_modification_invert_event(self, modification: EventDataDict, name: str = "undo") -> EventDataDict:
|
1454
1489
|
self.deselect("all", redraw=False)
|
1455
1490
|
event_data = event_dict(
|
1456
1491
|
name=modification["eventname"],
|
@@ -1615,7 +1650,7 @@ class MainTable(tk.Canvas):
|
|
1615
1650
|
|
1616
1651
|
self.sheet_modified(event_data, purge_redo=False)
|
1617
1652
|
self.refresh()
|
1618
|
-
return
|
1653
|
+
return event_data
|
1619
1654
|
|
1620
1655
|
def see(
|
1621
1656
|
self,
|
@@ -2733,9 +2768,10 @@ class MainTable(tk.Canvas):
|
|
2733
2768
|
popup_menu = self.rc_popup_menu
|
2734
2769
|
else:
|
2735
2770
|
self.deselect("all")
|
2736
|
-
|
2771
|
+
if self.rc_popup_menus_enabled:
|
2772
|
+
popup_menu = self.empty_rc_popup_menu
|
2737
2773
|
try_binding(self.extra_rc_func, event)
|
2738
|
-
if popup_menu
|
2774
|
+
if popup_menu:
|
2739
2775
|
popup_menu.tk_popup(event.x_root, event.y_root)
|
2740
2776
|
|
2741
2777
|
def b1_press(self, event=None):
|
@@ -3715,6 +3751,22 @@ class MainTable(tk.Canvas):
|
|
3715
3751
|
del self.row_positions[idx]
|
3716
3752
|
self.row_positions[idx:] = [e - w for e in islice(self.row_positions, idx, len(self.row_positions))]
|
3717
3753
|
|
3754
|
+
def del_col_positions(self, idxs: Iterator[int] | None = None):
|
3755
|
+
if idxs is None:
|
3756
|
+
del self.col_positions[-1]
|
3757
|
+
else:
|
3758
|
+
if not isinstance(idxs, set):
|
3759
|
+
idxs = set(idxs)
|
3760
|
+
self.set_col_positions(itr=(w for i, w in enumerate(self.gen_column_widths()) if i not in idxs))
|
3761
|
+
|
3762
|
+
def del_row_positions(self, idxs: Iterator[int] | None = None):
|
3763
|
+
if idxs is None:
|
3764
|
+
del self.row_positions[-1]
|
3765
|
+
else:
|
3766
|
+
if not isinstance(idxs, set):
|
3767
|
+
idxs = set(idxs)
|
3768
|
+
self.set_row_positions(itr=(h for i, h in enumerate(self.gen_row_heights()) if i not in idxs))
|
3769
|
+
|
3718
3770
|
def get_column_widths(self) -> list[int]:
|
3719
3771
|
return diff_list(self.col_positions)
|
3720
3772
|
|
@@ -3727,26 +3779,6 @@ class MainTable(tk.Canvas):
|
|
3727
3779
|
def gen_row_heights(self) -> Generator[int]:
|
3728
3780
|
return diff_gen(self.row_positions)
|
3729
3781
|
|
3730
|
-
def del_col_positions(self, idx: int, num: int = 1, deselect_all: bool = False):
|
3731
|
-
if deselect_all:
|
3732
|
-
self.deselect("all", redraw=False)
|
3733
|
-
if idx == "end" or len(self.col_positions) <= idx + 1:
|
3734
|
-
del self.col_positions[-1]
|
3735
|
-
else:
|
3736
|
-
cws = self.get_column_widths()
|
3737
|
-
cws[idx : idx + num] = []
|
3738
|
-
self.set_col_positions(itr=cws)
|
3739
|
-
|
3740
|
-
def del_row_positions(self, idx: int, numrows: int = 1, deselect_all: bool = False):
|
3741
|
-
if deselect_all:
|
3742
|
-
self.deselect("all", redraw=False)
|
3743
|
-
if idx == "end" or len(self.row_positions) <= idx + 1:
|
3744
|
-
del self.row_positions[-1]
|
3745
|
-
else:
|
3746
|
-
rhs = self.get_row_heights()
|
3747
|
-
rhs[idx : idx + numrows] = []
|
3748
|
-
self.set_row_positions(itr=rhs)
|
3749
|
-
|
3750
3782
|
def insert_col_position(
|
3751
3783
|
self,
|
3752
3784
|
idx: Literal["end"] | int = "end",
|
@@ -4301,7 +4333,7 @@ class MainTable(tk.Canvas):
|
|
4301
4333
|
event_data=event_data,
|
4302
4334
|
)
|
4303
4335
|
if self.undo_enabled:
|
4304
|
-
self.undo_stack.append(
|
4336
|
+
self.undo_stack.append(pickled_event_dict(event_data))
|
4305
4337
|
self.refresh()
|
4306
4338
|
try_binding(self.extra_end_insert_cols_rc_func, event_data, "end_add_columns")
|
4307
4339
|
self.sheet_modified(event_data)
|
@@ -4432,7 +4464,7 @@ class MainTable(tk.Canvas):
|
|
4432
4464
|
event_data=event_data,
|
4433
4465
|
)
|
4434
4466
|
if self.undo_enabled:
|
4435
|
-
self.undo_stack.append(
|
4467
|
+
self.undo_stack.append(pickled_event_dict(event_data))
|
4436
4468
|
self.refresh()
|
4437
4469
|
try_binding(self.extra_end_insert_rows_rc_func, event_data, "end_add_rows")
|
4438
4470
|
self.sheet_modified(event_data)
|
@@ -4604,7 +4636,7 @@ class MainTable(tk.Canvas):
|
|
4604
4636
|
data_cols = selected if self.all_columns_displayed else [self.displayed_columns[c] for c in selected]
|
4605
4637
|
event_data = self.delete_columns_data(data_cols, event_data)
|
4606
4638
|
if self.undo_enabled:
|
4607
|
-
self.undo_stack.append(
|
4639
|
+
self.undo_stack.append(pickled_event_dict(event_data))
|
4608
4640
|
self.deselect("all")
|
4609
4641
|
try_binding(self.extra_end_del_cols_rc_func, event_data, "end_delete_columns")
|
4610
4642
|
self.sheet_modified(event_data)
|
@@ -4658,7 +4690,7 @@ class MainTable(tk.Canvas):
|
|
4658
4690
|
data_rows = selected if self.all_rows_displayed else [self.displayed_rows[r] for r in selected]
|
4659
4691
|
event_data = self.delete_rows_data(data_rows, event_data)
|
4660
4692
|
if self.undo_enabled:
|
4661
|
-
self.undo_stack.append(
|
4693
|
+
self.undo_stack.append(pickled_event_dict(event_data))
|
4662
4694
|
self.deselect("all")
|
4663
4695
|
try_binding(self.extra_end_del_rows_rc_func, event_data, "end_delete_rows")
|
4664
4696
|
self.sheet_modified(event_data)
|
@@ -4881,7 +4913,7 @@ class MainTable(tk.Canvas):
|
|
4881
4913
|
if isinstance(at_least_cols, int) and at_least_cols > total_data_cols:
|
4882
4914
|
total_data_cols = at_least_cols
|
4883
4915
|
total_data_cols = max(total_data_cols, len(self.col_positions) - 1)
|
4884
|
-
if include_header and total_data_cols > len(self._headers):
|
4916
|
+
if not isinstance(self._headers, int) and include_header and total_data_cols > len(self._headers):
|
4885
4917
|
self.CH.fix_header(total_data_cols)
|
4886
4918
|
for rn, r in enumerate(self.data):
|
4887
4919
|
if total_data_cols > (lnr := len(r)):
|
@@ -5105,12 +5137,9 @@ class MainTable(tk.Canvas):
|
|
5105
5137
|
self.itemconfig(t, fill=fill, tag=tag, state="normal")
|
5106
5138
|
self.lift(t)
|
5107
5139
|
else:
|
5108
|
-
t = self.
|
5140
|
+
t = self.create_polygon(
|
5109
5141
|
points,
|
5110
5142
|
fill=fill,
|
5111
|
-
width=2,
|
5112
|
-
capstyle=tk.ROUND,
|
5113
|
-
joinstyle=tk.ROUND,
|
5114
5143
|
tag=tag,
|
5115
5144
|
)
|
5116
5145
|
self.disp_dropdown[t] = True
|
@@ -6970,7 +6999,7 @@ class MainTable(tk.Canvas):
|
|
6970
6999
|
)
|
6971
7000
|
if not check_input_valid or self.input_valid_for_cell(datarn, datacn, value):
|
6972
7001
|
if self.undo_enabled and undo:
|
6973
|
-
self.undo_stack.append(
|
7002
|
+
self.undo_stack.append(pickled_event_dict(event_data))
|
6974
7003
|
self.set_cell_data(datarn, datacn, value)
|
6975
7004
|
if cell_resize and self.PAR.ops.cell_auto_resize_enabled:
|
6976
7005
|
self.set_cell_size_to_text(r, c, only_set_if_too_small=True, redraw=redraw, run_binding=True)
|
@@ -29,11 +29,11 @@ from .formatters import (
|
|
29
29
|
)
|
30
30
|
from .functions import (
|
31
31
|
consecutive_chunks,
|
32
|
-
ev_stack_dict,
|
33
32
|
event_dict,
|
34
33
|
get_n2a,
|
35
34
|
is_contiguous,
|
36
35
|
num2alpha,
|
36
|
+
pickled_event_dict,
|
37
37
|
rounded_box_coords,
|
38
38
|
try_binding,
|
39
39
|
)
|
@@ -117,6 +117,7 @@ class RowIndex(tk.Canvas):
|
|
117
117
|
self.disp_resize_lines = {}
|
118
118
|
self.disp_dropdown = {}
|
119
119
|
self.disp_checkbox = {}
|
120
|
+
self.disp_tree_arrow = {}
|
120
121
|
self.disp_boxes = set()
|
121
122
|
self.hidd_text = {}
|
122
123
|
self.hidd_high = {}
|
@@ -126,6 +127,7 @@ class RowIndex(tk.Canvas):
|
|
126
127
|
self.hidd_resize_lines = {}
|
127
128
|
self.hidd_dropdown = {}
|
128
129
|
self.hidd_checkbox = {}
|
130
|
+
self.hidd_tree_arrow = {}
|
129
131
|
self.hidd_boxes = set()
|
130
132
|
|
131
133
|
self.align = kwargs["row_index_align"]
|
@@ -851,7 +853,7 @@ class RowIndex(tk.Canvas):
|
|
851
853
|
"displayed": disp_new_idxs,
|
852
854
|
}
|
853
855
|
if self.MT.undo_enabled:
|
854
|
-
self.MT.undo_stack.append(
|
856
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
855
857
|
self.MT.main_table_redraw_grid_and_text(redraw_header=True, redraw_row_index=True)
|
856
858
|
try_binding(self.ri_extra_end_drag_drop_func, event_data, "end_move_rows")
|
857
859
|
self.MT.sheet_modified(event_data)
|
@@ -1017,7 +1019,7 @@ class RowIndex(tk.Canvas):
|
|
1017
1019
|
align = self.align
|
1018
1020
|
if align == "w":
|
1019
1021
|
w += self.MT.index_txt_height
|
1020
|
-
w += self.get_treeview_indent(self.MT._row_index[datarn].iid)
|
1022
|
+
w += self.get_treeview_indent(self.MT._row_index[datarn].iid) + 4
|
1021
1023
|
return w, h
|
1022
1024
|
|
1023
1025
|
def set_row_height(
|
@@ -1205,7 +1207,7 @@ class RowIndex(tk.Canvas):
|
|
1205
1207
|
if kwargs[0] is not None:
|
1206
1208
|
c_1 = kwargs[0] if kwargs[0].startswith("#") else color_map[kwargs[0]]
|
1207
1209
|
if "rows" in selections and r in selections["rows"]:
|
1208
|
-
|
1210
|
+
txtfg = (
|
1209
1211
|
self.PAR.ops.index_selected_rows_fg
|
1210
1212
|
if kwargs[1] is None or self.PAR.ops.display_selected_fg_over_highlights
|
1211
1213
|
else kwargs[1]
|
@@ -1217,7 +1219,7 @@ class RowIndex(tk.Canvas):
|
|
1217
1219
|
+ f"{int((int(c_1[5:], 16) + int(c_3[5:], 16)) / 2):02X}"
|
1218
1220
|
)
|
1219
1221
|
elif "cells" in selections and r in selections["cells"]:
|
1220
|
-
|
1222
|
+
txtfg = (
|
1221
1223
|
self.PAR.ops.index_selected_cells_fg
|
1222
1224
|
if kwargs[1] is None or self.PAR.ops.display_selected_fg_over_highlights
|
1223
1225
|
else kwargs[1]
|
@@ -1229,7 +1231,7 @@ class RowIndex(tk.Canvas):
|
|
1229
1231
|
+ f"{int((int(c_1[5:], 16) + int(c_2[5:], 16)) / 2):02X}"
|
1230
1232
|
)
|
1231
1233
|
else:
|
1232
|
-
|
1234
|
+
txtfg = self.PAR.ops.index_fg if kwargs[1] is None else kwargs[1]
|
1233
1235
|
if kwargs[0] is not None:
|
1234
1236
|
fill = kwargs[0]
|
1235
1237
|
if kwargs[0] is not None:
|
@@ -1246,14 +1248,18 @@ class RowIndex(tk.Canvas):
|
|
1246
1248
|
),
|
1247
1249
|
tag="s",
|
1248
1250
|
)
|
1251
|
+
tree_arrow_fg = txtfg
|
1249
1252
|
elif not kwargs:
|
1250
1253
|
if "rows" in selections and r in selections["rows"]:
|
1251
|
-
|
1254
|
+
txtfg = self.PAR.ops.index_selected_rows_fg
|
1255
|
+
tree_arrow_fg = self.PAR.ops.selected_rows_tree_arrow_fg
|
1252
1256
|
elif "cells" in selections and r in selections["cells"]:
|
1253
|
-
|
1257
|
+
txtfg = self.PAR.ops.index_selected_cells_fg
|
1258
|
+
tree_arrow_fg = self.PAR.ops.selected_cells_tree_arrow_fg
|
1254
1259
|
else:
|
1255
|
-
|
1256
|
-
|
1260
|
+
txtfg = self.PAR.ops.index_fg
|
1261
|
+
tree_arrow_fg = self.PAR.ops.tree_arrow_fg
|
1262
|
+
return txtfg, tree_arrow_fg, redrawn
|
1257
1263
|
|
1258
1264
|
def redraw_highlight(self, x1, y1, x2, y2, fill, outline, tag):
|
1259
1265
|
coords = (x1, y1, x2, y2)
|
@@ -1281,6 +1287,56 @@ class RowIndex(tk.Canvas):
|
|
1281
1287
|
else:
|
1282
1288
|
self.disp_grid[self.create_line(points, fill=fill, width=width, tag=tag)] = True
|
1283
1289
|
|
1290
|
+
def redraw_tree_arrow(
|
1291
|
+
self,
|
1292
|
+
x1,
|
1293
|
+
y1,
|
1294
|
+
r,
|
1295
|
+
fill,
|
1296
|
+
tag,
|
1297
|
+
indent: float,
|
1298
|
+
open_: bool = False,
|
1299
|
+
) -> None:
|
1300
|
+
mod = (self.MT.index_txt_height - 1) if self.MT.index_txt_height % 2 else self.MT.index_txt_height
|
1301
|
+
half_mod = mod / 2
|
1302
|
+
qtr_mod = mod / 4
|
1303
|
+
mid_y = (self.MT.index_first_ln_ins - 1) if self.MT.index_first_ln_ins % 2 else self.MT.index_first_ln_ins
|
1304
|
+
# up arrow
|
1305
|
+
if open_:
|
1306
|
+
points = (
|
1307
|
+
x1 + 2 + indent,
|
1308
|
+
y1 + mid_y + qtr_mod,
|
1309
|
+
x1 + 2 + half_mod + indent,
|
1310
|
+
y1 + mid_y - qtr_mod,
|
1311
|
+
x1 + 2 + mod + indent,
|
1312
|
+
y1 + mid_y + qtr_mod,
|
1313
|
+
)
|
1314
|
+
# right pointing arrow
|
1315
|
+
else:
|
1316
|
+
points = (
|
1317
|
+
x1 + half_mod + indent,
|
1318
|
+
y1 + mid_y - half_mod + 1,
|
1319
|
+
x1 + mod + indent - 1,
|
1320
|
+
y1 + mid_y,
|
1321
|
+
x1 + half_mod + indent,
|
1322
|
+
y1 + mid_y + half_mod - 1,
|
1323
|
+
)
|
1324
|
+
if self.hidd_tree_arrow:
|
1325
|
+
t, sh = self.hidd_tree_arrow.popitem()
|
1326
|
+
self.coords(t, points)
|
1327
|
+
if sh:
|
1328
|
+
self.itemconfig(t, fill=fill)
|
1329
|
+
else:
|
1330
|
+
self.itemconfig(t, fill=fill, tag=tag, state="normal")
|
1331
|
+
self.lift(t)
|
1332
|
+
else:
|
1333
|
+
t = self.create_polygon(
|
1334
|
+
points,
|
1335
|
+
fill=fill,
|
1336
|
+
tag=tag,
|
1337
|
+
)
|
1338
|
+
self.disp_tree_arrow[t] = True
|
1339
|
+
|
1284
1340
|
def redraw_dropdown(
|
1285
1341
|
self,
|
1286
1342
|
x1,
|
@@ -1293,7 +1349,6 @@ class RowIndex(tk.Canvas):
|
|
1293
1349
|
draw_outline: bool = True,
|
1294
1350
|
draw_arrow: bool = True,
|
1295
1351
|
open_: bool = False,
|
1296
|
-
indent: None | float = None,
|
1297
1352
|
) -> None:
|
1298
1353
|
if draw_outline and self.PAR.ops.show_dropdown_borders:
|
1299
1354
|
self.redraw_highlight(x1 + 1, y1 + 1, x2, y2, fill="", outline=self.PAR.ops.index_fg, tag=tag)
|
@@ -1302,47 +1357,24 @@ class RowIndex(tk.Canvas):
|
|
1302
1357
|
half_mod = mod / 2
|
1303
1358
|
qtr_mod = mod / 4
|
1304
1359
|
mid_y = (self.MT.index_first_ln_ins - 1) if self.MT.index_first_ln_ins % 2 else self.MT.index_first_ln_ins
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
x1 + 2 + mod + indent,
|
1315
|
-
y1 + mid_y + qtr_mod,
|
1316
|
-
)
|
1317
|
-
# right pointing arrow
|
1318
|
-
else:
|
1319
|
-
points = (
|
1320
|
-
x1 + half_mod + indent,
|
1321
|
-
y1 + mid_y - half_mod + 1,
|
1322
|
-
x1 + mod + indent - 1,
|
1323
|
-
y1 + mid_y,
|
1324
|
-
x1 + half_mod + indent,
|
1325
|
-
y1 + mid_y + half_mod - 1,
|
1326
|
-
)
|
1360
|
+
if open_:
|
1361
|
+
points = (
|
1362
|
+
x2 - 3 - mod,
|
1363
|
+
y1 + mid_y + qtr_mod,
|
1364
|
+
x2 - 3 - half_mod,
|
1365
|
+
y1 + mid_y - qtr_mod,
|
1366
|
+
x2 - 3,
|
1367
|
+
y1 + mid_y + qtr_mod,
|
1368
|
+
)
|
1327
1369
|
else:
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
)
|
1337
|
-
else:
|
1338
|
-
points = (
|
1339
|
-
x2 - 3 - mod,
|
1340
|
-
y1 + mid_y - qtr_mod,
|
1341
|
-
x2 - 3 - half_mod,
|
1342
|
-
y1 + mid_y + qtr_mod,
|
1343
|
-
x2 - 3,
|
1344
|
-
y1 + mid_y - qtr_mod,
|
1345
|
-
)
|
1370
|
+
points = (
|
1371
|
+
x2 - 3 - mod,
|
1372
|
+
y1 + mid_y - qtr_mod,
|
1373
|
+
x2 - 3 - half_mod,
|
1374
|
+
y1 + mid_y + qtr_mod,
|
1375
|
+
x2 - 3,
|
1376
|
+
y1 + mid_y - qtr_mod,
|
1377
|
+
)
|
1346
1378
|
if self.hidd_dropdown:
|
1347
1379
|
t, sh = self.hidd_dropdown.popitem()
|
1348
1380
|
self.coords(t, points)
|
@@ -1352,12 +1384,9 @@ class RowIndex(tk.Canvas):
|
|
1352
1384
|
self.itemconfig(t, fill=fill, tag=tag, state="normal")
|
1353
1385
|
self.lift(t)
|
1354
1386
|
else:
|
1355
|
-
t = self.
|
1387
|
+
t = self.create_polygon(
|
1356
1388
|
points,
|
1357
1389
|
fill=fill,
|
1358
|
-
width=2,
|
1359
|
-
capstyle=tk.ROUND,
|
1360
|
-
joinstyle=tk.ROUND,
|
1361
1390
|
tag=tag,
|
1362
1391
|
)
|
1363
1392
|
self.disp_dropdown[t] = True
|
@@ -1428,6 +1457,8 @@ class RowIndex(tk.Canvas):
|
|
1428
1457
|
self.disp_dropdown = {}
|
1429
1458
|
self.hidd_checkbox.update(self.disp_checkbox)
|
1430
1459
|
self.disp_checkbox = {}
|
1460
|
+
self.hidd_tree_arrow.update(self.disp_tree_arrow)
|
1461
|
+
self.disp_tree_arrow = {}
|
1431
1462
|
self.visible_row_dividers = {}
|
1432
1463
|
draw_y = self.MT.row_positions[start_row]
|
1433
1464
|
xend = self.current_width - 6
|
@@ -1484,7 +1515,15 @@ class RowIndex(tk.Canvas):
|
|
1484
1515
|
if rbotgridln - rtopgridln < self.MT.index_txt_height:
|
1485
1516
|
continue
|
1486
1517
|
datarn = r if self.MT.all_rows_displayed else self.MT.displayed_rows[r]
|
1487
|
-
fill, dd_drawn = self.redraw_highlight_get_text_fg(
|
1518
|
+
fill, tree_arrow_fg, dd_drawn = self.redraw_highlight_get_text_fg(
|
1519
|
+
rtopgridln,
|
1520
|
+
rbotgridln,
|
1521
|
+
r,
|
1522
|
+
c_2,
|
1523
|
+
c_3,
|
1524
|
+
selections,
|
1525
|
+
datarn,
|
1526
|
+
)
|
1488
1527
|
|
1489
1528
|
if datarn in self.cell_options and "align" in self.cell_options[datarn]:
|
1490
1529
|
align = self.cell_options[datarn]["align"]
|
@@ -1584,20 +1623,16 @@ class RowIndex(tk.Canvas):
|
|
1584
1623
|
if align == "w":
|
1585
1624
|
draw_x += self.MT.index_txt_height + 1
|
1586
1625
|
indent = self.get_treeview_indent(iid)
|
1587
|
-
draw_x += indent
|
1626
|
+
draw_x += indent + 4
|
1588
1627
|
if self.tree[iid].children:
|
1589
|
-
self.
|
1628
|
+
self.redraw_tree_arrow(
|
1590
1629
|
0,
|
1591
1630
|
rtopgridln,
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
outline=fill,
|
1596
|
-
tag="dd",
|
1597
|
-
draw_outline=False,
|
1598
|
-
draw_arrow=True,
|
1599
|
-
open_=self.MT._row_index[datarn].iid in self.tree_open_ids,
|
1631
|
+
r=r,
|
1632
|
+
fill=tree_arrow_fg,
|
1633
|
+
tag="ta",
|
1600
1634
|
indent=indent,
|
1635
|
+
open_=self.MT._row_index[datarn].iid in self.tree_open_ids,
|
1601
1636
|
)
|
1602
1637
|
lns = self.get_valid_cell_data_as_str(datarn, fix=False)
|
1603
1638
|
if not lns:
|
@@ -1677,7 +1712,14 @@ class RowIndex(tk.Canvas):
|
|
1677
1712
|
draw_y += self.MT.index_xtra_lines_increment
|
1678
1713
|
if draw_y + self.MT.index_half_txt_height - 1 > rbotgridln:
|
1679
1714
|
break
|
1680
|
-
for dct in (
|
1715
|
+
for dct in (
|
1716
|
+
self.hidd_text,
|
1717
|
+
self.hidd_high,
|
1718
|
+
self.hidd_grid,
|
1719
|
+
self.hidd_dropdown,
|
1720
|
+
self.hidd_checkbox,
|
1721
|
+
self.hidd_tree_arrow,
|
1722
|
+
):
|
1681
1723
|
for iid, showing in dct.items():
|
1682
1724
|
if showing:
|
1683
1725
|
self.itemconfig(iid, state="hidden")
|
@@ -2189,7 +2231,7 @@ class RowIndex(tk.Canvas):
|
|
2189
2231
|
self.fix_index(datarn)
|
2190
2232
|
if not check_input_valid or self.input_valid_for_cell(datarn, value):
|
2191
2233
|
if self.MT.undo_enabled and undo:
|
2192
|
-
self.MT.undo_stack.append(
|
2234
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
2193
2235
|
self.set_cell_data(datarn=datarn, value=value)
|
2194
2236
|
edited = True
|
2195
2237
|
if edited and cell_resize and self.PAR.ops.cell_auto_resize_enabled:
|
@@ -19,7 +19,6 @@ from .functions import (
|
|
19
19
|
del_named_span_options,
|
20
20
|
del_named_span_options_nested,
|
21
21
|
dropdown_search_function,
|
22
|
-
ev_stack_dict,
|
23
22
|
event_dict,
|
24
23
|
fix_format_kwargs,
|
25
24
|
get_checkbox_dict,
|
@@ -30,6 +29,7 @@ from .functions import (
|
|
30
29
|
is_iterable,
|
31
30
|
key_to_span,
|
32
31
|
num2alpha,
|
32
|
+
pickled_event_dict,
|
33
33
|
pop_positions,
|
34
34
|
set_align,
|
35
35
|
set_readonly,
|
@@ -1050,29 +1050,23 @@ class Sheet(tk.Frame):
|
|
1050
1050
|
canvas.basic_bindings(enable)
|
1051
1051
|
return self
|
1052
1052
|
|
1053
|
-
def cut(self, event: object = None) ->
|
1054
|
-
self.MT.ctrl_x(event)
|
1055
|
-
return self
|
1053
|
+
def cut(self, event: object = None, validation: bool = True) -> None | EventDataDict:
|
1054
|
+
return self.MT.ctrl_x(event, validation)
|
1056
1055
|
|
1057
|
-
def copy(self, event: object = None) ->
|
1058
|
-
self.MT.ctrl_c(event)
|
1059
|
-
return self
|
1056
|
+
def copy(self, event: object = None) -> None | EventDataDict:
|
1057
|
+
return self.MT.ctrl_c(event)
|
1060
1058
|
|
1061
|
-
def paste(self, event: object = None) ->
|
1062
|
-
self.MT.ctrl_v(event)
|
1063
|
-
return self
|
1059
|
+
def paste(self, event: object = None, validation: bool = True) -> None | EventDataDict:
|
1060
|
+
return self.MT.ctrl_v(event, validation)
|
1064
1061
|
|
1065
|
-
def delete(self, event: object = None) ->
|
1066
|
-
self.MT.delete_key(event)
|
1067
|
-
return self
|
1062
|
+
def delete(self, event: object = None, validation: bool = True) -> None | EventDataDict:
|
1063
|
+
return self.MT.delete_key(event, validation)
|
1068
1064
|
|
1069
|
-
def undo(self, event: object = None) ->
|
1070
|
-
self.MT.undo(event)
|
1071
|
-
return self
|
1065
|
+
def undo(self, event: object = None) -> None | EventDataDict:
|
1066
|
+
return self.MT.undo(event)
|
1072
1067
|
|
1073
|
-
def redo(self, event: object = None) ->
|
1074
|
-
self.MT.redo(event)
|
1075
|
-
return self
|
1068
|
+
def redo(self, event: object = None) -> None | EventDataDict:
|
1069
|
+
return self.MT.redo(event)
|
1076
1070
|
|
1077
1071
|
def has_focus(
|
1078
1072
|
self,
|
@@ -1801,7 +1795,7 @@ class Sheet(tk.Frame):
|
|
1801
1795
|
or event_data["added"]["rows"]
|
1802
1796
|
):
|
1803
1797
|
if undo is True or (undo is None and span.undo):
|
1804
|
-
self.MT.undo_stack.append(
|
1798
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
1805
1799
|
if emit_event is True or (emit_event is None and span.emit_event):
|
1806
1800
|
self.emit_event("<<SheetModified>>", event_data)
|
1807
1801
|
self.set_refresh_timer(redraw)
|
@@ -1840,7 +1834,7 @@ class Sheet(tk.Frame):
|
|
1840
1834
|
event_data = clear_t(r, c, quick_tval(r, c), event_data)
|
1841
1835
|
if event_data["cells"]["table"] or event_data["cells"]["header"] or event_data["cells"]["index"]:
|
1842
1836
|
if undo is True or (undo is None and span.undo):
|
1843
|
-
self.MT.undo_stack.append(
|
1837
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
1844
1838
|
if emit_event is True or (emit_event is None and span.emit_event):
|
1845
1839
|
self.emit_event("<<SheetModified>>", event_data)
|
1846
1840
|
self.set_refresh_timer(redraw)
|
@@ -2009,7 +2003,7 @@ class Sheet(tk.Frame):
|
|
2009
2003
|
push_ops=push_ops,
|
2010
2004
|
)
|
2011
2005
|
if undo:
|
2012
|
-
self.MT.undo_stack.append(
|
2006
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
2013
2007
|
if emit_event:
|
2014
2008
|
self.emit_event("<<SheetModified>>", event_data)
|
2015
2009
|
self.set_refresh_timer(redraw)
|
@@ -2104,7 +2098,7 @@ class Sheet(tk.Frame):
|
|
2104
2098
|
push_ops=push_ops,
|
2105
2099
|
)
|
2106
2100
|
if undo:
|
2107
|
-
self.MT.undo_stack.append(
|
2101
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
2108
2102
|
if emit_event:
|
2109
2103
|
self.emit_event("<<SheetModified>>", event_data)
|
2110
2104
|
self.set_refresh_timer(redraw)
|
@@ -2178,7 +2172,7 @@ class Sheet(tk.Frame):
|
|
2178
2172
|
event_data,
|
2179
2173
|
)
|
2180
2174
|
if undo:
|
2181
|
-
self.MT.undo_stack.append(
|
2175
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
2182
2176
|
if emit_event:
|
2183
2177
|
self.emit_event("<<SheetModified>>", event_data)
|
2184
2178
|
self.MT.deselect("all", redraw=False)
|
@@ -2219,7 +2213,7 @@ class Sheet(tk.Frame):
|
|
2219
2213
|
event_data,
|
2220
2214
|
)
|
2221
2215
|
if undo:
|
2222
|
-
self.MT.undo_stack.append(
|
2216
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
2223
2217
|
if emit_event:
|
2224
2218
|
self.emit_event("<<SheetModified>>", event_data)
|
2225
2219
|
self.MT.deselect("all", redraw=False)
|
@@ -2320,7 +2314,7 @@ class Sheet(tk.Frame):
|
|
2320
2314
|
data_indexes=data_indexes,
|
2321
2315
|
)
|
2322
2316
|
if undo:
|
2323
|
-
self.MT.undo_stack.append(
|
2317
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
2324
2318
|
if emit_event:
|
2325
2319
|
self.emit_event("<<SheetModified>>", event_data)
|
2326
2320
|
self.set_refresh_timer(redraw)
|
@@ -2348,7 +2342,7 @@ class Sheet(tk.Frame):
|
|
2348
2342
|
data_indexes=data_indexes,
|
2349
2343
|
)
|
2350
2344
|
if undo:
|
2351
|
-
self.MT.undo_stack.append(
|
2345
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
2352
2346
|
if emit_event:
|
2353
2347
|
self.emit_event("<<SheetModified>>", event_data)
|
2354
2348
|
self.set_refresh_timer(redraw)
|
@@ -2375,7 +2369,7 @@ class Sheet(tk.Frame):
|
|
2375
2369
|
data_indexes=data_indexes,
|
2376
2370
|
)
|
2377
2371
|
if undo:
|
2378
|
-
self.MT.undo_stack.append(
|
2372
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
2379
2373
|
if emit_event:
|
2380
2374
|
self.emit_event("<<SheetModified>>", event_data)
|
2381
2375
|
self.set_refresh_timer(redraw)
|
@@ -2402,7 +2396,7 @@ class Sheet(tk.Frame):
|
|
2402
2396
|
data_indexes=data_indexes,
|
2403
2397
|
)
|
2404
2398
|
if undo:
|
2405
|
-
self.MT.undo_stack.append(
|
2399
|
+
self.MT.undo_stack.append(pickled_event_dict(event_data))
|
2406
2400
|
if emit_event:
|
2407
2401
|
self.emit_event("<<SheetModified>>", event_data)
|
2408
2402
|
self.set_refresh_timer(redraw)
|
@@ -3446,12 +3440,22 @@ class Sheet(tk.Frame):
|
|
3446
3440
|
|
3447
3441
|
delete_row_position = del_row_position
|
3448
3442
|
|
3443
|
+
def del_row_positions(self, idxs: Iterator[int] | None = None) -> Sheet:
|
3444
|
+
self.MT.del_row_positions(idxs=idxs)
|
3445
|
+
self.set_refresh_timer()
|
3446
|
+
return self
|
3447
|
+
|
3449
3448
|
def del_column_position(self, idx: int, deselect_all: bool = False) -> Sheet:
|
3450
3449
|
self.MT.del_col_position(idx, deselect_all=deselect_all)
|
3451
3450
|
return self
|
3452
3451
|
|
3453
3452
|
delete_column_position = del_column_position
|
3454
3453
|
|
3454
|
+
def del_column_positions(self, idxs: Iterator[int] | None = None) -> Sheet:
|
3455
|
+
self.MT.del_col_positions(idxs=idxs)
|
3456
|
+
self.set_refresh_timer()
|
3457
|
+
return self
|
3458
|
+
|
3455
3459
|
def insert_column_position(
|
3456
3460
|
self,
|
3457
3461
|
idx: Literal["end"] | int = "end",
|
@@ -4253,27 +4257,27 @@ class Sheet(tk.Frame):
|
|
4253
4257
|
target = self.CH.cell_options
|
4254
4258
|
if key is None:
|
4255
4259
|
return target
|
4256
|
-
return {k: v for k, v in target.items() if key in v}
|
4260
|
+
return {k: v[key] for k, v in target.items() if key in v}
|
4257
4261
|
|
4258
4262
|
def get_row_options(self, key: None | str = None) -> dict:
|
4259
4263
|
if key is None:
|
4260
4264
|
return self.MT.row_options
|
4261
|
-
return {k: v for k, v in self.MT.row_options.items() if key in v}
|
4265
|
+
return {k: v[key] for k, v in self.MT.row_options.items() if key in v}
|
4262
4266
|
|
4263
4267
|
def get_column_options(self, key: None | str = None) -> dict:
|
4264
4268
|
if key is None:
|
4265
4269
|
return self.MT.col_options
|
4266
|
-
return {k: v for k, v in self.MT.col_options.items() if key in v}
|
4270
|
+
return {k: v[key] for k, v in self.MT.col_options.items() if key in v}
|
4267
4271
|
|
4268
4272
|
def get_index_options(self, key: None | str = None) -> dict:
|
4269
4273
|
if key is None:
|
4270
4274
|
return self.RI.cell_options
|
4271
|
-
return {k: v for k, v in self.RI.cell_options.items() if key in v}
|
4275
|
+
return {k: v[key] for k, v in self.RI.cell_options.items() if key in v}
|
4272
4276
|
|
4273
4277
|
def get_header_options(self, key: None | str = None) -> dict:
|
4274
4278
|
if key is None:
|
4275
4279
|
return self.CH.cell_options
|
4276
|
-
return {k: v for k, v in self.CH.cell_options.items() if key in v}
|
4280
|
+
return {k: v[key] for k, v in self.CH.cell_options.items() if key in v}
|
4277
4281
|
|
4278
4282
|
def del_out_of_bounds_options(self) -> Sheet:
|
4279
4283
|
maxc = self.total_columns()
|
@@ -149,6 +149,9 @@ def new_sheet_options() -> DotDict:
|
|
149
149
|
"table_bg": theme_light_blue["table_bg"],
|
150
150
|
"table_grid_fg": theme_light_blue["table_grid_fg"],
|
151
151
|
"table_fg": theme_light_blue["table_fg"],
|
152
|
+
"tree_arrow_fg": theme_light_blue["tree_arrow_fg"],
|
153
|
+
"selected_cells_tree_arrow_fg": theme_light_blue["selected_cells_tree_arrow_fg"],
|
154
|
+
"selected_rows_tree_arrow_fg": theme_light_blue["selected_rows_tree_arrow_fg"],
|
152
155
|
"table_selected_box_cells_fg": theme_light_blue["table_selected_box_cells_fg"],
|
153
156
|
"table_selected_box_rows_fg": theme_light_blue["table_selected_box_rows_fg"],
|
154
157
|
"table_selected_box_columns_fg": theme_light_blue["table_selected_box_columns_fg"],
|
@@ -46,6 +46,9 @@ theme_light_blue: dict[str, str] = DotDict({
|
|
46
46
|
"table_selected_columns_border_fg": "#0B57D0",
|
47
47
|
"table_selected_columns_bg": "#E6EFFD",
|
48
48
|
"table_selected_columns_fg": "black",
|
49
|
+
"tree_arrow_fg": "#C4C7C5",
|
50
|
+
"selected_cells_tree_arrow_fg": "#D3E3FD",
|
51
|
+
"selected_rows_tree_arrow_fg": "#FFFFFF",
|
49
52
|
"vertical_scroll_background": "#FFFFFF",
|
50
53
|
"horizontal_scroll_background": "#FFFFFF",
|
51
54
|
"vertical_scroll_troughcolor": "#f9fbfd",
|
@@ -118,6 +121,9 @@ theme_light_green: dict[str, str] = DotDict({
|
|
118
121
|
"table_selected_columns_border_fg": "#217346",
|
119
122
|
"table_selected_columns_bg": "#E3E3E3",
|
120
123
|
"table_selected_columns_fg": "black",
|
124
|
+
"tree_arrow_fg": "#ababab",
|
125
|
+
"selected_cells_tree_arrow_fg": "#217346",
|
126
|
+
"selected_rows_tree_arrow_fg": "#217346",
|
121
127
|
"vertical_scroll_background": "#FFFFFF",
|
122
128
|
"horizontal_scroll_background": "#FFFFFF",
|
123
129
|
"vertical_scroll_troughcolor": "#f1f1f1",
|
@@ -190,6 +196,9 @@ theme_dark: dict[str, str] = DotDict({
|
|
190
196
|
"table_selected_columns_border_fg": "#4489F7",
|
191
197
|
"table_selected_columns_bg": "#404040",
|
192
198
|
"table_selected_columns_fg": "#F7F7F7",
|
199
|
+
"tree_arrow_fg": "#8C8C8C",
|
200
|
+
"selected_cells_tree_arrow_fg": "#6aa2fc",
|
201
|
+
"selected_rows_tree_arrow_fg": "white",
|
193
202
|
"vertical_scroll_background": "#3b3b3d",
|
194
203
|
"horizontal_scroll_background": "#3b3b3d",
|
195
204
|
"vertical_scroll_troughcolor": "#000000",
|
@@ -262,6 +271,9 @@ theme_black: dict[str, str] = DotDict({
|
|
262
271
|
"table_selected_columns_border_fg": "#FBB86C",
|
263
272
|
"table_selected_columns_bg": "#404040",
|
264
273
|
"table_selected_columns_fg": "#F7F7F7",
|
274
|
+
"tree_arrow_fg": "#8C8C8C",
|
275
|
+
"selected_cells_tree_arrow_fg": "#8C8C8C",
|
276
|
+
"selected_rows_tree_arrow_fg": "#8C8C8C",
|
265
277
|
"vertical_scroll_background": "#3b3a39",
|
266
278
|
"horizontal_scroll_background": "#3b3a39",
|
267
279
|
"vertical_scroll_troughcolor": "#000000",
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: tksheet
|
3
|
-
Version: 7.1.
|
3
|
+
Version: 7.1.21
|
4
4
|
Summary: Tkinter table / sheet widget
|
5
5
|
Author-email: ragardner <github@ragardner.simplelogin.com>
|
6
6
|
License: Copyright (c) 2019 ragardner and open source contributors
|
@@ -42,7 +42,7 @@ License-File: LICENSE.txt
|
|
42
42
|
|
43
43
|
# tksheet
|
44
44
|
|
45
|
-
[](https://pypi.python.org/pypi/tksheet/) ](https://pypi.python.org/pypi/tksheet/)  [](https://github.com/ragardner/tksheet/blob/master/LICENSE.txt)
|
46
46
|
|
47
47
|
[](https://github.com/ragardner/tksheet/releases) [](https://pypi.org/project/tksheet/)
|
48
48
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|