From 4f9f948b6db5531f3e56f5f8cb277ad005580350 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Fri, 29 Apr 2022 17:00:24 +0100 Subject: [PATCH] LibGUI: Support "modified" window state in SettingsWindow SettingsWindow now notices if the window is marked as modified, and shows a confirmation pop-up to check if the user wants to apply or discard their changes. It automatically marks the window as unmodified after restoring defaults or applying the changes, but each Tab subclass needs to call `set_modified(true)` when the user modifies things. The "Apply" button is automatically disabled when there are no unsaved changes to be applied. --- Userland/Libraries/LibGUI/SettingsWindow.cpp | 61 ++++++++++++++++---- Userland/Libraries/LibGUI/SettingsWindow.h | 19 ++++++ 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/Userland/Libraries/LibGUI/SettingsWindow.cpp b/Userland/Libraries/LibGUI/SettingsWindow.cpp index deaa478468..2034f82b0b 100644 --- a/Userland/Libraries/LibGUI/SettingsWindow.cpp +++ b/Userland/Libraries/LibGUI/SettingsWindow.cpp @@ -10,11 +10,19 @@ #include #include #include +#include #include #include namespace GUI { +void SettingsWindow::set_modified(bool modified) +{ + Window::set_modified(modified); + if (m_apply_button) + m_apply_button->set_enabled(modified); +} + ErrorOr> SettingsWindow::create(String title, ShowDefaultsButton show_defaults_button) { auto window = TRY(SettingsWindow::try_create()); @@ -41,10 +49,7 @@ ErrorOr> SettingsWindow::create(String title, Show window->m_reset_button = TRY(button_container->try_add("Defaults")); window->m_reset_button->set_fixed_width(75); window->m_reset_button->on_click = [window = window->make_weak_ptr()](auto) mutable { - for (auto& [id, tab] : window->m_tabs) { - tab->reset_default_values(); - tab->apply_settings(); - } + window->reset_default_values(); }; } @@ -53,24 +58,38 @@ ErrorOr> SettingsWindow::create(String title, Show window->m_ok_button = TRY(button_container->try_add("OK")); window->m_ok_button->set_fixed_width(75); window->m_ok_button->on_click = [window = window->make_weak_ptr()](auto) mutable { - for (auto& [id, tab] : window->m_tabs) - tab->apply_settings(); + window->apply_settings(); GUI::Application::the()->quit(); }; window->m_cancel_button = TRY(button_container->try_add("Cancel")); window->m_cancel_button->set_fixed_width(75); window->m_cancel_button->on_click = [window = window->make_weak_ptr()](auto) mutable { - for (auto& [id, tab] : window->m_tabs) - tab->cancel_settings(); + window->cancel_settings(); GUI::Application::the()->quit(); }; window->m_apply_button = TRY(button_container->try_add("Apply")); window->m_apply_button->set_fixed_width(75); window->m_apply_button->on_click = [window = window->make_weak_ptr()](auto) mutable { - for (auto& [id, tab] : window->m_tabs) - tab->apply_settings(); + window->apply_settings(); + }; + + window->on_close_request = [window = window->make_weak_ptr()]() mutable -> Window::CloseRequestDecision { + if (!window->is_modified()) + return Window::CloseRequestDecision::Close; + + auto result = MessageBox::show(window, "Apply these settings before closing?", "Unsaved changes", MessageBox::Type::Warning, MessageBox::InputType::YesNoCancel); + switch (result) { + case MessageBox::ExecYes: + window->apply_settings(); + return Window::CloseRequestDecision::Close; + case MessageBox::ExecNo: + window->cancel_settings(); + return Window::CloseRequestDecision::Close; + default: + return Window::CloseRequestDecision::StayOpen; + } }; return window; @@ -90,4 +109,26 @@ void SettingsWindow::set_active_tab(StringView id) m_tab_widget->set_active_widget(tab.value()); } +void SettingsWindow::apply_settings() +{ + for (auto& [id, tab] : m_tabs) + tab->apply_settings(); + set_modified(false); +} + +void SettingsWindow::cancel_settings() +{ + for (auto& [id, tab] : m_tabs) + tab->cancel_settings(); +} + +void SettingsWindow::reset_default_values() +{ + for (auto& [id, tab] : m_tabs) { + tab->reset_default_values(); + tab->apply_settings(); + } + set_modified(false); +} + } diff --git a/Userland/Libraries/LibGUI/SettingsWindow.h b/Userland/Libraries/LibGUI/SettingsWindow.h index 05b9a4748d..1d2471ae85 100644 --- a/Userland/Libraries/LibGUI/SettingsWindow.h +++ b/Userland/Libraries/LibGUI/SettingsWindow.h @@ -23,6 +23,18 @@ public: virtual void apply_settings() = 0; virtual void cancel_settings() { } virtual void reset_default_values() { } + + SettingsWindow& settings_window() { return *m_window; } + void set_settings_window(SettingsWindow& settings_window) { m_window = settings_window; } + + void set_modified(bool modified) + { + if (m_window) + m_window->set_modified(modified); + } + + private: + WeakPtr m_window; }; enum class ShowDefaultsButton { @@ -39,12 +51,19 @@ public: { auto tab = TRY(m_tab_widget->try_add_tab(move(title), forward(args)...)); TRY(m_tabs.try_set(id, tab)); + tab->set_settings_window(*this); return tab; } Optional> get_tab(StringView id) const; void set_active_tab(StringView id); + void apply_settings(); + void cancel_settings(); + void reset_default_values(); + + void set_modified(bool); + private: SettingsWindow() = default;