From 5fefdacf1e69f68b3768f419e3bed826eac79865 Mon Sep 17 00:00:00 2001 From: dam Date: Thu, 3 Feb 2022 01:08:58 +0000 Subject: Implement option sets load/store import/export functions. Setup option set buttons on stage screen. --- logic/database.gd | 1 + logic/stage.gd | 95 +++++++++++++++++++++++++++---------------------------- main.tscn | 68 ++++++++++++++++++++++++++++++++++++++- menu/menu.gd | 3 ++ readme.md | 4 +-- 5 files changed, 120 insertions(+), 51 deletions(-) diff --git a/logic/database.gd b/logic/database.gd index b76fda5..d88b710 100644 --- a/logic/database.gd +++ b/logic/database.gd @@ -143,6 +143,7 @@ func load_database(file_path: String = DATABASE_FILE_PATH): _: entry[field_name] = field_value db.append(entry) + file.close() func store_database(file_path: String = DATABASE_FILE_PATH): diff --git a/logic/stage.gd b/logic/stage.gd index 3c3d59c..4c1521c 100644 --- a/logic/stage.gd +++ b/logic/stage.gd @@ -4,7 +4,7 @@ class_name Stage signal save # (database_entry: Dictionary) signal discard # () -const OPTION_SETS_FILE_PATH: String = "user://option_sets.csv" +const OPTION_SETS_FILE_PATH: String = "user://option_sets.json" var staged_entry := {} var option_sets := { @@ -120,6 +120,8 @@ onready var discard_button := get_node("controls/discard") as Button func _init(): exclude_controls = ["date_picker", "save", "discard"] + load_option_sets() + store_option_sets() # @DAM Only for testing. func _ready(): @@ -132,20 +134,46 @@ func _ready(): it.connect("focus_entered", it, "set_cursor_position", [99999999]) # @DAM Use MAX_INT it.connect("focus_exited", it, "deselect") - - var auto_place := place.get_node("auto") as Button - auto_place.connect("pressed", self, "auto_populate", ["place"]) + # Map option sets buttons. + var option_sets_map := { + "place": place, + "anesthesia": anesthesia, + "first_assistant": first_assistant, + "type": type, + "sub_type": sub_type, + "sub_sub_type": sub_sub_type, + "pathology": pathology, + "intervention": intervention + } + for key in option_sets_map: + var button := option_sets_map[key].get_node("auto") as Button + button.connect("pressed", self, "auto_populate", [key]) + + +func get_option_sets(field: String): + var options: Array + # @DAM WIP Improve match to check if dictionaries being accessed are not null. + match field: + "sub_type": + options = option_sets["type"][type.text][field].keys() + "sub_sub_type", "pathology", "intervention": + options = option_sets["type"][type.text]["sub_type"][sub_type.text][field].keys() + _: + options = option_sets[field].keys() + return options func auto_populate(field: String): var stage_options = get_node("/root/main/popup_list") as Popup stage_options.connect("item_selected", self, "auto_selected", [field], CONNECT_ONESHOT) - stage_options.popup_options(option_sets[field].keys()) + # @DAM WIP Check if we can use directly the output of the get_option_sets(field). + stage_options.popup_options(get_option_sets(field)) func auto_selected(index: int, field: String): var field_input: LineEdit = self[field] - field_input.text = option_sets[field].keys()[index] + # @DAM WIP Check if we can use the index directly on the output of the get_option_sets(field). + field_input.text = get_option_sets(field)[index] field_input.caret_position = field_input.text.length() @@ -199,54 +227,25 @@ func get_stage() -> Dictionary: func load_option_sets(file_path: String = OPTION_SETS_FILE_PATH): var file := File.new() file.open(file_path, File.READ_WRITE) - var headers: PoolStringArray - var is_first_line := true - while file.get_position() < file.get_len(): - var csv_entry := file.get_csv_line() - if is_first_line: - is_first_line = false - headers = csv_entry - continue -# var entry = DatabaseEntry.instance_entry() -# for idx in headers.size(): -# var field_name := headers[idx] -# var field_value := csv_entry[idx] -# match field_name: -# "date_year", "date_month", "date_day": -# entry[field_name] = int(field_value) -# "is_urgency": -# entry[field_name] = true if field_value.strip_edges().to_lower() == "true" else false -# _: -# entry[field_name] = field_value -# option_sets.append(entry) + var file_content = file.get_as_text() + var parse_result = JSON.parse(file_content) + if parse_result.error == OK && typeof(parse_result.result) == TYPE_DICTIONARY: + option_sets = parse_result.result + else: + option_sets = {} + push_error("Failed to parse option sets file: '%s'.") + file.close() func store_option_sets(file_path: String = OPTION_SETS_FILE_PATH): - var list: Array - var entry := DatabaseEntry.instance_entry() - if option_sets.has("type"): - for type in option_sets["type"].keys(): - entry.type = type - if option_sets["type"][type].has("sub_type"): - for sub_type in option_sets["type"][type]["sub_type"]: - entry.sub_type = sub_type - if option_sets["type"][type]["sub_type"].has("sub_sub_type"): - for sub_sub_type in option_sets["type"][type]["sub_type"][sub_type]["sub_sub_type"].keys(): - entry.sub_sub_type = sub_sub_type - list.append(entry.duplicate()) - else: - pass - else: - pass - - -# if option_sets.has("type"): -# - pass # @DAM TODO + var file := File.new() + file.open(file_path, File.WRITE) + file.store_string(JSON.print(option_sets, "" if file_path == OPTION_SETS_FILE_PATH else "\t")) + file.close() func clear_option_sets(save_changes: bool = false): - pass # @DAM TODO + option_sets = {} if save_changes: store_option_sets() diff --git a/main.tscn b/main.tscn index 45cacd4..a6abf1b 100644 --- a/main.tscn +++ b/main.tscn @@ -115,6 +115,9 @@ anchor_left = 0.85 anchor_right = 1.0 anchor_bottom = 1.0 text = "X" +__meta__ = { +"_edit_use_anchors_": false +} [node name="anesthesia" type="LineEdit" parent="stage/controls" index="4"] margin_top = 363.0 @@ -124,6 +127,15 @@ placeholder_text = "Anestesia" caret_blink = true caret_blink_speed = 0.5 +[node name="auto" type="Button" parent="stage/controls/anesthesia"] +anchor_left = 0.85 +anchor_right = 1.0 +anchor_bottom = 1.0 +text = "X" +__meta__ = { +"_edit_use_anchors_": false +} + [node name="first_assistant" type="LineEdit" parent="stage/controls" index="5"] margin_top = 416.0 margin_right = 1080.0 @@ -132,6 +144,15 @@ placeholder_text = "1º Ajudante" caret_blink = true caret_blink_speed = 0.5 +[node name="auto" type="Button" parent="stage/controls/first_assistant"] +anchor_left = 0.85 +anchor_right = 1.0 +anchor_bottom = 1.0 +text = "X" +__meta__ = { +"_edit_use_anchors_": false +} + [node name="type" type="LineEdit" parent="stage/controls" index="6"] margin_top = 469.0 margin_right = 1080.0 @@ -140,6 +161,15 @@ placeholder_text = "Tipo" caret_blink = true caret_blink_speed = 0.5 +[node name="auto" type="Button" parent="stage/controls/type"] +anchor_left = 0.85 +anchor_right = 1.0 +anchor_bottom = 1.0 +text = "X" +__meta__ = { +"_edit_use_anchors_": false +} + [node name="sub_type" type="LineEdit" parent="stage/controls" index="7"] margin_top = 522.0 margin_right = 1080.0 @@ -148,6 +178,15 @@ placeholder_text = "Subtipo" caret_blink = true caret_blink_speed = 0.5 +[node name="auto" type="Button" parent="stage/controls/sub_type"] +anchor_left = 0.85 +anchor_right = 1.0 +anchor_bottom = 1.0 +text = "X" +__meta__ = { +"_edit_use_anchors_": false +} + [node name="sub_sub_type" type="LineEdit" parent="stage/controls" index="8"] margin_top = 575.0 margin_right = 1080.0 @@ -156,6 +195,15 @@ placeholder_text = "Sub-Subtipo" caret_blink = true caret_blink_speed = 0.5 +[node name="auto" type="Button" parent="stage/controls/sub_sub_type"] +anchor_left = 0.85 +anchor_right = 1.0 +anchor_bottom = 1.0 +text = "X" +__meta__ = { +"_edit_use_anchors_": false +} + [node name="pathology" type="LineEdit" parent="stage/controls" index="9"] margin_top = 628.0 margin_right = 1080.0 @@ -164,6 +212,15 @@ placeholder_text = "Patologia" caret_blink = true caret_blink_speed = 0.5 +[node name="auto" type="Button" parent="stage/controls/pathology"] +anchor_left = 0.85 +anchor_right = 1.0 +anchor_bottom = 1.0 +text = "X" +__meta__ = { +"_edit_use_anchors_": false +} + [node name="intervention" type="LineEdit" parent="stage/controls" index="10"] margin_top = 681.0 margin_right = 1080.0 @@ -172,6 +229,15 @@ placeholder_text = "Intervenção" caret_blink = true caret_blink_speed = 0.5 +[node name="auto" type="Button" parent="stage/controls/intervention"] +anchor_left = 0.85 +anchor_right = 1.0 +anchor_bottom = 1.0 +text = "X" +__meta__ = { +"_edit_use_anchors_": false +} + [node name="is_urgency" type="CheckBox" parent="stage/controls" index="11"] margin_top = 734.0 margin_right = 1080.0 @@ -228,7 +294,7 @@ size_flags_vertical = 3 window_title = "PICK FILE" mode_overrides_title = false access = 2 -filters = PoolStringArray( "*.csv" ) +filters = PoolStringArray( "*.*" ) show_hidden_files = true current_dir = "" current_path = "" diff --git a/menu/menu.gd b/menu/menu.gd index 9b7f99f..639a99b 100644 --- a/menu/menu.gd +++ b/menu/menu.gd @@ -41,6 +41,7 @@ func _menu_import_option_sets_action(): file_picker.window_title = "IMPORT OPTION SETS" file_picker.mode = FileDialog.MODE_OPEN_FILE file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) + file_picker.filters[0] = "*.json" file_picker.connect("file_selected", stage, "load_option_sets", [], CONNECT_ONESHOT) file_picker.show_modal(true) file_picker.invalidate() @@ -50,6 +51,7 @@ func _menu_export_option_sets_action(): file_picker.window_title = "EXPORT OPTION SETS" file_picker.mode = FileDialog.MODE_SAVE_FILE file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) + file_picker.filters[0] = "*.json" file_picker.connect("file_selected", stage, "store_option_sets", [], CONNECT_ONESHOT) file_picker.show_modal(true) file_picker.invalidate() @@ -66,6 +68,7 @@ func _menu_export_data_action(): file_picker.window_title = "EXPORT DATA" file_picker.mode = FileDialog.MODE_SAVE_FILE file_picker.current_dir = OS.get_system_dir(OS.SYSTEM_DIR_DOWNLOADS) + file_picker.filters[0] = "*.csv" file_picker.connect("file_selected", database, "store_database", [], CONNECT_ONESHOT) file_picker.show_modal(true) file_picker.invalidate() diff --git a/readme.md b/readme.md index d838d5b..476831d 100644 --- a/readme.md +++ b/readme.md @@ -18,8 +18,8 @@ Surgery Log - [x] allow to reset database; - [x] split touch logic from database (create TouchItemList); - [x] split touch logic from stage (create TouchVerticalContainer); -- [ ] load/store filters CSV file; -- [ ] import/export filters to CSV file; +- [x] load/store filters JSON file; +- [x] import/export filters to CSV file; - [ ] add auto-fill buttons on stage screen: - should show a pop-up with multiple options filtered according to current filters; - allow options to be scrolled by dragging; -- cgit v1.2.3