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.
This commit is contained in:
Bruno Herbelin
2022-01-05 15:08:52 +01:00
parent d402143989
commit 5fb70a9b9a
3 changed files with 84 additions and 28 deletions

View File

@@ -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() Rendering::Rendering()
{ {
// main_window_ = nullptr; // main_window_ = nullptr;
@@ -206,6 +217,7 @@ bool Rendering::init()
// set application icon // set application icon
main_.setIcon("images/vimix_256x256.png"); main_.setIcon("images/vimix_256x256.png");
// additional window callbacks for main window // additional window callbacks for main window
glfwSetWindowCloseCallback( main_.window(), WindowCloseCallback );
glfwSetWindowRefreshCallback( main_.window(), WindowRefreshCallback ); glfwSetWindowRefreshCallback( main_.window(), WindowRefreshCallback );
glfwSetDropCallback( main_.window(), Rendering::FileDropped); glfwSetDropCallback( main_.window(), Rendering::FileDropped);
@@ -357,7 +369,6 @@ void Rendering::draw()
} }
void Rendering::terminate() void Rendering::terminate()
{ {
// close window // close window
@@ -366,13 +377,6 @@ void Rendering::terminate()
// glfwTerminate(); // glfwTerminate();
} }
void Rendering::close()
{
glfwSetWindowShouldClose(main_.window(), true);
}
void Rendering::pushAttrib(RenderingAttrib ra) void Rendering::pushAttrib(RenderingAttrib ra)
{ {
// push it to top of pile // push it to top of pile

View File

@@ -145,6 +145,7 @@ UserInterface::UserInterface()
target_view_navigator = 1; target_view_navigator = 1;
currentTextEdit.clear(); currentTextEdit.clear();
screenshot_step = 0; screenshot_step = 0;
pending_save_on_exit = false;
// keep hold on frame grabbers // keep hold on frame grabbers
video_recorder_ = nullptr; video_recorder_ = nullptr;
@@ -240,7 +241,6 @@ void UserInterface::handleKeyboard()
alt_modifier_active = io.KeyAlt; alt_modifier_active = io.KeyAlt;
shift_modifier_active = io.KeyShift; shift_modifier_active = io.KeyShift;
bool ctrl = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl; bool ctrl = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl;
bool confirm_quit_popup = false;
// Application "CTRL +"" Shortcuts // Application "CTRL +"" Shortcuts
if ( ctrl ) { if ( ctrl ) {
@@ -248,9 +248,8 @@ void UserInterface::handleKeyboard()
ctrl_modifier_active = true; ctrl_modifier_active = true;
if (ImGui::IsKeyPressed( GLFW_KEY_Q )) { if (ImGui::IsKeyPressed( GLFW_KEY_Q )) {
// offer to Quit // try quit
ImGui::OpenPopup("confirm_quit_popup"); TryClose();
confirm_quit_popup = true;
} }
else if (ImGui::IsKeyPressed( GLFW_KEY_O )) { else if (ImGui::IsKeyPressed( GLFW_KEY_O )) {
// SHIFT + CTRL + O : reopen current session // SHIFT + CTRL + O : reopen current session
@@ -382,7 +381,6 @@ void UserInterface::handleKeyboard()
// No CTRL modifier // No CTRL modifier
else { else {
ctrl_modifier_active = false; ctrl_modifier_active = false;
// Source *_cs = Mixer::manager().currentSource();
// Application F-Keys // Application F-Keys
if (ImGui::IsKeyPressed( GLFW_KEY_F1 )) if (ImGui::IsKeyPressed( GLFW_KEY_F1 ))
@@ -478,17 +476,6 @@ void UserInterface::handleKeyboard()
Mixer::manager().setView((View::Mode) target_view_navigator); 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() void UserInterface::handleMouse()
@@ -733,6 +720,32 @@ bool UserInterface::saveOrSaveAs(bool force_versioning)
return finished; 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() void UserInterface::selectSaveFilename()
{ {
if (sessionsavedialog) 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 bar first
navigator.Render(); navigator.Render();
} }
@@ -944,13 +992,13 @@ void UserInterface::showMenuFile()
if (ImGui::MenuItem( MENU_SAVEAS_FILE, SHORTCUT_SAVEAS_FILE)) if (ImGui::MenuItem( MENU_SAVEAS_FILE, SHORTCUT_SAVEAS_FILE))
selectSaveFilename(); 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(); ImGui::Separator();
if (ImGui::MenuItem( IMGUI_TITLE_HELP, SHORTCUT_HELP)) if (ImGui::MenuItem( IMGUI_TITLE_HELP, SHORTCUT_HELP))
Settings::application.widget.help = true; Settings::application.widget.help = true;
if (ImGui::MenuItem( MENU_QUIT, SHORTCUT_QUIT)) if (ImGui::MenuItem( MENU_QUIT, SHORTCUT_QUIT))
Rendering::manager().close(); TryClose();
} }
@@ -5456,7 +5504,7 @@ void Navigator::RenderMainPannelSettings()
// //
ImGui::Text("Appearance"); ImGui::Text("Appearance");
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); 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; ImGui::GetIO().FontGlobalScale = Settings::application.scale;
bool b = ImGui::RadioButton("Blue", &Settings::application.accent_color, 0); ImGui::SameLine(); bool b = ImGui::RadioButton("Blue", &Settings::application.accent_color, 0); ImGui::SameLine();
bool o = ImGui::RadioButton("Orange", &Settings::application.accent_color, 1); 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.blit = blit;
Settings::application.render.multisampling = multi ? 3 : 0; Settings::application.render.multisampling = multi ? 3 : 0;
Settings::application.render.gpu_decoding = gpu; Settings::application.render.gpu_decoding = gpu;
Rendering::manager().close(); UserInterface::manager().TryClose();
} }
} }

View File

@@ -25,6 +25,7 @@
#define MENU_SAVE_FILE ICON_FA_FILE_DOWNLOAD " Save" #define MENU_SAVE_FILE ICON_FA_FILE_DOWNLOAD " Save"
#define SHORTCUT_SAVE_FILE CTRL_MOD "S" #define SHORTCUT_SAVE_FILE CTRL_MOD "S"
#define MENU_SAVEAS_FILE ICON_FA_FILE_DOWNLOAD " Save as" #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_SAVEAS_FILE CTRL_MOD "Shift+S"
#define SHORTCUT_HELP CTRL_MOD "H" #define SHORTCUT_HELP CTRL_MOD "H"
#define SHORTCUT_LOGS CTRL_MOD "L" #define SHORTCUT_LOGS CTRL_MOD "L"
@@ -281,6 +282,7 @@ class UserInterface
int show_view_navigator; int show_view_navigator;
int target_view_navigator; int target_view_navigator;
unsigned int screenshot_step; unsigned int screenshot_step;
bool pending_save_on_exit;
// frame grabbers // frame grabbers
VideoRecorder *video_recorder_; VideoRecorder *video_recorder_;
@@ -314,6 +316,8 @@ public:
void NewFrame(); void NewFrame();
// loop update rendering // loop update rendering
void Render(); void Render();
// try to close, return false if cannot
bool TryClose();
// Post-loop termination // Post-loop termination
void Terminate(); void Terminate();
// Runtime // Runtime