Assign control to cost items and UX Workschedules and Costchedules cleanup

This commit is contained in:
bosonprojets
2021-04-22 00:18:22 +00:00
parent 78314b1ec7
commit 8b35a3aadd
12 changed files with 502 additions and 272 deletions
@@ -6,12 +6,16 @@ classes = (
operator.RemoveCostSchedule, operator.RemoveCostSchedule,
operator.EditCostSchedule, operator.EditCostSchedule,
operator.EnableEditingCostSchedule, operator.EnableEditingCostSchedule,
operator.EnableEditingCostItems,
operator.EnableEditingCostItem,
operator.DisableEditingCostSchedule, operator.DisableEditingCostSchedule,
operator.AddCostItem, operator.AddCostItem,
operator.AddSummaryCostItem, operator.AddSummaryCostItem,
operator.ExpandCostItem, operator.ExpandCostItem,
operator.ContractCostItem, operator.ContractCostItem,
operator.RemoveCostItem, operator.RemoveCostItem,
operator.AssignControl,
operator.UnassignControl,
prop.CostItem, prop.CostItem,
prop.BIMCostProperties, prop.BIMCostProperties,
ui.BIM_PT_cost_schedules, ui.BIM_PT_cost_schedules,
@@ -15,6 +15,32 @@ class AddCostSchedule(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class EditCostSchedule(bpy.types.Operator):
bl_idname = "bim.edit_cost_schedule"
bl_label = "Edit Cost Schedule"
def execute(self, context):
props = context.scene.BIMCostProperties
attributes = {}
for attribute in props.cost_schedule_attributes:
if attribute.is_null:
attributes[attribute.name] = None
else:
if attribute.data_type == "string":
attributes[attribute.name] = attribute.string_value
elif attribute.data_type == "enum":
attributes[attribute.name] = attribute.enum_value
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"cost.edit_cost_schedule",
self.file,
**{"cost_schedule": self.file.by_id(props.active_cost_schedule_id), "attributes": attributes},
)
Data.load(IfcStore.get_file())
bpy.ops.bim.disable_editing_cost_schedule()
return {"FINISHED"}
class RemoveCostSchedule(bpy.types.Operator): class RemoveCostSchedule(bpy.types.Operator):
bl_idname = "bim.remove_cost_schedule" bl_idname = "bim.remove_cost_schedule"
bl_label = "Remove Cost Schedule" bl_label = "Remove Cost Schedule"
@@ -38,10 +64,13 @@ class EnableEditingCostSchedule(bpy.types.Operator):
def execute(self, context): def execute(self, context):
self.props = context.scene.BIMCostProperties self.props = context.scene.BIMCostProperties
self.props.active_cost_schedule_id = self.cost_schedule self.props.active_cost_schedule_id = self.cost_schedule
while len(self.props.cost_schedule_attributes) > 0: while len(self.props.cost_schedule_attributes) > 0:
self.props.cost_schedule_attributes.remove(0) self.props.cost_schedule_attributes.remove(0)
self.enable_editing_cost_schedule()
self.props.is_editing = "COST_SCHEDULE"
return {"FINISHED"}
def enable_editing_cost_schedule(self):
data = Data.cost_schedules[self.cost_schedule] data = Data.cost_schedules[self.cost_schedule]
for attribute in IfcStore.get_schema().declaration_by_name("IfcCostSchedule").all_attributes(): for attribute in IfcStore.get_schema().declaration_by_name("IfcCostSchedule").all_attributes():
@@ -62,12 +91,22 @@ class EnableEditingCostSchedule(bpy.types.Operator):
if data[attribute.name()]: if data[attribute.name()]:
new.enum_value = data[attribute.name()] new.enum_value = data[attribute.name()]
class EnableEditingCostItems(bpy.types.Operator):
bl_idname = "bim.enable_editing_cost_items"
bl_label = "Enable Editing Cost Items"
cost_schedule: bpy.props.IntProperty()
def execute(self, context):
self.props = context.scene.BIMCostProperties
self.props.active_cost_schedule_id = self.cost_schedule
while len(self.props.cost_items) > 0: while len(self.props.cost_items) > 0:
self.props.cost_items.remove(0) self.props.cost_items.remove(0)
self.contracted_cost_items = json.loads(self.props.contracted_cost_items) self.contracted_cost_items = json.loads(self.props.contracted_cost_items)
for related_object_id in Data.cost_schedules[self.cost_schedule]["RelatedObjects"]: for related_object_id in Data.cost_schedules[self.cost_schedule]["RelatedObjects"]:
self.create_new_cost_item_li(related_object_id, 0) self.create_new_cost_item_li(related_object_id, 0)
self.props.is_editing = "COST_ITEMS"
return {"FINISHED"} return {"FINISHED"}
def create_new_cost_item_li(self, related_object_id, level_index): def create_new_cost_item_li(self, related_object_id, level_index):
@@ -83,40 +122,15 @@ class EnableEditingCostSchedule(bpy.types.Operator):
for related_object_id in cost_item["RelatedObjects"]: for related_object_id in cost_item["RelatedObjects"]:
self.create_new_cost_item_li(related_object_id, level_index + 1) self.create_new_cost_item_li(related_object_id, level_index + 1)
return {"FINISHED"}
class DisableEditingCostSchedule(bpy.types.Operator): class DisableEditingCostSchedule(bpy.types.Operator):
bl_idname = "bim.disable_editing_cost_schedule" bl_idname = "bim.disable_editing_cost_schedule"
bl_label = "Disable Editing Cost Schedule" bl_label = "Disable Editing Cost Schedule"
def execute(self, context): def execute(self, context):
props = context.scene.BIMCostProperties context.scene.BIMCostProperties.active_cost_schedule_id = 0
props.active_cost_schedule_id = 0
return {"FINISHED"}
class EditCostSchedule(bpy.types.Operator):
bl_idname = "bim.edit_cost_schedule"
bl_label = "Edit Cost Schedule"
def execute(self, context):
props = context.scene.BIMCostProperties
attributes = {}
for attribute in props.cost_schedule_attributes:
if attribute.is_null:
attributes[attribute.name] = None
else:
if attribute.data_type == "string":
attributes[attribute.name] = attribute.string_value
elif attribute.data_type == "enum":
attributes[attribute.name] = attribute.enum_value
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"cost.edit_cost_schedule",
self.file,
**{"cost_schedule": self.file.by_id(props.active_cost_schedule_id), "attributes": attributes}
)
Data.load(IfcStore.get_file())
bpy.ops.bim.disable_editing_cost_schedule()
return {"FINISHED"} return {"FINISHED"}
@@ -130,7 +144,7 @@ class AddSummaryCostItem(bpy.types.Operator):
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
ifcopenshell.api.run("cost.add_cost_item", self.file, **{"cost_schedule": self.file.by_id(self.cost_schedule)}) ifcopenshell.api.run("cost.add_cost_item", self.file, **{"cost_schedule": self.file.by_id(self.cost_schedule)})
Data.load(self.file) Data.load(self.file)
bpy.ops.bim.enable_editing_cost_schedule(cost_schedule=self.cost_schedule) bpy.ops.bim.enable_editing_cost_items(cost_schedule=self.cost_schedule)
return {"FINISHED"} return {"FINISHED"}
@@ -142,10 +156,9 @@ class AddCostItem(bpy.types.Operator):
def execute(self, context): def execute(self, context):
props = context.scene.BIMCostProperties props = context.scene.BIMCostProperties
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
data = {"cost_item": self.file.by_id(self.cost_item)} ifcopenshell.api.run("cost.add_cost_item", self.file, **{"cost_item": self.file.by_id(self.cost_item)})
ifcopenshell.api.run("cost.add_cost_item", self.file, **data)
Data.load(self.file) Data.load(self.file)
bpy.ops.bim.enable_editing_cost_schedule(cost_schedule=props.active_cost_schedule_id) bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id)
return {"FINISHED"} return {"FINISHED"}
@@ -160,7 +173,7 @@ class ExpandCostItem(bpy.types.Operator):
contracted_cost_items = json.loads(props.contracted_cost_items) contracted_cost_items = json.loads(props.contracted_cost_items)
contracted_cost_items.remove(self.cost_item) contracted_cost_items.remove(self.cost_item)
props.contracted_cost_items = json.dumps(contracted_cost_items) props.contracted_cost_items = json.dumps(contracted_cost_items)
bpy.ops.bim.enable_editing_cost_schedule(cost_schedule=props.active_cost_schedule_id) bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id)
return {"FINISHED"} return {"FINISHED"}
@@ -175,7 +188,7 @@ class ContractCostItem(bpy.types.Operator):
contracted_cost_items = json.loads(props.contracted_cost_items) contracted_cost_items = json.loads(props.contracted_cost_items)
contracted_cost_items.append(self.cost_item) contracted_cost_items.append(self.cost_item)
props.contracted_cost_items = json.dumps(contracted_cost_items) props.contracted_cost_items = json.dumps(contracted_cost_items)
bpy.ops.bim.enable_editing_cost_schedule(cost_schedule=props.active_cost_schedule_id) bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id)
return {"FINISHED"} return {"FINISHED"}
@@ -197,5 +210,124 @@ class RemoveCostItem(bpy.types.Operator):
contracted_cost_items.remove(props.active_cost_item_index) contracted_cost_items.remove(props.active_cost_item_index)
props.contracted_cost_items = json.dumps(contracted_cost_items) props.contracted_cost_items = json.dumps(contracted_cost_items)
Data.load(self.file) Data.load(self.file)
bpy.ops.bim.enable_editing_cost_schedule(cost_schedule=props.active_cost_schedule_id) bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id)
return {"FINISHED"}
class EnableEditingCostItem(bpy.types.Operator):
bl_idname = "bim.enable_editing_cost_item"
bl_label = "Enable Editing Cost Item"
cost_item: bpy.props.IntProperty()
def execute(self, context):
props = context.scene.BIMCostProperties
while len(props.cost_item_attributes) > 0:
props.cost_item_attributes.remove(0)
data = Data.cost_items[self.cost_item]
for attribute in IfcStore.get_schema().declaration_by_name("IfcCostItem").all_attributes():
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
if data_type == "entity":
continue
new = props.cost_item_attributes.add()
new.name = attribute.name()
new.is_null = data[attribute.name()] is None
new.is_optional = attribute.optional()
new.data_type = data_type
if data_type == "string":
new.string_value = "" if new.is_null else data[attribute.name()]
elif data_type == "boolean":
new.bool_value = False if new.is_null else data[attribute.name()]
elif data_type == "integer":
new.int_value = 0 if new.is_null else data[attribute.name()]
elif data_type == "enum":
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
if data[attribute.name()]:
new.enum_value = data[attribute.name()]
props.active_cost_item_id = self.cost_item
return {"FINISHED"}
class DisableEditingCostItem(bpy.types.Operator):
bl_idname = "bim.disable_editing_cost_item"
bl_label = "Disable Editing Cost Item"
def execute(self, context):
context.scene.BIMCostProperties.active_cost_item_id = 0
return {"FINISHED"}
class EditCostItem(bpy.types.Operator):
bl_idname = "bim.edit_cost_item"
bl_label = "Edit Cost Item"
def execute(self, context):
props = context.scene.BIMCostProperties
attributes = {}
for attribute in props.cost_item_attributes:
if attribute.is_null:
attributes[attribute.name] = None
else:
if attribute.data_type == "string":
attributes[attribute.name] = attribute.string_value
elif attribute.data_type == "boolean":
attributes[attribute.name] = attribute.bool_value
elif attribute.data_type == "integer":
attributes[attribute.name] = attribute.int_value
elif attribute.data_type == "enum":
attributes[attribute.name] = attribute.enum_value
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"cost.edit_cost_item",
self.file,
**{"cost_item": self.file.by_id(props.active_cost_item_id), "attributes": attributes},
)
Data.load(IfcStore.get_file())
bpy.ops.bim.disable_editing_cost_item()
bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id)
return {"FINISHED"}
class AssignControl(bpy.types.Operator):
bl_idname = "bim.assign_control"
bl_label = "Assign Control"
cost_item: bpy.props.IntProperty()
related_object: bpy.props.StringProperty()
def execute(self, context):
related_objects = (
[bpy.data.objects.get(self.related_object)] if self.related_object else bpy.context.selected_objects
)
for related_object in related_objects:
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"control.assign_control",
self.file,
related_object=self.file.by_id(related_object.BIMObjectProperties.ifc_definition_id),
relating_control=self.file.by_id(self.cost_item),
)
Data.load(self.file)
return {"FINISHED"}
class UnassignControl(bpy.types.Operator):
bl_idname = "bim.unassign_control"
bl_label = "Unassign Control"
cost_item: bpy.props.IntProperty()
related_object: bpy.props.StringProperty()
def execute(self, context):
related_objects = (
[bpy.data.objects.get(self.related_object)] if self.related_object else bpy.context.selected_objects
)
for related_object in related_objects:
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"control.unassign_control",
self.file,
related_object=self.file.by_id(related_object.BIMObjectProperties.ifc_definition_id),
relating_control=self.file.by_id(self.cost_item),
)
Data.load(self.file)
return {"FINISHED"} return {"FINISHED"}
@@ -1,4 +1,7 @@
import bpy import bpy
import ifcopenshell.api
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.cost.data import Data
from blenderbim.bim.prop import StrProperty, Attribute from blenderbim.bim.prop import StrProperty, Attribute
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
from bpy.props import ( from bpy.props import (
@@ -13,8 +16,24 @@ from bpy.props import (
) )
def updateCostItemName(self, context):
if self.name == "Unnamed":
return
self.file = IfcStore.get_file()
props = context.scene.BIMCostProperties
ifcopenshell.api.run(
"cost.edit_cost_item",
self.file,
**{"cost_item": self.file.by_id(self.ifc_definition_id), "attributes": {"Name": self.name}},
)
Data.load(IfcStore.get_file())
if props.active_cost_item_id == self.ifc_definition_id:
attribute = props.cost_item_attributes.get("Name")
attribute.string_value = self.name
class CostItem(PropertyGroup): class CostItem(PropertyGroup):
name: StringProperty(name="Name") name: StringProperty(name="Name", update=updateCostItemName)
ifc_definition_id: IntProperty(name="IFC Definition ID") ifc_definition_id: IntProperty(name="IFC Definition ID")
has_children: BoolProperty(name="Has Children") has_children: BoolProperty(name="Has Children")
is_expanded: BoolProperty(name="Is Expanded") is_expanded: BoolProperty(name="Is Expanded")
@@ -23,7 +42,10 @@ class CostItem(PropertyGroup):
class BIMCostProperties(PropertyGroup): class BIMCostProperties(PropertyGroup):
cost_schedule_attributes: CollectionProperty(name="Cost Schedule Attributes", type=Attribute) cost_schedule_attributes: CollectionProperty(name="Cost Schedule Attributes", type=Attribute)
is_editing: StringProperty(name="Is Editing")
active_cost_schedule_id: IntProperty(name="Active Cost Schedule Id") active_cost_schedule_id: IntProperty(name="Active Cost Schedule Id")
cost_items: CollectionProperty(name="Work Calendar", type=CostItem) cost_items: CollectionProperty(name="Work Calendar", type=CostItem)
active_cost_item_id: IntProperty(name="Active Cost Id")
active_cost_item_index: IntProperty(name="Active Cost Item Index") active_cost_item_index: IntProperty(name="Active Cost Item Index")
cost_item_attributes: CollectionProperty(name="Task Attributes", type=Attribute)
contracted_cost_items: StringProperty(name="Contracted Cost Items", default="[]") contracted_cost_items: StringProperty(name="Contracted Cost Items", default="[]")
+72 -21
View File
@@ -25,22 +25,34 @@ class BIM_PT_cost_schedules(Panel):
row.operator("bim.add_cost_schedule", icon="ADD") row.operator("bim.add_cost_schedule", icon="ADD")
for cost_schedule_id, cost_schedule in Data.cost_schedules.items(): for cost_schedule_id, cost_schedule in Data.cost_schedules.items():
row = self.layout.row(align=True) self.draw_cost_schedule_ui(cost_schedule_id, cost_schedule)
row.label(text=cost_schedule["Name"] or "Unnamed", icon="LINENUMBERS_ON")
if self.props.active_cost_schedule_id and self.props.active_cost_schedule_id == cost_schedule_id: def draw_cost_schedule_ui(self, cost_schedule_id, cost_schedule):
row = self.layout.row(align=True)
row.label(text=cost_schedule["Name"] or "Unnamed", icon="LINENUMBERS_ON")
if self.props.active_cost_schedule_id and self.props.active_cost_schedule_id == cost_schedule_id:
if self.props.is_editing == "COST_SCHEDULE":
row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK") row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_cost_schedule", text="", icon="X") elif self.props.is_editing == "COST_ITEMS":
elif self.props.active_cost_schedule_id: row.operator("bim.add_summary_cost_item", text="", icon="ADD").cost_schedule = cost_schedule_id
row.operator("bim.remove_cost_schedule", text="", icon="X").cost_schedule = cost_schedule_id row.operator("bim.disable_editing_cost_schedule", text="", icon="CANCEL")
else: elif self.props.active_cost_schedule_id:
row.operator("bim.enable_editing_cost_schedule", text="", icon="GREASEPENCIL").cost_schedule = cost_schedule_id row.operator("bim.remove_cost_schedule", text="", icon="X").cost_schedule = cost_schedule_id
row.operator("bim.remove_cost_schedule", text="", icon="X").cost_schedule = cost_schedule_id else:
row.operator("bim.enable_editing_cost_items", text="", icon="OUTLINER").cost_schedule = cost_schedule_id
row.operator(
"bim.enable_editing_cost_schedule", text="", icon="GREASEPENCIL"
).cost_schedule = cost_schedule_id
row.operator("bim.remove_cost_schedule", text="", icon="X").cost_schedule = cost_schedule_id
if self.props.active_cost_schedule_id == cost_schedule_id: if self.props.active_cost_schedule_id == cost_schedule_id:
self.draw_editable_cost_schedule_ui(cost_schedule_id, cost_schedule) if self.props.is_editing == "COST_SCHEDULE":
self.draw_editable_cost_schedule_ui()
elif self.props.is_editing == "COST_ITEMS":
self.draw_editable_cost_item_ui(cost_schedule_id)
def draw_editable_cost_schedule_ui(self, cost_schedule_id, cost_schedule): def draw_editable_cost_schedule_ui(self):
for attribute in self.props.cost_schedule_attributes: for attribute in self.props.cost_schedule_attributes:
row = self.layout.row(align=True) row = self.layout.row(align=True)
if attribute.data_type == "string": if attribute.data_type == "string":
@@ -50,9 +62,10 @@ class BIM_PT_cost_schedules(Panel):
if attribute.is_optional: if attribute.is_optional:
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
row = self.layout.row(align=True) # row = self.layout.row(align=True)
row.label(text="X Summary Cost Items") # row.label(text="X Summary Cost Items")
row.operator("bim.add_summary_cost_item", text="", icon="ADD").cost_schedule = cost_schedule_id
def draw_editable_cost_item_ui(self, cost_schedule_id):
self.layout.template_list( self.layout.template_list(
"BIM_UL_cost_items", "BIM_UL_cost_items",
"", "",
@@ -61,22 +74,60 @@ class BIM_PT_cost_schedules(Panel):
self.props, self.props,
"active_cost_item_index", "active_cost_item_index",
) )
if self.props.active_cost_item_id:
self.draw_editable_cost_item_attributes_ui()
def draw_editable_cost_item_attributes_ui(self):
for attribute in self.props.cost_item_attributes:
row = self.layout.row(align=True)
if attribute.data_type == "string":
row.prop(attribute, "string_value", text=attribute.name)
elif attribute.data_type == "boolean":
row.prop(attribute, "bool_value", text=attribute.name)
elif attribute.data_type == "integer":
row.prop(attribute, "int_value", text=attribute.name)
elif attribute.data_type == "enum":
row.prop(attribute, "enum_value", text=attribute.name)
if attribute.is_optional:
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
class BIM_UL_cost_items(UIList): class BIM_UL_cost_items(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname): def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item: if item:
props = context.scene.BIMCostProperties
row = layout.row(align=True) row = layout.row(align=True)
for i in range(0, item.level_index): for i in range(0, item.level_index):
row.label(text="", icon="BLANK1") row.label(text="", icon="BLANK1")
if item.has_children: if item.has_children:
if item.is_expanded: if item.is_expanded:
row.operator("bim.contract_cost_item", text="", emboss=False, icon="DISCLOSURE_TRI_DOWN").cost_item = item.ifc_definition_id row.operator(
"bim.contract_cost_item", text="", emboss=False, icon="DISCLOSURE_TRI_DOWN"
).cost_item = item.ifc_definition_id
else: else:
row.operator("bim.expand_cost_item", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT").cost_item = item.ifc_definition_id row.operator(
"bim.expand_cost_item", text="", emboss=False, icon="DISCLOSURE_TRI_RIGHT"
).cost_item = item.ifc_definition_id
else: else:
row.label(text="", icon="DOT") row.label(text="", icon="DOT")
row.label(text=item.name) row.prop(item, "name", emboss=False, text="")
row.operator("bim.add_cost_item", text="", icon="ADD").cost_item = item.ifc_definition_id
op = row.operator("bim.remove_cost_item", text="", icon="X") if context.active_object:
op.cost_item = item.ifc_definition_id oprops = context.active_object.BIMObjectProperties
row = layout.row(align=True)
if oprops.ifc_definition_id in Data.cost_items[item.ifc_definition_id]["Controls"]:
op = row.operator("bim.unassign_control", text="", icon="KEYFRAME_HLT", emboss=False)
op.cost_item = item.ifc_definition_id
else:
op = row.operator("bim.assign_control", text="", icon="KEYFRAME", emboss=False)
op.cost_item = item.ifc_definition_id
if props.active_cost_item_id == item.ifc_definition_id:
row.operator("bim.edit_cost_item", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_cost_item", text="", icon="CANCEL")
else:
row.operator(
"bim.enable_editing_cost_item", text="", icon="GREASEPENCIL"
).cost_item = item.ifc_definition_id
row.operator("bim.add_cost_item", text="", icon="ADD").cost_item = item.ifc_definition_id
row.operator("bim.remove_cost_item", text="", icon="X").cost_item = item.ifc_definition_id
@@ -15,7 +15,6 @@ classes = (
operator.EnableEditingWorkSchedule, operator.EnableEditingWorkSchedule,
operator.EnableEditingTasks, operator.EnableEditingTasks,
operator.DisableEditingWorkSchedule, operator.DisableEditingWorkSchedule,
operator.LoadTasks,
operator.DisableTaskEditingUI, operator.DisableTaskEditingUI,
operator.LoadWorkCalendars, operator.LoadWorkCalendars,
operator.DisableWorkCalendarEditingUI, operator.DisableWorkCalendarEditingUI,
@@ -56,11 +55,13 @@ classes = (
ui.BIM_UL_tasks, ui.BIM_UL_tasks,
) )
def register(): def register():
bpy.types.Scene.BIMWorkPlanProperties = bpy.props.PointerProperty(type=prop.BIMWorkPlanProperties) bpy.types.Scene.BIMWorkPlanProperties = bpy.props.PointerProperty(type=prop.BIMWorkPlanProperties)
bpy.types.Scene.BIMWorkScheduleProperties = bpy.props.PointerProperty(type=prop.BIMWorkScheduleProperties) bpy.types.Scene.BIMWorkScheduleProperties = bpy.props.PointerProperty(type=prop.BIMWorkScheduleProperties)
bpy.types.Scene.BIMWorkCalendarProperties = bpy.props.PointerProperty(type=prop.BIMWorkCalendarProperties) bpy.types.Scene.BIMWorkCalendarProperties = bpy.props.PointerProperty(type=prop.BIMWorkCalendarProperties)
def unregister(): def unregister():
del bpy.types.Scene.BIMWorkPlanProperties del bpy.types.Scene.BIMWorkPlanProperties
del bpy.types.Scene.BIMWorkScheduleProperties del bpy.types.Scene.BIMWorkScheduleProperties
@@ -66,7 +66,7 @@ class EditWorkPlan(bpy.types.Operator):
ifcopenshell.api.run( ifcopenshell.api.run(
"sequence.edit_work_plan", "sequence.edit_work_plan",
self.file, self.file,
**{"work_plan": self.file.by_id(props.active_work_plan_id), "attributes": attributes} **{"work_plan": self.file.by_id(props.active_work_plan_id), "attributes": attributes},
) )
Data.load(IfcStore.get_file()) Data.load(IfcStore.get_file())
bpy.ops.bim.load_work_plans() bpy.ops.bim.load_work_plans()
@@ -157,7 +157,7 @@ class EditWorkSchedule(bpy.types.Operator):
ifcopenshell.api.run( ifcopenshell.api.run(
"sequence.edit_work_schedule", "sequence.edit_work_schedule",
self.file, self.file,
**{"work_schedule": self.file.by_id(props.active_work_schedule_id), "attributes": attributes} **{"work_schedule": self.file.by_id(props.active_work_schedule_id), "attributes": attributes},
) )
Data.load(IfcStore.get_file()) Data.load(IfcStore.get_file())
bpy.ops.bim.disable_editing_work_schedule() bpy.ops.bim.disable_editing_work_schedule()
@@ -236,7 +236,7 @@ class EnableEditingTasks(bpy.types.Operator):
new = self.props.tasks.add() new = self.props.tasks.add()
new.ifc_definition_id = related_object_id new.ifc_definition_id = related_object_id
new.name = task["Name"] or "Unnamed" new.name = task["Name"] or "Unnamed"
new.identification = task["Identification"] or "X" new.identification = task["Identification"] or "XXX"
if task["TaskTime"]: if task["TaskTime"]:
task_time = Data.task_times[task["TaskTime"]] task_time = Data.task_times[task["TaskTime"]]
new.start = self.canonicalise_time(task_time["ScheduleStart"]) new.start = self.canonicalise_time(task_time["ScheduleStart"])
@@ -254,6 +254,7 @@ class EnableEditingTasks(bpy.types.Operator):
if new.is_expanded: if new.is_expanded:
for related_object_id in task["RelatedObjects"]: for related_object_id in task["RelatedObjects"]:
self.create_new_task_li(related_object_id, level_index + 1) self.create_new_task_li(related_object_id, level_index + 1)
return {"FINISHED"}
def canonicalise_time(self, time): def canonicalise_time(self, time):
if not time: if not time:
@@ -270,142 +271,6 @@ class DisableEditingWorkSchedule(bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class LoadWorkCalendars(bpy.types.Operator):
bl_idname = "bim.load_work_calendars"
bl_label = "Load Work Calendars"
def execute(self, context):
props = context.scene.BIMWorkCalendarProperties
while len(props.work_calendars) > 0:
props.work_calendars.remove(0)
for ifc_definition_id, work_calendar in Data.work_calendars.items():
new = props.work_calendars.add()
new.ifc_definition_id = ifc_definition_id
new.name = work_calendar["Name"] or "Unnamed"
props.is_editing = True
bpy.ops.bim.disable_editing_work_calendar()
return {"FINISHED"}
class DisableWorkCalendarEditingUI(bpy.types.Operator):
bl_idname = "bim.disable_work_calendar_editing_ui"
bl_label = "Disable WorkCalendar Editing UI"
def execute(self, context):
context.scene.BIMWorkCalendarProperties.is_editing = False
return {"FINISHED"}
class AddWorkCalendar(bpy.types.Operator):
bl_idname = "bim.add_work_calendar"
bl_label = "Add Work Calendar"
def execute(self, context):
ifcopenshell.api.run("sequence.add_work_calendar", IfcStore.get_file())
Data.load(IfcStore.get_file())
bpy.ops.bim.load_work_calendars()
return {"FINISHED"}
class EditWorkCalendar(bpy.types.Operator):
bl_idname = "bim.edit_work_calendar"
bl_label = "Edit Work Calendar"
def execute(self, context):
props = context.scene.BIMWorkCalendarProperties
attributes = {}
for attribute in props.work_calendar_attributes:
if attribute.is_null:
attributes[attribute.name] = None
else:
if attribute.data_type == "string":
attributes[attribute.name] = attribute.string_value
elif attribute.data_type == "enum":
attributes[attribute.name] = attribute.enum_value
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"sequence.edit_work_calendar",
self.file,
**{"work_calendar": self.file.by_id(props.active_work_calendar_id), "attributes": attributes}
)
Data.load(IfcStore.get_file())
bpy.ops.bim.load_work_calendars()
return {"FINISHED"}
class RemoveWorkCalendar(bpy.types.Operator):
bl_idname = "bim.remove_work_calendar"
bl_label = "Remove Work Plan"
work_calendar: bpy.props.IntProperty()
def execute(self, context):
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"sequence.remove_work_calendar", self.file, **{"work_calendar": self.file.by_id(self.work_calendar)}
)
Data.load(self.file)
bpy.ops.bim.load_work_calendars()
return {"FINISHED"}
class EnableEditingWorkCalendar(bpy.types.Operator):
bl_idname = "bim.enable_editing_work_calendar"
bl_label = "Enable Editing Work Plan"
work_calendar: bpy.props.IntProperty()
def execute(self, context):
props = context.scene.BIMWorkCalendarProperties
while len(props.work_calendar_attributes) > 0:
props.work_calendar_attributes.remove(0)
data = Data.work_calendars[self.work_calendar]
for attribute in IfcStore.get_schema().declaration_by_name("IfcWorkCalendar").all_attributes():
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
if data_type == "entity":
continue
new = props.work_calendar_attributes.add()
new.name = attribute.name()
new.is_null = data[attribute.name()] is None
new.is_optional = attribute.optional()
new.data_type = data_type
if data_type == "string":
new.string_value = "" if new.is_null else data[attribute.name()]
elif data_type == "enum":
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
if data[attribute.name()]:
new.enum_value = data[attribute.name()]
props.active_work_calendar_id = self.work_calendar
return {"FINISHED"}
class DisableEditingWorkCalendar(bpy.types.Operator):
bl_idname = "bim.disable_editing_work_calendar"
bl_label = "Disable Editing Work Calendar"
def execute(self, context):
context.scene.BIMWorkCalendarProperties.active_work_calendar_id = 0
return {"FINISHED"}
class LoadTasks(bpy.types.Operator):
bl_idname = "bim.load_tasks"
bl_label = "Load Tasks"
work_schedule: bpy.props.IntProperty()
def execute(self, context):
props = context.scene.BIMWorkScheduleProperties
while len(props.tasks) > 0:
props.tasks.remove(0)
for ifc_definition_id in Data.work_schedules[self.work_schedule]["RelatedObjects"]:
task = Data.tasks[ifc_definition_id]
new = props.tasks.add()
new.ifc_definition_id = ifc_definition_id
new.name = task["Name"] or "Unnamed"
new.identification = task["Identification"]
return {"FINISHED"}
class DisableTaskEditingUI(bpy.types.Operator): class DisableTaskEditingUI(bpy.types.Operator):
bl_idname = "bim.disable_task_editing_ui" bl_idname = "bim.disable_task_editing_ui"
bl_label = "Disable Task Editing UI" bl_label = "Disable Task Editing UI"
@@ -577,7 +442,7 @@ class EditTaskTime(bpy.types.Operator):
ifcopenshell.api.run( ifcopenshell.api.run(
"sequence.edit_task_time", "sequence.edit_task_time",
self.file, self.file,
**{"task_time": self.file.by_id(props.active_task_time_id), "attributes": attributes} **{"task_time": self.file.by_id(props.active_task_time_id), "attributes": attributes},
) )
Data.load(IfcStore.get_file()) Data.load(IfcStore.get_file())
bpy.ops.bim.disable_editing_task_time() bpy.ops.bim.disable_editing_task_time()
@@ -825,3 +690,121 @@ class GenerateGanttChart(bpy.types.Operator):
) )
for task_id in Data.tasks[task_id]["RelatedObjects"]: for task_id in Data.tasks[task_id]["RelatedObjects"]:
self.create_new_task_json(task_id) self.create_new_task_json(task_id)
class LoadWorkCalendars(bpy.types.Operator):
bl_idname = "bim.load_work_calendars"
bl_label = "Load Work Calendars"
def execute(self, context):
props = context.scene.BIMWorkCalendarProperties
while len(props.work_calendars) > 0:
props.work_calendars.remove(0)
for ifc_definition_id, work_calendar in Data.work_calendars.items():
new = props.work_calendars.add()
new.ifc_definition_id = ifc_definition_id
new.name = work_calendar["Name"] or "Unnamed"
props.is_editing = True
bpy.ops.bim.disable_editing_work_calendar()
return {"FINISHED"}
class DisableWorkCalendarEditingUI(bpy.types.Operator):
bl_idname = "bim.disable_work_calendar_editing_ui"
bl_label = "Disable WorkCalendar Editing UI"
def execute(self, context):
context.scene.BIMWorkCalendarProperties.is_editing = False
return {"FINISHED"}
class AddWorkCalendar(bpy.types.Operator):
bl_idname = "bim.add_work_calendar"
bl_label = "Add Work Calendar"
def execute(self, context):
ifcopenshell.api.run("sequence.add_work_calendar", IfcStore.get_file())
Data.load(IfcStore.get_file())
bpy.ops.bim.load_work_calendars()
return {"FINISHED"}
class EditWorkCalendar(bpy.types.Operator):
bl_idname = "bim.edit_work_calendar"
bl_label = "Edit Work Calendar"
def execute(self, context):
props = context.scene.BIMWorkCalendarProperties
attributes = {}
for attribute in props.work_calendar_attributes:
if attribute.is_null:
attributes[attribute.name] = None
else:
if attribute.data_type == "string":
attributes[attribute.name] = attribute.string_value
elif attribute.data_type == "enum":
attributes[attribute.name] = attribute.enum_value
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"sequence.edit_work_calendar",
self.file,
**{"work_calendar": self.file.by_id(props.active_work_calendar_id), "attributes": attributes},
)
Data.load(IfcStore.get_file())
bpy.ops.bim.load_work_calendars()
return {"FINISHED"}
class RemoveWorkCalendar(bpy.types.Operator):
bl_idname = "bim.remove_work_calendar"
bl_label = "Remove Work Plan"
work_calendar: bpy.props.IntProperty()
def execute(self, context):
self.file = IfcStore.get_file()
ifcopenshell.api.run(
"sequence.remove_work_calendar", self.file, **{"work_calendar": self.file.by_id(self.work_calendar)}
)
Data.load(self.file)
bpy.ops.bim.load_work_calendars()
return {"FINISHED"}
class EnableEditingWorkCalendar(bpy.types.Operator):
bl_idname = "bim.enable_editing_work_calendar"
bl_label = "Enable Editing Work Plan"
work_calendar: bpy.props.IntProperty()
def execute(self, context):
props = context.scene.BIMWorkCalendarProperties
while len(props.work_calendar_attributes) > 0:
props.work_calendar_attributes.remove(0)
data = Data.work_calendars[self.work_calendar]
for attribute in IfcStore.get_schema().declaration_by_name("IfcWorkCalendar").all_attributes():
data_type = ifcopenshell.util.attribute.get_primitive_type(attribute)
if data_type == "entity":
continue
new = props.work_calendar_attributes.add()
new.name = attribute.name()
new.is_null = data[attribute.name()] is None
new.is_optional = attribute.optional()
new.data_type = data_type
if data_type == "string":
new.string_value = "" if new.is_null else data[attribute.name()]
elif data_type == "enum":
new.enum_items = json.dumps(ifcopenshell.util.attribute.get_enum_items(attribute))
if data[attribute.name()]:
new.enum_value = data[attribute.name()]
props.active_work_calendar_id = self.work_calendar
return {"FINISHED"}
class DisableEditingWorkCalendar(bpy.types.Operator):
bl_idname = "bim.disable_editing_work_calendar"
bl_label = "Disable Editing Work Calendar"
def execute(self, context):
context.scene.BIMWorkCalendarProperties.active_work_calendar_id = 0
return {"FINISHED"}
@@ -25,11 +25,11 @@ def updateTaskName(self, context):
ifcopenshell.api.run( ifcopenshell.api.run(
"sequence.edit_task", "sequence.edit_task",
self.file, self.file,
**{"task": self.file.by_id(self.ifc_definition_id), "attributes": {"Name": self.name}} **{"task": self.file.by_id(self.ifc_definition_id), "attributes": {"Name": self.name}},
) )
Data.load(IfcStore.get_file()) Data.load(IfcStore.get_file())
if props.active_task_id == self.ifc_definition_id: if props.active_task_id == self.ifc_definition_id:
attribute = context.scene.BIMWorkScheduleProperties.task_attributes.get("Name") attribute = props.task_attributes.get("Name")
attribute.string_value = self.name attribute.string_value = self.name
@@ -41,7 +41,7 @@ def updateTaskIdentification(self, context):
ifcopenshell.api.run( ifcopenshell.api.run(
"sequence.edit_task", "sequence.edit_task",
self.file, self.file,
**{"task": self.file.by_id(self.ifc_definition_id), "attributes": {"Identification": self.identification}} **{"task": self.file.by_id(self.ifc_definition_id), "attributes": {"Identification": self.identification}},
) )
Data.load(IfcStore.get_file()) Data.load(IfcStore.get_file())
if props.active_task_id == self.ifc_definition_id: if props.active_task_id == self.ifc_definition_id:
@@ -96,7 +96,7 @@ def updateTaskTimeDateTime(self, context, startfinish):
ifcopenshell.api.run( ifcopenshell.api.run(
"sequence.edit_task_time", "sequence.edit_task_time",
self.file, self.file,
**{"task_time": task_time, "attributes": {startfinish_key: startfinish_datetime}} **{"task_time": task_time, "attributes": {startfinish_key: startfinish_datetime}},
) )
Data.load(IfcStore.get_file()) Data.load(IfcStore.get_file())
setattr(self, startfinish, canonicalise_time(startfinish_datetime)) setattr(self, startfinish, canonicalise_time(startfinish_datetime))
@@ -93,7 +93,7 @@ class BIM_PT_work_schedules(Panel):
def draw_work_schedule_ui(self, work_schedule_id, work_schedule): def draw_work_schedule_ui(self, work_schedule_id, work_schedule):
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.label(text=work_schedule["Name"] or "Unnamed", icon="TEXT") row.label(text=work_schedule["Name"] or "Unnamed", icon="LINENUMBERS_ON")
if self.props.active_work_schedule_id and self.props.active_work_schedule_id == work_schedule_id: if self.props.active_work_schedule_id and self.props.active_work_schedule_id == work_schedule_id:
if self.props.is_editing == "WORK_SCHEDULE": if self.props.is_editing == "WORK_SCHEDULE":
@@ -107,8 +107,7 @@ class BIM_PT_work_schedules(Panel):
row.operator("bim.remove_work_schedule", text="", icon="X").work_schedule = work_schedule_id row.operator("bim.remove_work_schedule", text="", icon="X").work_schedule = work_schedule_id
else: else:
row.operator("bim.enable_editing_tasks", text="", icon="ACTION").work_schedule = work_schedule_id row.operator("bim.enable_editing_tasks", text="", icon="ACTION").work_schedule = work_schedule_id
op = row.operator("bim.enable_editing_work_schedule", text="", icon="GREASEPENCIL") row.operator("bim.enable_editing_work_schedule", text="", icon="GREASEPENCIL").work_schedule = work_schedule_id
op.work_schedule = work_schedule_id
row.operator("bim.remove_work_schedule", text="", icon="X").work_schedule = work_schedule_id row.operator("bim.remove_work_schedule", text="", icon="X").work_schedule = work_schedule_id
if self.props.active_work_schedule_id == work_schedule_id: if self.props.active_work_schedule_id == work_schedule_id:
@@ -172,70 +171,6 @@ class BIM_PT_work_schedules(Panel):
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
class BIM_PT_work_calendars(Panel):
bl_label = "IFC Work Calendars"
bl_idname = "BIM_PT_work_calendars"
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(IfcStore.get_file())
self.props = context.scene.BIMWorkCalendarProperties
row = self.layout.row(align=True)
row.label(text="{} Work Calendar Found".format(len(Data.work_calendars)), icon="TEXT")
if self.props.is_editing:
row.operator("bim.add_work_calendar", text="", icon="ADD")
row.operator("bim.disable_work_calendar_editing_ui", text="", icon="CHECKMARK")
else:
row.operator("bim.load_work_calendars", text="", icon="GREASEPENCIL")
if self.props.is_editing:
self.layout.template_list(
"BIM_UL_work_calendars",
"",
self.props,
"work_calendars",
self.props,
"active_work_calendar_index",
)
if self.props.active_work_calendar_id:
self.draw_editable_ui(context)
def draw_editable_ui(self, context):
for attribute in self.props.work_calendar_attributes:
row = self.layout.row(align=True)
if attribute.data_type == "string":
row.prop(attribute, "string_value", text=attribute.name)
elif attribute.data_type == "enum":
row.prop(attribute, "enum_value", text=attribute.name)
if attribute.is_optional:
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
class BIM_UL_work_calendars(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item:
row = layout.row(align=True)
row.label(text=item.name)
if context.scene.BIMWorkCalendarProperties.active_work_calendar_id == item.ifc_definition_id:
row.operator("bim.edit_work_calendar", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_work_calendar", text="", icon="X")
elif context.scene.BIMWorkCalendarProperties.active_work_calendar_id:
row.operator("bim.remove_work_calendar", text="", icon="X").work_calendar = item.ifc_definition_id
else:
op = row.operator("bim.enable_editing_work_calendar", text="", icon="GREASEPENCIL")
op.work_calendar = item.ifc_definition_id
row.operator("bim.remove_work_calendar", text="", icon="X").work_calendar = item.ifc_definition_id
class BIM_UL_tasks(UIList): class BIM_UL_tasks(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname): def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item: if item:
@@ -304,3 +239,67 @@ class BIM_UL_tasks(UIList):
row.operator("bim.enable_editing_task", text="", icon="GREASEPENCIL").task = item.ifc_definition_id row.operator("bim.enable_editing_task", text="", icon="GREASEPENCIL").task = item.ifc_definition_id
row.operator("bim.add_task", text="", icon="ADD").task = item.ifc_definition_id row.operator("bim.add_task", text="", icon="ADD").task = item.ifc_definition_id
row.operator("bim.remove_task", text="", icon="X").task = item.ifc_definition_id row.operator("bim.remove_task", text="", icon="X").task = item.ifc_definition_id
class BIM_PT_work_calendars(Panel):
bl_label = "IFC Work Calendars"
bl_idname = "BIM_PT_work_calendars"
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(IfcStore.get_file())
self.props = context.scene.BIMWorkCalendarProperties
row = self.layout.row(align=True)
row.label(text="{} Work Calendar Found".format(len(Data.work_calendars)), icon="TEXT")
if self.props.is_editing:
row.operator("bim.add_work_calendar", text="", icon="ADD")
row.operator("bim.disable_work_calendar_editing_ui", text="", icon="CHECKMARK")
else:
row.operator("bim.load_work_calendars", text="", icon="GREASEPENCIL")
if self.props.is_editing:
self.layout.template_list(
"BIM_UL_work_calendars",
"",
self.props,
"work_calendars",
self.props,
"active_work_calendar_index",
)
if self.props.active_work_calendar_id:
self.draw_editable_ui(context)
def draw_editable_ui(self, context):
for attribute in self.props.work_calendar_attributes:
row = self.layout.row(align=True)
if attribute.data_type == "string":
row.prop(attribute, "string_value", text=attribute.name)
elif attribute.data_type == "enum":
row.prop(attribute, "enum_value", text=attribute.name)
if attribute.is_optional:
row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="")
class BIM_UL_work_calendars(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item:
row = layout.row(align=True)
row.label(text=item.name)
if context.scene.BIMWorkCalendarProperties.active_work_calendar_id == item.ifc_definition_id:
row.operator("bim.edit_work_calendar", text="", icon="CHECKMARK")
row.operator("bim.disable_editing_work_calendar", text="", icon="X")
elif context.scene.BIMWorkCalendarProperties.active_work_calendar_id:
row.operator("bim.remove_work_calendar", text="", icon="X").work_calendar = item.ifc_definition_id
else:
op = row.operator("bim.enable_editing_work_calendar", text="", icon="GREASEPENCIL")
op.work_calendar = item.ifc_definition_id
row.operator("bim.remove_work_calendar", text="", icon="X").work_calendar = item.ifc_definition_id
@@ -6,8 +6,8 @@ class Usecase:
def __init__(self, file, **settings): def __init__(self, file, **settings):
self.file = file self.file = file
self.settings = { self.settings = {
"related_object": None,
"relating_control": None, "relating_control": None,
"related_object": None,
} }
for key, value in settings.items(): for key, value in settings.items():
self.settings[key] = value self.settings[key] = value
@@ -38,6 +38,6 @@ class Usecase:
"OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file), "OwnerHistory": ifcopenshell.api.run("owner.create_owner_history", self.file),
"RelatedObjects": [self.settings["related_object"]], "RelatedObjects": [self.settings["related_object"]],
"RelatingControl": self.settings["relating_control"], "RelatingControl": self.settings["relating_control"],
} },
) )
return controls return controls
@@ -0,0 +1,25 @@
import ifcopenshell
import ifcopenshell.api
class Usecase:
def __init__(self, file, **settings):
self.file = file
self.settings = {
"relating_control": None,
"related_object": None,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
for rel in self.settings["related_object"].HasAssignments or []:
if not rel.is_a("IfcRelAssignsToControl") or rel.RelatingControl != self.settings["relating_control"]:
continue
if len(rel.RelatedObjects) == 1:
return self.file.remove(rel)
related_objects = list(rel.RelatedObjects)
related_objects.remove(self.settings["related_object"])
rel.RelatedObjects = related_objects
ifcopenshell.api.run("owner.update_owner_history", self.file, **{"element": rel})
return rel
@@ -38,7 +38,10 @@ class Data:
del data["CostValues"] del data["CostValues"]
del data["CostQuantities"] del data["CostQuantities"]
data["RelatedObjects"] = [] data["RelatedObjects"] = []
data["Controls"] = []
for rel in cost_item.IsNestedBy: for rel in cost_item.IsNestedBy:
[data["RelatedObjects"].append(o.id()) for o in rel.RelatedObjects if o.is_a("IfcCostItem")] [data["RelatedObjects"].append(o.id()) for o in rel.RelatedObjects if o.is_a("IfcCostItem")]
for rel in cost_item.Controls:
[data["Controls"].append(o.id()) for o in rel.RelatedObjects or []]
cls.cost_items[cost_item.id()] = data cls.cost_items[cost_item.id()] = data
cls.is_loaded=True cls.is_loaded=True
@@ -0,0 +1,10 @@
class Usecase:
def __init__(self, file, **settings):
self.file = file
self.settings = {"cost_item": 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["cost_item"], name, value)