Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/editors/include/ED_image.h1
-rw-r--r--source/blender/editors/space_image/image_ops.c147
-rw-r--r--source/blender/windowmanager/WM_api.h4
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c11
-rw-r--r--source/blender/windowmanager/intern/wm_files.c275
-rw-r--r--source/blender/windowmanager/intern/wm_window.c162
-rw-r--r--source/blender/windowmanager/wm_files.h11
7 files changed, 367 insertions, 244 deletions
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index affe98e10f8..a09e1d579fd 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -111,6 +111,7 @@ void ED_image_draw_info(struct Scene *scene,
bool ED_space_image_show_cache(struct SpaceImage *sima);
+bool ED_image_should_save_modified(const struct bContext *C);
int ED_image_save_all_modified_info(const struct bContext *C, struct ReportList *reports);
bool ED_image_save_all_modified(const struct bContext *C, struct ReportList *reports);
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index b49fd92beb3..533e39a27bc 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -2161,126 +2161,117 @@ void IMAGE_OT_save_sequence(wmOperatorType *ot)
/********************** save all operator **********************/
-static int image_save_all_modified(const bContext *C,
- ReportList *reports,
- int *num_files,
- const bool dry_run,
- const bool ignore_dry_run_warnings)
+static bool image_should_be_saved_when_modified(Image *ima)
+{
+ return !ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE);
+}
+
+static bool image_should_be_saved(Image *ima)
+{
+ if (BKE_image_is_dirty(ima) && (ima->source == IMA_SRC_FILE)) {
+ return image_should_be_saved_when_modified(ima);
+ }
+ else {
+ return false;
+ }
+}
+
+static bool image_has_valid_path(Image *ima)
+{
+ return strchr(ima->name, '\\') || strchr(ima->name, '/');
+}
+
+bool ED_image_should_save_modified(const bContext *C)
+{
+ return ED_image_save_all_modified_info(C, NULL) > 0;
+}
+
+int ED_image_save_all_modified_info(const bContext *C, ReportList *reports)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
GSet *unique_paths = BLI_gset_str_new(__func__);
- bool ok = true;
- if (num_files) {
- *num_files = 0;
- }
+ int num_saveable_images = 0;
for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
- if (ELEM(ima->type, IMA_TYPE_R_RESULT, IMA_TYPE_COMPOSITE)) {
- /* Don't save render results automatically. */
- }
- else if (BKE_image_is_dirty(ima) && (ima->source == IMA_SRC_FILE)) {
+ if (image_should_be_saved(ima)) {
if (BKE_image_has_packedfile(ima)) {
if (ima->id.lib == NULL) {
- /* Re-pack. */
- if (!dry_run) {
- BKE_image_memorypack(ima);
- }
-
- if (num_files) {
- (*num_files)++;
- }
+ num_saveable_images++;
}
- else if (!ignore_dry_run_warnings) {
- /* Can't pack to library data. */
+ else {
BKE_reportf(reports,
RPT_WARNING,
"Packed library image: %s from library %s can't be saved",
ima->id.name,
ima->id.lib->name);
- ok = false;
}
}
else {
- /* Save to file. */
- const bool valid_path = strchr(ima->name, '\\') || strchr(ima->name, '/');
-
- if (valid_path) {
- ImageSaveOptions opts;
-
- BKE_image_save_options_init(&opts, bmain, scene);
-
- if (image_save_options_init(bmain, &opts, ima, NULL, false, false)) {
- if (!BLI_gset_haskey(unique_paths, opts.filepath)) {
- if (!dry_run) {
- const bool save_ok = BKE_image_save(reports, bmain, ima, NULL, &opts);
-
- if (save_ok) {
- BLI_gset_insert(unique_paths, BLI_strdup(opts.filepath));
- }
-
- ok = ok && save_ok;
- }
-
- if (num_files) {
- (*num_files)++;
- }
- }
- else if (!ignore_dry_run_warnings) {
- BKE_reportf(reports,
- RPT_WARNING,
- "File path used by more than one saved image: %s",
- opts.filepath);
- ok = false;
- }
+ if (image_has_valid_path(ima)) {
+ num_saveable_images++;
+ if (BLI_gset_haskey(unique_paths, ima->name)) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "File path used by more than one saved image: %s",
+ ima->name);
+ }
+ else {
+ BLI_gset_insert(unique_paths, BLI_strdup(ima->name));
}
}
- else if (!ignore_dry_run_warnings) {
+ else {
BKE_reportf(reports,
RPT_WARNING,
"Image %s can't be saved, no valid file path: %s",
ima->id.name,
ima->name);
- ok = false;
}
}
}
}
BLI_gset_free(unique_paths, MEM_freeN);
-
- return ok;
-}
-
-int ED_image_save_all_modified_info(const bContext *C, ReportList *reports)
-{
- /* Dry run to get number of files, and any warnings we can detect in advance. */
- int num_files;
- image_save_all_modified(C, reports, &num_files, true, false);
- return num_files;
+ return num_saveable_images;
}
bool ED_image_save_all_modified(const bContext *C, ReportList *reports)
{
- /* Save, and ignore any warnings that we already detected in
- * ED_image_save_all_modified_info. */
- return image_save_all_modified(C, reports, NULL, false, true);
+ ED_image_save_all_modified_info(C, reports);
+
+ Main *bmain = CTX_data_main(C);
+ bool ok = true;
+
+ for (Image *ima = bmain->images.first; ima; ima = ima->id.next) {
+ if (image_should_be_saved(ima)) {
+ if (BKE_image_has_packedfile(ima)) {
+ BKE_image_memorypack(ima);
+ }
+ else {
+ if (image_has_valid_path(ima)) {
+ ImageSaveOptions opts;
+ Scene *scene = CTX_data_scene(C);
+ BKE_image_save_options_init(&opts, bmain, scene);
+ if (image_save_options_init(bmain, &opts, ima, NULL, false, false)) {
+ bool saved_successfully = BKE_image_save(reports, bmain, ima, NULL, &opts);
+ ok = ok && saved_successfully;
+ }
+ }
+ }
+ }
+ }
+ return ok;
}
static bool image_save_all_modified_poll(bContext *C)
{
- /* Let operator run if there are any files to saved, or any warnings to
- * report about files that we can't save. */
- int num_files;
- bool ok = image_save_all_modified(C, NULL, &num_files, true, false);
- return (num_files > 0) || !ok;
+ int num_files = ED_image_save_all_modified_info(C, NULL);
+ return num_files > 0;
}
static int image_save_all_modified_exec(bContext *C, wmOperator *op)
{
- /* Save, and show all warnings. */
- image_save_all_modified(C, op->reports, NULL, false, false);
+ ED_image_save_all_modified(C, op->reports);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index bd02a1e13c1..70f986732ad 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -401,6 +401,10 @@ int WM_operator_name_call(struct bContext *C,
const char *opstring,
short context,
struct PointerRNA *properties);
+int WM_operator_name_call_with_properties(struct bContext *C,
+ const char *opstring,
+ short context,
+ struct IDProperty *properties);
int WM_operator_call_py(struct bContext *C,
struct wmOperatorType *ot,
short context,
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 8ad23af446d..6683085e6d3 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1678,6 +1678,17 @@ int WM_operator_name_call(bContext *C, const char *opstring, short context, Poin
return 0;
}
+int WM_operator_name_call_with_properties(struct bContext *C,
+ const char *opstring,
+ short context,
+ struct IDProperty *properties)
+{
+ PointerRNA props_ptr;
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
+ RNA_pointer_create(NULL, ot->srna, properties, &props_ptr);
+ return WM_operator_name_call_ptr(C, ot, context, &props_ptr);
+}
+
/**
* Call an existent menu. The menu can be created in C or Python.
*/
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 329763a17fd..fabdd71fc5c 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -76,6 +76,7 @@
#include "BKE_blender_undo.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_idprop.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
@@ -98,6 +99,7 @@
#include "ED_datafiles.h"
#include "ED_fileselect.h"
+#include "ED_image.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_util.h"
@@ -1922,11 +1924,27 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static void wm_homefile_read_after_dialog_callback(bContext *C, void *user_data)
+{
+ WM_operator_name_call_with_properties(
+ C, "WM_OT_read_homefile", WM_OP_EXEC_DEFAULT, (IDProperty *)user_data);
+}
+
+static void wm_free_operator_properties_callback(void *user_data)
+{
+ IDProperty *properties = (IDProperty *)user_data;
+ IDP_FreeProperty(properties);
+}
+
static int wm_homefile_read_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- wmWindowManager *wm = CTX_wm_manager(C);
- if (U.uiflag & USER_SAVE_PROMPT && !wm->file_saved) {
- return WM_operator_confirm_message(C, op, "Changes in current file will be lost. Continue?");
+ if (U.uiflag & USER_SAVE_PROMPT && wm_file_or_image_is_modified(C)) {
+ GenericCallback *callback = MEM_callocN(sizeof(*callback), __func__);
+ callback->exec = wm_homefile_read_after_dialog_callback;
+ callback->user_data = IDP_CopyProperty(op->properties);
+ callback->free_user_data = wm_free_operator_properties_callback;
+ wm_close_file_dialog(C, callback);
+ return OPERATOR_INTERFACE;
}
else {
return wm_homefile_read_exec(C, op);
@@ -2071,6 +2089,12 @@ enum {
static int wm_open_mainfile_dispatch(bContext *C, wmOperator *op);
+static void wm_open_mainfile_after_dialog_callback(bContext *C, void *user_data)
+{
+ WM_operator_name_call_with_properties(
+ C, "WM_OT_open_mainfile", WM_OP_INVOKE_DEFAULT, (IDProperty *)user_data);
+}
+
static int wm_open_mainfile__discard_changes(bContext *C, wmOperator *op)
{
if (RNA_boolean_get(op->ptr, "display_file_selector")) {
@@ -2080,14 +2104,13 @@ static int wm_open_mainfile__discard_changes(bContext *C, wmOperator *op)
set_next_operator_state(op, OPEN_MAINFILE_STATE_OPEN);
}
- wmWindowManager *wm = CTX_wm_manager(C);
- if (U.uiflag & USER_SAVE_PROMPT && !wm->file_saved) {
- return WM_operator_confirm_message_ex(C,
- op,
- "Warning",
- ICON_INFO,
- "Changes in current file will be lost. Continue?",
- WM_OP_INVOKE_DEFAULT);
+ if (U.uiflag & USER_SAVE_PROMPT && wm_file_or_image_is_modified(C)) {
+ GenericCallback *callback = MEM_callocN(sizeof(*callback), __func__);
+ callback->exec = wm_open_mainfile_after_dialog_callback;
+ callback->user_data = IDP_CopyProperty(op->properties);
+ callback->free_user_data = wm_free_operator_properties_callback;
+ wm_close_file_dialog(C, callback);
+ return OPERATOR_INTERFACE;
}
else {
return wm_open_mainfile_dispatch(C, op);
@@ -2819,4 +2842,234 @@ void wm_test_autorun_warning(bContext *C)
}
}
+/* Close File Dialog
+ *************************************/
+
+static char save_images_when_file_is_closed = true;
+
+static void wm_block_file_close_cancel(bContext *C, void *arg_block, void *UNUSED(arg_data))
+{
+ wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, arg_block);
+}
+
+static void wm_block_file_close_discard(bContext *C, void *arg_block, void *arg_data)
+{
+ GenericCallback *callback = wm_generic_callback_steal((GenericCallback *)arg_data);
+
+ /* Close the popup before executing the callback. Otherwise
+ * the popup might be closed by the callback, which will lead
+ * to a crash. */
+ wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, arg_block);
+
+ callback->exec(C, callback->user_data);
+ wm_generic_callback_free(callback);
+}
+
+static void wm_block_file_close_save(bContext *C, void *arg_block, void *arg_data)
+{
+ GenericCallback *callback = wm_generic_callback_steal((GenericCallback *)arg_data);
+ bool execute_callback = true;
+
+ wmWindow *win = CTX_wm_window(C);
+ UI_popup_block_close(C, win, arg_block);
+
+ if (save_images_when_file_is_closed) {
+ ReportList *reports = CTX_wm_reports(C);
+ if (!ED_image_save_all_modified(C, reports)) {
+ execute_callback = false;
+ }
+ WM_report_banner_show();
+ }
+
+ Main *bmain = CTX_data_main(C);
+ bool file_has_been_saved_before = BKE_main_blendfile_path(bmain)[0] != '\0';
+
+ if (file_has_been_saved_before) {
+ WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_EXEC_DEFAULT, NULL);
+ }
+ else {
+ WM_operator_name_call(C, "WM_OT_save_mainfile", WM_OP_INVOKE_DEFAULT, NULL);
+ execute_callback = false;
+ }
+
+ if (execute_callback) {
+ callback->exec(C, callback->user_data);
+ }
+ wm_generic_callback_free(callback);
+}
+
+static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegion *ar, void *arg1)
+{
+ GenericCallback *post_action = (GenericCallback *)arg1;
+ Main *bmain = CTX_data_main(C);
+
+ uiStyle *style = UI_style_get();
+ uiBlock *block = UI_block_begin(C, ar, "file_close_popup", UI_EMBOSS);
+
+ UI_block_flag_enable(
+ block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT);
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ uiLayout *layout = UI_block_layout(block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ 10,
+ 2,
+ U.widget_unit * 24,
+ U.widget_unit * 6,
+ 0,
+ style);
+
+ bool blend_file_is_saved = BKE_main_blendfile_path(bmain)[0] != '\0';
+ if (blend_file_is_saved) {
+ uiItemL(layout, "This file has unsaved changes.", ICON_NONE);
+ }
+ else {
+ uiItemL(layout, "This file has not been saved yet.", ICON_NONE);
+ }
+
+ ReportList reports;
+ BKE_reports_init(&reports, RPT_STORE);
+ uint modified_images_count = ED_image_save_all_modified_info(C, &reports);
+
+ if (modified_images_count > 0) {
+ char message[64];
+ BLI_snprintf(message,
+ sizeof(message),
+ (modified_images_count == 1) ? "Save %u modified image" :
+ "Save %u modified images",
+ modified_images_count);
+ uiDefButBitC(block,
+ UI_BTYPE_CHECKBOX,
+ 1,
+ 0,
+ message,
+ 0,
+ 0,
+ 0,
+ UI_UNIT_Y,
+ &save_images_when_file_is_closed,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+
+ LISTBASE_FOREACH (Report *, report, &reports.list) {
+ uiItemL(layout, report->message, ICON_ERROR);
+ }
+ }
+
+ BKE_reports_clear(&reports);
+
+ uiItemL(layout, "", ICON_NONE);
+
+ 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,
+ "");
+ UI_but_func_set(but, wm_block_file_close_cancel, block, post_action);
+
+ /* empty space between buttons */
+ col = uiLayoutColumn(split, false);
+ uiItemS(col);
+
+ col = uiLayoutColumn(split, true);
+ but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_CANCEL,
+ IFACE_("Discard Changes"),
+ 0,
+ 0,
+ 50,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but, wm_block_file_close_discard, block, post_action);
+
+ col = uiLayoutColumn(split, true);
+ but = uiDefIconTextBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_CANCEL,
+ IFACE_("Save"),
+ 0,
+ 0,
+ 50,
+ UI_UNIT_Y,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ UI_but_func_set(but, wm_block_file_close_save, block, post_action);
+ UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
+
+ UI_block_bounds_set_centered(block, 10);
+ return block;
+}
+
+static void free_post_file_close_action(void *arg)
+{
+ GenericCallback *action = (GenericCallback *)arg;
+ wm_generic_callback_free(action);
+}
+
+void wm_close_file_dialog(bContext *C, GenericCallback *post_action)
+{
+ UI_popup_block_invoke(
+ C, block_create__close_file_dialog, post_action, free_post_file_close_action);
+}
+
+bool wm_file_or_image_is_modified(const bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ return !wm->file_saved || ED_image_should_save_modified(C);
+}
+
+void wm_generic_callback_free(GenericCallback *callback)
+{
+ if (callback->free_user_data) {
+ callback->free_user_data(callback->user_data);
+ }
+ MEM_freeN(callback);
+}
+
+static void do_nothing(bContext *UNUSED(C), void *UNUSED(user_data))
+{
+}
+
+GenericCallback *wm_generic_callback_steal(GenericCallback *callback)
+{
+ GenericCallback *new_callback = MEM_dupallocN(callback);
+ callback->exec = do_nothing;
+ callback->free_user_data = NULL;
+ callback->user_data = NULL;
+ return new_callback;
+}
+
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 409befd8c47..c7168673f26 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -61,6 +61,7 @@
#include "WM_types.h"
#include "wm.h"
#include "wm_draw.h"
+#include "wm_files.h"
#include "wm_window.h"
#include "wm_event_system.h"
@@ -356,150 +357,9 @@ wmWindow *wm_window_copy_test(bContext *C,
/** \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))
+static void wm_save_file_on_quit_dialog_callback(bContext *C, void *UNUSED(user_data))
{
- wmWindow *win = CTX_wm_window(C);
- UI_popup_block_close(C, win, arg_block);
-}
-
-/** Discard the file changes and quit */
-ATTR_NORETURN
-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);
- /* No need for second confirmation popup. */
- RNA_boolean_set(&props_ptr, "check_existing", false);
- 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))
-{
- Main *bmain = CTX_data_main(C);
-
- 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_NUMSELECT);
- UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
- UI_block_emboss_set(block, UI_EMBOSS);
-
- uiLayout *layout = UI_block_layout(block,
- UI_LAYOUT_VERTICAL,
- UI_LAYOUT_PANEL,
- 10,
- 2,
- U.widget_unit * 24,
- U.widget_unit * 6,
- 0,
- style);
-
- /* Text and some vertical space */
- {
- char *message;
- if (BKE_main_blendfile_path(bmain)[0] == '\0') {
- message = BLI_strdup(IFACE_("This file has not been saved yet. Save before closing?"));
- }
- else {
- const char *basename = BLI_path_basename(BKE_main_blendfile_path(bmain));
- 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_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
-
- UI_block_bounds_set_centered(block, 10);
-
- return block;
+ wm_exit_schedule_delayed(C);
}
/**
@@ -508,16 +368,9 @@ static uiBlock *block_create_confirm_quit(struct bContext *C,
*/
static void wm_confirm_quit(bContext *C)
{
- wmWindow *win = CTX_wm_window(C);
-
- if (GHOST_SupportsNativeDialogs() == 0) {
- if (!UI_popup_block_name_exists(C, "confirm_quit_popup")) {
- UI_popup_block_invoke(C, block_create_confirm_quit, NULL, NULL);
- }
- }
- else if (GHOST_confirmQuit(win->ghostwin)) {
- wm_exit_schedule_delayed(C);
- }
+ GenericCallback *action = MEM_callocN(sizeof(*action), __func__);
+ action->exec = wm_save_file_on_quit_dialog_callback;
+ wm_close_file_dialog(C, action);
}
/**
@@ -529,7 +382,6 @@ static void wm_confirm_quit(bContext *C)
*/
void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
{
- wmWindowManager *wm = CTX_wm_manager(C);
wmWindow *win_ctx = CTX_wm_window(C);
/* The popup will be displayed in the context window which may not be set
@@ -537,7 +389,7 @@ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win)
CTX_wm_window_set(C, win);
if (U.uiflag & USER_SAVE_PROMPT) {
- if (!wm->file_saved && !G.background) {
+ if (wm_file_or_image_is_modified(C) && !G.background) {
wm_confirm_quit(C);
}
else {
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index 24209504a07..8b3f1ead215 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -40,6 +40,17 @@ void wm_homefile_read(struct bContext *C,
bool *r_is_factory_startup);
void wm_file_read_report(bContext *C, struct Main *bmain);
+typedef struct GenericCallback {
+ void (*exec)(bContext *C, void *user_data);
+ void *user_data;
+ void (*free_user_data)(void *user_data);
+} GenericCallback;
+
+GenericCallback *wm_generic_callback_steal(GenericCallback *callback);
+void wm_generic_callback_free(GenericCallback *callback);
+void wm_close_file_dialog(bContext *C, GenericCallback *post_action);
+bool wm_file_or_image_is_modified(const struct bContext *C);
+
void WM_OT_save_homefile(struct wmOperatorType *ot);
void WM_OT_userpref_autoexec_path_add(struct wmOperatorType *ot);
void WM_OT_userpref_autoexec_path_remove(struct wmOperatorType *ot);