tksheet 7.4.2__py3-none-any.whl → 7.4.4__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/sheet.py CHANGED
@@ -54,6 +54,7 @@ from .functions import (
54
54
  )
55
55
  from .main_table import MainTable
56
56
  from .other_classes import (
57
+ Box_nt,
57
58
  DotDict,
58
59
  EventDataDict,
59
60
  FontTuple,
@@ -66,6 +67,7 @@ from .other_classes import (
66
67
  )
67
68
  from .row_index import RowIndex
68
69
  from .sheet_options import new_sheet_options
70
+ from .sorting import fast_sort_key, natural_sort_key, version_sort_key # noqa: F401
69
71
  from .themes import (
70
72
  theme_black,
71
73
  theme_dark,
@@ -84,7 +86,7 @@ class Sheet(tk.Frame):
84
86
  parent: tk.Misc,
85
87
  name: str = "!sheet",
86
88
  show_table: bool = True,
87
- show_top_left: bool = False,
89
+ show_top_left: bool | None = None,
88
90
  show_row_index: bool = True,
89
91
  show_header: bool = True,
90
92
  show_x_scrollbar: bool = True,
@@ -187,6 +189,7 @@ class Sheet(tk.Frame):
187
189
  table_wrap: Literal["", "w", "c"] = "c",
188
190
  index_wrap: Literal["", "w", "c"] = "c",
189
191
  header_wrap: Literal["", "w", "c"] = "c",
192
+ sort_key: Callable = natural_sort_key,
190
193
  # colors
191
194
  outline_thickness: int = 0,
192
195
  theme: str = "light blue",
@@ -429,14 +432,18 @@ class Sheet(tk.Frame):
429
432
  orient="vertical",
430
433
  style=f"Sheet{self.unique_id}.Vertical.TScrollbar",
431
434
  )
435
+ self.MT["yscrollcommand"] = self.yscroll.set
436
+ self.RI["yscrollcommand"] = self.yscroll.set
432
437
  self.xscroll = ttk.Scrollbar(
433
438
  self,
434
439
  command=self.MT._xscrollbar,
435
440
  orient="horizontal",
436
441
  style=f"Sheet{self.unique_id}.Horizontal.TScrollbar",
437
442
  )
443
+ self.MT["xscrollcommand"] = self.xscroll.set
444
+ self.CH["xscrollcommand"] = self.xscroll.set
438
445
  self.show()
439
- if not show_top_left and not (show_row_index and show_header):
446
+ if show_top_left is False or (show_top_left is None and (not show_row_index or not show_header)):
440
447
  self.hide("top_left")
441
448
  if not show_row_index:
442
449
  self.hide("row_index")
@@ -728,9 +735,9 @@ class Sheet(tk.Frame):
728
735
  - "begin_rc_delete_column", "begin_delete_columns"
729
736
  - "rc_delete_column", "end_rc_delete_column","end_delete_columns", "delete_columns"
730
737
  - "begin_rc_insert_column", "begin_insert_column", "begin_insert_columns", "begin_add_column","begin_rc_add_column", "begin_add_columns"
731
- - "rc_insert_column", "end_rc_insert_column", "end_insert_column", "end_insert_columns", "rc_add_column", "end_rc_add_column", "end_add_column", "end_add_columns"
738
+ - "rc_insert_column", "end_rc_insert_column", "end_insert_column", "end_insert_columns", "rc_add_column", "end_rc_add_column", "end_add_column", "end_add_columns", "add_columns"
732
739
  - "begin_rc_insert_row", "begin_insert_row", "begin_insert_rows", "begin_rc_add_row", "begin_add_row", "begin_add_rows"
733
- - "rc_insert_row", "end_rc_insert_row", "end_insert_row", "end_insert_rows", "rc_add_row", "end_rc_add_row", "end_add_row", "end_add_rows"
740
+ - "rc_insert_row", "end_rc_insert_row", "end_insert_row", "end_insert_rows", "rc_add_row", "end_rc_add_row", "end_add_row", "end_add_rows", "add_rows"
734
741
  - "row_height_resize"
735
742
  - "column_width_resize"
736
743
  - "cell_select"
@@ -1031,6 +1038,7 @@ class Sheet(tk.Frame):
1031
1038
  "end_rc_add_column",
1032
1039
  "end_add_column",
1033
1040
  "end_add_columns",
1041
+ "add_columns",
1034
1042
  ):
