UI: show blocking popup when auto execution of scripts is disabled.
This is important information, and it was easily missed at the top/bottom of the screen. Ref T57197.
This commit is contained in:
parent
1e8a2e1a10
commit
c2bcde5c28
Notes:
blender-bot
2023-02-14 10:37:50 +01:00
Referenced by issue #57197, Improvements to Python script autoexecution
|
@ -34,19 +34,6 @@ class STATUSBAR_HT_header(Header):
|
|||
|
||||
# messages
|
||||
layout.template_reports_banner()
|
||||
|
||||
row = layout.row(align=True)
|
||||
if bpy.app.autoexec_fail is True and bpy.app.autoexec_fail_quiet is False:
|
||||
row.label(text="Auto-run disabled", icon='ERROR')
|
||||
if bpy.data.is_saved:
|
||||
props = row.operator("wm.revert_mainfile", icon='SCREEN_BACK', text="Reload Trusted")
|
||||
props.use_scripts = True
|
||||
|
||||
row.operator("script.autoexec_warn_clear", text="Ignore")
|
||||
|
||||
# include last so text doesn't push buttons out of the header
|
||||
row.label(text=bpy.app.autoexec_fail_message)
|
||||
|
||||
layout.template_running_jobs()
|
||||
|
||||
layout.separator_spacer()
|
||||
|
|
|
@ -145,23 +145,3 @@ void SCRIPT_OT_reload(wmOperatorType *ot)
|
|||
/* api callbacks */
|
||||
ot->exec = script_reload_exec;
|
||||
}
|
||||
|
||||
static int script_autoexec_warn_clear_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
|
||||
{
|
||||
G.f |= G_SCRIPT_AUTOEXEC_FAIL_QUIET;
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void SCRIPT_OT_autoexec_warn_clear(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Continue Untrusted";
|
||||
ot->description = "Ignore autoexec warning";
|
||||
ot->idname = "SCRIPT_OT_autoexec_warn_clear";
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = script_autoexec_warn_clear_exec;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,5 @@ void script_keymap(struct wmKeyConfig *keyconf);
|
|||
/* script_edit.c */
|
||||
void SCRIPT_OT_reload(struct wmOperatorType *ot);
|
||||
void SCRIPT_OT_python_file_run(struct wmOperatorType *ot);
|
||||
void SCRIPT_OT_autoexec_warn_clear(struct wmOperatorType *ot);
|
||||
|
||||
#endif /* __SCRIPT_INTERN_H__ */
|
||||
|
|
|
@ -44,7 +44,6 @@ void script_operatortypes(void)
|
|||
{
|
||||
WM_operatortype_append(SCRIPT_OT_python_file_run);
|
||||
WM_operatortype_append(SCRIPT_OT_reload);
|
||||
WM_operatortype_append(SCRIPT_OT_autoexec_warn_clear);
|
||||
}
|
||||
|
||||
void script_keymap(wmKeyConfig *UNUSED(keyconf))
|
||||
|
|
|
@ -316,12 +316,6 @@ static int bpy_app_debug_value_set(PyObject *UNUSED(self), PyObject *value, void
|
|||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *bpy_app_global_flag_get(PyObject *UNUSED(self), void *closure)
|
||||
{
|
||||
const int flag = POINTER_AS_INT(closure);
|
||||
return PyBool_FromLong(G.f & flag);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_app_tempdir_doc,
|
||||
"String, the temp directory used by blender (read-only)"
|
||||
);
|
||||
|
@ -353,12 +347,6 @@ static PyObject *bpy_app_preview_render_size_get(PyObject *UNUSED(self), void *c
|
|||
return PyLong_FromLong((long)UI_preview_render_size(POINTER_AS_INT(closure)));
|
||||
}
|
||||
|
||||
static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void *UNUSED(closure))
|
||||
{
|
||||
return PyC_UnicodeFromByte(G.autoexec_fail);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(bpy_app_use_static_override_doc,
|
||||
"Boolean, whether static override is exposed in UI or not."
|
||||
);
|
||||
|
@ -410,12 +398,6 @@ static PyGetSetDef bpy_app_getsets[] = {
|
|||
|
||||
{(char *)"render_icon_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_ICON},
|
||||
{(char *)"render_preview_size", bpy_app_preview_render_size_get, NULL, (char *)bpy_app_preview_render_size_doc, (void *)ICON_SIZE_PREVIEW},
|
||||
|
||||
/* security */
|
||||
{(char *)"autoexec_fail", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL},
|
||||
{(char *)"autoexec_fail_quiet", bpy_app_global_flag_get, NULL, NULL, (void *)G_SCRIPT_AUTOEXEC_FAIL_QUIET},
|
||||
{(char *)"autoexec_fail_message", bpy_app_autoexec_fail_message_get, NULL, NULL, NULL},
|
||||
{NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static void py_struct_seq_getset_init(void)
|
||||
|
|
|
@ -521,6 +521,9 @@ void wm_event_do_notifiers(bContext *C)
|
|||
WM_window_cursor_keymap_status_refresh(C, win);
|
||||
CTX_wm_window_set(C, NULL);
|
||||
}
|
||||
|
||||
/* Autorun warning */
|
||||
wm_test_autorun_warning(C);
|
||||
}
|
||||
|
||||
static int wm_event_always_pass(const wmEvent *event)
|
||||
|
|
|
@ -2322,3 +2322,110 @@ void WM_OT_save_mainfile(wmOperatorType *ot)
|
|||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name Auto-execution of scripts warning popup
|
||||
*
|
||||
* \{ */
|
||||
|
||||
static void wm_block_autorun_warning_ignore(bContext *C, void *arg_block, void *UNUSED(arg))
|
||||
{
|
||||
wmWindow *win = CTX_wm_window(C);
|
||||
UI_popup_block_close(C, win, arg_block);
|
||||
}
|
||||
|
||||
static void wm_block_autorun_warning_allow(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_revert_mainfile", false);
|
||||
|
||||
WM_operator_properties_create_ptr(&props_ptr, ot);
|
||||
RNA_boolean_set(&props_ptr, "use_scripts", true);
|
||||
WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr);
|
||||
WM_operator_properties_free(&props_ptr);
|
||||
}
|
||||
|
||||
/* Build the autorun warning dialog UI */
|
||||
static uiBlock *block_create_autorun_warning(struct bContext *C, struct ARegion *ar, void *UNUSED(arg1))
|
||||
{
|
||||
uiStyle *style = UI_style_get();
|
||||
uiBlock *block = UI_block_begin(C, ar, "autorun_warning_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 */
|
||||
uiLayout *col = uiLayoutColumn(layout, true);
|
||||
uiItemL(col, IFACE_("For security reasons, automatic execution of Python scripts in this file was disabled:"), ICON_ERROR);
|
||||
uiLayout *sub = uiLayoutRow(col, true);
|
||||
uiLayoutSetRedAlert(sub, true);
|
||||
uiItemL(sub, G.autoexec_fail, ICON_BLANK1);
|
||||
uiItemL(col, IFACE_("This may lead to unexpected behavior."), ICON_BLANK1);
|
||||
|
||||
uiItemS(layout);
|
||||
uiItemS(layout);
|
||||
|
||||
/* Buttons */
|
||||
uiBut *but;
|
||||
uiLayout *split = uiLayoutSplit(layout, 0.0f, true);
|
||||
col = uiLayoutColumn(split, false);
|
||||
|
||||
/* Allow reload if we have a saved file. */
|
||||
if (G.relbase_valid) {
|
||||
but = uiDefIconTextBut(
|
||||
block, UI_BTYPE_BUT, 0, ICON_NONE, IFACE_("Allow Executon"), 0, 0, 50, UI_UNIT_Y,
|
||||
NULL, 0, 0, 0, 0, TIP_("Reload file with execution of Python scripts enabled"));
|
||||
UI_but_func_set(but, wm_block_autorun_warning_allow, block, NULL);
|
||||
}
|
||||
else {
|
||||
uiItemS(col);
|
||||
}
|
||||
|
||||
/* empty space between buttons */
|
||||
col = uiLayoutColumn(split, false);
|
||||
uiItemS(col);
|
||||
|
||||
col = uiLayoutColumn(split, 1);
|
||||
but = uiDefIconTextBut(
|
||||
block, UI_BTYPE_BUT, 0, ICON_NONE, IFACE_("Ignore"), 0, 0, 50, UI_UNIT_Y,
|
||||
NULL, 0, 0, 0, 0, TIP_("Continue using file without Python scripts"));
|
||||
UI_but_func_set(but, wm_block_autorun_warning_ignore, block, NULL);
|
||||
|
||||
UI_block_bounds_set_centered(block, 10);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void wm_test_autorun_warning(bContext *C)
|
||||
{
|
||||
/* Test if any auto-execution of scripts failed. */
|
||||
if ((G.f & G_SCRIPT_AUTOEXEC_FAIL) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only show the warning once. */
|
||||
if (G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET) {
|
||||
return;
|
||||
}
|
||||
|
||||
G.f |= G_SCRIPT_AUTOEXEC_FAIL_QUIET;
|
||||
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmWindow *win = (wm->winactive) ? wm->winactive : wm->windows.first;
|
||||
|
||||
if (win) {
|
||||
wmWindow *prevwin = CTX_wm_window(C);
|
||||
CTX_wm_window_set(C, win);
|
||||
UI_popup_block_invoke(C, block_create_autorun_warning, NULL);
|
||||
CTX_wm_window_set(C, prevwin);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -88,6 +88,8 @@ void wm_quit_with_optional_confirmation_prompt(bContext *C, wmWindow *win) ATTR
|
|||
int wm_window_new_exec(bContext *C, struct wmOperator *op);
|
||||
int wm_window_new_main_exec(bContext *C, struct wmOperator *op);
|
||||
|
||||
void wm_test_autorun_warning(bContext *C);
|
||||
|
||||
/* Initial (unmaximized) size to start with for
|
||||
* systems that can't find it for themselves (X11).
|
||||
* Clamped by real desktop limits */
|
||||
|
|
Loading…
Reference in New Issue