From bf9af8c9968cc9bbd09f1dde5bfac9e6c4ba6cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lera=20Elvo=C3=A9?= Date: Wed, 13 Dec 2023 19:25:30 +0300 Subject: [PATCH] prompt to save dirty deck when closing it --- graph_node_renderer/deck_holder_renderer.gd | 61 +++++++++++++------ graph_node_renderer/deck_holder_renderer.tscn | 7 ++- .../unsaved_changes_dialog_single_deck.gd | 6 ++ .../unsaved_changes_dialog_single_deck.tscn | 20 ++++++ 4 files changed, 76 insertions(+), 18 deletions(-) create mode 100644 graph_node_renderer/unsaved_changes_dialog_single_deck.gd create mode 100644 graph_node_renderer/unsaved_changes_dialog_single_deck.tscn diff --git a/graph_node_renderer/deck_holder_renderer.gd b/graph_node_renderer/deck_holder_renderer.gd index 0b90e8b..b65eda6 100644 --- a/graph_node_renderer/deck_holder_renderer.gd +++ b/graph_node_renderer/deck_holder_renderer.gd @@ -12,7 +12,7 @@ const DEBUG_DECKS_LIST := preload("res://graph_node_renderer/debug_decks_list.ts const PERSISTENCE_NAMESPACE := "default" ## Reference to the main windows [TabContainerCustom] -@onready var tab_container: TabContainerCustom = %TabContainerCustom as TabContainerCustom +@onready var tab_container := %TabContainerCustom as TabContainerCustom ## Reference to the [FileDialog] used for File operations through the program. @onready var file_dialog: FileDialog = $FileDialog @@ -34,6 +34,7 @@ enum FileMenuId { @onready var file_popup_menu: PopupMenu = %File as PopupMenu var max_recents := 4 var recent_files := [] +@onready var unsaved_changes_dialog_single_deck := $UnsavedChangesDialogSingleDeck as UnsavedChangesDialogSingleDeck enum ConnectionsMenuId { OBS, @@ -43,10 +44,10 @@ enum ConnectionsMenuId { ## Weak Reference to the Deck that is currently going to be saved. var _deck_to_save: WeakRef -@onready var no_obsws: NoOBSWS = %NoOBSWS as NoOBSWS +@onready var no_obsws := %NoOBSWS as NoOBSWS -@onready var obs_setup_dialog: OBSWebsocketSetupDialog = $OBSWebsocketSetupDialog as OBSWebsocketSetupDialog -@onready var twitch_setup_dialog : TwitchSetupDialog = $Twitch_Setup_Dialog as TwitchSetupDialog +@onready var obs_setup_dialog := $OBSWebsocketSetupDialog as OBSWebsocketSetupDialog +@onready var twitch_setup_dialog := $Twitch_Setup_Dialog as TwitchSetupDialog func _ready() -> void: @@ -62,14 +63,11 @@ func _ready() -> void: tab_container.tab_close_requested.connect( func(tab: int): - var groups := DeckHolder.close_deck(tab_container.get_tab_metadata(tab, "id")) - # close tabs associated with this deck's groups - for group in groups: - for c_tab in tab_container.get_tab_count(): - if tab_container.get_tab_metadata(c_tab, "id") == group: - tab_container.close_tab(tab) - await get_tree().process_frame - tab_container.close_tab(tab) + if tab_container.get_tab_metadata(tab, "dirty"): + unsaved_changes_dialog_single_deck.set_meta("tab", tab) + unsaved_changes_dialog_single_deck.show() + return + close_tab(tab) ) file_dialog.canceled.connect(disconnect_file_dialog_signals) @@ -116,6 +114,17 @@ func add_empty_deck() -> void: func close_current_tab() -> void: tab_container.close_tab(tab_container.get_current_tab()) + +func close_tab(tab: int) -> void: + var groups := DeckHolder.close_deck(tab_container.get_tab_metadata(tab, "id")) + # close tabs associated with this deck's groups + for group in groups: + for c_tab in tab_container.get_tab_count(): + if tab_container.get_tab_metadata(c_tab, "id") == group: + tab_container.close_tab(tab) + await get_tree().process_frame + tab_container.close_tab(tab) + ## Opens [member file_dialog] with the mode [member FileDialog.FILE_MODE_SAVE_FILE] ## as well as getting a weakref to the active [Deck] func open_save_dialog(path: String) -> void: @@ -185,14 +194,21 @@ func get_active_deck() -> Deck: ## Saves the active [Deck] in [member tab_container] func save_active_deck() -> void: - if get_active_deck().save_path.is_empty(): + save_tab(tab_container.get_current_tab()) + + +func save_tab(tab: int) -> void: + var renderer := tab_container.get_content(tab) as DeckRendererGraphEdit + var deck := renderer.deck + if deck.save_path.is_empty(): open_save_dialog("res://") else: - var json := JSON.stringify(get_active_deck().to_dict(), "\t") - var f := FileAccess.open(get_active_deck().save_path, FileAccess.WRITE) + var json := JSON.stringify(deck.to_dict(), "\t") + var f := FileAccess.open(deck.save_path, FileAccess.WRITE) f.store_string(json) - add_recent_file(get_active_deck().save_path) - (tab_container.get_content(tab_container.get_current_tab()) as DeckRendererGraphEdit).dirty = false + add_recent_file(deck.save_path) + renderer.dirty = false + ## Disconnects the [FileDialog] signals if they are already connected. func disconnect_file_dialog_signals() -> void: @@ -281,6 +297,7 @@ func _on_deck_renderer_dirty_state_changed(renderer: DeckRendererGraphEdit) -> v tab_container.set_tab_title(idx, "%s(*)" % title) else: tab_container.set_tab_title(idx, title.trim_suffix("(*)")) + tab_container.set_tab_metadata(idx, "dirty", renderer.dirty) func add_recent_file(path: String) -> void: @@ -328,3 +345,13 @@ func add_recents_to_menu() -> void: RendererPersistence.set_value(PERSISTENCE_NAMESPACE, "config", "recent_files", recent_files) RendererPersistence.commit(PERSISTENCE_NAMESPACE) + + +func _on_unsaved_changes_dialog_single_deck_confirmed() -> void: + save_tab(unsaved_changes_dialog_single_deck.get_meta("tab")) + close_tab(unsaved_changes_dialog_single_deck.get_meta("tab")) + + +func _on_unsaved_changes_dialog_single_deck_custom_action(action: StringName) -> void: + if action == &"force_close": + close_tab(unsaved_changes_dialog_single_deck.get_meta("tab")) diff --git a/graph_node_renderer/deck_holder_renderer.tscn b/graph_node_renderer/deck_holder_renderer.tscn index 91f250e..90b3abd 100644 --- a/graph_node_renderer/deck_holder_renderer.tscn +++ b/graph_node_renderer/deck_holder_renderer.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=18 format=3 uid="uid://duaah5x0jhkn6"] +[gd_scene load_steps=19 format=3 uid="uid://duaah5x0jhkn6"] [ext_resource type="Script" path="res://graph_node_renderer/deck_holder_renderer.gd" id="1_67g2g"] [ext_resource type="PackedScene" uid="uid://b84f2ngtcm5b8" path="res://graph_node_renderer/tab_container_custom.tscn" id="1_s3ug2"] @@ -7,6 +7,7 @@ [ext_resource type="Script" path="res://addons/no_twitch/twitch_connection.gd" id="5_3n36q"] [ext_resource type="PackedScene" uid="uid://eioso6jb42jy" path="res://graph_node_renderer/obs_websocket_setup_dialog.tscn" id="5_uo2gj"] [ext_resource type="PackedScene" uid="uid://bq2lxmbnic4lc" path="res://graph_node_renderer/twitch_setup_dialog.tscn" id="7_7rhap"] +[ext_resource type="PackedScene" uid="uid://cuwou2aa7qfc2" path="res://graph_node_renderer/unsaved_changes_dialog_single_deck.tscn" id="8_qf6ve"] [sub_resource type="InputEventKey" id="InputEventKey_giamc"] device = -1 @@ -158,7 +159,11 @@ script = ExtResource("5_3n36q") [node name="Twitch_Setup_Dialog" parent="." instance=ExtResource("7_7rhap")] visible = false +[node name="UnsavedChangesDialogSingleDeck" parent="." instance=ExtResource("8_qf6ve")] + [connection signal="id_pressed" from="MarginContainer/VSplitContainer/VBoxContainer/MenuBar/File" to="." method="_on_file_id_pressed"] [connection signal="id_pressed" from="MarginContainer/VSplitContainer/VBoxContainer/MenuBar/Connections" to="." method="_on_connections_id_pressed"] [connection signal="id_pressed" from="MarginContainer/VSplitContainer/VBoxContainer/MenuBar/Debug" to="." method="_on_debug_id_pressed"] [connection signal="connect_button_pressed" from="OBSWebsocketSetupDialog" to="." method="_on_obs_websocket_setup_dialog_connect_button_pressed"] +[connection signal="confirmed" from="UnsavedChangesDialogSingleDeck" to="." method="_on_unsaved_changes_dialog_single_deck_confirmed"] +[connection signal="custom_action" from="UnsavedChangesDialogSingleDeck" to="." method="_on_unsaved_changes_dialog_single_deck_custom_action"] diff --git a/graph_node_renderer/unsaved_changes_dialog_single_deck.gd b/graph_node_renderer/unsaved_changes_dialog_single_deck.gd new file mode 100644 index 0000000..6592a31 --- /dev/null +++ b/graph_node_renderer/unsaved_changes_dialog_single_deck.gd @@ -0,0 +1,6 @@ +extends ConfirmationDialog +class_name UnsavedChangesDialogSingleDeck + + +func _init() -> void: + add_button("Don't Save", true, "force_close") diff --git a/graph_node_renderer/unsaved_changes_dialog_single_deck.tscn b/graph_node_renderer/unsaved_changes_dialog_single_deck.tscn new file mode 100644 index 0000000..92b3cae --- /dev/null +++ b/graph_node_renderer/unsaved_changes_dialog_single_deck.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=2 format=3 uid="uid://cuwou2aa7qfc2"] + +[ext_resource type="Script" path="res://graph_node_renderer/unsaved_changes_dialog_single_deck.gd" id="1_qpf7a"] + +[node name="UnsavedChangesDialogSingleDeck" type="ConfirmationDialog"] +initial_position = 2 +size = Vector2i(356, 206) +ok_button_text = "Save" +script = ExtResource("1_qpf7a") + +[node name="Label" type="Label" parent="."] +offset_left = 8.0 +offset_top = 8.0 +offset_right = 348.0 +offset_bottom = 157.0 +text = "This deck has unsaved changes. Closing it will discard any changes. +Save now?" +horizontal_alignment = 1 +vertical_alignment = 1 +autowrap_mode = 3