From 00694854afe56e1f285451dd8d9d63a065f8d524 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Wed, 28 Apr 2021 17:59:57 +1000 Subject: [PATCH] UI clean up for work plans and code review for assign schedules to plan --- .../bim/module/sequence/__init__.py | 8 +- .../bim/module/sequence/operator.py | 77 ++++++++++--------- .../blenderbim/bim/module/sequence/prop.py | 22 ++---- .../blenderbim/bim/module/sequence/ui.py | 76 +++++++++--------- .../ifcopenshell/api/sequence/data.py | 3 + .../api/sequence/remove_work_plan.py | 3 + 6 files changed, 93 insertions(+), 96 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/sequence/__init__.py b/src/blenderbim/blenderbim/bim/module/sequence/__init__.py index d311e356f8..8fbc13bdb3 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/__init__.py @@ -2,15 +2,14 @@ import bpy from . import ui, prop, operator classes = ( - operator.LoadWorkPlans, - operator.DisableWorkPlanEditingUI, operator.AddWorkPlan, operator.EditWorkPlan, operator.RemoveWorkPlan, operator.EnableEditingWorkPlan, operator.DisableEditingWorkPlan, - operator.EnableAggregatingWorkSchedule, - operator.AggregateWorkSchedule, + operator.EnableEditingWorkPlanSchedules, + operator.AssignWorkSchedule, + operator.UnassignWorkSchedule, operator.AddWorkSchedule, operator.EditWorkSchedule, operator.RemoveWorkSchedule, @@ -53,7 +52,6 @@ classes = ( prop.WorkCalendar, prop.BIMWorkCalendarProperties, ui.BIM_PT_work_plans, - ui.BIM_UL_work_plans, ui.BIM_PT_work_schedules, ui.BIM_PT_work_calendars, ui.BIM_UL_work_calendars, diff --git a/src/blenderbim/blenderbim/bim/module/sequence/operator.py b/src/blenderbim/blenderbim/bim/module/sequence/operator.py index 57e408bac9..1bfd302b23 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/operator.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/operator.py @@ -12,32 +12,6 @@ from bpy_extras.io_utils import ImportHelper from ifcopenshell.api.sequence.data import Data -class LoadWorkPlans(bpy.types.Operator): - bl_idname = "bim.load_work_plans" - bl_label = "Load Work Plans" - - def execute(self, context): - props = context.scene.BIMWorkPlanProperties - while len(props.work_plans) > 0: - props.work_plans.remove(0) - for ifc_definition_id, work_plan in Data.work_plans.items(): - new = props.work_plans.add() - new.ifc_definition_id = ifc_definition_id - new.name = work_plan["Name"] or "Unnamed" - props.is_editing = True - bpy.ops.bim.disable_editing_work_plan() - return {"FINISHED"} - - -class DisableWorkPlanEditingUI(bpy.types.Operator): - bl_idname = "bim.disable_work_plan_editing_ui" - bl_label = "Disable WorkPlan Editing UI" - - def execute(self, context): - context.scene.BIMWorkPlanProperties.is_editing = False - return {"FINISHED"} - - class AddWorkPlan(bpy.types.Operator): bl_idname = "bim.add_work_plan" bl_label = "Add Work Plan" @@ -45,7 +19,6 @@ class AddWorkPlan(bpy.types.Operator): def execute(self, context): ifcopenshell.api.run("sequence.add_work_plan", IfcStore.get_file()) Data.load(IfcStore.get_file()) - bpy.ops.bim.load_work_plans() return {"FINISHED"} @@ -71,7 +44,6 @@ class EditWorkPlan(bpy.types.Operator): **{"work_plan": self.file.by_id(props.active_work_plan_id), "attributes": attributes}, ) Data.load(IfcStore.get_file()) - bpy.ops.bim.load_work_plans() return {"FINISHED"} @@ -84,7 +56,6 @@ class RemoveWorkPlan(bpy.types.Operator): self.file = IfcStore.get_file() ifcopenshell.api.run("sequence.remove_work_plan", self.file, **{"work_plan": self.file.by_id(self.work_plan)}) Data.load(IfcStore.get_file()) - bpy.ops.bim.load_work_plans() return {"FINISHED"} @@ -118,6 +89,7 @@ class EnableEditingWorkPlan(bpy.types.Operator): if data[attribute.name()]: new.enum_value = data[attribute.name()] props.active_work_plan_id = self.work_plan + props.is_editing = "ATTRIBUTES" return {"FINISHED"} @@ -130,27 +102,57 @@ class DisableEditingWorkPlan(bpy.types.Operator): return {"FINISHED"} -class EnableAggregatingWorkSchedule(bpy.types.Operator): - bl_idname = "bim.enable_aggregating_work_schedules" - bl_label = "Enable Assigning Work Schedules" +class EnableEditingWorkPlanSchedules(bpy.types.Operator): + bl_idname = "bim.enable_editing_work_plan_schedules" + bl_label = "Enable Editing Work Plan Schedules" + work_plan: bpy.props.IntProperty() def execute(self, context): props = context.scene.BIMWorkPlanProperties - props.aggregate_work_schedule = True + props.active_work_plan_id = self.work_plan + props.is_editing = "SCHEDULES" return {"FINISHED"} -class AggregateWorkSchedule(bpy.types.Operator): - bl_idname = "bim.aggregate_work_schedule" - bl_label = "Enable Assigning Work Schedule" + +class AssignWorkSchedule(bpy.types.Operator): + bl_idname = "bim.assign_work_schedule" + bl_label = "Assign Work Schedule" + work_plan: bpy.props.IntProperty() work_schedule: bpy.props.IntProperty() def execute(self, context): + self.file = IfcStore.get_file() ifcopenshell.api.run( "aggregate.assign_object", self.file, - **{"relating_object": self.file.by_id(props.active_work_plan_id), "product": self.file.by_id(self.work_schedule)}, + **{ + "relating_object": self.file.by_id(self.work_plan), + "product": self.file.by_id(self.work_schedule), + }, ) Data.load(IfcStore.get_file()) + return {"FINISHED"} + + +class UnassignWorkSchedule(bpy.types.Operator): + bl_idname = "bim.unassign_work_schedule" + bl_label = "Unassign Work Schedule" + work_plan: bpy.props.IntProperty() + work_schedule: bpy.props.IntProperty() + + def execute(self, context): + self.file = IfcStore.get_file() + ifcopenshell.api.run( + "aggregate.unassign_object", + self.file, + **{ + "relating_object": self.file.by_id(self.work_plan), + "product": self.file.by_id(self.work_schedule), + }, + ) + Data.load(IfcStore.get_file()) + return {"FINISHED"} + class AddWorkSchedule(bpy.types.Operator): bl_idname = "bim.add_work_schedule" @@ -870,6 +872,7 @@ class ImportP6(bpy.types.Operator, ImportHelper): def execute(self, context): from ifcp6.p62ifc import P62Ifc + self.file = IfcStore.get_file() start = time.time() p62ifc = P62Ifc() diff --git a/src/blenderbim/blenderbim/bim/module/sequence/prop.py b/src/blenderbim/blenderbim/bim/module/sequence/prop.py index 4ec71209aa..cd8a589eb7 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/prop.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/prop.py @@ -106,21 +106,13 @@ def updateTaskTimeDateTime(self, context, startfinish): Data.load(IfcStore.get_file()) setattr(self, startfinish, canonicalise_time(startfinish_datetime)) + workschedule_enum = [] + def getWorkSchedules(self, context): - global workschedule_enum - self.file = IfcStore.get_file() - if len(workschedule_enum) == 0 and IfcStore.get_schema(): - workschedule_enum.clear() - workschedule_enum = [("")] - workschedule_enum.extend( - [ - (s.id(), s.Name, "") - for s in self.file.by_type("IfcWorkSchedule") - ] - ) - return workschedule_enum + return [(str(k), v["Name"], "") for k, v in Data.work_schedules.items()] + class Task(PropertyGroup): name: StringProperty(name="Name", update=updateTaskName) @@ -143,12 +135,12 @@ class WorkPlan(PropertyGroup): class BIMWorkPlanProperties(PropertyGroup): work_plan_attributes: CollectionProperty(name="Work Plan Attributes", type=Attribute) - is_editing: BoolProperty(name="Is Editing", default=False) + is_editing: StringProperty(name="Is Editing") work_plans: CollectionProperty(name="Work Plans", type=WorkPlan) active_work_plan_index: IntProperty(name="Active Work Plan Index") active_work_plan_id: IntProperty(name="Active Work Plan Id") - work_schedules: EnumProperty(items=getWorkSchedules, name="Quantity Types") - aggregate_work_schedule: BoolProperty(name="Is Aggregating WorkSchedule", default=False) + work_schedules: EnumProperty(items=getWorkSchedules, name="Work Schedules") + class BIMWorkScheduleProperties(PropertyGroup): work_schedule_attributes: CollectionProperty(name="Work Schedule Attributes", type=Attribute) diff --git a/src/blenderbim/blenderbim/bim/module/sequence/ui.py b/src/blenderbim/blenderbim/bim/module/sequence/ui.py index 1907eee951..c4381f5ba0 100644 --- a/src/blenderbim/blenderbim/bim/module/sequence/ui.py +++ b/src/blenderbim/blenderbim/bim/module/sequence/ui.py @@ -19,30 +19,36 @@ class BIM_PT_work_plans(Panel): if not Data.is_loaded: Data.load(IfcStore.get_file()) self.props = context.scene.BIMWorkPlanProperties + + row = self.layout.row() + row.operator("bim.add_work_plan", icon="ADD") + + for work_plan_id, work_plan in Data.work_plans.items(): + self.draw_work_plan_ui(work_plan_id, work_plan) + + def draw_work_plan_ui(self, work_plan_id, work_plan): row = self.layout.row(align=True) - row.label(text="{} Work Plans Found".format(len(Data.work_plans)), icon="TEXT") - if self.props.is_editing: - - row.operator("bim.add_work_plan", text="", icon="ADD") - row.operator("bim.disable_work_plan_editing_ui", text="", icon="CHECKMARK") + row.label(text=work_plan["Name"] or "Unnamed", icon="TEXT") + if self.props.active_work_plan_id == work_plan_id: + row.operator("bim.edit_work_plan", text="", icon="CHECKMARK") + row.operator("bim.disable_editing_work_plan", text="", icon="CANCEL") + elif self.props.active_work_plan_id: + row.operator("bim.remove_work_plan", text="", icon="X").work_plan = work_plan_id else: - row.operator("bim.load_work_plans", text="", icon="GREASEPENCIL") + op = row.operator("bim.enable_editing_work_plan_schedules", text="", icon="LINENUMBERS_ON") + op.work_plan = work_plan_id + op = row.operator("bim.enable_editing_work_plan", text="", icon="GREASEPENCIL") + op.work_plan = work_plan_id + row.operator("bim.remove_work_plan", text="", icon="X").work_plan = work_plan_id - if self.props.is_editing: - self.layout.template_list( - "BIM_UL_work_plans", - "", - self.props, - "work_plans", - self.props, - "active_work_plan_index", - ) + if self.props.active_work_plan_id == work_plan_id: + if self.props.is_editing == "ATTRIBUTES": + self.draw_editable_ui() + elif self.props.is_editing == "SCHEDULES": + self.draw_work_schedule_ui() - if self.props.active_work_plan_id: - self.draw_editable_ui(context) - - def draw_editable_ui(self, context): + def draw_editable_ui(self): for attribute in self.props.work_plan_attributes: row = self.layout.row(align=True) if attribute.data_type == "string": @@ -51,30 +57,22 @@ class BIM_PT_work_plans(Panel): 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="") - if self.props.aggregate_work_schedule: - self.draw_aggregating_work_schedule_ui() - def draw_aggregating_work_schedule_ui(self): + def draw_work_schedule_ui(self): row = self.layout.row(align=True) row.prop(self.props, "work_schedules", text="") - op = row.operator("bim.aggregate_work_schedule", text="", icon="ADD") - # op.work_schedule = self.props.work_schedules + op = row.operator("bim.assign_work_schedule", text="", icon="ADD") + op.work_plan = self.props.active_work_plan_id + op.work_schedule = int(self.props.work_schedules) + + for work_schedule_id in Data.work_plans[self.props.active_work_plan_id]["IsDecomposedBy"]: + work_schedule = Data.work_schedules[work_schedule_id] + row = self.layout.row(align=True) + row.label(text=work_schedule["Name"] or "Unnamed", icon="LINENUMBERS_ON") + op = row.operator("bim.unassign_work_schedule", text="", icon="X") + op.work_plan = self.props.active_work_plan_id + op.work_schedule = int(self.props.work_schedules) -class BIM_UL_work_plans(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.BIMWorkPlanProperties.active_work_plan_id == item.ifc_definition_id: - row.operator("bim.enable_aggregating_work_schedules", text="", icon="LINENUMBERS_ON") - row.operator("bim.edit_work_plan", text="", icon="CHECKMARK") - row.operator("bim.disable_editing_work_plan", text="", icon="X") - elif context.scene.BIMWorkPlanProperties.active_work_plan_id: - row.operator("bim.remove_work_plan", text="", icon="X").work_plan = item.ifc_definition_id - else: - op = row.operator("bim.enable_editing_work_plan", text="", icon="GREASEPENCIL") - op.work_plan = item.ifc_definition_id - row.operator("bim.remove_work_plan", text="", icon="X").work_plan = item.ifc_definition_id class BIM_PT_work_schedules(Panel): diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py index c193551f23..0333c524b3 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/data.py @@ -41,6 +41,9 @@ class Data: data["StartTime"] = ifcopenshell.util.date.ifc2datetime(data["StartTime"]) if data["FinishTime"]: data["FinishTime"] = ifcopenshell.util.date.ifc2datetime(data["FinishTime"]) + data["IsDecomposedBy"] = [] + for rel in work_plan.IsDecomposedBy: + data["IsDecomposedBy"].extend([o.id() for o in rel.RelatedObjects]) cls.work_plans[work_plan.id()] = data @classmethod diff --git a/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py index ddd36ad88e..d49dccd7da 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py +++ b/src/ifcopenshell-python/ifcopenshell/api/sequence/remove_work_plan.py @@ -1,3 +1,6 @@ +import ifcopenshell + + class Usecase: def __init__(self, file, **settings): self.file = file