tksheet 7.3.4__py3-none-any.whl → 7.4.1__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 +11 -11
- tksheet/column_headers.py +328 -239
- tksheet/constants.py +13 -0
- tksheet/functions.py +194 -11
- tksheet/main_table.py +957 -583
- tksheet/other_classes.py +12 -8
- tksheet/row_index.py +830 -259
- tksheet/sheet.py +465 -589
- tksheet/sheet_options.py +44 -1
- tksheet/sorting.py +287 -0
- tksheet/text_editor.py +2 -6
- tksheet/{types.py → tksheet_types.py} +10 -1
- {tksheet-7.3.4.dist-info → tksheet-7.4.1.dist-info}/METADATA +13 -16
- tksheet-7.4.1.dist-info/RECORD +22 -0
- tksheet-7.3.4.dist-info/RECORD +0 -21
- {tksheet-7.3.4.dist-info → tksheet-7.4.1.dist-info}/LICENSE.txt +0 -0
- {tksheet-7.3.4.dist-info → tksheet-7.4.1.dist-info}/WHEEL +0 -0
- {tksheet-7.3.4.dist-info → tksheet-7.4.1.dist-info}/top_level.txt +0 -0
tksheet/sheet_options.py
CHANGED
@@ -29,12 +29,14 @@ def new_sheet_options() -> DotDict:
|
|
29
29
|
13 if USER_OS == "darwin" else 11,
|
30
30
|
"normal",
|
31
31
|
),
|
32
|
+
# cell editing
|
32
33
|
"edit_header_label": "Edit header",
|
33
34
|
"edit_header_accelerator": "",
|
34
35
|
"edit_index_label": "Edit index",
|
35
36
|
"edit_index_accelerator": "",
|
36
37
|
"edit_cell_label": "Edit cell",
|
37
38
|
"edit_cell_accelerator": "",
|
39
|
+
# cut/copy/paste
|
38
40
|
"cut_label": "Cut",
|
39
41
|
"cut_accelerator": "Ctrl+X",
|
40
42
|
"cut_contents_label": "Cut contents",
|
@@ -45,10 +47,12 @@ def new_sheet_options() -> DotDict:
|
|
45
47
|
"copy_contents_accelerator": "Ctrl+C",
|
46
48
|
"paste_label": "Paste",
|
47
49
|
"paste_accelerator": "Ctrl+V",
|
50
|
+
# clear/del
|
48
51
|
"delete_label": "Delete",
|
49
52
|
"delete_accelerator": "Del",
|
50
53
|
"clear_contents_label": "Clear contents",
|
51
54
|
"clear_contents_accelerator": "Del",
|
55
|
+
# del/insert columns
|
52
56
|
"delete_columns_label": "Delete columns",
|
53
57
|
"delete_columns_accelerator": "",
|
54
58
|
"insert_columns_left_label": "Insert columns left",
|
@@ -57,6 +61,7 @@ def new_sheet_options() -> DotDict:
|
|
57
61
|
"insert_column_accelerator": "",
|
58
62
|
"insert_columns_right_label": "Insert columns right",
|
59
63
|
"insert_columns_right_accelerator": "",
|
64
|
+
# del/insert rows
|
60
65
|
"delete_rows_label": "Delete rows",
|
61
66
|
"delete_rows_accelerator": "",
|
62
67
|
"insert_rows_above_label": "Insert rows above",
|
@@ -65,10 +70,42 @@ def new_sheet_options() -> DotDict:
|
|
65
70
|
"insert_rows_below_accelerator": "",
|
66
71
|
"insert_row_label": "Insert row",
|
67
72
|
"insert_row_accelerator": "",
|
73
|
+
# sorting
|
74
|
+
# labels
|
75
|
+
"sort_cells_label": "Sort ↓",
|
76
|
+
"sort_cells_x_label": "Sort →",
|
77
|
+
"sort_row_label": "Sort values →",
|
78
|
+
"sort_column_label": "Sort values ↓",
|
79
|
+
"sort_rows_label": "Sort rows ↓",
|
80
|
+
"sort_columns_label": "Sort columns →",
|
81
|
+
# reverse labels
|
82
|
+
"sort_cells_reverse_label": "Sort ↑",
|
83
|
+
"sort_cells_x_reverse_label": "Sort ←",
|
84
|
+
"sort_row_reverse_label": "Sort values ←",
|
85
|
+
"sort_column_reverse_label": "Sort values ↑",
|
86
|
+
"sort_rows_reverse_label": "Sort rows ↑",
|
87
|
+
"sort_columns_reverse_label": "Sort columns ←",
|
88
|
+
# accelerators
|
89
|
+
"sort_cells_accelerator": "",
|
90
|
+
"sort_cells_x_accelerator": "",
|
91
|
+
"sort_row_accelerator": "",
|
92
|
+
"sort_column_accelerator": "",
|
93
|
+
"sort_rows_accelerator": "",
|
94
|
+
"sort_columns_accelerator": "",
|
95
|
+
# reverse accelerators
|
96
|
+
"sort_cells_reverse_accelerator": "",
|
97
|
+
"sort_cells_x_reverse_accelerator": "",
|
98
|
+
"sort_row_reverse_accelerator": "",
|
99
|
+
"sort_column_reverse_accelerator": "",
|
100
|
+
"sort_rows_reverse_accelerator": "",
|
101
|
+
"sort_columns_reverse_accelerator": "",
|
102
|
+
# select all
|
68
103
|
"select_all_label": "Select all",
|
69
104
|
"select_all_accelerator": "Ctrl+A",
|
105
|
+
# undo
|
70
106
|
"undo_label": "Undo",
|
71
107
|
"undo_accelerator": "Ctrl+Z",
|
108
|
+
# bindings
|
72
109
|
"copy_bindings": [
|
73
110
|
f"<{ctrl_key}-c>",
|
74
111
|
f"<{ctrl_key}-C>",
|
@@ -158,6 +195,7 @@ def new_sheet_options() -> DotDict:
|
|
158
195
|
"escape_bindings": [
|
159
196
|
"<Escape>",
|
160
197
|
],
|
198
|
+
# other
|
161
199
|
"vertical_scroll_borderwidth": 1,
|
162
200
|
"horizontal_scroll_borderwidth": 1,
|
163
201
|
"vertical_scroll_gripcount": 0,
|
@@ -204,13 +242,18 @@ def new_sheet_options() -> DotDict:
|
|
204
242
|
"edit_cell_return": "down",
|
205
243
|
"editor_del_key": "forward",
|
206
244
|
"treeview": False,
|
207
|
-
"treeview_indent": "
|
245
|
+
"treeview_indent": "2",
|
208
246
|
"rounded_boxes": True,
|
209
247
|
"alternate_color": "",
|
248
|
+
"allow_cell_overflow": False,
|
249
|
+
"table_wrap": "c",
|
250
|
+
"header_wrap": "c",
|
251
|
+
"index_wrap": "c",
|
210
252
|
"min_column_width": 1,
|
211
253
|
"max_column_width": float("inf"),
|
212
254
|
"max_header_height": float("inf"),
|
213
255
|
"max_row_height": float("inf"),
|
214
256
|
"max_index_width": float("inf"),
|
257
|
+
"show_top_left": False,
|
215
258
|
}
|
216
259
|
)
|
tksheet/sorting.py
ADDED
@@ -0,0 +1,287 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from collections.abc import Callable, Generator
|
4
|
+
from datetime import datetime
|
5
|
+
from re import finditer
|
6
|
+
|
7
|
+
from .other_classes import Node
|
8
|
+
from .tksheet_types import AnyIter
|
9
|
+
|
10
|
+
# Possible date formats to try for the entire string
|
11
|
+
date_formats = [
|
12
|
+
# Common formats
|
13
|
+
"%d/%m/%Y", # Day/Month/Year
|
14
|
+
"%m/%d/%Y", # Month/Day/Year (US format)
|
15
|
+
"%Y/%m/%d", # Year/Month/Day
|
16
|
+
"%d.%m.%Y", # Day.Month.Year (European format)
|
17
|
+
"%d-%m-%Y", # Day-Month-Year
|
18
|
+
"%m-%d-%Y", # Month-Day-Year
|
19
|
+
"%Y-%m-%d", # Year-Month-Day (ISO format without time)
|
20
|
+
"%d/%m/%y", # Day/Month/2-digit year
|
21
|
+
"%m/%d/%y", # Month/Day/2-digit year
|
22
|
+
"%y/%m/%d", # 2-digit year/Month/Day
|
23
|
+
"%d,%m,%Y", # Day,Month,Year
|
24
|
+
"%m,%d,%Y", # Month,Day,Year
|
25
|
+
"%Y,%m,%d", # Year,Month,Day
|
26
|
+
"%d %m %Y", # Day Month Year (with space)
|
27
|
+
"%m %d %Y", # Month Day Year
|
28
|
+
# With month names
|
29
|
+
"%d %b %Y", # Day Abbreviated Month Year
|
30
|
+
"%b %d, %Y", # Abbreviated Month Day, Year
|
31
|
+
"%d %B %Y", # Day Full Month Name Year
|
32
|
+
"%B %d, %Y", # Full Month Name Day, Year
|
33
|
+
# ISO 8601 with/without time
|
34
|
+
"%Y-%m-%dT%H:%M:%S", # With time
|
35
|
+
"%Y-%m-%d", # Without time
|
36
|
+
# Regional or less common formats
|
37
|
+
# "%Y年%m月%d日", # Japanese-style date
|
38
|
+
"%Y%m%d", # YYYYMMDD format, often used in logs or filenames
|
39
|
+
"%y%m%d", # YYMMDD
|
40
|
+
"%d%m%Y", # DDMMYYYY, sometimes used in Europe
|
41
|
+
# Additional formats
|
42
|
+
"%d/%m/%y %H:%M", # Day/Month/Year Hour:Minute
|
43
|
+
"%m/%d/%y %H:%M", # Month/Day/Year Hour:Minute
|
44
|
+
"%Y-%m-%d %H:%M:%S", # Year-Month-Day Hour:Minute:Second
|
45
|
+
]
|
46
|
+
|
47
|
+
|
48
|
+
def natural_sort_key(item: object) -> tuple[int, object]:
|
49
|
+
"""
|
50
|
+
A key function for natural sorting that handles various Python types, including
|
51
|
+
date-like strings in multiple formats.
|
52
|
+
|
53
|
+
This function aims to sort elements in a human-readable order:
|
54
|
+
- None values first
|
55
|
+
- Booleans (False before True)
|
56
|
+
- Numbers (integers, floats combined)
|
57
|
+
- Datetime objects
|
58
|
+
- Strings with natural sorting for embedded numbers and dates
|
59
|
+
- Unknown types treated as strings or left at the end
|
60
|
+
|
61
|
+
Args:
|
62
|
+
item: Any Python object to be sorted.
|
63
|
+
|
64
|
+
Returns:
|
65
|
+
A tuple or value that can be used for sorting.
|
66
|
+
"""
|
67
|
+
if item is None:
|
68
|
+
return (0,)
|
69
|
+
|
70
|
+
elif isinstance(item, bool):
|
71
|
+
return (1, item)
|
72
|
+
|
73
|
+
elif isinstance(item, (int, float)):
|
74
|
+
return (2, item)
|
75
|
+
|
76
|
+
elif isinstance(item, datetime):
|
77
|
+
return (3, item.timestamp())
|
78
|
+
|
79
|
+
elif isinstance(item, str):
|
80
|
+
for date_format in date_formats:
|
81
|
+
try:
|
82
|
+
return (3, datetime.strptime(item, date_format).timestamp())
|
83
|
+
except ValueError:
|
84
|
+
continue
|
85
|
+
|
86
|
+
try:
|
87
|
+
return (2, float(item))
|
88
|
+
except Exception:
|
89
|
+
n = []
|
90
|
+
s = []
|
91
|
+
for match in finditer(r"\d+|[^\d\s]+", item):
|
92
|
+
if (m := match.group()).isdigit():
|
93
|
+
n.append(int(m))
|
94
|
+
else:
|
95
|
+
s.append(m.lower())
|
96
|
+
return (5, s, n)
|
97
|
+
|
98
|
+
else:
|
99
|
+
# For unknown types, attempt to convert to string, or place at end
|
100
|
+
try:
|
101
|
+
return (6, f"{item}".lower())
|
102
|
+
except Exception:
|
103
|
+
return (7, item)
|
104
|
+
|
105
|
+
|
106
|
+
def sort_selection(
|
107
|
+
data: list[list[object]],
|
108
|
+
reverse: bool = False,
|
109
|
+
key: Callable | None = None,
|
110
|
+
row_wise: bool = False,
|
111
|
+
) -> list[list[object]]:
|
112
|
+
if not data or not isinstance(data[0], list):
|
113
|
+
raise ValueError("Data must be a list of lists.")
|
114
|
+
|
115
|
+
if key is None:
|
116
|
+
key = natural_sort_key
|
117
|
+
|
118
|
+
if row_wise:
|
119
|
+
return [sorted(row, key=key, reverse=reverse) for row in data]
|
120
|
+
else:
|
121
|
+
return list(
|
122
|
+
zip(
|
123
|
+
*(
|
124
|
+
sorted(
|
125
|
+
(row[col] for row in data),
|
126
|
+
key=key,
|
127
|
+
reverse=reverse,
|
128
|
+
)
|
129
|
+
for col in range(len(data[0]))
|
130
|
+
)
|
131
|
+
)
|
132
|
+
)
|
133
|
+
|
134
|
+
|
135
|
+
def sort_column(
|
136
|
+
data: list[list[object]] | list[object] | AnyIter[object],
|
137
|
+
column: int = 0,
|
138
|
+
reverse: bool = False,
|
139
|
+
key: Callable | None = None,
|
140
|
+
) -> list[list[object]] | list[object]:
|
141
|
+
if not data:
|
142
|
+
return data
|
143
|
+
|
144
|
+
if key is None:
|
145
|
+
key = natural_sort_key
|
146
|
+
|
147
|
+
if isinstance(data, list) and isinstance(data[0], list):
|
148
|
+
return sorted(data, key=lambda row: key(row[column]) if len(row) > column else key(None), reverse=reverse)
|
149
|
+
else:
|
150
|
+
return sorted(data, reverse=reverse, key=key)
|
151
|
+
|
152
|
+
|
153
|
+
def sort_row(
|
154
|
+
data: list[list[object]] | list[object] | AnyIter[object],
|
155
|
+
row: int = 0,
|
156
|
+
reverse: bool = False,
|
157
|
+
key: Callable | None = None,
|
158
|
+
) -> list[list[object]]:
|
159
|
+
if not data:
|
160
|
+
return data
|
161
|
+
|
162
|
+
if key is None:
|
163
|
+
key = natural_sort_key
|
164
|
+
|
165
|
+
if isinstance(data, list) and isinstance(data[0], list):
|
166
|
+
if 0 <= row < len(data):
|
167
|
+
data[row] = sorted(data[row], key=key, reverse=reverse)
|
168
|
+
return data
|
169
|
+
else:
|
170
|
+
raise IndexError(f"Row index {row} out of range for data with {len(data)} rows.")
|
171
|
+
else:
|
172
|
+
return sorted(data, reverse=reverse, key=key)
|
173
|
+
|
174
|
+
|
175
|
+
def sort_rows_by_column(
|
176
|
+
data: list[list[object]],
|
177
|
+
column: int = 0,
|
178
|
+
reverse: bool = False,
|
179
|
+
key: Callable | None = None,
|
180
|
+
) -> tuple[list[tuple[int, list[object]]], dict[int, int]]:
|
181
|
+
if not data:
|
182
|
+
return data, {}
|
183
|
+
|
184
|
+
# Check if data is a list of lists
|
185
|
+
if not isinstance(data[0], list):
|
186
|
+
raise ValueError("Data must be a list of lists for row sorting.")
|
187
|
+
|
188
|
+
if key is None:
|
189
|
+
key = natural_sort_key
|
190
|
+
|
191
|
+
# Use a generator expression for sorting to avoid creating an intermediate list
|
192
|
+
sorted_indexed_data = sorted(
|
193
|
+
((i, row) for i, row in enumerate(data)),
|
194
|
+
key=lambda item: key(item[1][column]) if len(item[1]) > column else key(None),
|
195
|
+
reverse=reverse,
|
196
|
+
)
|
197
|
+
|
198
|
+
# Return sorted rows [(old index, row), ...] and create the mapping dictionary
|
199
|
+
return sorted_indexed_data, {old: new for new, (old, _) in enumerate(sorted_indexed_data)}
|
200
|
+
|
201
|
+
|
202
|
+
def sort_columns_by_row(
|
203
|
+
data: list[list[object]],
|
204
|
+
row: int = 0,
|
205
|
+
reverse: bool = False,
|
206
|
+
key: Callable | None = None,
|
207
|
+
) -> tuple[list[int], dict[int, int]]:
|
208
|
+
if not data:
|
209
|
+
return data, {}
|
210
|
+
|
211
|
+
# Check if data is a list of lists
|
212
|
+
if not isinstance(data[0], list):
|
213
|
+
raise ValueError("Data must be a list of lists for column sorting.")
|
214
|
+
|
215
|
+
if row >= len(data) or row < 0:
|
216
|
+
raise IndexError(f"Row index {row} out of range for data with {len(data)} rows.")
|
217
|
+
|
218
|
+
if key is None:
|
219
|
+
key = natural_sort_key
|
220
|
+
|
221
|
+
# Get sorting indices based on the elements of the specified row
|
222
|
+
sort_indices = sorted(range(len(data[row])), key=lambda i: key(data[row][i]), reverse=reverse)
|
223
|
+
sort_indices_set = set(sort_indices)
|
224
|
+
|
225
|
+
new_data = []
|
226
|
+
for row_data in data:
|
227
|
+
# Sort the columns based on sort_indices, then append any additional elements from longer rows
|
228
|
+
sorted_part = [row_data[i] for i in sort_indices if i < len(row_data)]
|
229
|
+
unsorted_part = [elem for idx, elem in enumerate(row_data) if idx not in sort_indices_set]
|
230
|
+
new_data.append(sorted_part + unsorted_part)
|
231
|
+
|
232
|
+
return sort_indices, {old: new for old, new in zip(range(len(data[row])), sort_indices)}
|
233
|
+
|
234
|
+
|
235
|
+
def _sort_node_children(
|
236
|
+
node: Node,
|
237
|
+
tree: dict[str, Node],
|
238
|
+
reverse: bool,
|
239
|
+
key: Callable,
|
240
|
+
) -> Generator[Node, None, None]:
|
241
|
+
sorted_children = sorted(
|
242
|
+
(tree[child_iid] for child_iid in node.children if child_iid in tree),
|
243
|
+
key=lambda child: key(child.text),
|
244
|
+
reverse=reverse,
|
245
|
+
)
|
246
|
+
for child in sorted_children:
|
247
|
+
yield child
|
248
|
+
if child.children: # If the child node has children
|
249
|
+
yield from _sort_node_children(child, tree, reverse, key)
|
250
|
+
|
251
|
+
|
252
|
+
def sort_tree_view(
|
253
|
+
_row_index: list[Node],
|
254
|
+
tree_rns: dict[str, int],
|
255
|
+
tree: dict[str, Node],
|
256
|
+
key: Callable = natural_sort_key,
|
257
|
+
reverse: bool = False,
|
258
|
+
) -> tuple[list[Node], dict[int, int]]:
|
259
|
+
if not _row_index or not tree_rns or not tree:
|
260
|
+
return [], {}
|
261
|
+
|
262
|
+
if key is None:
|
263
|
+
key = natural_sort_key
|
264
|
+
|
265
|
+
# Create the index map and sorted nodes list
|
266
|
+
mapping = {}
|
267
|
+
sorted_nodes = []
|
268
|
+
new_index = 0
|
269
|
+
|
270
|
+
# Sort top-level nodes
|
271
|
+
for node in sorted(
|
272
|
+
(node for node in _row_index if node.parent == ""),
|
273
|
+
key=lambda node: key(node.text),
|
274
|
+
reverse=reverse,
|
275
|
+
):
|
276
|
+
iid = node.iid
|
277
|
+
mapping[tree_rns[iid]] = new_index
|
278
|
+
sorted_nodes.append(node)
|
279
|
+
new_index += 1
|
280
|
+
|
281
|
+
# Sort children recursively
|
282
|
+
for descendant_node in _sort_node_children(node, tree, reverse, key):
|
283
|
+
mapping[tree_rns[descendant_node.iid]] = new_index
|
284
|
+
sorted_nodes.append(descendant_node)
|
285
|
+
new_index += 1
|
286
|
+
|
287
|
+
return sorted_nodes, mapping
|
tksheet/text_editor.py
CHANGED
@@ -4,7 +4,7 @@ import tkinter as tk
|
|
4
4
|
from collections.abc import Callable
|
5
5
|
from typing import Literal
|
6
6
|
|
7
|
-
from .constants import ctrl_key, rc_binding
|
7
|
+
from .constants import align_helper, ctrl_key, rc_binding
|
8
8
|
from .functions import convert_align
|
9
9
|
from .other_classes import DotDict
|
10
10
|
|
@@ -92,11 +92,7 @@ class TextEditorTkText(tk.Text):
|
|
92
92
|
command=self.undo,
|
93
93
|
**menu_kwargs,
|
94
94
|
)
|
95
|
-
align = convert_align(align)
|
96
|
-
if align == "w":
|
97
|
-
self.align = "left"
|
98
|
-
elif align == "e":
|
99
|
-
self.align = "right"
|
95
|
+
self.align = align_helper[convert_align(align)]
|
100
96
|
self.delete(1.0, "end")
|
101
97
|
self.insert(1.0, text)
|
102
98
|
self.yview_moveto(1)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
from collections.abc import Iterable, Iterator
|
4
|
-
from typing import Tuple, Union
|
4
|
+
from typing import Literal, Tuple, Union
|
5
5
|
|
6
6
|
from .other_classes import Span
|
7
7
|
|
@@ -17,4 +17,13 @@ CreateSpanTypes = Union[
|
|
17
17
|
Span,
|
18
18
|
]
|
19
19
|
|
20
|
+
CellPropertyKey = Literal[
|
21
|
+
"format",
|
22
|
+
"highlight",
|
23
|
+
"dropdown",
|
24
|
+
"checkbox",
|
25
|
+
"readonly",
|
26
|
+
"align",
|
27
|
+
]
|
28
|
+
|
20
29
|
AnyIter = Iterable | Iterator
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: tksheet
|
3
|
-
Version: 7.
|
4
|
-
Summary: Tkinter table / sheet widget
|
3
|
+
Version: 7.4.1
|
4
|
+
Summary: Tkinter table / sheet and treeview widget
|
5
5
|
Author-email: ragardner <github@ragardner.simplelogin.com>
|
6
6
|
License: Copyright (c) 2019 ragardner and open source contributors
|
7
7
|
|
@@ -26,7 +26,7 @@ License: Copyright (c) 2019 ragardner and open source contributors
|
|
26
26
|
Project-URL: Homepage, https://github.com/ragardner/tksheet
|
27
27
|
Project-URL: Bug Reports, https://github.com/ragardner/tksheet/issues
|
28
28
|
Project-URL: Funding, https://github.com/ragardner
|
29
|
-
Keywords: tkinter,table,widget,sheet,grid,tk
|
29
|
+
Keywords: tkinter,table,widget,tree,treeview,sheet,grid,tk
|
30
30
|
Classifier: Development Status :: 5 - Production/Stable
|
31
31
|
Classifier: Intended Audience :: Developers
|
32
32
|
Classifier: Topic :: Software Development :: Libraries
|
@@ -46,7 +46,7 @@ License-File: LICENSE.txt
|
|
46
46
|
<img width="45%"src="https://github.com/user-attachments/assets/08e77e89-00ea-4c52-9222-9bd421284360" alt="tksheet treeview">
|
47
47
|
</p>
|
48
48
|
|
49
|
-
# <div align="center">tksheet - python tkinter table widget</div>
|
49
|
+
# <div align="center">tksheet - python tkinter table + treeview widget</div>
|
50
50
|
|
51
51
|
[](https://pypi.python.org/pypi/tksheet/)  [](https://github.com/ragardner/tksheet/blob/master/LICENSE.txt)
|
52
52
|
|
@@ -82,33 +82,23 @@ License-File: LICENSE.txt
|
|
82
82
|
</tbody>
|
83
83
|
</table>
|
84
84
|
|
85
|
-
This library is maintained with the help of **[others](https://github.com/ragardner/tksheet/graphs/contributors)**. If you would like to contribute please read this [help section](https://github.com/ragardner/tksheet/wiki/Version-7#contributing).
|
86
|
-
|
87
|
-
## **Changes for versions `7`+:**
|
88
|
-
|
89
|
-
- **ALL** `extra_bindings()` event objects have changed, information [here](https://github.com/ragardner/tksheet/wiki/Version-7#bind-specific-table-functionality).
|
90
|
-
- The bound function for `extra_bindings()` with `"edit_cell"`/`"end_edit_cell"` **no longer** requires a return value and no longer sets the cell to the return value. Use [this](https://github.com/ragardner/tksheet/wiki/Version-7#validate-user-cell-edits) instead.
|
91
|
-
- `edit_cell_validation` has been removed and replaced with the function `edit_validation()`, information [here](https://github.com/ragardner/tksheet/wiki/Version-7#validate-user-cell-edits).
|
92
|
-
- Only Python versions >= `3.8` are supported.
|
93
|
-
- `tksheet` file names have been changed.
|
94
|
-
- Many other smaller changes, see the [changelog](https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md) for more information.
|
95
|
-
|
96
85
|
## **Features**
|
97
86
|
|
98
87
|
- Smoothly display and modify tabular data
|
99
88
|
- [Edit cells directly](https://github.com/ragardner/tksheet/wiki/Version-7#table-functionality-and-bindings)
|
100
89
|
- Cell values can potentially be [any class](https://github.com/ragardner/tksheet/wiki/Version-7#data-formatting), the default is any class with a `__str__` method
|
101
90
|
- [Drag and drop columns and rows](https://github.com/ragardner/tksheet/wiki/Version-7#table-functionality-and-bindings)
|
91
|
+
- [Editable Treeview mode](https://github.com/ragardner/tksheet/wiki/Version-7#treeview-mode) with working drag and drop, undo, etc.
|
102
92
|
- Multiple line header and index cells
|
103
93
|
- [Expand row heights and column widths](https://github.com/ragardner/tksheet/wiki/Version-7#table-functionality-and-bindings)
|
104
94
|
- [Change fonts and font size (not for individual cells)](https://github.com/ragardner/tksheet/wiki/Version-7#text-font-and-alignment)
|
105
95
|
- [Change any colors in the sheet](https://github.com/ragardner/tksheet/wiki/Version-7#sheet-appearance)
|
106
|
-
- [Treeview mode](https://github.com/ragardner/tksheet/wiki/Version-7#treeview-mode)
|
107
96
|
- [Dropdown boxes](https://github.com/ragardner/tksheet/wiki/Version-7#dropdown-boxes)
|
108
97
|
- [Check boxes](https://github.com/ragardner/tksheet/wiki/Version-7#check-boxes)
|
109
98
|
- [Progress bars](https://github.com/ragardner/tksheet/wiki/Version-7#progress-bars)
|
110
99
|
- [Hide rows and/or columns](https://github.com/ragardner/tksheet/wiki/Version-7#example-header-dropdown-boxes-and-row-filtering)
|
111
100
|
- [Left `"w"`, Center `"center"` or Right `"e"` text alignment for any cell/row/column](https://github.com/ragardner/tksheet/wiki/Version-7#text-font-and-alignment)
|
101
|
+
- [In-built natural sorting](https://github.com/ragardner/tksheet/wiki/Version-7#sorting-the-table)
|
112
102
|
- [Optional built-in find window](https://github.com/ragardner/tksheet/wiki/Version-7#table-functionality-and-bindings)
|
113
103
|
|
114
104
|
```python
|
@@ -140,4 +130,11 @@ sheet.delete_columns(columns=[0, 3], undo=True)
|
|
140
130
|
|
141
131
|

|
142
132
|
|
133
|
+
## **Changes for versions `7`+:**
|
143
134
|
|
135
|
+
- **ALL** `extra_bindings()` event objects have changed, information [here](https://github.com/ragardner/tksheet/wiki/Version-7#bind-specific-table-functionality).
|
136
|
+
- The bound function for `extra_bindings()` with `"edit_cell"`/`"end_edit_cell"` **no longer** requires a return value and no longer sets the cell to the return value. Use [this](https://github.com/ragardner/tksheet/wiki/Version-7#validate-user-cell-edits) instead.
|
137
|
+
- `edit_cell_validation` has been removed and replaced with the function `edit_validation()`, information [here](https://github.com/ragardner/tksheet/wiki/Version-7#validate-user-cell-edits).
|
138
|
+
- Only Python versions >= `3.8` are supported.
|
139
|
+
- `tksheet` file names have been changed.
|
140
|
+
- Many other smaller changes, see the [changelog](https://github.com/ragardner/tksheet/blob/master/docs/CHANGELOG.md) for more information.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
tksheet/__init__.py,sha256=fR2C-xu9T3nD65tI8sKGFUjapge6Nev2Uy1n_K86b_4,2241
|
2
|
+
tksheet/colors.py,sha256=dHhmdFuQDlwohDHsAfT9VdrKoSl_R33L72a3HCin5zo,51591
|
3
|
+
tksheet/column_headers.py,sha256=kWCK1fTf0poj5vilqxh99r6gJ4-bBaIJfB-oNbH7oE8,103245
|
4
|
+
tksheet/constants.py,sha256=PkvAtdYXSOiOO5zuxqrObvGIVV2sEE0enN8YLhI8zCc,3922
|
5
|
+
tksheet/find_window.py,sha256=JfkgpGluSng3bKMBneDNQg-AJmBcmCW7JIhtYbSUZaE,8036
|
6
|
+
tksheet/formatters.py,sha256=21ZkMaDIJNUtjvtlAbPl8Y19I9nDxue-JJegw6hblz8,10551
|
7
|
+
tksheet/functions.py,sha256=tVwMLWsW4n5M-RCL8DrLMOXygDhBP26wz4nEQq1gkUo,52734
|
8
|
+
tksheet/main_table.py,sha256=mK74o6VlN8EdM6iJt3XyLlJc4DvNGENyjmDJcNEIcX0,357780
|
9
|
+
tksheet/other_classes.py,sha256=ADybikLipEG4NABXx8bGVAovJJhWcomQOWTorzS1CPU,16581
|
10
|
+
tksheet/row_index.py,sha256=F64DrvSBmq89JVhYomSRzyQtS4nWAeWDcqnPL8cgsGI,133222
|
11
|
+
tksheet/sheet.py,sha256=2_fMNnJqwvEkYsrDuyxFC68l6XZROzZVjG2FrSZc7IU,284689
|
12
|
+
tksheet/sheet_options.py,sha256=RAQX9NF8Bvauj4fHW-8TGtZG6cRVSzwGxSUKplg3c28,9625
|
13
|
+
tksheet/sorting.py,sha256=ttjPPJwbYKaiQ_uNDU8hXjPiGkCVeGp2Hfd6SWYIN8w,9181
|
14
|
+
tksheet/text_editor.py,sha256=ZLVF-0WxDin5qUAJ5r7dmsdwvhyEoxw0PlPvi_AGNPE,7328
|
15
|
+
tksheet/themes.py,sha256=AoNAxibnQi04MN0Zpbn9-kyDnkiiV8TDNWP9FYjpuf0,18473
|
16
|
+
tksheet/tksheet_types.py,sha256=8JQVlA6N9jEZTEAytbcyuhOGuNE4fUPxYhTqoidxEE0,588
|
17
|
+
tksheet/top_left_rectangle.py,sha256=KhTT-rBUwQTgaHjSwL83cL5_71k2L1B7gxkSxZlTSK8,8598
|
18
|
+
tksheet-7.4.1.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
|
19
|
+
tksheet-7.4.1.dist-info/METADATA,sha256=bI-Stt1T78UK-_qsUjpFpWxsOHNwULQvAsMadKxP8ak,7717
|
20
|
+
tksheet-7.4.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
21
|
+
tksheet-7.4.1.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
|
22
|
+
tksheet-7.4.1.dist-info/RECORD,,
|
tksheet-7.3.4.dist-info/RECORD
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
tksheet/__init__.py,sha256=R9-cO_1-zGTQ17K8KDglbM9MacYfa-IM6BzqSlQhFxc,2241
|
2
|
-
tksheet/colors.py,sha256=dHhmdFuQDlwohDHsAfT9VdrKoSl_R33L72a3HCin5zo,51591
|
3
|
-
tksheet/column_headers.py,sha256=ukYtRorIpq6gTIYHQrQdGqMKD0ybA5FI-56qt8-Cqww,100361
|
4
|
-
tksheet/constants.py,sha256=-NWaHEEpcQ0YHn4yGDf8SSffjceiEOayGqnEYw6VwPM,3507
|
5
|
-
tksheet/find_window.py,sha256=JfkgpGluSng3bKMBneDNQg-AJmBcmCW7JIhtYbSUZaE,8036
|
6
|
-
tksheet/formatters.py,sha256=21ZkMaDIJNUtjvtlAbPl8Y19I9nDxue-JJegw6hblz8,10551
|
7
|
-
tksheet/functions.py,sha256=kxL7dutuL_hTdoaK4rBidd3VGsWvYx1PAB7J_5oP8qg,46509
|
8
|
-
tksheet/main_table.py,sha256=vyqJPdzEQMmQXg4RQgFp3T3IuWpYouxibsnYsB4zP5c,342095
|
9
|
-
tksheet/other_classes.py,sha256=Jdy11Q_Hwx2x9j3xTMTEUR6mc16nPVy_zrv38ZmpM2Y,16411
|
10
|
-
tksheet/row_index.py,sha256=VV6Dy-NHiN7XVSeB5AmCzsfM1mO5tARcKaVe9o8pWDU,109036
|
11
|
-
tksheet/sheet.py,sha256=FbFb4Abyiv5-DfqBNQqvaeZ6gubF613hX7Ggz48i6A0,290363
|
12
|
-
tksheet/sheet_options.py,sha256=FOCZgSDnED10UjKJXhvfaRr2sNFnga2_dFHU_0cLJ6U,7856
|
13
|
-
tksheet/text_editor.py,sha256=4r6JJnzwfqAcYxdtBpPVRgePk_ijhMT0-2EgcD1fKJ0,7416
|
14
|
-
tksheet/themes.py,sha256=AoNAxibnQi04MN0Zpbn9-kyDnkiiV8TDNWP9FYjpuf0,18473
|
15
|
-
tksheet/top_left_rectangle.py,sha256=KhTT-rBUwQTgaHjSwL83cL5_71k2L1B7gxkSxZlTSK8,8598
|
16
|
-
tksheet/types.py,sha256=e1w3Op6RrRdG4u_e1ZAieCVf_lGu2CBQKIB_vKuiYyE,448
|
17
|
-
tksheet-7.3.4.dist-info/LICENSE.txt,sha256=ndbcCPe9SlHfweE_W2RAueWUe2k7yudyxYLq6WjFdn4,1101
|
18
|
-
tksheet-7.3.4.dist-info/METADATA,sha256=FokcL8Lyih0jrvJ4C7J1MSSgVXQXUcbXhxmR2yV_XpM,7781
|
19
|
-
tksheet-7.3.4.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
20
|
-
tksheet-7.3.4.dist-info/top_level.txt,sha256=my61PXCcck_HHAc9cq3NAlyAr3A3FXxCy9gptEOaCN8,8
|
21
|
-
tksheet-7.3.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|