168
168
DELETE_RETURNED : int = 2 # A result was found
169
169
DELETE_ABORTED : int = 4 # The search was aborted, likely during a callback
170
170
DELETE_RECURSION_LIMIT_ERROR : int = 8 # We hit max nested levels
171
- DELETE_CASCADE_RECURSION_LIMIT : int = (
172
- 15 # Mysql sets this as 15 when using foreign key CASCADE DELETE
173
- )
171
+
172
+ # Mysql sets this as 15 when using foreign key CASCADE DELETE
173
+ DELETE_CASCADE_RECURSION_LIMIT : int = 15
174
174
175
175
# -------
176
176
# Sorting
@@ -987,7 +987,7 @@ def requery(
987
987
not len (self .frm [parent_table ].rows .index )
988
988
or Relationship .parent_virtual (self .table , self .frm )
989
989
):
990
- self .rows = pd .DataFrame ([] ) # purge rows
990
+ self .rows = pd .DataFrame (columns = self . rows . columns ) # purge rows
991
991
if update_elements :
992
992
self .frm .update_elements (self .key )
993
993
if requery_dependents :
@@ -1008,9 +1008,15 @@ def requery(
1008
1008
rows = self .driver .execute (query )
1009
1009
self .rows = rows
1010
1010
1011
- # now we can restore the sort order
1012
- self .load_sort_settings (sort_settings )
1013
- self .sort (self .table )
1011
+ if len (self .rows .index ):
1012
+ # if "sort_order" not in self.rows.attrs:
1013
+ # # Store the sort order as a dictionary in the attrs of the DataFrame
1014
+ # sort_order = self.rows[self.pk_column].to_list()
1015
+ # self.rows.attrs["sort_order"] = {self.pk_column: sort_order}
1016
+
1017
+ # now we can restore the sort order
1018
+ self .load_sort_settings (sort_settings )
1019
+ self .sort (self .table )
1014
1020
1015
1021
# Perform transform one row at a time
1016
1022
if self .transform is not None :
@@ -1022,8 +1028,9 @@ def requery(
1022
1028
# can have an equal comparison. Not the prettiest solution. Will look into
1023
1029
# this more on the PySimpleGUI end and make a follow-up ticket.
1024
1030
1025
- # Note on the below. Without rows.loc[:,:], the .applymap would return an entirely new DataFrame, and not
1026
- # a ResultSet. TODO: Move this into it's own ResultSet method?
1031
+ # Note on the below. Without rows.loc[:,:], the .applymap would return an
1032
+ # entirely new DataFrame, and not a ResultSet. TODO: Move this into it's own
1033
+ # ResultSet method?
1027
1034
self .rows .loc [:, :] = self .rows .applymap (
1028
1035
lambda x : x .rstrip () if isinstance (x , str ) else x
1029
1036
)
@@ -1369,7 +1376,7 @@ def set_by_pk(
1369
1376
omit_elements = []
1370
1377
# don't update self/dependents if we are going to below anyway
1371
1378
self .prompt_save (update_elements = False )
1372
-
1379
+
1373
1380
self .current_index = self .rows .index [self .rows [self .pk_column ] == pk ].tolist ()[
1374
1381
0
1375
1382
]
@@ -1683,7 +1690,7 @@ def save_record(
1683
1690
else :
1684
1691
result = self .driver .save_record (self , changed_row )
1685
1692
1686
- if result .exception is not None :
1693
+ if not isinstance ( result , pd . DataFrame ) and result .exception is not None :
1687
1694
self .frm .popup .ok (
1688
1695
lang .dataset_save_fail_title ,
1689
1696
lang .dataset_save_fail .format_map (
@@ -1708,7 +1715,7 @@ def save_record(
1708
1715
1709
1716
# If child changes parent, move index back and requery/requery_dependents
1710
1717
if (
1711
- cascade_fk_changed and not current_row . virtual
1718
+ cascade_fk_changed and not self . row_is_virtual ()
1712
1719
): # Virtual rows already requery, and have no dependents.
1713
1720
self .frm [self .table ].requery (select_first = False ) # keep spot in table
1714
1721
self .frm [self .table ].requery_dependents ()
@@ -1829,18 +1836,22 @@ def delete_record(
1829
1836
1830
1837
# Delete child records first!
1831
1838
result = self .driver .delete_record (self , True )
1832
- if result == DELETE_RECURSION_LIMIT_ERROR :
1833
- self .frm .popup .ok (
1834
- lang .delete_failed_title ,
1835
- lang .delete_failed .format_map (
1836
- LangFormat (exception = lang .delete_recursion_limit_error )
1837
- ),
1838
- )
1839
- elif result .exception is not None :
1840
- self .frm .popup .ok (
1841
- lang .delete_failed_title ,
1842
- lang .delete_failed .format_map (LangFormat (exception = result .exception )),
1843
- )
1839
+
1840
+ if not isinstance (result , pd .DataFrame ):
1841
+ if result == DELETE_RECURSION_LIMIT_ERROR :
1842
+ self .frm .popup .ok (
1843
+ lang .delete_failed_title ,
1844
+ lang .delete_failed .format_map (
1845
+ LangFormat (exception = lang .delete_recursion_limit_error )
1846
+ ),
1847
+ )
1848
+ elif result .exception is not None :
1849
+ self .frm .popup .ok (
1850
+ lang .delete_failed_title ,
1851
+ lang .delete_failed .format_map (
1852
+ LangFormat (exception = result .exception )
1853
+ ),
1854
+ )
1844
1855
1845
1856
# callback
1846
1857
if "after_delete" in self .callbacks :
@@ -1990,7 +2001,9 @@ def row_is_virtual(self, index: int = None) -> bool:
1990
2001
"""
1991
2002
if index is None :
1992
2003
index = self .current_index
1993
- return self .rows .attrs ["virtual" ][index ]
2004
+ if self .rows is not None and len (self .rows .index ):
2005
+ return self .rows .attrs ["virtual" ][index ]
2006
+ return False
1994
2007
1995
2008
def table_values (
1996
2009
self , columns : List [str ] = None , mark_virtual : bool = False
@@ -2291,12 +2304,15 @@ def sort(self, table: str) -> None:
2291
2304
self .sort_reset ()
2292
2305
else :
2293
2306
print (
2294
- f"Sort column is not None. Sorting by column { self .rows .attrs ['sort_column' ]} "
2307
+ f"Sort column is not None. "
2308
+ f"Sorting by column { self .rows .attrs ['sort_column' ]} "
2295
2309
)
2296
2310
self .sort_by_column (
2297
2311
self .rows .attrs ["sort_column" ], table , self .rows .attrs ["sort_reverse" ]
2298
2312
)
2299
- self .set_by_pk (pk )
2313
+ self .set_by_pk (
2314
+ pk , update_elements = False , requery_dependents = False , skip_prompt_save = True
2315
+ )
2300
2316
2301
2317
def sort_cycle (self , column : str , table : str ) -> int :
2302
2318
"""
@@ -2333,7 +2349,11 @@ def insert_row(self, row: dict, idx: int = None) -> None:
2333
2349
:returns: None
2334
2350
"""
2335
2351
row_series = pd .Series (row )
2336
- self .rows .append (row_series , ignore_index = True )
2352
+ attrs = self .rows .attrs .copy ()
2353
+ self .rows = pd .concat ([self .rows , row_series .to_frame ().T ], ignore_index = True )
2354
+ self .rows .attrs = attrs .copy ()
2355
+ # not quite working, but closer
2356
+ # just need to update attrs with new index
2337
2357
return
2338
2358
if idx is None :
2339
2359
idx = len (self .rows .index )
@@ -3244,22 +3264,23 @@ def update_elements(
3244
3264
for data_key in self .datasets :
3245
3265
if target_data_key is not None and data_key != target_data_key :
3246
3266
continue
3267
+
3247
3268
# disable mapped elements for this table if
3248
3269
# there are no records in this table or edit protect mode
3249
- disable = len (self [data_key ].rows ) == 0 or self ._edit_protect
3270
+ disable = len (self [data_key ].rows . index ) == 0 or self ._edit_protect
3250
3271
self .update_element_states (data_key , disable )
3251
3272
3252
3273
for m in (m for m in self .event_map if m ["table" ] == self [data_key ].table ):
3253
3274
# Disable delete and mapped elements for this table if there are no
3254
3275
# records in this table or edit protect mode
3255
3276
if ":table_delete" in m ["event" ]:
3256
- disable = len (self [data_key ].rows ) == 0 or self ._edit_protect
3277
+ disable = len (self [data_key ].rows . index ) == 0 or self ._edit_protect
3257
3278
win [m ["event" ]].update (disabled = disable )
3258
3279
3259
3280
# Disable duplicate if no rows, edit protect, or current row virtual
3260
3281
elif ":table_duplicate" in m ["event" ]:
3261
3282
disable = (
3262
- len (self [data_key ].rows ) == 0
3283
+ len (self [data_key ].rows . index ) == 0
3263
3284
or self ._edit_protect
3264
3285
or self [data_key ]
3265
3286
.get_current_row ()
@@ -3271,15 +3292,16 @@ def update_elements(
3271
3292
# Disable first/prev if only 1 row, or first row
3272
3293
elif ":table_first" in m ["event" ] or ":table_previous" in m ["event" ]:
3273
3294
disable = (
3274
- len (self [data_key ].rows ) < 2
3295
+ len (self [data_key ].rows . index ) < 2
3275
3296
or self [data_key ].current_index == 0
3276
3297
)
3277
3298
win [m ["event" ]].update (disabled = disable )
3278
3299
3279
3300
# Disable next/last if only 1 row, or last row
3280
3301
elif ":table_next" in m ["event" ] or ":table_last" in m ["event" ]:
3281
- disable = len (self [data_key ].rows ) < 2 or (
3282
- self [data_key ].current_index == len (self [data_key ].rows ) - 1
3302
+ disable = len (self [data_key ].rows .index ) < 2 or (
3303
+ self [data_key ].current_index
3304
+ == len (self [data_key ].rows .index ) - 1
3283
3305
)
3284
3306
win [m ["event" ]].update (disabled = disable )
3285
3307
@@ -3289,7 +3311,7 @@ def update_elements(
3289
3311
parent = Relationship .get_parent (data_key )
3290
3312
if parent is not None :
3291
3313
disable = (
3292
- len (self [parent ].rows ) == 0
3314
+ len (self [parent ].rows . index ) == 0
3293
3315
or self ._edit_protect
3294
3316
or Relationship .parent_virtual (data_key , self )
3295
3317
)
@@ -3299,7 +3321,7 @@ def update_elements(
3299
3321
3300
3322
# Disable db_save when needed
3301
3323
elif ":db_save" in m ["event" ] or ":save_table" in m ["event" ]:
3302
- disable = len (self [data_key ].rows ) == 0 or self ._edit_protect
3324
+ disable = len (self [data_key ].rows . index ) == 0 or self ._edit_protect
3303
3325
win [m ["event" ]].update (disabled = disable )
3304
3326
3305
3327
# Enable/Disable quick edit buttons
@@ -3819,7 +3841,8 @@ def update_table_element(
3819
3841
# update element
3820
3842
element .update (values = values , select_rows = select_rows )
3821
3843
# set vertical scroll bar to follow selected element
3822
- if vscroll_position :
3844
+ # call even for 0.0, so that a 'reset sort' repositions vscroll to top.
3845
+ if vscroll_position is not None :
3823
3846
element .set_vscroll_position (vscroll_position )
3824
3847
window .refresh () # Event handled and bypassed
3825
3848
# Enable handling for "<<TreeviewSelect>>" event
@@ -5268,14 +5291,18 @@ def __init__(
5268
5291
def __call__ (self , column ):
5269
5292
# store the pk:
5270
5293
pk = self .frm [self .data_key ].get_current_pk ()
5271
- sort_order = self .frm [self .data_key ].sort_cycle (column , self .data_key )
5272
- # We only need to update the selectors not all elements,
5273
- # so first set by the primary key, then update_selectors()
5274
- self .frm [self .data_key ].set_by_pk (
5275
- pk , update_elements = False , requery_dependents = False , skip_prompt_save = True
5276
- )
5277
- self .frm .update_selectors (self .data_key )
5278
- self .table_heading .update_headings (self .element , column , sort_order )
5294
+ if len (self .frm [data_key ].rows .index ):
5295
+ sort_order = self .frm [self .data_key ].sort_cycle (column , self .data_key )
5296
+ # We only need to update the selectors not all elements,
5297
+ # so first set by the primary key, then update_selectors()
5298
+ self .frm [self .data_key ].set_by_pk (
5299
+ pk ,
5300
+ update_elements = False ,
5301
+ requery_dependents = False ,
5302
+ skip_prompt_save = True ,
5303
+ )
5304
+ self .frm .update_selectors (self .data_key )
5305
+ self .table_heading .update_headings (self .element , column , sort_order )
5279
5306
5280
5307
5281
5308
# ======================================================================================
@@ -6041,9 +6068,11 @@ def set(
6041
6068
df .attrs ["lastrowid" ] = lastrowid
6042
6069
df .attrs ["exception" ] = exception
6043
6070
df .attrs ["column_info" ] = column_info
6071
+
6072
+ # Store virtual flags for each row
6044
6073
df .attrs ["virtual" ] = pd .Series (
6045
- [False ] * len (df .index ), index = df .index
6046
- ) # Store virtual flags for each row
6074
+ [False ] * len (df .index ), index = df .index , dtype = "int64"
6075
+ )
6047
6076
return df
6048
6077
6049
6078
0 commit comments