From 0a40f5682c923792b159f64511a637fa91f6bff5 Mon Sep 17 00:00:00 2001 From: ssweber <57631333+ssweber@users.noreply.github.com> Date: Wed, 8 Mar 2023 12:00:11 -0500 Subject: [PATCH 1/5] Add sg.Text as available field element Only needed 1 change. I updated the update_event_states to be type(element) in to match. --- pysimplesql/pysimplesql.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pysimplesql/pysimplesql.py b/pysimplesql/pysimplesql.py index 24f6a86c..06572e12 100644 --- a/pysimplesql/pysimplesql.py +++ b/pysimplesql/pysimplesql.py @@ -2473,7 +2473,7 @@ def update_elements(self, target_data_key: str = None, edit_protect_only: bool = eat_events(self.window) continue - elif type(mapped.element) is sg.PySimpleGUI.InputText or type(mapped.element) is sg.PySimpleGUI.Multiline: + elif type(mapped.element) in [sg.PySimpleGUI.InputText, sg.PySimpleGUI.Multiline, sg.PySimpleGUI.Text]: # Update the element in the GUI # For text objects, lets clear it first... mapped.element.update('') # HACK for sqlite query not making needed keys! This will blank it out @@ -2674,8 +2674,8 @@ def update_element_states(self, table: str, disable: bool = None, visible: bool if mapped.table != table: continue element = mapped.element - if type(element) is sg.PySimpleGUI.InputText or type(element) is sg.PySimpleGUI.MLine or type( - element) is sg.PySimpleGUI.Combo or type(element) is sg.PySimpleGUI.Checkbox: + if type(element) in [sg.PySimpleGUI.InputText, sg.PySimpleGUI.MLine, sg.PySimpleGUI.Combo, + sg.PySimpleGUI.Checkbox]: # if element.Key in self.window.key_dict.keys(): logger.debug(f'Updating element {element.Key} to disabled: {disable}, visible: {visible}') if disable is not None: From e24d98804e46735b99ef0d426f17745e723fa1d9 Mon Sep 17 00:00:00 2001 From: ssweber <57631333+ssweber@users.noreply.github.com> Date: Wed, 8 Mar 2023 13:30:26 -0500 Subject: [PATCH 2/5] Edit-protect a sg.CalendarButton (or any button) Added ability to map_element a column-less element. Allows edit-protecting any button using a key-name, and very little code. I think it's pretty slick. But what do you think? --- examples/journal_internal.py | 13 +++++++++++-- pysimplesql/pysimplesql.py | 10 ++++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/examples/journal_internal.py b/examples/journal_internal.py index 586a2d18..0373b8bb 100644 --- a/examples/journal_internal.py +++ b/examples/journal_internal.py @@ -53,8 +53,12 @@ layout = [ [ss.selector('Journal', sg.Table, num_rows=10, headings=headings)], - [ss.actions('Journal', edit_protect=False)], - [ss.field('Journal.entry_date')], + [ss.actions('Journal')], + [ss.field('Journal.entry_date'), + # Add a CalendarButton to your date fields + sg.CalendarButton("Select Date", close_when_date_chosen=True, target="Journal.entry_date", + # ^ match your ss.Field + format="%Y-%m-%d", size=(10, 1),key='datepicker')], [ss.field('Journal.mood_id', sg.Combo, size=(30, 10), label='My mood:', auto_size_text=False)], [ss.field('Journal.title')], [ss.field('Journal.entry', sg.MLine, size=(71, 20))] @@ -72,6 +76,11 @@ # Requery the data since we made changes to the sort order frm['Journal'].requery() +# To edit-protect a Calendar button (or any button), call map_elment() +frm.map_element(win['datepicker'], frm['Journal'], column=None) +# ['Key of Button'] ^ must be None +frm.edit_protect() # disable edit-protect to start + # --------- # MAIN LOOP # --------- diff --git a/pysimplesql/pysimplesql.py b/pysimplesql/pysimplesql.py index 06572e12..1c67065f 100644 --- a/pysimplesql/pysimplesql.py +++ b/pysimplesql/pysimplesql.py @@ -1919,9 +1919,9 @@ def map_element(self, element: sg.Element, dataset: DataSet, column: str, where_ :param element: A PySimpleGUI Element :param dataset: A `DataSet` object - :param column: The name of the column to bind to the element - :param where_column: Used for ke, value shorthand TODO: expand on this - :param where_value: Used for ey, value shorthand TODO: expand on this + :param column: The name of the column to bind to the element. Pass None if mapping a button to table to enable edit_protect + :param where_column: Used for key, value shorthand TODO: expand on this + :param where_value: Used for key, value shorthand TODO: expand on this :returns: None """ logger.debug(f'Mapping element {element.key}') @@ -2386,6 +2386,8 @@ def update_elements(self, target_data_key: str = None, edit_protect_only: bool = # skip updating this element if requested if mapped.element in omit_elements: continue + # if a column-less element is added + if mapped.column is None: continue # Show the Required Record marker if the column has notnull set and this is a virtual row marker_key = mapped.element.key + ':marker' @@ -2675,7 +2677,7 @@ def update_element_states(self, table: str, disable: bool = None, visible: bool continue element = mapped.element if type(element) in [sg.PySimpleGUI.InputText, sg.PySimpleGUI.MLine, sg.PySimpleGUI.Combo, - sg.PySimpleGUI.Checkbox]: + sg.PySimpleGUI.Checkbox, sg.PySimpleGUI.Button]: # if element.Key in self.window.key_dict.keys(): logger.debug(f'Updating element {element.Key} to disabled: {disable}, visible: {visible}') if disable is not None: From 08e9d2748525695e8eb6ed08bd163ff506358f4a Mon Sep 17 00:00:00 2001 From: ssweber <57631333+ssweber@users.noreply.github.com> Date: Wed, 8 Mar 2023 13:43:20 -0500 Subject: [PATCH 3/5] little nit --- examples/journal_internal.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/journal_internal.py b/examples/journal_internal.py index 0373b8bb..3d031c33 100644 --- a/examples/journal_internal.py +++ b/examples/journal_internal.py @@ -56,8 +56,7 @@ [ss.actions('Journal')], [ss.field('Journal.entry_date'), # Add a CalendarButton to your date fields - sg.CalendarButton("Select Date", close_when_date_chosen=True, target="Journal.entry_date", - # ^ match your ss.Field + sg.CalendarButton("Select Date", close_when_date_chosen=True, target="Journal.entry_date", # <- target matches your ss.field format="%Y-%m-%d", size=(10, 1),key='datepicker')], [ss.field('Journal.mood_id', sg.Combo, size=(30, 10), label='My mood:', auto_size_text=False)], [ss.field('Journal.title')], From 76805d50fb2685e8af4cece92f09629f33f45b3d Mon Sep 17 00:00:00 2001 From: ssweber <57631333+ssweber@users.noreply.github.com> Date: Wed, 8 Mar 2023 13:57:40 -0500 Subject: [PATCH 4/5] small nit --- pysimplesql/pysimplesql.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pysimplesql/pysimplesql.py b/pysimplesql/pysimplesql.py index 1c67065f..c7f5abdd 100644 --- a/pysimplesql/pysimplesql.py +++ b/pysimplesql/pysimplesql.py @@ -1919,7 +1919,8 @@ def map_element(self, element: sg.Element, dataset: DataSet, column: str, where_ :param element: A PySimpleGUI Element :param dataset: A `DataSet` object - :param column: The name of the column to bind to the element. Pass None if mapping a button to table to enable edit_protect + :param column: The name of the column to bind to the element. + Pass None if mapping a `sg.Button` to a `DataSet` to enable edit_protect. :param where_column: Used for key, value shorthand TODO: expand on this :param where_value: Used for key, value shorthand TODO: expand on this :returns: None From 18cc092a8264b04bc4af80a75d315a073659a6a3 Mon Sep 17 00:00:00 2001 From: ssweber <57631333+ssweber@users.noreply.github.com> Date: Wed, 8 Mar 2023 16:03:20 -0500 Subject: [PATCH 5/5] Skipping column-less mapped elements --- examples/journal_internal.py | 18 +++++++++++++++--- pysimplesql/pysimplesql.py | 14 ++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/examples/journal_internal.py b/examples/journal_internal.py index 3d031c33..4fee0449 100644 --- a/examples/journal_internal.py +++ b/examples/journal_internal.py @@ -75,10 +75,21 @@ # Requery the data since we made changes to the sort order frm['Journal'].requery() -# To edit-protect a Calendar button (or any button), call map_elment() +# ------------------------------------------ +# How to Edit Protect your sg.CalendarButton +# ------------------------------------------ + +# The sg.CalendarButton was not auto-mapped during Form creation. +# We need to do it manually, using `frm.map_element`. +# Typically, to manually map an sg.Input, you would pass the sg.Element, DataSet, and column it refers to, +# but when edit-protecting a Calendar button (or any button), pass None as the column. + frm.map_element(win['datepicker'], frm['Journal'], column=None) # ['Key of Button'] ^ must be None -frm.edit_protect() # disable edit-protect to start + +# By default, action() includes an edit_protect() call, that disables edits in the window. +# You can toggle it off with: +frm.edit_protect() # toggle on/off # --------- # MAIN LOOP @@ -108,4 +119,5 @@ - using the label keyword argument to Form.record() to define a custom label - using Tables as Form.selector() element types - changing the sort order of database dataset -""" \ No newline at end of file +- Edit-Protecting a sg.CalendarButton +""" diff --git a/pysimplesql/pysimplesql.py b/pysimplesql/pysimplesql.py index c7f5abdd..a4a2a47f 100644 --- a/pysimplesql/pysimplesql.py +++ b/pysimplesql/pysimplesql.py @@ -652,6 +652,10 @@ def records_changed(self, column: str = None, recursive=True) -> bool: dirty = False # First check the current record to see if it's dirty for mapped in self.frm.element_map: + # skip mapped items with no column + if mapped.column is None: + continue + # Compare the DB version to the GUI version if mapped.table == self.table: # if passed custom column name @@ -1220,6 +1224,10 @@ def save_record(self, display_message: bool = True, update_elements: bool = True # Propagate GUI data back to the stored current_row for mapped in self.frm.element_map: + # skip mapped items with no column + if mapped.column is None: + continue + if mapped.dataset == self: # convert the data into the correct data type using the domain in ColumnInfo @@ -2380,6 +2388,10 @@ def update_elements(self, target_data_key: str = None, edit_protect_only: bool = # Render GUI Elements # d= dictionary (the element map dictionary) for mapped in self.element_map: + # if a column-less element is added + if mapped.column is None: + continue + # If the optional target_data_key parameter was passed, we will only update elements bound to that table if target_data_key is not None: if mapped.table != self[target_data_key].table: @@ -2387,8 +2399,6 @@ def update_elements(self, target_data_key: str = None, edit_protect_only: bool = # skip updating this element if requested if mapped.element in omit_elements: continue - # if a column-less element is added - if mapped.column is None: continue # Show the Required Record marker if the column has notnull set and this is a virtual row marker_key = mapped.element.key + ':marker'