1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-18 17:19:50 +00:00

Greatly simplify backup code, got rid of OpenSave's current_save_paths and backup_save_paths

The previous backup code was unnecessarily complicated, hard to read/understand and prone to errors. The new system simply stores the save and backup paths in the `Project` class, and stores the backup files inside `user://backups`, instead of having their file paths be in `cache.ini`.
This commit is contained in:
Emmanouil Papadeas 2024-03-22 18:24:41 +02:00
parent 42bce917dc
commit dd8145d369
6 changed files with 51 additions and 131 deletions

View file

@ -4,9 +4,6 @@ extends Node
signal project_saved
signal reference_image_imported
var current_save_paths: PackedStringArray = []
## Stores a filename of a backup file in user:// until user saves manually
var backup_save_paths: PackedStringArray = []
var preview_dialog_tscn := preload("res://src/UI/Dialogs/ImportPreviewDialog.tscn")
var preview_dialogs := [] ## Array of preview dialogs
var last_dialog_option := 0
@ -253,9 +250,11 @@ func open_pxo_file(path: String, is_backup := false, replace_empty := true) -> v
Global.tabs.current_tab = Global.tabs.get_tab_count() - 1
Global.canvas.camera_zoom()
if not is_backup:
if is_backup:
new_project.backup_path = path
else:
# Loading a backup should not change window title and save path
current_save_paths[Global.current_project_index] = path
new_project.save_path = path
Global.main_window.title = path.get_file() + " - Pixelorama " + Global.current_version
Global.save_sprites_dialog.current_path = path
# Set last opened project path and save
@ -366,8 +365,8 @@ func save_pxo_file(
zip_packer.write_file(to_save.to_utf8_buffer())
zip_packer.close_file()
if !autosave:
current_save_paths[Global.current_project_index] = path
if not autosave:
project.save_path = path
var frame_index := 1
for frame in project.frames:
@ -417,7 +416,7 @@ func save_pxo_file(
# First remove backup then set current save path
if project.has_changed:
project.has_changed = false
remove_backup(Global.current_project_index)
Global.current_project.remove_backup_file()
Global.notification_label("File saved")
Global.main_window.title = path.get_file() + " - Pixelorama " + Global.current_version
@ -809,83 +808,22 @@ func update_autosave() -> void:
func _on_Autosave_timeout() -> void:
for i in range(backup_save_paths.size()):
if backup_save_paths[i] == "":
# Create a new backup file if it doesn't exist yet
backup_save_paths[i] = (
"user://backup-" + str(Time.get_unix_time_from_system()) + "-%s" % i
for i in Global.projects.size():
var project := Global.projects[i]
if project.backup_path.is_empty():
project.backup_path = (
"user://backups/backup-" + str(Time.get_unix_time_from_system()) + "-%s" % i
)
store_backup_path(i)
save_pxo_file(backup_save_paths[i], true, false, Global.projects[i])
save_pxo_file(project.backup_path, true, false, project)
## Backup paths are stored in two ways:
## 1) User already manually saved and defined a save path -> {current_save_path, backup_save_path}
## 2) User didn't manually save, "untitled" backup is stored -> {backup_save_path, backup_save_path}
func store_backup_path(i: int) -> void:
if current_save_paths[i] != "":
# Remove "untitled" backup if it existed on this project instance
if Global.config_cache.has_section_key("backups", backup_save_paths[i]):
Global.config_cache.erase_section_key("backups", backup_save_paths[i])
Global.config_cache.set_value("backups", current_save_paths[i], backup_save_paths[i])
else:
Global.config_cache.set_value("backups", backup_save_paths[i], backup_save_paths[i])
Global.config_cache.save("user://cache.ini")
func remove_backup(i: int) -> void:
# Remove backup file
if backup_save_paths[i] != "":
if current_save_paths[i] != "":
remove_backup_by_path(current_save_paths[i], backup_save_paths[i])
else:
# If manual save was not yet done - remove "untitled" backup
remove_backup_by_path(backup_save_paths[i], backup_save_paths[i])
backup_save_paths[i] = ""
func remove_backup_by_path(project_path: String, backup_path: String) -> void:
DirAccess.open("user://").remove(backup_path)
if Global.config_cache.has_section_key("backups", project_path):
Global.config_cache.erase_section_key("backups", project_path)
elif Global.config_cache.has_section_key("backups", backup_path):
Global.config_cache.erase_section_key("backups", backup_path)
Global.config_cache.save("user://cache.ini")
func reload_backup_file(project_paths: Array, backup_paths: Array) -> void:
assert(project_paths.size() == backup_paths.size())
# Clear non-existent backups
var existing_backups_count := 0
for i in range(backup_paths.size()):
var dir := DirAccess.open("user://")
if dir.file_exists(backup_paths[i]):
project_paths[existing_backups_count] = project_paths[i]
backup_paths[existing_backups_count] = backup_paths[i]
existing_backups_count += 1
else:
if Global.config_cache.has_section_key("backups", backup_paths[i]):
Global.config_cache.erase_section_key("backups", backup_paths[i])
Global.config_cache.save("user://cache.ini")
project_paths.resize(existing_backups_count)
backup_paths.resize(existing_backups_count)
# Load the backup files
for i in range(project_paths.size()):
open_pxo_file(backup_paths[i], true, i == 0)
backup_save_paths[i] = backup_paths[i]
# If project path is the same as backup save path -> the backup was untitled
if project_paths[i] != backup_paths[i]: # If the user has saved
current_save_paths[i] = project_paths[i]
Global.main_window.title = (
project_paths[i].get_file() + " - Pixelorama(*) " + Global.current_version
)
Global.current_project.has_changed = true
## Load the backup files
func reload_backup_file() -> void:
var dir := DirAccess.open("user://backups")
var i := 0
for file in dir.get_files():
open_pxo_file("user://backups".path_join(file), true, i == 0)
i += 1
Global.notification_label("Backup reloaded")

View file

@ -73,11 +73,13 @@ var cameras_zoom: PackedVector2Array = [
var cameras_offset: PackedVector2Array = [Vector2.ZERO, Vector2.ZERO, Vector2.ZERO]
# Export directory path and export file name
var save_path := ""
var export_directory_path := ""
var file_name := "untitled"
var file_format := Export.FileFormat.PNG
var was_exported := false
var export_overwrite := false
var backup_path := ""
var animation_tag_node := preload("res://src/UI/Timeline/AnimationTagUI.tscn")
@ -88,20 +90,15 @@ func _init(_frames: Array[Frame] = [], _name := tr("untitled"), _size := Vector2
size = _size
tiles = Tiles.new(size)
selection_map.copy_from(Image.create(size.x, size.y, false, Image.FORMAT_LA8))
Global.tabs.add_tab(name)
OpenSave.current_save_paths.append("")
OpenSave.backup_save_paths.append("")
x_symmetry_point = size.x - 1
y_symmetry_point = size.y - 1
x_symmetry_axis.type = x_symmetry_axis.Types.HORIZONTAL
x_symmetry_axis.project = self
x_symmetry_axis.add_point(Vector2(-19999, y_symmetry_point / 2 + 0.5))
x_symmetry_axis.add_point(Vector2(19999, y_symmetry_point / 2 + 0.5))
Global.canvas.add_child(x_symmetry_axis)
y_symmetry_axis.type = y_symmetry_axis.Types.VERTICAL
y_symmetry_axis.project = self
y_symmetry_axis.add_point(Vector2(x_symmetry_point / 2 + 0.5, -19999))
@ -118,6 +115,7 @@ func _init(_frames: Array[Frame] = [], _name := tr("untitled"), _size := Vector2
func remove() -> void:
remove_backup_file()
undo_redo.free()
for ri in reference_images:
ri.queue_free()
@ -138,6 +136,12 @@ func remove() -> void:
Global.projects.erase(self)
func remove_backup_file() -> void:
if not backup_path.is_empty():
if FileAccess.file_exists(backup_path):
DirAccess.remove_absolute(backup_path)
func commit_undo() -> void:
if not can_undo:
return

View file

@ -24,6 +24,8 @@ var splash_dialog: AcceptDialog:
func _init() -> void:
if not DirAccess.dir_exists_absolute("user://backups"):
DirAccess.make_dir_recursive_absolute("user://backups")
Global.shrink = _get_auto_display_scale()
_handle_layout_files()
@ -171,27 +173,14 @@ func _show_splash_screen() -> void:
func _handle_backup() -> void:
# If backup file exists, Pixelorama was not closed properly (probably crashed) - reopen backup
backup_confirmation.add_button("Discard All", false, "discard")
if Global.config_cache.has_section("backups"):
var project_paths = Global.config_cache.get_section_keys("backups")
if project_paths.size() > 0:
# Get backup paths
var backup_paths := []
for p_path in project_paths:
backup_paths.append(Global.config_cache.get_value("backups", p_path))
# Temporatily stop autosave until user confirms backup
OpenSave.autosave_timer.stop()
backup_confirmation.confirmed.connect(
_on_BackupConfirmation_confirmed.bind(project_paths, backup_paths)
)
backup_confirmation.custom_action.connect(
_on_BackupConfirmation_custom_action.bind(project_paths, backup_paths)
)
await get_tree().process_frame
backup_confirmation.popup_centered()
modulate = Color(0.5, 0.5, 0.5)
else:
if Global.open_last_project:
load_last_project()
var backup_dir := DirAccess.open("user://backups")
if backup_dir.get_files().size() > 0:
# Temporatily stop autosave until user confirms backup
OpenSave.autosave_timer.stop()
backup_confirmation.confirmed.connect(_on_BackupConfirmation_confirmed)
backup_confirmation.custom_action.connect(_on_BackupConfirmation_custom_action)
backup_confirmation.popup_centered()
modulate = Color(0.5, 0.5, 0.5)
else:
if Global.open_last_project:
load_last_project()
@ -367,18 +356,15 @@ func _quit() -> void:
get_tree().quit()
func _on_BackupConfirmation_confirmed(project_paths: Array, backup_paths: Array) -> void:
OpenSave.reload_backup_file(project_paths, backup_paths)
func _on_BackupConfirmation_confirmed() -> void:
OpenSave.reload_backup_file()
func _on_BackupConfirmation_custom_action(
action: String, project_paths: Array, backup_paths: Array
) -> void:
func _on_BackupConfirmation_custom_action(action: String) -> void:
backup_confirmation.hide()
if action != "discard":
return
for i in range(project_paths.size()):
OpenSave.remove_backup_by_path(project_paths[i], backup_paths[i])
_clear_backup_files()
# Reopen last project
if Global.open_last_project:
load_last_project()
@ -392,6 +378,11 @@ func _on_backup_confirmation_visibility_changed() -> void:
Global.dialog_open(false)
func _clear_backup_files() -> void:
for file in DirAccess.get_files_at("user://backups"):
DirAccess.remove_absolute("user://backups".path_join(file))
func _exit_tree() -> void:
Global.config_cache.set_value("window", "layout", Global.layouts.find(main_ui.layout))
Global.config_cache.set_value("window", "screen", get_window().current_screen)
@ -415,8 +406,7 @@ func _exit_tree() -> void:
Global.config_cache.set_value("view_menu", "show_mouse_guides", Global.show_mouse_guides)
Global.config_cache.save("user://cache.ini")
var i := 0
for project in Global.projects:
project.remove()
OpenSave.remove_backup(i)
i += 1
# For some reason, the above is not enough to remove all backup files
_clear_backup_files()

View file

@ -77,7 +77,6 @@ popup_window = true
dialog_text = "This is an error message!"
[node name="BackupConfirmation" type="ConfirmationDialog" parent="Dialogs"]
exclusive = false
popup_window = true
dialog_text = "Autosaved project(s) from a crashed session were found.
Do you want to recover the data?"

View file

@ -47,21 +47,10 @@ func _on_active_tab_rearranged(idx_to: int) -> void:
Global.projects.erase(temp)
Global.projects.insert(idx_to, temp)
# Change save paths
var temp_save_path := OpenSave.current_save_paths[Global.current_project_index]
OpenSave.current_save_paths.remove_at(Global.current_project_index)
OpenSave.current_save_paths.insert(idx_to, temp_save_path)
var temp_backup_path := OpenSave.backup_save_paths[Global.current_project_index]
OpenSave.backup_save_paths.remove_at(Global.current_project_index)
OpenSave.backup_save_paths.insert(idx_to, temp_backup_path)
func delete_tab(tab: int) -> void:
remove_tab(tab)
Global.projects[tab].remove()
OpenSave.remove_backup(tab)
OpenSave.current_save_paths.remove_at(tab)
OpenSave.backup_save_paths.remove_at(tab)
if Global.current_project_index == tab:
if tab > 0:
Global.current_project_index -= 1

View file

@ -461,7 +461,7 @@ func _on_open_last_project_file_menu_option_pressed() -> void:
func _save_project_file() -> void:
var path: String = OpenSave.current_save_paths[Global.current_project_index]
var path: String = Global.current_project.save_path
if path == "":
Global.control.show_save_dialog()
else: