WIP implement organisation editing. Also new features see commit message. See #1222.

* Organisations are now imported.
 * Organisation identification attribute support is now added, which I missed before
This commit is contained in:
Dion Moult
2021-01-09 11:42:21 +11:00
parent 84de1f1b09
commit 06e1ee7825
11 changed files with 271 additions and 315 deletions
@@ -72,16 +72,6 @@ if bpy is not None:
operator.AssignConstraint,
operator.UnassignConstraint,
operator.RemoveObjectConstraint,
operator.AddPersonRole,
operator.RemovePersonRole,
operator.AddPersonAddress,
operator.RemovePersonAddress,
operator.AddOrganisation,
operator.RemoveOrganisation,
operator.AddOrganisationRole,
operator.RemoveOrganisationRole,
operator.AddOrganisationAddress,
operator.RemoveOrganisationAddress,
operator.AddDocumentInformation,
operator.RemoveDocumentInformation,
operator.AssignDocumentInformation,
@@ -264,7 +254,6 @@ if bpy is not None:
ui.BIM_PT_ifccsv,
ui.BIM_PT_ifcclash,
ui.BIM_PT_owner,
ui.BIM_PT_organisations,
ui.BIM_PT_qa,
ui.BIM_PT_library,
ui.BIM_PT_gis,
@@ -7,6 +7,11 @@ classes = (
operator.AddPerson,
operator.EditPerson,
operator.RemovePerson,
operator.EnableEditingOrganisation,
operator.DisableEditingOrganisation,
operator.AddOrganisation,
operator.EditOrganisation,
operator.RemoveOrganisation,
operator.EnableEditingRole,
operator.DisableEditingRole,
operator.AddRole,
@@ -18,6 +23,7 @@ classes = (
operator.EditAddress,
operator.RemoveAddress,
ui.BIM_PT_people,
ui.BIM_PT_organisations,
)
@@ -0,0 +1,6 @@
class Usecase:
def __init__(self, file):
self.file = file
def execute(self):
self.file.createIfcOrganization("APTR", "Apeture Science")
@@ -4,6 +4,7 @@ from blenderbim.bim.ifc import IfcStore
class Data:
is_loaded = False
people = {}
organisations = {}
addresses = {}
roles = {}
@@ -15,6 +16,8 @@ class Data:
cls.people = {}
for person in file.by_type("IfcPerson"):
data = person.get_info()
data["is_engaged"] = bool(person.EngagedIn)
cls.people[person.id()] = data
roles = []
if data["Roles"]:
@@ -28,9 +31,24 @@ class Data:
addresses.append(address.id())
data["Addresses"] = addresses
data["is_engaged"] = bool(person.EngagedIn)
for organisation in file.by_type("IfcOrganization"):
data = organisation.get_info()
data["is_engaged"] = (
bool(organisation.IsRelatedBy) or bool(organisation.Relates) or bool(organisation.Engages)
)
cls.organisations[organisation.id()] = data
cls.people[person.id()] = data
roles = []
if data["Roles"]:
for role in data["Roles"]:
roles.append(role.id())
data["Roles"] = roles
addresses = []
if data["Addresses"]:
for address in data["Addresses"]:
addresses.append(address.id())
data["Addresses"] = addresses
for address in file.by_type("IfcAddress"):
cls.addresses[address.id()] = address.get_info()
@@ -0,0 +1,13 @@
class Usecase:
def __init__(self, file, settings=None):
self.file = file
self.settings = {
"organisation": None,
"attributes": {}
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for name, value in self.settings["attributes"].items():
setattr(self.settings["organisation"], name, value)
@@ -3,6 +3,9 @@ import json
import blenderbim.bim.module.owner.add_person as add_person
import blenderbim.bim.module.owner.edit_person as edit_person
import blenderbim.bim.module.owner.remove_person as remove_person
import blenderbim.bim.module.owner.add_organisation as add_organisation
import blenderbim.bim.module.owner.edit_organisation as edit_organisation
import blenderbim.bim.module.owner.remove_organisation as remove_organisation
import blenderbim.bim.module.owner.add_role as add_role
import blenderbim.bim.module.owner.edit_role as edit_role
import blenderbim.bim.module.owner.remove_role as remove_role
@@ -279,3 +282,74 @@ class RemoveAddress(bpy.types.Operator):
remove_address.Usecase(self.file, {"address": self.file.by_id(self.address_id)}).execute()
Data.load()
return {"FINISHED"}
class EnableEditingOrganisation(bpy.types.Operator):
bl_idname = "bim.enable_editing_organisation"
bl_label = "Enable Editing Organisation"
organisation_id: bpy.props.IntProperty()
def execute(self, context):
self.file = IfcStore.get_file()
props = context.scene.BIMProperties
props.active_organisation_id = self.organisation_id
data = Data.organisations[self.organisation_id]
identification = data["Id"] if self.file.schema == "IFC2X3" else data["Identification"]
props.organisation.identification = identification or ""
props.organisation.name = data["Name"]
props.organisation.description = data["Description"] or ""
return {"FINISHED"}
class DisableEditingOrganisation(bpy.types.Operator):
bl_idname = "bim.disable_editing_organisation"
bl_label = "Disable Editing Organisation"
def execute(self, context):
context.scene.BIMProperties.active_organisation_id = 0
return {"FINISHED"}
class AddOrganisation(bpy.types.Operator):
bl_idname = "bim.add_organisation"
bl_label = "Add Organisation"
def execute(self, context):
add_organisation.Usecase(IfcStore.get_file()).execute()
Data.load()
return {"FINISHED"}
class EditOrganisation(bpy.types.Operator):
bl_idname = "bim.edit_organisation"
bl_label = "Edit Organisation"
def execute(self, context):
self.file = IfcStore.get_file()
props = context.scene.BIMProperties
attributes = {
"Identification": props.organisation.identification or None,
"Name": props.organisation.name,
"Description": props.organisation.description or None,
}
if self.file.schema == "IFC2X3":
attributes["Id"] = attributes["Identification"]
del attributes["Identification"]
edit_organisation.Usecase(
self.file, {"organisation": self.file.by_id(props.active_organisation_id), "attributes": attributes}
).execute()
Data.load()
bpy.ops.bim.disable_editing_organisation()
return {"FINISHED"}
class RemoveOrganisation(bpy.types.Operator):
bl_idname = "bim.remove_organisation"
bl_label = "Remove Organisation"
organisation_id: bpy.props.IntProperty()
def execute(self, context):
self.file = IfcStore.get_file()
remove_organisation.Usecase(self.file, {"organisation": self.file.by_id(self.organisation_id)}).execute()
Data.load()
return {"FINISHED"}
@@ -0,0 +1,9 @@
class Usecase:
def __init__(self, file, settings=None):
self.file = file
self.settings = {"organisation": None}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
self.file.remove(self.settings["organisation"])
@@ -1,8 +1,97 @@
import bpy
from bpy.types import Panel
from blenderbim.bim.module.owner.data import Data
from blenderbim.bim.ifc import IfcStore
def draw_roles_ui(box, assigned_object_id, roles):
props = bpy.context.scene.BIMProperties
row = box.row(align=True)
row.label(text="Roles")
row.operator("bim.add_role", icon="ADD", text="").assigned_object_id = assigned_object_id
for role_id in roles:
role = Data.roles[role_id]
if props.active_role_id == role_id:
blender_role = props.role
box2 = box.box()
row = box2.row(align=True)
row.prop(blender_role, "name", icon="MOD_CLOTH", text="")
row.operator("bim.edit_role", icon="CHECKMARK", text="")
row.operator("bim.disable_editing_role", icon="X", text="")
if blender_role.name == "USERDEFINED":
row = box2.row()
row.prop(blender_role, "user_defined_role")
row = box2.row()
row.prop(blender_role, "description")
else:
row = box.row(align=True)
row.label(text=role["UserDefinedRole"] or role["Role"])
row.operator("bim.enable_editing_role", icon="GREASEPENCIL", text="").role_id = role_id
row.operator("bim.remove_role", icon="X", text="").role_id = role_id
def draw_addresses_ui(box, assigned_object_id, addresses, file):
props = bpy.context.scene.BIMProperties
row = box.row(align=True)
row.label(text="Addresses")
op = row.operator("bim.add_address", icon="LINK_BLEND", text="")
op.assigned_object_id = assigned_object_id
op.ifc_class = "IfcTelecomAddress"
op = row.operator("bim.add_address", icon="APPEND_BLEND", text="")
op.assigned_object_id = assigned_object_id
op.ifc_class = "IfcPostalAddress"
for address_id in addresses:
address = Data.addresses[address_id]
if props.active_address_id == address_id:
blender_address = props.address
box2 = box.box()
row = box2.row(align=True)
row.prop(blender_address, "purpose", icon="MOD_CLOTH", text="")
row.operator("bim.edit_address", icon="CHECKMARK", text="")
row.operator("bim.disable_editing_address", icon="X", text="")
if blender_address.purpose == "USERDEFINED":
row = box2.row()
row.prop(blender_address, "user_defined_purpose")
row = box2.row()
row.prop(blender_address, "description")
if address["type"] == "IfcTelecomAddress":
row = box2.row()
row.prop(blender_address, "telephone_numbers")
row = box2.row()
row.prop(blender_address, "facsimile_numbers")
row = box2.row()
row.prop(blender_address, "pager_number")
row = box2.row()
row.prop(blender_address, "electronic_mail_addresses")
row = box2.row()
row.prop(blender_address, "www_home_page_url")
if file.schema != "IFC2X3":
row = box2.row()
row.prop(blender_address, "messaging_ids")
elif address["type"] == "IfcPostalAddress":
row = box2.row()
row.prop(blender_address, "internal_location")
row = box2.row()
row.prop(blender_address, "address_lines")
row = box2.row()
row.prop(blender_address, "postal_box")
row = box2.row()
row.prop(blender_address, "town")
row = box2.row()
row.prop(blender_address, "region")
row = box2.row()
row.prop(blender_address, "postal_code")
row = box2.row()
row.prop(blender_address, "country")
else:
row = box.row(align=True)
row.label(text=address["type"])
row.operator("bim.enable_editing_address", icon="GREASEPENCIL", text="").address_id = address_id
row.operator("bim.remove_address", icon="X", text="").address_id = address_id
class BIM_PT_people(Panel):
bl_label = "IFC People"
bl_idname = "BIM_PT_people"
@@ -24,7 +113,7 @@ class BIM_PT_people(Panel):
props = context.scene.BIMProperties
row = self.layout.row()
row.operator("bim.add_person")
row.operator("bim.add_person", icon="ADD")
for person_id, person in Data.people.items():
if props.active_person_id == person_id:
@@ -45,87 +134,8 @@ class BIM_PT_people(Panel):
row = box.row()
row.prop(blender_person, "suffix_titles")
row = box.row(align=True)
row.label(text="Roles")
row.operator("bim.add_role", icon="ADD", text="").assigned_object_id = person_id
for role_id in person["Roles"]:
role = Data.roles[role_id]
if props.active_role_id == role_id:
blender_role = props.role
box2 = box.box()
row = box2.row(align=True)
row.prop(blender_role, "name", icon="MOD_CLOTH", text="")
row.operator("bim.edit_role", icon="CHECKMARK", text="")
row.operator("bim.disable_editing_role", icon="X", text="")
if blender_role.name == "USERDEFINED":
row = box2.row()
row.prop(blender_role, "user_defined_role")
row = box2.row()
row.prop(blender_role, "description")
else:
row = box.row(align=True)
row.label(text=role["UserDefinedRole"] or role["Role"])
row.operator("bim.enable_editing_role", icon="GREASEPENCIL", text="").role_id = role_id
row.operator("bim.remove_role", icon="X", text="").role_id = role_id
row = box.row(align=True)
row.label(text="Addresses")
op = row.operator("bim.add_address", icon="LINK_BLEND", text="")
op.assigned_object_id = person_id
op.ifc_class = "IfcTelecomAddress"
op = row.operator("bim.add_address", icon="APPEND_BLEND", text="")
op.assigned_object_id = person_id
op.ifc_class = "IfcPostalAddress"
for address_id in person["Addresses"]:
address = Data.addresses[address_id]
if props.active_address_id == address_id:
blender_address = props.address
box2 = box.box()
row = box2.row(align=True)
row.prop(blender_address, "purpose", icon="MOD_CLOTH", text="")
row.operator("bim.edit_address", icon="CHECKMARK", text="")
row.operator("bim.disable_editing_address", icon="X", text="")
if blender_address.purpose == "USERDEFINED":
row = box2.row()
row.prop(blender_address, "user_defined_purpose")
row = box2.row()
row.prop(blender_address, "description")
if address["type"] == "IfcTelecomAddress":
row = box2.row()
row.prop(blender_address, "telephone_numbers")
row = box2.row()
row.prop(blender_address, "facsimile_numbers")
row = box2.row()
row.prop(blender_address, "pager_number")
row = box2.row()
row.prop(blender_address, "electronic_mail_addresses")
row = box2.row()
row.prop(blender_address, "www_home_page_url")
if self.file.schema != "IFC2X3":
row = box2.row()
row.prop(blender_address, "messaging_ids")
elif address["type"] == "IfcPostalAddress":
row = box2.row()
row.prop(blender_address, "internal_location")
row = box2.row()
row.prop(blender_address, "address_lines")
row = box2.row()
row.prop(blender_address, "postal_box")
row = box2.row()
row.prop(blender_address, "town")
row = box2.row()
row.prop(blender_address, "region")
row = box2.row()
row.prop(blender_address, "postal_code")
row = box2.row()
row.prop(blender_address, "country")
else:
row = box.row(align=True)
row.label(text=address["type"])
row.operator("bim.enable_editing_address", icon="GREASEPENCIL", text="").address_id = address_id
row.operator("bim.remove_address", icon="X", text="").address_id = address_id
draw_roles_ui(box, person_id, person["Roles"])
draw_addresses_ui(box, person_id, person["Addresses"], self.file)
else:
row = self.layout.row(align=True)
name = person["Id"] if self.file.schema == "IFC2X3" else person["Identification"]
@@ -139,3 +149,51 @@ class BIM_PT_people(Panel):
row.operator("bim.enable_editing_person", icon="GREASEPENCIL", text="").person_id = person_id
if not person["is_engaged"]:
row.operator("bim.remove_person", icon="X", text="").person_id = person_id
class BIM_PT_organisations(Panel):
bl_label = "IFC Organisations"
bl_idname = "BIM_PT_organisations"
bl_options = {"DEFAULT_CLOSED"}
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
@classmethod
def poll(cls, context):
return IfcStore.get_file()
def draw(self, context):
if not Data.is_loaded:
Data.load()
self.file = IfcStore.get_file()
self.layout.use_property_split = True
props = context.scene.BIMProperties
row = self.layout.row()
row.operator("bim.add_organisation", icon="ADD")
for organisation_id, organisation in Data.organisations.items():
if props.active_organisation_id == organisation_id:
blender_organisation = props.organisation
box = self.layout.box()
row = box.row(align=True)
row.prop(blender_organisation, "name", icon="USER", text="")
row.operator("bim.edit_organisation", icon="CHECKMARK", text="")
row.operator("bim.disable_editing_organisation", icon="X", text="")
row = box.row()
row.prop(blender_organisation, "identification")
row = box.row()
row.prop(blender_organisation, "description")
draw_roles_ui(box, organisation_id, organisation["Roles"])
draw_addresses_ui(box, organisation_id, organisation["Addresses"], self.file)
else:
row = self.layout.row(align=True)
row.label(text=organisation["Name"])
if organisation["Roles"]:
row.label(text=", ".join([Data.roles[r]["Role"] for r in organisation["Roles"]]))
row.operator("bim.enable_editing_organisation", icon="GREASEPENCIL", text="").organisation_id = organisation_id
if not organisation["is_engaged"]:
row.operator("bim.remove_organisation", icon="X", text="").organisation_id = organisation_id
@@ -578,118 +578,6 @@ class RemoveObjectConstraint(bpy.types.Operator):
return {"FINISHED"}
class AddPersonAddress(bpy.types.Operator):
bl_idname = "bim.add_person_address"
bl_label = "Add Person Address"
def execute(self, context):
new = bpy.context.scene.BIMProperties.people[
bpy.context.scene.BIMProperties.active_person_index
].addresses.add()
new.name = "IfcPostalAddress"
return {"FINISHED"}
class RemovePersonAddress(bpy.types.Operator):
bl_idname = "bim.remove_person_address"
bl_label = "Remove Person Address"
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.scene.BIMProperties.people[bpy.context.scene.BIMProperties.active_person_index].addresses.remove(
self.index
)
return {"FINISHED"}
class AddPersonRole(bpy.types.Operator):
bl_idname = "bim.add_person_role"
bl_label = "Add Person Role"
def execute(self, context):
new = bpy.context.scene.BIMProperties.people[bpy.context.scene.BIMProperties.active_person_index].roles.add()
return {"FINISHED"}
class RemovePersonRole(bpy.types.Operator):
bl_idname = "bim.remove_person_role"
bl_label = "Remove Person Role"
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.scene.BIMProperties.people[bpy.context.scene.BIMProperties.active_person_index].roles.remove(
self.index
)
return {"FINISHED"}
class AddOrganisation(bpy.types.Operator):
bl_idname = "bim.add_organisation"
bl_label = "Add Organisation"
def execute(self, context):
new = bpy.context.scene.BIMProperties.organisations.add()
new.name = "New Organisation"
return {"FINISHED"}
class RemoveOrganisation(bpy.types.Operator):
bl_idname = "bim.remove_organisation"
bl_label = "Remove Organisation"
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.scene.BIMProperties.organisations.remove(self.index)
return {"FINISHED"}
class AddOrganisationAddress(bpy.types.Operator):
bl_idname = "bim.add_organisation_address"
bl_label = "Add Organisation Address"
def execute(self, context):
new = bpy.context.scene.BIMProperties.organisations[
bpy.context.scene.BIMProperties.active_organisation_index
].addresses.add()
new.name = "IfcPostalAddress"
return {"FINISHED"}
class RemoveOrganisationAddress(bpy.types.Operator):
bl_idname = "bim.remove_organisation_address"
bl_label = "Remove Organisation Address"
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.scene.BIMProperties.organisations[
bpy.context.scene.BIMProperties.active_organisation_index
].addresses.remove(self.index)
return {"FINISHED"}
class AddOrganisationRole(bpy.types.Operator):
bl_idname = "bim.add_organisation_role"
bl_label = "Add Organisation Role"
def execute(self, context):
new = bpy.context.scene.BIMProperties.organisations[
bpy.context.scene.BIMProperties.active_organisation_index
].roles.add()
return {"FINISHED"}
class RemoveOrganisationRole(bpy.types.Operator):
bl_idname = "bim.remove_organisation_role"
bl_label = "Remove Organisation Role"
index: bpy.props.IntProperty()
def execute(self, context):
bpy.context.scene.BIMProperties.organisations[
bpy.context.scene.BIMProperties.active_organisation_index
].roles.remove(self.index)
return {"FINISHED"}
class AddDocumentInformation(bpy.types.Operator):
bl_idname = "bim.add_document_information"
bl_label = "Add Document Information"
+3 -6
View File
@@ -1151,12 +1151,9 @@ class Role(PropertyGroup):
class Organisation(PropertyGroup):
identification: StringProperty(name="Identification")
name: StringProperty(name="Name")
description: StringProperty(name="Description")
roles: CollectionProperty(name="Roles", type=Role)
active_role_index: bpy.props.IntProperty()
addresses: CollectionProperty(name="Addresses", type=Address)
active_address_index: bpy.props.IntProperty()
class Person(PropertyGroup):
@@ -1285,18 +1282,18 @@ class BIMProperties(PropertyGroup):
import_should_offset_model: BoolProperty(name="Import and Offset Model", default=False)
import_model_offset_coordinates: StringProperty(name="Model Offset Coordinates", default="0,0,0")
qa_reject_element_reason: StringProperty(name="Element Rejection Reason")
organisation: EnumProperty(items=getOrganisations, name="Organisation")
people: CollectionProperty(name="People", type=Person)
organisations: CollectionProperty(name="Organisations", type=Organisation)
person: PointerProperty(type=Person)
active_person_id: IntProperty(name="Active Person Id")
organisation: PointerProperty(type=Organisation)
active_organisation_id: IntProperty(name="Active Organisation Id")
role: PointerProperty(type=Role)
active_role_id: IntProperty(name="Active Role Id")
address: PointerProperty(type=Address)
active_address_id: IntProperty(name="Active Address Id")
active_organisation_index: IntProperty(name="Active Organisation Index")
has_georeferencing: BoolProperty(name="Has Georeferencing", default=False)
has_library: BoolProperty(name="Has Project Library", default=False)
search_regex: BoolProperty(name="Search With Regex", default=False)
-102
View File
@@ -1058,108 +1058,6 @@ class BIM_PT_owner(Panel):
row.prop(props, "organisation")
class BIM_PT_organisations(Panel):
bl_label = "IFC Organisations"
bl_idname = "BIM_PT_organisations"
bl_options = {"DEFAULT_CLOSED"}
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
props = context.scene.BIMProperties
row = layout.row()
row.operator("bim.add_organisation")
if props.organisations:
layout.template_list("BIM_UL_generic", "", props, "organisations", props, "active_organisation_index")
if props.active_organisation_index < len(props.organisations):
organisation = props.organisations[props.active_organisation_index]
row = layout.row()
row.prop(organisation, "name")
row.operator("bim.remove_organisation", icon="X", text="").index = props.active_organisation_index
row = layout.row()
row.prop(organisation, "description")
layout.label(text="Roles:")
draw_roles_ui(layout, organisation, "organisation")
layout.label(text="Addresses:")
draw_addresses_ui(layout, organisation, "organisation")
def draw_roles_ui(layout, parent, parent_type):
row = layout.row()
row.operator(f"bim.add_{parent_type}_role")
if parent.roles:
layout.template_list("BIM_UL_generic", "", parent, "roles", parent, "active_role_index")
if parent.active_role_index < len(parent.roles):
role = parent.roles[parent.active_role_index]
row = layout.row()
row.prop(role, "name")
row.operator(f"bim.remove_{parent_type}_role", icon="X", text="").index = parent.active_role_index
if role.name == "USERDEFINED":
row = layout.row()
row.prop(role, "user_defined_role")
row = layout.row()
row.prop(role, "description")
def draw_addresses_ui(layout, parent, parent_type):
row = layout.row()
row.operator(f"bim.add_{parent_type}_address")
if parent.addresses:
layout.template_list("BIM_UL_generic", "", parent, "addresses", parent, "active_address_index")
if parent.active_address_index < len(parent.addresses):
address = parent.addresses[parent.active_address_index]
row = layout.row()
row.prop(address, "name")
row.operator(f"bim.remove_{parent_type}_address", icon="X", text="").index = parent.active_address_index
row = layout.row()
row.prop(address, "purpose")
if address.purpose == "USERDEFINED":
row = layout.row()
row.prop(address, "user_defined_purpose")
row = layout.row()
row.prop(address, "description")
if "IfcPostalAddress" in address.name:
row = layout.row()
row.prop(address, "internal_location")
row = layout.row()
row.prop(address, "address_lines")
row = layout.row()
row.prop(address, "postal_box")
row = layout.row()
row.prop(address, "town")
row = layout.row()
row.prop(address, "region")
row = layout.row()
row.prop(address, "postal_code")
row = layout.row()
row.prop(address, "country")
elif "IfcTelecomAddress" in address.name:
row = layout.row()
row.prop(address, "telephone_numbers")
row = layout.row()
row.prop(address, "fascimile_numbers")
row = layout.row()
row.prop(address, "pager_number")
row = layout.row()
row.prop(address, "electronic_mail_addresses")
row = layout.row()
row.prop(address, "www_home_page_url")
row = layout.row()
row.prop(address, "messaging_ids")
class BIM_PT_bim(Panel):
bl_label = "Building Information Modeling"
bl_idname = "BIM_PT_bim"