7
$\begingroup$

I want to use the EnumProperty the dynamic way. I've got two dialog boxes. In the first one I'm asking for database parameters and in the second one the user has to choose between some options using a dropdown. It works with a static select EnumProperty, but not with a dynamic one.

Here are my two boxes:

class IMPORT_DATABASE(Operator):

    bl_idname = "importgis.database"  # important since its how bpy.ops.import.shapefile is constructed (allows calling operator from python console or another script)
    # bl_idname rules: must contain one '.' (dot) charactere, no capital letters, no reserved words (like 'import')
    bl_description = 'Import data from postgis database'
    bl_label = "Import database"

    host = bpy.props.StringProperty(name="Host:", default="localhost")
    port = bpy.props.StringProperty(name="Port:", default="5432")
    database = bpy.props.StringProperty(name="Database:", default="scans")
    user = bpy.props.StringProperty(name="Username:",default="postgres")
    password = bpy.props.StringProperty(name="Password:",default="postgres")

    def execute(self, context):
        bpy.ops.importgis.database_connection('INVOKE_DEFAULT', password=self.password, username=self.user, database=self.database, port=self.port, host=self.host)
        return {'FINISHED'}

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

And the second dialog box:

class IMPORT_DATABASE_CONNECTION(Operator):
    bl_idname = "importgis.database_connection"  # important since its how bpy.ops.import.shapefile is constructed (allows calling operator from python console or another script)
    # bl_idname rules: must contain one '.' (dot) charactere, no capital letters, no reserved words (like 'import')
    bl_description = 'Geometry'
    bl_label = "Geometry"

    host = StringProperty(options={'HIDDEN'})
    port = StringProperty(options={'HIDDEN'})
    database = StringProperty(options={'HIDDEN'})
    username = StringProperty(options={'HIDDEN'})
    password = StringProperty(options={'HIDDEN'})

    num = EnumProperty(
        items=get_items(),
        name="Geometry",
        description="choose a geometry",
        default=None,
        options={'ANIMATABLE'},
        update=None,
        get=None,
        set=None)



    def get_items(self):
        # condata = "dbname='%s' user='%s' host='%s' password='%s'" % \
        #          (self.database, self.user, self.host, self.password)
        # try:
        #    conn = psycopg2.connect(condata)
        # except:
        #    print ("I am unable to connect to the database")
        # cur = conn.cursor()
        # cur.execute("""SELECT * FROM public.geometry_columns""")
        # rows = cur.fetchall()
        # items = []
        # for row in rows:
        # geomItems = geomItems+row[0]+"//"+row[1]+"//"+row[2]+"#"
        # geomItems = geomItems + row[0] + "#"
        # items.append(row[0],row[1],row[2])

        items = [
            ('NONE', 'None', "Flat geometry"),
            ('GEOM', 'Geometry', "Use z value from shape geometry if exists"),
            ('FIELD', 'Field', "Extract z elevation value from an attribute field"),
            ('OBJ', 'Object', "Get z elevation value from an existing ground mesh")
        ]
        return items

    def execute(self, context):
        message = "Connection"
        self.report({'INFO'}, message)
        return {'FINISHED'}

    def invoke(self, context, event):
        print("Invoke")
        self.pretty_print()
        wm = context.window_manager
        return wm.invoke_props_dialog(self)

Maybe I can't find a way to build the select options in this way. I still get this error:

File "C:\Blender\2.79\scripts\modules\addon_utils.py", line 331, in enable mod = import(module_name) File "C:\Users\R62ad002\AppData\Roaming\Blender Foundation\Blender\2.79\scripts\addons\BlenderGIS-master__init__.py", line 45, in from .operators import * #see operators/init/all File "C:\Users\R62ad002\AppData\Roaming\Blender Foundation\Blender\2.79\scripts\addons\BlenderGIS-master\operators\io_import_database.py", line 74, in class IMPORT_DATABASE_CONNECTION(Operator): File "C:\Users\R62ad002\AppData\Roaming\Blender Foundation\Blender\2.79\scripts\addons\BlenderGIS-master\operators\io_import_database.py", line 86, in IMPORT_DATABASE_CONNECTION num = EnumProperty(items=get_items, name="Geometry") NameError: name 'get_items' is not defined

Can someone help me?

$\endgroup$
5
  • $\begingroup$ Couple of things from quick look. The items callback needs two arguments, get_items(self, context) where self is the object the enum is on (the operator in this case). Should be an error message to explain such. For the commented part if cant connect to server still need to return a list. $\endgroup$
    – batFINGER
    Commented Nov 13, 2018 at 13:34
  • $\begingroup$ I´ve changed the def get_items(self): to def get_items(self, context):, but i still get the same error: NameError: name 'get_items' is not defined $\endgroup$
    – AndyLicht
    Commented Nov 13, 2018 at 14:04
  • $\begingroup$ num = EnumProperty(items=get_items, name="Blah") Pass the method not the return value. for a dynamic property. See docs. $\endgroup$
    – batFINGER
    Commented Nov 13, 2018 at 14:08
  • $\begingroup$ i get the same error by changing to EnumProperty(items=get_items... $\endgroup$
    – AndyLicht
    Commented Nov 13, 2018 at 14:13
  • $\begingroup$ Note that you have to keep a reference to the enum items, otherwise you can get weird behaviour in Blender (even crashes). See the red box here: docs.blender.org/api/current/… $\endgroup$
    – B.Y.O.B.
    Commented Nov 14, 2018 at 19:48

1 Answer 1

13
$\begingroup$

Fixes to question code.

  • define items as a method items=get_items, not what is returned items=get_items() See Documentation

  • The items method requires two arguments self and context

  • Ensure the items method is defined before assigning argment to it Not doing so will result in

    NameError: name 'get_items' is not defined

Code

EDIT Update for 2.8. For prior see revisions

import bpy
from bpy.props import StringProperty, EnumProperty

class ImportDataBaseConnection(bpy.types.Operator):
    bl_idname = "importgis.database_connection" 
    bl_description = 'Import Geometry Data'
    bl_label = "Geometry"

    host : StringProperty(options={'HIDDEN'})
    port : StringProperty(options={'HIDDEN'})
    database : StringProperty(options={'HIDDEN'})
    username : StringProperty(options={'HIDDEN'})
    password : StringProperty(options={'HIDDEN'})

    def item_callback(self, context):
        return (
            ('NONE', 'None', "Flat geometry"),
            ('GEOM', 'Geometry', "Use z value from shape geometry if exists"),
            ('FIELD', 'Field', "Extract z elevation value from an attribute field"),
            ('OBJ', 'Object', "Get z elevation value from an existing ground mesh"),
        )

    geo_type : EnumProperty(
        items=item_callback,
        name="Geometry Type",
        description="choose a geometry",
        default=None,
        options={'ANIMATABLE'},
        update=None,
        get=None,
        set=None)

    def execute(self, context):
        message = "Connection"
        self.report({'INFO'}, message)
        return {'FINISHED'}

    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_props_dialog(self, width=500)


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


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


if __name__ == "__main__":
    register()

    # test call
    bpy.ops.importgis.database_connection('INVOKE_DEFAULT')

Made a minimal working example, run in test editor, pops up dialog with enum items from the update method.

$\endgroup$
1
  • $\begingroup$ Thanks for akk this great help. These examples solve my problems. $\endgroup$
    – AndyLicht
    Commented Nov 15, 2018 at 6:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .