From 5ba5254ec1ebba6c1e89b663592d716b92e13165 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 21 Mar 2018 16:00:18 +0100 Subject: UI: Optional prompt to quit for non win32 systems D566 by @januz Use Blender native dialog when OS dialog's aren't supported. --- source/blender/windowmanager/intern/wm_files.c | 8 ++ source/blender/windowmanager/intern/wm_operators.c | 15 ++- source/blender/windowmanager/intern/wm_window.c | 136 ++++++++++++++++++++- source/blender/windowmanager/wm_window.h | 1 + 4 files changed, 149 insertions(+), 11 deletions(-) (limited to 'source/blender/windowmanager') diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 16cc1d44923..551b17302fe 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -2075,6 +2075,10 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_WM | ND_FILESAVE, NULL); + if (RNA_boolean_get(op->ptr, "exit")) { + WM_exit(C); + } + return OPERATOR_FINISHED; } @@ -2174,12 +2178,16 @@ void WM_OT_save_mainfile(wmOperatorType *ot) ot->check = blend_save_check; /* omit window poll so this can work in background mode */ + PropertyRNA *prop; WM_operator_properties_filesel( ot, FILE_TYPE_FOLDER | FILE_TYPE_BLENDER, FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); RNA_def_boolean(ot->srna, "compress", false, "Compress", "Write compressed .blend file"); RNA_def_boolean(ot->srna, "relative_remap", false, "Remap Relative", "Remap relative paths when saving in a different directory"); + + prop = RNA_def_boolean(ot->srna, "exit", false, "Exit", "Exit Blender after saving"); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } /** \} */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 2a50de62dda..363b8e61763 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2162,10 +2162,16 @@ static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot) static int wm_exit_blender_exec(bContext *C, wmOperator *op) { - WM_operator_free(op); - - WM_exit(C); - + wmWindowManager *wm = CTX_wm_manager(C); + + if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved) { + wm_confirm_quit(C); + } + else { + WM_operator_free(op); + WM_exit(C); + } + return OPERATOR_FINISHED; } @@ -2175,7 +2181,6 @@ static void WM_OT_quit_blender(wmOperatorType *ot) ot->idname = "WM_OT_quit_blender"; ot->description = "Quit Blender"; - ot->invoke = WM_operator_confirm; ot->exec = wm_exit_blender_exec; } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index cbf06e8c6e9..2e12ceab5b3 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -70,6 +70,7 @@ #include "ED_fileselect.h" #include "UI_interface.h" +#include "UI_resources.h" #include "PIL_time.h" @@ -295,6 +296,124 @@ wmWindow *wm_window_copy_test(bContext *C, wmWindow *win_src) } } + +/* -------------------------------------------------------------------- */ +/** \name Quit Confirmation Dialog + * \{ */ + +/** Cancel quitting and close the dialog */ +static void wm_block_confirm_quit_cancel(bContext *C, void *arg_block, void *UNUSED(arg)) +{ + wmWindow *win = CTX_wm_window(C); + UI_popup_block_close(C, win, arg_block); +} + +/** Discard the file changes and quit */ +static void wm_block_confirm_quit_discard(bContext *C, void *arg_block, void *UNUSED(arg)) +{ + wmWindow *win = CTX_wm_window(C); + UI_popup_block_close(C, win, arg_block); + WM_exit(C); +} + +/* Save changes and quit */ +static void wm_block_confirm_quit_save(bContext *C, void *arg_block, void *UNUSED(arg)) +{ + PointerRNA props_ptr; + wmWindow *win = CTX_wm_window(C); + + UI_popup_block_close(C, win, arg_block); + + wmOperatorType *ot = WM_operatortype_find("WM_OT_save_mainfile", false); + + WM_operator_properties_create_ptr(&props_ptr, ot); + RNA_boolean_set(&props_ptr, "exit", true); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); + WM_operator_properties_free(&props_ptr); +} + + +/* Build the confirm dialog UI */ +static uiBlock *block_create_confirm_quit(struct bContext *C, struct ARegion *ar, void *UNUSED(arg1)) +{ + + uiStyle *style = UI_style_get(); + uiBlock *block = UI_block_begin(C, ar, "confirm_quit_popup", UI_EMBOSS); + + UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP ); + UI_block_emboss_set(block, UI_EMBOSS); + + uiLayout *layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, U.pixelsize * 480, U.pixelsize * 110, 0, style); + + /* Text and some vertical space */ + { + char *message; + if (G.main->name[0] == '\0') { + message = BLI_strdup(IFACE_("This file has not been saved yet. Save before closing?")); + } + else { + const char *basename = BLI_path_basename(G.main->name); + message = BLI_sprintfN(IFACE_("Save changes to \"%s\" before closing?"), basename); + } + uiItemL(layout, message, ICON_ERROR); + MEM_freeN(message); + } + + uiItemS(layout); + uiItemS(layout); + + + /* Buttons */ + uiBut *but; + + uiLayout *split = uiLayoutSplit(layout, 0.0f, true); + + uiLayout *col = uiLayoutColumn(split, false); + + but = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_SCREEN_BACK, IFACE_("Cancel"), 0, 0, 0, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Do not quit")); + UI_but_func_set(but, wm_block_confirm_quit_cancel, block, NULL); + + /* empty space between buttons */ + col = uiLayoutColumn(split, false); + uiItemS(col); + + col = uiLayoutColumn(split, 1); + but = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_CANCEL, IFACE_("Discard Changes"), 0, 0, 50, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Discard changes and quit")); + UI_but_func_set(but, wm_block_confirm_quit_discard, block, NULL); + + col = uiLayoutColumn(split, 1); + but = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_FILE_TICK, IFACE_("Save & Quit"), 0, 0, 50, UI_UNIT_Y, + NULL, 0, 0, 0, 0, TIP_("Save and quit")); + UI_but_func_set(but, wm_block_confirm_quit_save, block, NULL); + + UI_block_bounds_set_centered(block, 10); + + return block; +} + + +/** Call the confirm dialog on quitting. */ +void wm_confirm_quit(bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + + /* The popup needs to have a window set in context to show up since + * it's being called outside the normal operator event handling loop */ + if (wm->winactive) { + CTX_wm_window_set(C, wm->winactive); + } + + UI_popup_block_invoke(C, block_create_confirm_quit, NULL); +} + +/** \} */ + /* this is event from ghost, or exit-blender op */ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) { @@ -311,19 +430,24 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) if (tmpwin == NULL) do_exit = 1; - - if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) { - if (do_exit) { + + if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background && do_exit) { + /* We have unsaved changes and we're quitting */ + if(GHOST_SupportsNativeDialogs() == 0) { + wm_confirm_quit(C); + } + else { if (!GHOST_confirmQuit(win->ghostwin)) return; } } - - /* let WM_exit do all freeing, for correct quit.blend save */ - if (do_exit) { + else if (do_exit) { + /* No changes but we're quitting */ + /* let WM_exit do all freeing, for correct quit.blend save */ WM_exit(C); } else { + /* We're just closing a window */ bScreen *screen = win->screen; BLI_remlink(&wm->windows, win); diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index f70ec6b47f6..4313c978ef4 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -78,6 +78,7 @@ void wm_window_IME_end (wmWindow *win); int wm_window_close_exec(bContext *C, struct wmOperator *op); int wm_window_duplicate_exec(bContext *C, struct wmOperator *op); int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op); +void wm_confirm_quit(bContext *C); /* Initial (unmaximized) size to start with for * systems that can't find it for themselves (X11). -- cgit v1.2.3