aboutsummaryrefslogtreecommitdiff
path: root/logic/database.gd
diff options
context:
space:
mode:
Diffstat (limited to 'logic/database.gd')
-rw-r--r--logic/database.gd145
1 files changed, 95 insertions, 50 deletions
diff --git a/logic/database.gd b/logic/database.gd
index 262a18a..8acf1b6 100644
--- a/logic/database.gd
+++ b/logic/database.gd
@@ -8,7 +8,7 @@ var db: Array
var selected_idx: int
var staged_idx: int
-onready var stage := get_node("/root/main/stage") as Stage
+onready var stage := get_node("/root/main/stage") # as Stage @DAM Commented to avoid cyclic dependency.
onready var delete_button := get_node("actions/delete") as Button
onready var edit_button := get_node("actions/edit") as Button
onready var add_button := get_node("actions/add") as Button
@@ -18,7 +18,6 @@ onready var dialog := get_node("/root/main/dialog") as Dialog
func _init():
selected_idx = -1
staged_idx = -1
- load_database()
func _ready():
@@ -32,10 +31,7 @@ func _ready():
stage.connect("save", self, "save_stage")
stage.connect("discard", self, "discard_stage")
- for it in db:
- self.add_item(get_entry_view(it))
-
- clear_selection()
+ load_database()
func get_entry_view(database_entry: Dictionary) -> String:
@@ -62,7 +58,7 @@ func delete_action():
if selected_idx < 0:
return
- dialog.setup("The entry with process ID '%s' will be deleted from the database." % db[selected_idx].process_id, "Delete", "No")
+ dialog.setup("The entry #%d with process ID '%s' will be deleted from the database." % [selected_idx+1, db[selected_idx].process_id], "Delete", "No")
dialog.connect("accepted", self, "delete_action_confirmed")
popup.open_popup("Delete entry?", dialog)
@@ -95,8 +91,8 @@ func add_action():
func save_stage(entry: Dictionary):
if DatabaseEntry.is_valid_entry(entry) == false:
- printerr("INVALID ENTRY RECEIVED")
- return # @DAM Deal with this.
+ printerr("Invalid entry detected.")
+ return
var next_selected_idx: int
if staged_idx >= 0:
@@ -125,7 +121,89 @@ func discard_stage():
grab_focus()
+func save_database(file_path: String = DATABASE_FILE_PATH):
+ match file_path.get_extension():
+ "json":
+ export_json(file_path, db)
+
+ "csv":
+ export_csv(file_path, db)
+
+ _:
+ printerr("Invalid database file extension: '%s'." % file_path.get_file())
+ return
+
+
+static func export_json(file_path: String, data: Array):
+ var database_file := {
+ "version": DATABASE_FILE_VERSION,
+ "database": data,
+ }
+ var indentation_char := "" if file_path == DATABASE_FILE_PATH else "\t"
+ var file_content := JSON.print(database_file, indentation_char)
+
+ var file := File.new()
+ file.open(file_path, File.WRITE)
+ file.store_string(file_content)
+ file.close()
+
+
+static func export_csv(file_path: String, data: Array):
+ var file := File.new()
+ file.open(file_path, File.WRITE)
+ var header := PoolStringArray(DatabaseEntry.ENTRY_PROTOTYPE.keys())
+ file.store_csv_line(header)
+ for it in data:
+ file.store_csv_line(it.values())
+ file.close()
+
+
func load_database(file_path: String = DATABASE_FILE_PATH):
+ match file_path.get_extension():
+ "json":
+ clear_database()
+ db = import_json(file_path)
+ if file_path != DATABASE_FILE_PATH:
+ sanitize_database(db)
+
+ "csv":
+ clear_database()
+ db = import_csv(file_path)
+
+ _:
+ printerr("Invalid database file extension: '%s'." % file_path.get_file())
+ return
+
+ for it in db:
+ # The JSON specification does not define integer or float types, but only a number type.
+ # Therefore, converting a Variant to JSON text will convert all numerical values to float types.
+ # Thus, we cast all integer values once we load them.
+ it["date_year"] = int(it["date_year"])
+ it["date_month"] = int(it["date_month"])
+ it["date_day"] = int(it["date_day"])
+
+ self.add_item(get_entry_view(it))
+
+
+static func sanitize_database(database: Array):
+ var blueprint := DatabaseEntry.ENTRY_PROTOTYPE
+
+ for entry in database:
+ # Delete extra keys.
+ var keys_to_delete: Array
+ for key in entry:
+ if blueprint.has(key) == false:
+ keys_to_delete.append(key)
+ for key in keys_to_delete:
+ entry.erase(key)
+
+ # Fix wrong value types.
+ for key in blueprint:
+ if entry.has(key) == false || typeof(entry[key]) != typeof(blueprint[key]):
+ entry[key] = blueprint[key]
+
+
+static func import_json(file_path: String) -> Array:
var file := File.new()
file.open(file_path, File.READ_WRITE)
var file_content = file.get_as_text()
@@ -133,43 +211,21 @@ func load_database(file_path: String = DATABASE_FILE_PATH):
var parse_result = JSON.parse(file_content)
if parse_result.error != OK || typeof(parse_result.result) != TYPE_DICTIONARY:
- push_error("Failed to parse database file: '%s'.")
- return
+ printerr("Failed to parse database file: '%s'.")
+ return []
if parse_result.result["version"] != DATABASE_FILE_VERSION:
- push_error("Invalid database file version '%s', expected '%s'." % DATABASE_FILE_VERSION)
- return
+ printerr("Invalid database file version '%s', expected '%s'." % DATABASE_FILE_VERSION)
+ return []
if typeof(parse_result.result["database"]) != TYPE_ARRAY:
- push_error("Failed to load database file contents.")
- return
-
- db = parse_result.result["database"]
-
- # The JSON specification does not define integer or float types, but only a number type.
- # Therefore, converting a Variant to JSON text will convert all numerical values to float types.
- # Thus, we cast all integer values once we load them.
- for it in db:
- it.date_year = int(it.date_year)
- it.date_month = int(it.date_month)
- it.date_day = int(it.date_day)
-
-
-func save_database(file_path: String = DATABASE_FILE_PATH):
- var database_file := {
- "version": DATABASE_FILE_VERSION,
- "database": db,
- }
- var indentation_char := "" if file_path == DATABASE_FILE_PATH else "\t"
- var file_content := JSON.print(database_file, indentation_char)
+ printerr("Failed to load database file contents.")
+ return []
- var file := File.new()
- file.open(file_path, File.WRITE)
- file.store_string(file_content)
- file.close()
+ return parse_result.result["database"]
-static func import_database(file_path: String) -> Array:
+static func import_csv(file_path: String) -> Array:
var result: Array
var file := File.new()
file.open(file_path, File.READ_WRITE)
@@ -196,17 +252,6 @@ static func import_database(file_path: String) -> Array:
return result
-static func export_database(file_path: String, database: Array = db):
- var file := File.new()
- file.open(file_path, File.WRITE)
- var header := PoolStringArray(DatabaseEntry.ENTRY_PROTOTYPE.keys())
- file.store_csv_line(header)
- for it in database:
- # @DAM This approach depends on the order the dictionary fields are created.
- file.store_csv_line(it.values())
- file.close()
-
-
func clear_database():
clear_selection()
self.clear()