From 5fb70a9b9a077784e7cf9856c568a4dc72afe7b0 Mon Sep 17 00:00:00 2001 From: Bruno Herbelin Date: Wed, 5 Jan 2022 15:08:52 +0100 Subject: [PATCH] Save on exit; test before closing Detect window close or quit events to make sure a filename is given if save-on-exit is active. --- RenderingManager.cpp | 20 +++++---- UserInterfaceManager.cpp | 88 +++++++++++++++++++++++++++++++--------- UserInterfaceManager.h | 4 ++ 3 files changed, 84 insertions(+), 28 deletions(-) diff --git a/RenderingManager.cpp b/RenderingManager.cpp index d86b8ce..3908fc7 100644 --- a/RenderingManager.cpp +++ b/RenderingManager.cpp @@ -174,6 +174,17 @@ static void WindowToggleFullscreen( GLFWwindow *w, int button, int action, int) } } +static void WindowCloseCallback( GLFWwindow* w ) +{ + if (!UserInterface::manager().TryClose()) + glfwSetWindowShouldClose(w, GLFW_FALSE); +} + +void Rendering::close() +{ + glfwSetWindowShouldClose(main_.window(), GLFW_TRUE); +} + Rendering::Rendering() { // main_window_ = nullptr; @@ -206,6 +217,7 @@ bool Rendering::init() // set application icon main_.setIcon("images/vimix_256x256.png"); // additional window callbacks for main window + glfwSetWindowCloseCallback( main_.window(), WindowCloseCallback ); glfwSetWindowRefreshCallback( main_.window(), WindowRefreshCallback ); glfwSetDropCallback( main_.window(), Rendering::FileDropped); @@ -357,7 +369,6 @@ void Rendering::draw() } - void Rendering::terminate() { // close window @@ -366,13 +377,6 @@ void Rendering::terminate() // glfwTerminate(); } - -void Rendering::close() -{ - glfwSetWindowShouldClose(main_.window(), true); -} - - void Rendering::pushAttrib(RenderingAttrib ra) { // push it to top of pile diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index 72b5261..693cb76 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -145,6 +145,7 @@ UserInterface::UserInterface() target_view_navigator = 1; currentTextEdit.clear(); screenshot_step = 0; + pending_save_on_exit = false; // keep hold on frame grabbers video_recorder_ = nullptr; @@ -240,7 +241,6 @@ void UserInterface::handleKeyboard() alt_modifier_active = io.KeyAlt; shift_modifier_active = io.KeyShift; bool ctrl = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl; - bool confirm_quit_popup = false; // Application "CTRL +"" Shortcuts if ( ctrl ) { @@ -248,9 +248,8 @@ void UserInterface::handleKeyboard() ctrl_modifier_active = true; if (ImGui::IsKeyPressed( GLFW_KEY_Q )) { - // offer to Quit - ImGui::OpenPopup("confirm_quit_popup"); - confirm_quit_popup = true; + // try quit + TryClose(); } else if (ImGui::IsKeyPressed( GLFW_KEY_O )) { // SHIFT + CTRL + O : reopen current session @@ -382,7 +381,6 @@ void UserInterface::handleKeyboard() // No CTRL modifier else { ctrl_modifier_active = false; -// Source *_cs = Mixer::manager().currentSource(); // Application F-Keys if (ImGui::IsKeyPressed( GLFW_KEY_F1 )) @@ -478,17 +476,6 @@ void UserInterface::handleKeyboard() Mixer::manager().setView((View::Mode) target_view_navigator); } - // confirmation for leaving vimix: prevent un-wanted Ctrl+Q, but make it easy to confirm - if (ImGui::BeginPopup("confirm_quit_popup")) - { - ImGui::Text(" Leave vimix? [Q to confirm]"); - // Clic Quit or press Q to confirm exit - if (ImGui::Button( MENU_QUIT, ImVec2(250,0)) || - ( !confirm_quit_popup && ImGui::IsKeyPressed( GLFW_KEY_Q )) ) - Rendering::manager().close(); - ImGui::EndPopup(); - } - } void UserInterface::handleMouse() @@ -733,6 +720,32 @@ bool UserInterface::saveOrSaveAs(bool force_versioning) return finished; } + +bool UserInterface::TryClose() +{ + // cannot close if a file dialog is pending + if (DialogToolkit::FileDialog::busy()) + return false; + + // force close if trying to close again although it is already pending for save + if (pending_save_on_exit) { + Rendering::manager().close(); + return true; + } + + // general case: determine if a pending save of session is required + pending_save_on_exit = ( Settings::application.recentSessions.save_on_exit + && !Mixer::manager().session()->empty() + && Mixer::manager().session()->filename().empty() ); + + // if no pending save of session is needed, close + if (!pending_save_on_exit) + Rendering::manager().close(); + + // say we can close if no pending save of session is needed + return !pending_save_on_exit; +} + void UserInterface::selectSaveFilename() { if (sessionsavedialog) @@ -782,6 +795,41 @@ void UserInterface::NewFrame() } } + // popup to inform to save before close + if (pending_save_on_exit && !ImGui::IsPopupOpen(MENU_SAVE_ON_EXIT)) + ImGui::OpenPopup(MENU_SAVE_ON_EXIT); + if (ImGui::BeginPopupModal(MENU_SAVE_ON_EXIT, NULL, ImGuiWindowFlags_AlwaysAutoResize)) + { + const ImVec2 area = ImGui::GetContentRegionAvail(); + ImGui::Spacing(); + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_ITALIC); + ImGui::Text("Looks like you started some work"); + ImGui::Text("but didn't save the session."); + ImGui::Text(""); + ImGui::Text(""); + ImGui::Text(""); + ImGui::PopFont(); + + bool quit = false; + ImGui::SetCursorPos( area - ImVec2(area.x - 10.f, ImGui::GetFrameHeightWithSpacing()) ); + if (ImGui::Button(ICON_FA_POWER_OFF " Quit anyway !", ImVec2(area.x, 0))) { + Rendering::manager().close(); + quit = true; + } + + bool cancel = false; + ImGui::SetCursorPos( area - ImVec2(area.x - 10.f, 0) ); + if (ImGui::Button(ICON_FA_FILE_DOWNLOAD " Save", ImVec2(area.x, 0))) { + pending_save_on_exit = false; + cancel = true; + saveOrSaveAs(); + } + + if (cancel || quit) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + // navigator bar first navigator.Render(); } @@ -944,13 +992,13 @@ void UserInterface::showMenuFile() if (ImGui::MenuItem( MENU_SAVEAS_FILE, SHORTCUT_SAVEAS_FILE)) selectSaveFilename(); - ImGui::MenuItem( ICON_FA_LEVEL_DOWN_ALT " Save on exit", nullptr, &Settings::application.recentSessions.save_on_exit); + ImGui::MenuItem( MENU_SAVE_ON_EXIT, nullptr, &Settings::application.recentSessions.save_on_exit); ImGui::Separator(); if (ImGui::MenuItem( IMGUI_TITLE_HELP, SHORTCUT_HELP)) Settings::application.widget.help = true; if (ImGui::MenuItem( MENU_QUIT, SHORTCUT_QUIT)) - Rendering::manager().close(); + TryClose(); } @@ -5456,7 +5504,7 @@ void Navigator::RenderMainPannelSettings() // ImGui::Text("Appearance"); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if ( ImGui::DragFloat("Scale", &Settings::application.scale, 0.01, 0.5f, 2.0f, "%.1f")) + if ( ImGui::DragFloat("Scale", &Settings::application.scale, 0.01f, 0.5f, 2.0f, "%.1f")) ImGui::GetIO().FontGlobalScale = Settings::application.scale; bool b = ImGui::RadioButton("Blue", &Settings::application.accent_color, 0); ImGui::SameLine(); bool o = ImGui::RadioButton("Orange", &Settings::application.accent_color, 1); ImGui::SameLine(); @@ -5588,7 +5636,7 @@ void Navigator::RenderMainPannelSettings() Settings::application.render.blit = blit; Settings::application.render.multisampling = multi ? 3 : 0; Settings::application.render.gpu_decoding = gpu; - Rendering::manager().close(); + UserInterface::manager().TryClose(); } } diff --git a/UserInterfaceManager.h b/UserInterfaceManager.h index 9cd51b5..72d7308 100644 --- a/UserInterfaceManager.h +++ b/UserInterfaceManager.h @@ -25,6 +25,7 @@ #define MENU_SAVE_FILE ICON_FA_FILE_DOWNLOAD " Save" #define SHORTCUT_SAVE_FILE CTRL_MOD "S" #define MENU_SAVEAS_FILE ICON_FA_FILE_DOWNLOAD " Save as" +#define MENU_SAVE_ON_EXIT ICON_FA_LEVEL_DOWN_ALT " Save on exit" #define SHORTCUT_SAVEAS_FILE CTRL_MOD "Shift+S" #define SHORTCUT_HELP CTRL_MOD "H" #define SHORTCUT_LOGS CTRL_MOD "L" @@ -281,6 +282,7 @@ class UserInterface int show_view_navigator; int target_view_navigator; unsigned int screenshot_step; + bool pending_save_on_exit; // frame grabbers VideoRecorder *video_recorder_; @@ -314,6 +316,8 @@ public: void NewFrame(); // loop update rendering void Render(); + // try to close, return false if cannot + bool TryClose(); // Post-loop termination void Terminate(); // Runtime