7
$\begingroup$

I have a button in my menu named "New File" as shown:

enter image description here

and I want when I click on the "New File" button to imitate what the Blender File->New does, where a check message box appear first confirming that you want to reload the Start-up File and if pressed then the startup file is loaded as shown below.

enter image description here

This is my script, when I press on new it opens the startup file without checking:

class NewFile(bpy.types.Operator):
    """New File"""
    bl_idname = "wm.newfile"  
    bl_label = "New File"
    bl_options = {'REGISTER', 'UNDO'}

    def execute(self, context):
        bpy.ops.wm.read_homefile()
        return {"FINISHED"} 
$\endgroup$
  • $\begingroup$ My Python isn't the greatest, but this seems to work with wm.open_mainfile and wm.read_homefile. I tested with the ui panel template though, I hadn't seen your edit. $\endgroup$ – Timaroberts Feb 9 '17 at 5:54
  • $\begingroup$ @Timaroberts no it doesn't show the checking message $\endgroup$ – Tak Feb 9 '17 at 12:08
  • 1
    $\begingroup$ @poor thank you so much my friend, very detailed and beneficial (Y) :) $\endgroup$ – Tak Feb 13 '17 at 22:51
14
$\begingroup$

When calling an operator via bpy.ops.* without any execution context the execute() method of the respective operator runs by default. If the operator provides any kind of 'user interaction' like a 'confirmation dialog' in this case, then you can pass 'INVOKE_DEFAULT' as execution context when calling the operator which will also run its invoke() method:

bpy.ops.wm.read_homefile('INVOKE_DEFAULT')

enter image description here

In order to display the operator as a button and also 'enable' its user interaction, you have to set the operator_context in the 'layout' before calling the operator:

enter image description here

Blender 2.7x

import bpy

class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_idname = "CUSTOM_my_panel"
    bl_label = "My Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "Tools"

    def draw(self, context):
        layout = self.layout
        layout.operator_context = 'INVOKE_DEFAULT' #'INVOKE_AREA'
        layout.operator("wm.read_homefile", text="New", icon='NEW')

def register():
    bpy.utils.register_class(HelloWorldPanel)

def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)

if __name__ == "__main__":
    register()

Blender 2.8x

class OBJECT_PT_CustomPanel(bpy.types.Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        layout.operator_context = 'INVOKE_DEFAULT' #'INVOKE_AREA'
        layout.operator("wm.read_homefile", text="New", icon='FILE_NEW')

def register():
    bpy.utils.register_class(OBJECT_PT_CustomPanel)

def unregister():
    bpy.utils.unregister_class(OBJECT_PT_CustomPanel)

if __name__ == "__main__":
    register()

Custom Confirm Dialog

For a custom conformation dialog you can wrap the operator into another one and invoke invoke_confirm(operator, event) classmethod of the window-manager to confirm the execution by the user.

enter image description here

Blender 2.7x

import bpy

class SimpleConfirmOperator(bpy.types.Operator):
    """Really?"""
    bl_idname = "my_category.custom_confirm_dialog"
    bl_label = "Do you really want to do that?"
    bl_options = {'REGISTER', 'INTERNAL'}

    @classmethod
    def poll(cls, context):
        return True

    def execute(self, context):
        self.report({'INFO'}, "YES!")
        return {'FINISHED'}

    def invoke(self, context, event):
        return context.window_manager.invoke_confirm(self, event)

class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_idname = "CUSTOM_my_panel"
    bl_label = "My Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "Tools"

    def draw(self, context):
        layout = self.layout
        layout.operator(SimpleConfirmOperator.bl_idname)

def register():
    bpy.utils.register_class(SimpleConfirmOperator)
    bpy.utils.register_class(HelloWorldPanel)

def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)
    bpy.utils.unregister_class(SimpleConfirmOperator)

if __name__ == "__main__":
    register()

Blender 2.8x

import bpy

class SimpleConfirmOperator(bpy.types.Operator):
    """Really?"""
    bl_idname = "my_category.custom_confirm_dialog"
    bl_label = "Do you really want to do that?"
    bl_options = {'REGISTER', 'INTERNAL'}

    @classmethod
    def poll(cls, context):
        return True

    def execute(self, context):
        self.report({'INFO'}, "YES!")
        return {'FINISHED'}

    def invoke(self, context, event):
        return context.window_manager.invoke_confirm(self, event)


class OBJECT_PT_CustomPanel(bpy.types.Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        layout.operator(SimpleConfirmOperator.bl_idname)

def register():
    bpy.utils.register_class(OBJECT_PT_CustomPanel)
    bpy.utils.register_class(SimpleConfirmOperator)

def unregister():
    bpy.utils.unregister_class(SimpleConfirmOperator)
    bpy.utils.unregister_class(OBJECT_PT_CustomPanel)

if __name__ == "__main__":
    register()

Property Confirm

In order to display a popup, some properties and an OK 'button' you can return wm.invoke_props_dialog(self) instead:

enter image description here

Blender 2.7x

import bpy

class SimplePropConfirmOperator(bpy.types.Operator):
    """Really?"""
    bl_idname = "my_category.custom_confirm_dialog"
    bl_label = "Do you really want to do that?"
    bl_options = {'REGISTER', 'INTERNAL'}

    prop1 = bpy.props.BoolProperty()
    prop2 = bpy.props.BoolProperty()

    @classmethod
    def poll(cls, context):
        return True

    def execute(self, context):
        self.report({'INFO'}, "YES!")
        return {'FINISHED'}

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def draw(self, context):
        row = self.layout
        row.prop(self, "prop1", text="Property A")
        row.prop(self, "prop2", text="Property B")


class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_idname = "CUSTOM_my_panel"
    bl_label = "My Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "Tools"

    def draw(self, context):
        layout = self.layout
        layout.operator(SimplePropConfirmOperator.bl_idname)

def register():
    bpy.utils.register_class(SimplePropConfirmOperator)
    bpy.utils.register_class(HelloWorldPanel)

def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)
    bpy.utils.unregister_class(SimplePropConfirmOperator)

if __name__ == "__main__":
    register()

Blender 2.8x

import bpy

class SimplePropConfirmOperator(bpy.types.Operator):
    """Really?"""
    bl_idname = "my_category.custom_confirm_dialog"
    bl_label = "Do you really want to do that?"
    bl_options = {'REGISTER', 'INTERNAL'}

    prop1: bpy.props.BoolProperty()
    prop2: bpy.props.BoolProperty()

    @classmethod
    def poll(cls, context):
        return True

    def execute(self, context):
        self.report({'INFO'}, "YES!")
        return {'FINISHED'}

    def invoke(self, context, event):
        return context.window_manager.invoke_props_dialog(self)

    def draw(self, context):
        row = self.layout
        row.prop(self, "prop1", text="Property A")
        row.prop(self, "prop2", text="Property B")


class OBJECT_PT_CustomPanel(bpy.types.Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"

    def draw(self, context):
        layout = self.layout
        layout.operator(SimplePropConfirmOperator.bl_idname)

def register():
    bpy.utils.register_class(OBJECT_PT_CustomPanel)
    bpy.utils.register_class(SimplePropConfirmOperator)

def unregister():
    bpy.utils.unregister_class(SimplePropConfirmOperator)
    bpy.utils.unregister_class(OBJECT_PT_CustomPanel)

if __name__ == "__main__":
    register()

Note: bl_options of both examples are set to 'INTERNAL' which excludes the operators from search results, remove it if you'd like to run the operator via space bar/F3.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.