1035
1043
  self.MT.extra_end_insert_cols_rc_func = f
1036
1044
 
@@ -1052,6 +1060,7 @@ class Sheet(tk.Frame):
1052
1060
  "end_rc_add_row",
1053
1061
  "end_add_row",
1054
1062
  "end_add_rows",
1063
+ "add_rows",
1055
1064
  ):
1056
1065
  self.MT.extra_end_insert_rows_rc_func = f
1057
1066
 
@@ -2328,7 +2337,6 @@ class Sheet(tk.Frame):
2328
2337
  data_indexes=data_indexes,
2329
2338
  undo=undo,
2330
2339
  emit_event=emit_event,
2331
- ext=True,
2332
2340
  )
2333
2341
  self.set_refresh_timer(redraw)
2334
2342
  return event_data
@@ -2350,7 +2358,6 @@ class Sheet(tk.Frame):
2350
2358
  data_indexes=data_indexes,
2351
2359
  undo=undo,
2352
2360
  emit_event=emit_event,
2353
- ext=True,
2354
2361
  )
2355
2362
  self.set_refresh_timer(redraw)
2356
2363
  return event_data
@@ -2582,7 +2589,7 @@ class Sheet(tk.Frame):
2582
2589
 
2583
2590
  def sort(
2584
2591
  self,
2585
- boxes: AnyIter[Sequence[int, int, int, int]] | Span | None = None,
2592
+ *box: CreateSpanTypes,
2586
2593
  reverse: bool = False,
2587
2594
  row_wise: bool = False,
2588
2595
  validation: bool = True,
@@ -2595,17 +2602,11 @@ class Sheet(tk.Frame):
2595
2602
  This method sorts the data within one or multiple box regions defined by their coordinates. Each box's columns are sorted independently.
2596
2603
 
2597
2604
  Args:
2598
- boxes (AnyIter[Sequence[int, int, int, int]] | Span | None): An iterable of box coordinates. Each box is defined by:
2599
- - From Row (inclusive)
2600
- - From Column (inclusive)
2601
- - Up To Row (exclusive)
2602
- - Up To Column (exclusive)
2603
- If None, it will sort the currently selected boxes or the entire table.
2604
- If Span, it will use the span coordinates.
2605
+ boxes (CreateSpanTypes): A type that can create a Span.
2605
2606
 
2606
2607
  reverse (bool): If True, sorts in descending order. Default is False (ascending).
2607
2608
 
2608
- row_wise (bool): if True sorts cells row-wise. Default is column-wise
2609
+ row_wise (bool): if True sorts cells row-wise. Default is column-wise.
2609
2610
 
2610
2611
  validation (bool): If True, checks if the new cell values are valid according to any restrictions
2611
2612
  (e.g., dropdown validations) before applying the sort. Default is True.
@@ -2622,19 +2623,21 @@ class Sheet(tk.Frame):
2622
2623
  ValueError: If the input boxes are not in the expected format or if the data cannot be sorted.
2623
2624
 
2624
2625
  Note:
2625
- - Sorting is performed column-wise within each box.
2626
2626
  - If validation is enabled, any cell content that fails validation will not be updated.
2627
2627
  - Any cell options attached to cells will not be moved. Event data can be used to re-locate them.
2628
2628
  """
2629
- if isinstance(boxes, Span):
2630
- boxes = [boxes.coords]
2631
2629
  return self.MT.sort_boxes(
2632
- boxes=boxes, reverse=reverse, row_wise=row_wise, validation=validation, key=key, undo=undo
2630
+ boxes={Box_nt(*self.span_from_key(*box).coords): "cells"},
2631
+ reverse=reverse,
2632
+ row_wise=row_wise,
2633
+ validation=validation,
2634
+ key=key,
2635
+ undo=undo,
2633
2636
  )
2634
2637
 
2635
2638
  def sort_rows(
2636
2639
  self,
2637
- rows: AnyIter[int] | Span | None = None,
2640
+ rows: AnyIter[int] | Span | int | None = None,
2638
2641
  reverse: bool = False,
2639
2642
  validation: bool = True,
2640
2643
  key: Callable | None = None,
@@ -2642,11 +2645,13 @@ class Sheet(tk.Frame):
2642
2645
  ) -> EventDataDict:
2643
2646
  if isinstance(rows, Span):
2644
2647
  rows = rows.rows
2648
+ elif isinstance(rows, int):
2649
+ rows = (rows,)
2645
2650
  return self.RI._sort_rows(rows=rows, reverse=reverse, validation=validation, key=key, undo=undo)
2646
2651
 
2647
2652
  def sort_columns(
2648
2653
  self,
2649
- columns: AnyIter[int] | Span | None = None,
2654
+ columns: AnyIter[int] | Span | int | None = None,
2650
2655
  reverse: bool = False,
2651
2656
  validation: bool = True,
2652
2657
  key: Callable | None = None,
@@ -2654,6 +2659,8 @@ class Sheet(tk.Frame):
2654
2659
  ) -> EventDataDict:
2655
2660
  if isinstance(columns, Span):
2656
2661
  columns = columns.columns
2662
+ elif isinstance(columns, int):
2663
+ columns = (columns,)
2657
2664
  return self.CH._sort_columns(columns=columns, reverse=reverse, validation=validation, key=key, undo=undo)
2658
2665
 
2659
2666
  def sort_rows_by_column(
@@ -4365,19 +4372,13 @@ class Sheet(tk.Frame):
4365
4372
  self.MT.grid(row=1, column=1, sticky="nswe")
4366
4373
  if canvas in ("all", "row_index", "index"):
4367
4374
  self.RI.grid(row=1, column=0, sticky="nswe")
4368
- self.MT["yscrollcommand"] = self.yscroll.set
4369
- self.RI["yscrollcommand"] = self.yscroll.set
4370
4375
  self.MT.show_index = True
4371
- if self.MT.show_header:
4372
- self.show("top_left")
4373
4376
  if canvas in ("all", "header"):
4374
4377
  self.CH.grid(row=0, column=1, sticky="nswe")
4375
- self.MT["xscrollcommand"] = self.xscroll.set
4376
- self.CH["xscrollcommand"] = self.xscroll.set
4377
4378
  self.MT.show_header = True
4378
- if self.MT.show_index:
4379
- self.show("top_left")
4380
- if canvas in ("all", "top_left"):
4379
+ if canvas in ("all", "top_left") or (
4380
+ self.ops.show_top_left is not False and self.MT.show_header and self.MT.show_index
4381
+ ):
4381
4382
  self.TL.grid(row=0, column=0)
4382
4383
  if canvas in ("all", "x_scrollbar"):
4383
4384
  self.xscroll.grid(row=2, column=0, columnspan=2, sticky="nswe")
@@ -4405,17 +4406,13 @@ class Sheet(tk.Frame):
4405
4406
  ) -> Sheet:
4406
4407
  if canvas in ("all", "row_index"):
4407
4408
  self.RI.grid_remove()
4408
- self.RI["yscrollcommand"] = 0
4409
4409
  self.MT.show_index = False
4410
- if not self.ops.show_top_left:
4411
- self.hide("top_left")
4412
4410
  if canvas in ("all", "header"):
4413
4411
  self.CH.grid_remove()
4414
- self.CH["xscrollcommand"] = 0
4415
4412
  self.MT.show_header = False
4416
- if not self.ops.show_top_left:
4417
- self.hide("top_left")
4418
- if canvas in ("all", "top_left"):
4413
+ if canvas in ("all", "top_left") or (
4414
+ not self.ops.show_top_left and (not self.MT.show_index or not self.MT.show_header)
4415
+ ):
4419
4416
  self.TL.grid_remove()
4420
4417
  if canvas in ("all", "x_scrollbar"):
4421
4418
  self.xscroll.grid_remove()
@@ -4668,24 +4665,14 @@ class Sheet(tk.Frame):
4668
4665
  Also retrieves any row or column options
4669
4666
  impacting that cell
4670
4667
  """
4671
- if isinstance(column, str):
4672
- column = alpha2idx(column)
4673
- if key is not None:
4674
- return self.MT.get_cell_kwargs(
4675
- datarn=row,
4676
- datacn=column,
4677
- key=key,
4678
- cell=cellops,
4679
- row=rowops,
4680
- column=columnops,
4681
- )
4682
- if cellops and (row, column) in self.MT.cell_options:
4683
- return self.MT.cell_options[(row, column)]
4684
- if rowops and row in self.MT.row_options:
4685
- return self.MT.row_options[row]
4686
- if columnops and column in self.MT.col_options:
4687
- return self.MT.col_options[column]
4688
- return {}
4668
+ return self.MT.get_cell_kwargs(
4669
+ datarn=row,
4670
+ datacn=alpha2idx(column) if isinstance(column, str) else column,
4671
+ key=key,
4672
+ cell=cellops,
4673
+ row=rowops,
4674
+ column=columnops,
4675
+ )
4689
4676
 
4690
4677
  def index_props(
4691
4678
  self,
@@ -4696,12 +4683,10 @@ class Sheet(tk.Frame):
4696
4683
  Retrieve options (properties - props)
4697
4684
  from a cell in the index
4698
4685
  """
4699
- if key is not None:
4700
- return self.RI.get_cell_kwargs(
4701
- datarn=row,
4702
- key=key,
4703
- )
4704
- return self.RI.cell_options[row] if row in self.RI.cell_options else {}
4686
+ return self.RI.get_cell_kwargs(
4687
+ datarn=row,
4688
+ key=key,
4689
+ )
4705
4690
 
4706
4691
  def header_props(
4707
4692
  self,
@@ -4712,14 +4697,10 @@ class Sheet(tk.Frame):
4712
4697
  Retrieve options (properties - props)
4713
4698
  from a cell in the header
4714
4699
  """
4715
- if isinstance(column, str):
4716
- column = alpha2idx(column)
4717
- if key is not None:
4718
- return self.CH.get_cell_kwargs(
4719
- datacn=column,
4720
- key=key,
4721
- )
4722
- return self.CH.cell_options[column] if column in self.CH.cell_options else {}
4700
+ return self.CH.get_cell_kwargs(
4701
+ datacn=alpha2idx(column) if isinstance(column, str) else column,
4702
+ key=key,
4703
+ )
4723
4704
 
4724
4705
  def get_cell_options(
4725
4706
  self,
@@ -7241,7 +7222,7 @@ class Dropdown(Sheet):
7241
7222
 
7242
7223
  def search_and_see(self, event: object = None) -> str:
7243
7224
  if self.search_function is not None:
7244
- rn = self.search_function(search_for=rf"{event['value']}".lower(), data=self.MT.data)
7225
+ rn = self.search_function(search_for=rf"{event['value']}", data=(r[0] for r in self.MT.data))
7245
7226
  if isinstance(rn, int):
7246
7227
  self.row = rn
7247
7228
  self.see(self.row, 0, redraw=False)
tksheet/sheet_options.py CHANGED
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from .constants import USER_OS, ctrl_key
4
4
  from .other_classes import DotDict, FontTuple
5
+ from .sorting import fast_sort_key, natural_sort_key, version_sort_key # noqa: F401
5
6
  from .themes import theme_light_blue
6
7
 
7
8
 
@@ -254,6 +255,7 @@ def new_sheet_options() -> DotDict:
254
255
  "max_header_height": float("inf"),
255
256
  "max_row_height": float("inf"),
256
257
  "max_index_width": float("inf"),
257
- "show_top_left": False,
258
+ "show_top_left": None,
259
+ "sort_key": natural_sort_key,
258
260
  }
259
261
  )