tksheet 7.3.2__tar.gz → 7.3.3__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.3.2/tksheet.egg-info → tksheet-7.3.3}/PKG-INFO +1 -1
- {tksheet-7.3.2 → tksheet-7.3.3}/pyproject.toml +1 -1
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/__init__.py +1 -1
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/functions.py +103 -13
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/main_table.py +122 -119
- {tksheet-7.3.2 → tksheet-7.3.3/tksheet.egg-info}/PKG-INFO +1 -1
- {tksheet-7.3.2 → tksheet-7.3.3}/LICENSE.txt +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/README.md +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/setup.cfg +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/colors.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/column_headers.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/constants.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/find_window.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/formatters.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/other_classes.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/row_index.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/sheet.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/sheet_options.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/text_editor.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/themes.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/top_left_rectangle.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet/types.py +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet.egg-info/SOURCES.txt +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet.egg-info/dependency_links.txt +0 -0
- {tksheet-7.3.2 → tksheet-7.3.3}/tksheet.egg-info/top_level.txt +0 -0
@@ -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.3.
|
9
|
+
version = "7.3.3"
|
10
10
|
authors = [{ name = "ragardner", email = "github@ragardner.simplelogin.com" }]
|
11
11
|
requires-python = ">=3.8"
|
12
12
|
license = {file = "LICENSE.txt"}
|
@@ -21,6 +21,9 @@ from itertools import islice, repeat
|
|
21
21
|
from typing import Literal
|
22
22
|
|
23
23
|
from .colors import color_map
|
24
|
+
from .constants import (
|
25
|
+
symbols_set,
|
26
|
+
)
|
24
27
|
from .formatters import (
|
25
28
|
to_bool,
|
26
29
|
)
|
@@ -35,9 +38,6 @@ from .other_classes import (
|
|
35
38
|
from .types import (
|
36
39
|
AnyIter,
|
37
40
|
)
|
38
|
-
from .constants import (
|
39
|
-
symbols_set,
|
40
|
-
)
|
41
41
|
|
42
42
|
unpickle_obj = pickle.loads
|
43
43
|
|
@@ -590,17 +590,8 @@ def move_elements_by_mapping(
|
|
590
590
|
# old_idxs = {new index: old index, ...}
|
591
591
|
if old_idxs is None:
|
592
592
|
old_idxs = dict(zip(new_idxs.values(), new_idxs))
|
593
|
-
|
594
|
-
res = [0] * len(seq)
|
595
|
-
|
596
593
|
remaining_values = (e for i, e in enumerate(seq) if i not in new_idxs)
|
597
|
-
for i in range(len(
|
598
|
-
if i in old_idxs:
|
599
|
-
res[i] = seq[old_idxs[i]]
|
600
|
-
else:
|
601
|
-
res[i] = next(remaining_values)
|
602
|
-
|
603
|
-
return res
|
594
|
+
return [seq[old_idxs[i]] if i in old_idxs else next(remaining_values) for i in range(len(seq))]
|
604
595
|
|
605
596
|
|
606
597
|
def move_elements_to(
|
@@ -734,6 +725,105 @@ def diff_gen(seq: list[float]) -> Generator[int]:
|
|
734
725
|
)
|
735
726
|
|
736
727
|
|
728
|
+
def gen_coords(
|
729
|
+
start_row: int,
|
730
|
+
start_col: int,
|
731
|
+
end_row: int,
|
732
|
+
end_col: int,
|
733
|
+
reverse: bool = False,
|
734
|
+
) -> Generator[tuple[int, int]]:
|
735
|
+
if reverse:
|
736
|
+
for r in reversed(range(start_row, end_row)):
|
737
|
+
for c in reversed(range(start_col, end_col)):
|
738
|
+
yield (r, c)
|
739
|
+
else:
|
740
|
+
for r in range(start_row, end_row):
|
741
|
+
for c in range(start_col, end_col):
|
742
|
+
yield (r, c)
|
743
|
+
|
744
|
+
|
745
|
+
def box_gen_coords(
|
746
|
+
start_row: int,
|
747
|
+
start_col: int,
|
748
|
+
total_cols: int,
|
749
|
+
total_rows: int,
|
750
|
+
reverse: bool = False,
|
751
|
+
) -> Generator[tuple[int, int]]:
|
752
|
+
if reverse:
|
753
|
+
# yield start cell
|
754
|
+
yield (start_row, start_col)
|
755
|
+
# yield any remaining cells in the starting row before the start column
|
756
|
+
if start_col:
|
757
|
+
for col in reversed(range(start_col)):
|
758
|
+
yield (start_row, col)
|
759
|
+
# yield any cells above start row
|
760
|
+
for row in reversed(range(start_row)):
|
761
|
+
for col in reversed(range(total_cols)):
|
762
|
+
yield (row, col)
|
763
|
+
# yield cells from bottom of table upward
|
764
|
+
for row in range(total_rows - 1, start_row, -1):
|
765
|
+
for col in reversed(range(total_cols)):
|
766
|
+
yield (row, col)
|
767
|
+
# yield any remaining cells in start row
|
768
|
+
for col in range(total_cols - 1, start_col, -1):
|
769
|
+
yield (start_row, col)
|
770
|
+
else:
|
771
|
+
# Yield cells from the start position to the end of the current row
|
772
|
+
for col in range(start_col, total_cols):
|
773
|
+
yield (start_row, col)
|
774
|
+
# yield from the next row to the last row
|
775
|
+
for row in range(start_row + 1, total_rows):
|
776
|
+
for col in range(total_cols):
|
777
|
+
yield (row, col)
|
778
|
+
# yield from the beginning up to the start
|
779
|
+
for row in range(start_row):
|
780
|
+
for col in range(total_cols):
|
781
|
+
yield (row, col)
|
782
|
+
# yield any remaining cells in the starting row before the start column
|
783
|
+
for col in range(start_col):
|
784
|
+
yield (start_row, col)
|
785
|
+
|
786
|
+
|
787
|
+
def next_cell(
|
788
|
+
start_row: int,
|
789
|
+
start_col: int,
|
790
|
+
end_row: int,
|
791
|
+
end_col: int,
|
792
|
+
row: int,
|
793
|
+
col: int,
|
794
|
+
reverse: bool = False,
|
795
|
+
) -> tuple[int, int]:
|
796
|
+
if reverse:
|
797
|
+
col -= 1
|
798
|
+
if col < start_col:
|
799
|
+
col = end_col - 1
|
800
|
+
row -= 1
|
801
|
+
if row < start_row:
|
802
|
+
row = end_row - 1
|
803
|
+
else:
|
804
|
+
col += 1
|
805
|
+
if col == end_col:
|
806
|
+
col = start_col
|
807
|
+
row += 1
|
808
|
+
if row == end_row:
|
809
|
+
row = start_row
|
810
|
+
return row, col
|
811
|
+
|
812
|
+
|
813
|
+
def is_last_cell(
|
814
|
+
start_row: int,
|
815
|
+
start_col: int,
|
816
|
+
end_row: int,
|
817
|
+
end_col: int,
|
818
|
+
row: int,
|
819
|
+
col: int,
|
820
|
+
reverse: bool = False,
|
821
|
+
) -> bool:
|
822
|
+
if reverse:
|
823
|
+
return row == start_row and col == start_col
|
824
|
+
return row == end_row - 1 and col == end_col - 1
|
825
|
+
|
826
|
+
|
737
827
|
def zip_fill_2nd_value(x: AnyIter[object], o: object) -> Generator[object, object]:
|
738
828
|
return zip(x, repeat(o))
|
739
829
|
|
@@ -67,6 +67,7 @@ from .functions import (
|
|
67
67
|
add_to_displayed,
|
68
68
|
b_index,
|
69
69
|
bisect_in,
|
70
|
+
box_gen_coords,
|
70
71
|
box_is_single_cell,
|
71
72
|
cell_right_within_box,
|
72
73
|
color_tup,
|
@@ -78,6 +79,7 @@ from .functions import (
|
|
78
79
|
event_has_char_key,
|
79
80
|
event_opens_dropdown_or_checkbox,
|
80
81
|
float_to_int,
|
82
|
+
gen_coords,
|
81
83
|
gen_formatted,
|
82
84
|
get_data_from_clipboard,
|
83
85
|
get_new_indexes,
|
@@ -86,6 +88,7 @@ from .functions import (
|
|
86
88
|
insert_items,
|
87
89
|
int_x_iter,
|
88
90
|
is_iterable,
|
91
|
+
is_last_cell,
|
89
92
|
is_type_int,
|
90
93
|
len_to_idx,
|
91
94
|
mod_event_val,
|
@@ -93,6 +96,7 @@ from .functions import (
|
|
93
96
|
mod_span_widget,
|
94
97
|
move_elements_by_mapping,
|
95
98
|
new_tk_event,
|
99
|
+
next_cell,
|
96
100
|
rounded_box_coords,
|
97
101
|
span_idxs_post_move,
|
98
102
|
stored_event_dict,
|
@@ -547,19 +551,25 @@ class MainTable(tk.Canvas):
|
|
547
551
|
self.find_window.tktext.focus_set()
|
548
552
|
return "break"
|
549
553
|
|
550
|
-
def find_see_and_set(
|
554
|
+
def find_see_and_set(
|
555
|
+
self,
|
556
|
+
coords: tuple[int, int, int | None] | None,
|
557
|
+
just_see: bool = False,
|
558
|
+
) -> tuple[int, int]:
|
551
559
|
if coords:
|
560
|
+
row, column, item = coords
|
552
561
|
if not self.all_rows_displayed:
|
553
|
-
|
562
|
+
row = self.disprn(row)
|
554
563
|
if not self.all_columns_displayed:
|
555
|
-
|
564
|
+
column = self.dispcn(column)
|
556
565
|
if not just_see:
|
557
566
|
if self.find_window.window.find_in_selection:
|
558
|
-
self.set_currently_selected(
|
567
|
+
self.set_currently_selected(row, column, item=item)
|
559
568
|
else:
|
560
|
-
self.select_cell(
|
569
|
+
self.select_cell(row, column, redraw=False)
|
561
570
|
if not self.see(
|
562
|
-
|
571
|
+
row,
|
572
|
+
column,
|
563
573
|
keep_yscroll=False,
|
564
574
|
keep_xscroll=False,
|
565
575
|
bottom_right_corner=False,
|
@@ -569,78 +579,6 @@ class MainTable(tk.Canvas):
|
|
569
579
|
self.refresh()
|
570
580
|
return coords
|
571
581
|
|
572
|
-
def find_gen_all_cells(
|
573
|
-
self,
|
574
|
-
start_row: int,
|
575
|
-
start_col: int,
|
576
|
-
total_cols: int | None = None,
|
577
|
-
reverse: bool = False,
|
578
|
-
) -> Generator[tuple[int, int]]:
|
579
|
-
if total_cols is None:
|
580
|
-
total_cols = self.total_data_cols(include_header=False)
|
581
|
-
total_rows = self.total_data_rows(include_index=False)
|
582
|
-
if reverse:
|
583
|
-
# yield start cell
|
584
|
-
yield (start_row, start_col)
|
585
|
-
# yield any remaining cells in the starting row before the start column
|
586
|
-
if start_col:
|
587
|
-
for col in reversed(range(start_col)):
|
588
|
-
yield (start_row, col)
|
589
|
-
# yield any cells above start row
|
590
|
-
for row in reversed(range(start_row)):
|
591
|
-
for col in reversed(range(total_cols)):
|
592
|
-
yield (row, col)
|
593
|
-
# yield cells from bottom of table upward
|
594
|
-
for row in range(total_rows - 1, start_row, -1):
|
595
|
-
for col in reversed(range(total_cols)):
|
596
|
-
yield (row, col)
|
597
|
-
# yield any remaining cells in start row
|
598
|
-
for col in range(total_cols - 1, start_col, -1):
|
599
|
-
yield (start_row, col)
|
600
|
-
else:
|
601
|
-
# Yield cells from the start position to the end of the current row
|
602
|
-
for col in range(start_col, total_cols):
|
603
|
-
yield (start_row, col)
|
604
|
-
# yield from the next row to the last row
|
605
|
-
for row in range(start_row + 1, total_rows):
|
606
|
-
for col in range(total_cols):
|
607
|
-
yield (row, col)
|
608
|
-
# yield from the beginning up to the start
|
609
|
-
for row in range(start_row):
|
610
|
-
for col in range(total_cols):
|
611
|
-
yield (row, col)
|
612
|
-
# yield any remaining cells in the starting row before the start column
|
613
|
-
for col in range(start_col):
|
614
|
-
yield (start_row, col)
|
615
|
-
|
616
|
-
def find_get_start_coords(
|
617
|
-
self,
|
618
|
-
plus_one: bool = True,
|
619
|
-
within: None | list = None,
|
620
|
-
reverse: bool = False,
|
621
|
-
) -> tuple[int, int, int]:
|
622
|
-
selected = self.selected
|
623
|
-
if not selected:
|
624
|
-
return 0, 0, 0
|
625
|
-
max_row = len(self.row_positions) - 2
|
626
|
-
max_col = len(self.col_positions) - 2
|
627
|
-
row, col = selected.row, selected.column
|
628
|
-
if plus_one and within:
|
629
|
-
curridx = bisect_left(within, (row, col)) + (1 if not reverse else -1)
|
630
|
-
return row, col, curridx % len(within)
|
631
|
-
if plus_one:
|
632
|
-
if reverse:
|
633
|
-
if col == 0:
|
634
|
-
col = max_col
|
635
|
-
row = max_row if row == 0 else row - 1
|
636
|
-
else:
|
637
|
-
col -= 1
|
638
|
-
else:
|
639
|
-
col = (col + 1) % (max_col + 1)
|
640
|
-
if col == 0:
|
641
|
-
row = (row + 1) % (max_row + 1)
|
642
|
-
return row, col, 0
|
643
|
-
|
644
582
|
def find_match(self, find: str, r: int, c: int) -> bool:
|
645
583
|
return (
|
646
584
|
not find
|
@@ -653,41 +591,104 @@ class MainTable(tk.Canvas):
|
|
653
591
|
)
|
654
592
|
)
|
655
593
|
|
656
|
-
def
|
594
|
+
def find_within_match(self, find: str, r: int, c: int) -> bool:
|
595
|
+
if not self.all_rows_displayed:
|
596
|
+
r = self.datarn(r)
|
597
|
+
if not self.all_columns_displayed:
|
598
|
+
c = self.datacn(c)
|
599
|
+
return self.find_match(find, r, c)
|
600
|
+
|
601
|
+
def find_within_current_box(
|
657
602
|
self,
|
603
|
+
current_box: SelectionBox,
|
658
604
|
find: str,
|
659
|
-
reverse: bool
|
660
|
-
) -> tuple[int, int]
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
605
|
+
reverse: bool,
|
606
|
+
) -> None | tuple[int, int]:
|
607
|
+
start_row, start_col = next_cell(
|
608
|
+
*current_box.coords,
|
609
|
+
self.selected.row,
|
610
|
+
self.selected.column,
|
611
|
+
reverse=reverse,
|
666
612
|
)
|
667
|
-
_, _,
|
668
|
-
for r, c in
|
669
|
-
if
|
670
|
-
r
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
613
|
+
_, _, r2, c2 = current_box.coords
|
614
|
+
for r, c in box_gen_coords(start_row, start_col, c2, r2, reverse=reverse):
|
615
|
+
if self.find_within_match(find, r, c):
|
616
|
+
return (r, c, current_box.fill_iid)
|
617
|
+
return None
|
618
|
+
|
619
|
+
def find_within_non_current_boxes(
|
620
|
+
self,
|
621
|
+
current_id: int,
|
622
|
+
find: str,
|
623
|
+
reverse: bool,
|
624
|
+
) -> None | tuple[int, int]:
|
625
|
+
if reverse:
|
626
|
+
# iterate backwards through selection boxes from the box before current
|
627
|
+
idx = next(i for i, k in enumerate(reversed(self.selection_boxes)) if k == current_id)
|
628
|
+
for item, box in chain(
|
629
|
+
islice(reversed(self.selection_boxes.items()), idx + 1, None),
|
630
|
+
islice(reversed(self.selection_boxes.items()), 0, idx),
|
631
|
+
):
|
632
|
+
for r, c in gen_coords(*box.coords, reverse=reverse):
|
633
|
+
if self.find_within_match(find, r, c):
|
634
|
+
return (r, c, item)
|
635
|
+
else:
|
636
|
+
# iterate forwards through selection boxes from the box after current
|
637
|
+
idx = next(i for i, k in enumerate(self.selection_boxes) if k == current_id)
|
638
|
+
for item, box in chain(
|
639
|
+
islice(self.selection_boxes.items(), idx + 1, None),
|
640
|
+
islice(self.selection_boxes.items(), 0, idx),
|
641
|
+
):
|
642
|
+
for r, c in gen_coords(*box.coords, reverse=reverse):
|
643
|
+
if self.find_within_match(find, r, c):
|
644
|
+
return (r, c, item)
|
645
|
+
return None
|
646
|
+
|
647
|
+
def find_within(
|
648
|
+
self,
|
649
|
+
find: str,
|
650
|
+
reverse: bool = False,
|
651
|
+
) -> tuple[int, int, int] | None:
|
652
|
+
current_box = self.selection_boxes[self.selected.fill_iid]
|
653
|
+
current_id = self.selected.fill_iid
|
654
|
+
if is_last_cell(*current_box.coords, self.selected.row, self.selected.column, reverse=reverse):
|
655
|
+
if coord := self.find_within_non_current_boxes(current_id=current_id, find=find, reverse=reverse):
|
656
|
+
return coord
|
657
|
+
if coord := self.find_within_current_box(current_box=current_box, find=find, reverse=reverse):
|
658
|
+
return coord
|
659
|
+
else:
|
660
|
+
if coord := self.find_within_current_box(current_box=current_box, find=find, reverse=reverse):
|
661
|
+
return coord
|
662
|
+
if coord := self.find_within_non_current_boxes(current_id=current_id, find=find, reverse=reverse):
|
663
|
+
return coord
|
675
664
|
return None
|
676
665
|
|
677
666
|
def find_all_cells(
|
678
667
|
self,
|
679
668
|
find: str,
|
680
669
|
reverse: bool = False,
|
681
|
-
) -> tuple[int, int] | None:
|
682
|
-
|
670
|
+
) -> tuple[int, int, None] | None:
|
671
|
+
if self.selected:
|
672
|
+
row, col = next_cell(
|
673
|
+
0,
|
674
|
+
0,
|
675
|
+
len(self.row_positions) - 1,
|
676
|
+
len(self.col_positions) - 1,
|
677
|
+
self.selected.row,
|
678
|
+
self.selected.column,
|
679
|
+
reverse=reverse,
|
680
|
+
)
|
681
|
+
else:
|
682
|
+
row, col = 0, 0
|
683
683
|
row, col = self.datarn(row), self.datacn(col)
|
684
|
-
|
684
|
+
result = next(
|
685
685
|
(
|
686
686
|
(r, c)
|
687
|
-
for r, c in
|
687
|
+
for r, c in box_gen_coords(
|
688
688
|
start_row=row,
|
689
689
|
start_col=col,
|
690
690
|
total_cols=self.total_data_cols(include_header=False),
|
691
|
+
total_rows=self.total_data_rows(include_index=False),
|
691
692
|
reverse=reverse,
|
692
693
|
)
|
693
694
|
if (
|
@@ -698,13 +699,16 @@ class MainTable(tk.Canvas):
|
|
698
699
|
),
|
699
700
|
None,
|
700
701
|
)
|
702
|
+
if result:
|
703
|
+
return result + (None,)
|
704
|
+
return None
|
701
705
|
|
702
706
|
def find_next(self, event: tk.Misc | None = None) -> Literal["break"]:
|
703
707
|
find = self.find_window.get().lower()
|
704
708
|
if not self.find_window.open:
|
705
709
|
self.open_find_window(focus=False)
|
706
710
|
if self.find_window.window.find_in_selection:
|
707
|
-
self.find_see_and_set(self.
|
711
|
+
self.find_see_and_set(self.find_within(find))
|
708
712
|
else:
|
709
713
|
self.find_see_and_set(self.find_all_cells(find))
|
710
714
|
return "break"
|
@@ -714,7 +718,7 @@ class MainTable(tk.Canvas):
|
|
714
718
|
if not self.find_window.open:
|
715
719
|
self.open_find_window(focus=False)
|
716
720
|
if self.find_window.window.find_in_selection:
|
717
|
-
self.find_see_and_set(self.
|
721
|
+
self.find_see_and_set(self.find_within(find, reverse=True))
|
718
722
|
else:
|
719
723
|
self.find_see_and_set(self.find_all_cells(find, reverse=True))
|
720
724
|
return "break"
|
@@ -1216,25 +1220,24 @@ class MainTable(tk.Canvas):
|
|
1216
1220
|
event_data["selection_boxes"] = boxes
|
1217
1221
|
if not try_binding(self.extra_begin_delete_key_func, event_data, "begin_delete"):
|
1218
1222
|
return
|
1219
|
-
for
|
1220
|
-
for r in
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
)
|
1223
|
+
for box in boxes:
|
1224
|
+
for r, c in gen_coords(*box):
|
1225
|
+
datarn, datacn = self.datarn(r), self.datacn(c)
|
1226
|
+
val = self.get_value_for_empty_cell(datarn, datacn)
|
1227
|
+
if (
|
1228
|
+
not self.edit_validation_func
|
1229
|
+
or not validation
|
1230
|
+
or (
|
1231
|
+
self.edit_validation_func
|
1232
|
+
and (val := self.edit_validation_func(mod_event_val(event_data, val, (r, c)))) is not None
|
1233
|
+
)
|
1234
|
+
):
|
1235
|
+
event_data = self.event_data_set_cell(
|
1236
|
+
datarn,
|
1237
|
+
datacn,
|
1238
|
+
val,
|
1239
|
+
event_data,
|
1240
|
+
)
|
1238
1241
|
if event_data["cells"]["table"]:
|
1239
1242
|
self.refresh()
|
1240
1243
|
self.undo_stack.append(stored_event_dict(event_data))
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|