diff --git a/src/blenderbim/blenderbim/bim/module/cost/__init__.py b/src/blenderbim/blenderbim/bim/module/cost/__init__.py index 2605c0910c..62142317a1 100644 --- a/src/blenderbim/blenderbim/bim/module/cost/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/cost/__init__.py @@ -1,16 +1,20 @@ import bpy -from . import ui, operator +from . import ui, prop, operator classes = ( operator.AddCostSchedule, operator.RemoveCostSchedule, + operator.EditCostSchedule, + operator.EnableEditingCostSchedule, + operator.DisableEditingCostSchedule, + prop.BIMCostProperties, ui.BIM_PT_cost_schedules, ) def register(): - pass + bpy.types.Scene.BIMCostProperties = bpy.props.PointerProperty(type=prop.BIMCostProperties) def unregister(): - pass + del bpy.types.Scene.BIMCostProperties diff --git a/src/blenderbim/blenderbim/bim/module/cost/operator.py b/src/blenderbim/blenderbim/bim/module/cost/operator.py index ef6997b9ad..35e3a2db21 100644 --- a/src/blenderbim/blenderbim/bim/module/cost/operator.py +++ b/src/blenderbim/blenderbim/bim/module/cost/operator.py @@ -1,4 +1,5 @@ import bpy +import json import ifcopenshell.api from blenderbim.bim.ifc import IfcStore from ifcopenshell.api.cost.data import Data @@ -27,3 +28,73 @@ class RemoveCostSchedule(bpy.types.Operator): ) Data.load(IfcStore.get_file()) return {"FINISHED"} + + +class EnableEditingCostSchedule(bpy.types.Operator): + bl_idname = "bim.enable_editing_cost_schedule" + bl_label = "Enable Editing Cost Schedule" + cost_schedule: bpy.props.IntProperty() + + def execute(self, context): + props = context.scene.BIMCostProperties + props.active_cost_schedule_id = self.cost_schedule + + while len(props.cost_schedule_attributes) > 0: + props.cost_schedule_attributes.remove(0) + + data = Data.cost_schedules[self.cost_schedule] + + for attribute in IfcStore.get_schema().declaration_by_name("IfcCostSchedule").all_attributes(): + data_type = ifcopenshell.util.attribute.get_primitive_type(attribute) + if data_type == "entity": + continue + new = props.cost_schedule_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 attribute.name() in ["SubmittedOn", "UpdateDate"]: + new.string_value = "" if new.is_null else data[attribute.name()].isoformat() + elif 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()] + return {"FINISHED"} + + +class DisableEditingCostSchedule(bpy.types.Operator): + bl_idname = "bim.disable_editing_cost_schedule" + bl_label = "Disable Editing Cost Schedule" + + def execute(self, context): + props = context.scene.BIMCostProperties + 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"} diff --git a/src/blenderbim/blenderbim/bim/module/cost/prop.py b/src/blenderbim/blenderbim/bim/module/cost/prop.py new file mode 100644 index 0000000000..30db28fd2c --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/cost/prop.py @@ -0,0 +1,18 @@ +import bpy +from blenderbim.bim.prop import StrProperty, Attribute +from bpy.types import PropertyGroup +from bpy.props import ( + PointerProperty, + StringProperty, + EnumProperty, + BoolProperty, + IntProperty, + FloatProperty, + FloatVectorProperty, + CollectionProperty, +) + + +class BIMCostProperties(PropertyGroup): + cost_schedule_attributes: CollectionProperty(name="Cost Schedule Attributes", type=Attribute) + active_cost_schedule_id: IntProperty(name="Active Cost Schedule Id") diff --git a/src/blenderbim/blenderbim/bim/module/cost/ui.py b/src/blenderbim/blenderbim/bim/module/cost/ui.py index 43ecd1bf19..d527d6dcb5 100644 --- a/src/blenderbim/blenderbim/bim/module/cost/ui.py +++ b/src/blenderbim/blenderbim/bim/module/cost/ui.py @@ -16,6 +16,8 @@ class BIM_PT_cost_schedules(Panel): return IfcStore.get_file() def draw(self, context): + props = context.scene.BIMCostProperties + if not Data.is_loaded: Data.load(IfcStore.get_file()) @@ -25,5 +27,22 @@ class BIM_PT_cost_schedules(Panel): for cost_schedule_id, cost_schedule in Data.cost_schedules.items(): row = self.layout.row(align=True) row.label(text=cost_schedule["Name"] or "Unnamed", icon="LINENUMBERS_ON") - row.operator("bim.add_cost_schedule", text="", icon="GREASEPENCIL") - row.operator("bim.remove_cost_schedule", text="", icon="X").cost_schedule = cost_schedule_id + + if props.active_cost_schedule_id and props.active_cost_schedule_id == cost_schedule_id: + row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK") + row.operator("bim.disable_editing_cost_schedule", text="", icon="X") + elif props.active_cost_schedule_id: + row.operator("bim.remove_cost_schedule", text="", icon="X").cost_schedule = cost_schedule_id + else: + 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 props.active_cost_schedule_id == cost_schedule_id: + for attribute in props.cost_schedule_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="") diff --git a/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_schedule.py b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_schedule.py new file mode 100644 index 0000000000..efb8650f02 --- /dev/null +++ b/src/ifcopenshell-python/ifcopenshell/api/cost/edit_cost_schedule.py @@ -0,0 +1,10 @@ +class Usecase: + def __init__(self, file, **settings): + self.file = file + self.settings = {"cost_schedule": 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_schedule"], name, value)