From 693960a4abae2fe505b8e47e5e7bb243ed6f6193 Mon Sep 17 00:00:00 2001 From: Sigma Dimensions <79010126+myoualid@users.noreply.github.com> Date: Wed, 8 Feb 2023 13:39:15 +0100 Subject: [PATCH] start refactoring costing operators into core & tool --- .../blenderbim/bim/module/cost/operator.py | 179 ++++-------------- .../blenderbim/bim/module/cost/ui.py | 11 +- src/blenderbim/blenderbim/core/cost.py | 65 +++++++ src/blenderbim/blenderbim/core/tool.py | 19 ++ src/blenderbim/blenderbim/tool/__init__.py | 1 + src/blenderbim/blenderbim/tool/cost.py | 158 ++++++++++++++++ src/blenderbim/test/bim/feature/cost.feature | 12 +- 7 files changed, 292 insertions(+), 153 deletions(-) create mode 100644 src/blenderbim/blenderbim/core/cost.py create mode 100644 src/blenderbim/blenderbim/tool/cost.py diff --git a/src/blenderbim/blenderbim/bim/module/cost/operator.py b/src/blenderbim/blenderbim/bim/module/cost/operator.py index fe69a2b6d9..a57e2fb6c7 100644 --- a/src/blenderbim/blenderbim/bim/module/cost/operator.py +++ b/src/blenderbim/blenderbim/bim/module/cost/operator.py @@ -25,16 +25,18 @@ import blenderbim.bim.helper import blenderbim.tool as tool from blenderbim.bim.ifc import IfcStore from bpy_extras.io_utils import ImportHelper +import blenderbim.tool as tool +import blenderbim.core.cost as core class AddCostSchedule(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.add_cost_schedule" bl_label = "Add Cost Schedule" bl_options = {"REGISTER", "UNDO"} + bl_description = "Add a new cost schedule" def _execute(self, context): - ifcopenshell.api.run("cost.add_cost_schedule", IfcStore.get_file()) - return {"FINISHED"} + core.add_cost_schedule(tool.Ifc) class EditCostSchedule(bpy.types.Operator, tool.Ifc.Operator): @@ -43,16 +45,11 @@ class EditCostSchedule(bpy.types.Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - props = context.scene.BIMCostProperties - attributes = blenderbim.bim.helper.export_attributes(props.cost_schedule_attributes) - 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}, + core.edit_cost_schedule( + tool.Ifc, + tool.Cost, + cost_schedule=tool.Ifc.get().by_id(context.scene.BIMCostProperties.active_cost_schedule_id), ) - bpy.ops.bim.disable_editing_cost_schedule() - return {"FINISHED"} class RemoveCostSchedule(bpy.types.Operator, tool.Ifc.Operator): @@ -62,39 +59,18 @@ class RemoveCostSchedule(bpy.types.Operator, tool.Ifc.Operator): cost_schedule: bpy.props.IntProperty() def _execute(self, context): - ifcopenshell.api.run( - "cost.remove_cost_schedule", - IfcStore.get_file(), - cost_schedule=IfcStore.get_file().by_id(self.cost_schedule), - ) - return {"FINISHED"} + core.remove_cost_schedule(tool.Ifc, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule)) class EnableEditingCostSchedule(bpy.types.Operator, tool.Ifc.Operator): - bl_idname = "bim.enable_editing_cost_schedule" + bl_idname = "bim.enable_editing_cost_schedule_attributes" bl_label = "Enable Editing Cost Schedule" bl_options = {"REGISTER", "UNDO"} + bl_description = "Enable editing cost schedule" cost_schedule: bpy.props.IntProperty() def _execute(self, context): - self.props = context.scene.BIMCostProperties - self.props.active_cost_schedule_id = self.cost_schedule - self.props.cost_schedule_attributes.clear() - self.enable_editing_cost_schedule() - self.props.is_editing = "COST_SCHEDULE" - return {"FINISHED"} - - def enable_editing_cost_schedule(self): - blenderbim.bim.helper.import_attributes2( - tool.Ifc.get().by_id(self.cost_schedule), - self.props.cost_schedule_attributes, - callback=self.import_attributes, - ) - - def import_attributes(self, name, prop, data): - if name in ["SubmittedOn", "UpdateDate"]: - prop.string_value = "" if prop.is_null else ifcopenshell.util.date.ifc2datetime(data[name]).isoformat() - return True + core.enable_editing_cost_schedule_attributes(tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule)) class EnableEditingCostItems(bpy.types.Operator, tool.Ifc.Operator): @@ -104,50 +80,7 @@ class EnableEditingCostItems(bpy.types.Operator, tool.Ifc.Operator): cost_schedule: bpy.props.IntProperty() def _execute(self, context): - if context.preferences.addons["blenderbim"].preferences.should_play_chaching_sound: - self.play_chaching_sound() # lol - self.props = context.scene.BIMCostProperties - self.props.is_cost_update_enabled = False - self.props.active_cost_schedule_id = self.cost_schedule - self.props.cost_items.clear() - - self.contracted_cost_items = json.loads(self.props.contracted_cost_items) - for rel in tool.Ifc.get().by_id(self.cost_schedule).Controls or []: - for cost_item in rel.RelatedObjects: - self.create_new_cost_item_li(cost_item, 0) - self.props.is_editing = "COST_ITEMS" - self.props.is_cost_update_enabled = True - return {"FINISHED"} - - def play_chaching_sound(self): - # TODO: make pitch higher as costs rise - try: - import aud - - device = aud.Device() - # chaching.mp3 is by Lucish_ CC-BY-3.0 https://freesound.org/people/Lucish_/sounds/554841/ - sound = aud.Sound(os.path.join(context.scene.BIMProperties.data_dir, "chaching.mp3")) - handle = device.play(sound) - sound_buffered = aud.Sound.buffer(sound) - handle_buffered = device.play(sound_buffered) - handle.stop() - handle_buffered.stop() - except: - pass # ah well - - def create_new_cost_item_li(self, cost_item, level_index): - new = self.props.cost_items.add() - new.ifc_definition_id = cost_item.id() - new.name = cost_item.Name or "Unnamed" - new.identification = cost_item.Identification or "XXX" - new.is_expanded = cost_item.id() not in self.contracted_cost_items - new.level_index = level_index - if cost_item.IsNestedBy: - new.has_children = True - if new.is_expanded: - for rel in cost_item.IsNestedBy: - for sub_cost_item in rel.RelatedObjects: - self.create_new_cost_item_li(sub_cost_item, level_index + 1) + core.enable_editing_cost_items(tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule)) class DisableEditingCostSchedule(bpy.types.Operator, tool.Ifc.Operator): @@ -156,68 +89,62 @@ class DisableEditingCostSchedule(bpy.types.Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - context.scene.BIMCostProperties.active_cost_schedule_id = 0 - return {"FINISHED"} + core.disable_editing_cost_schedule(tool.Cost) class AddSummaryCostItem(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.add_summary_cost_item" bl_label = "Add Cost Item" bl_options = {"REGISTER", "UNDO"} + bl_description = "Add a summary cost item" cost_schedule: bpy.props.IntProperty() def _execute(self, context): - props = context.scene.BIMCostProperties - self.file = IfcStore.get_file() - ifcopenshell.api.run("cost.add_cost_item", self.file, **{"cost_schedule": self.file.by_id(self.cost_schedule)}) - bpy.ops.bim.enable_editing_cost_items(cost_schedule=self.cost_schedule) - return {"FINISHED"} + core.add_summary_cost_item(tool.Ifc, tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule)) class AddCostItem(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.add_cost_item" bl_label = "Add Cost Item" bl_options = {"REGISTER", "UNDO"} + bl_description = "Add a new cost item" cost_item: bpy.props.IntProperty() def _execute(self, context): - props = context.scene.BIMCostProperties - self.file = IfcStore.get_file() - ifcopenshell.api.run("cost.add_cost_item", self.file, **{"cost_item": self.file.by_id(self.cost_item)}) - bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id) - return {"FINISHED"} + core.add_cost_item(tool.Ifc, tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item)) class ExpandCostItem(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.expand_cost_item" bl_label = "Expand Cost Item" bl_options = {"REGISTER", "UNDO"} + bl_description = "Expand this cost item" cost_item: bpy.props.IntProperty() def _execute(self, context): - props = context.scene.BIMCostProperties - self.file = IfcStore.get_file() - contracted_cost_items = json.loads(props.contracted_cost_items) - contracted_cost_items.remove(self.cost_item) - props.contracted_cost_items = json.dumps(contracted_cost_items) - bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id) - return {"FINISHED"} + core.expand_cost_item(tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item)) + + +class ExpandCostItems(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.expand_cost_items" + bl_label = "Expand Cost Items" + bl_options = {"REGISTER", "UNDO"} + bl_description = "Expand all cost items" + cost_items: bpy.props.StringProperty() + + def _execute(self, context): + core.expand_cost_items(tool.Cost) class ContractCostItem(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.contract_cost_item" bl_label = "Contract Cost Item" bl_options = {"REGISTER", "UNDO"} + bl_description = "Contract a cost item" cost_item: bpy.props.IntProperty() def _execute(self, context): - props = context.scene.BIMCostProperties - self.file = IfcStore.get_file() - contracted_cost_items = json.loads(props.contracted_cost_items) - contracted_cost_items.append(self.cost_item) - props.contracted_cost_items = json.dumps(contracted_cost_items) - bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id) - return {"FINISHED"} + core.contract_cost_item(tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item)) class RemoveCostItem(bpy.types.Operator, tool.Ifc.Operator): @@ -227,37 +154,17 @@ class RemoveCostItem(bpy.types.Operator, tool.Ifc.Operator): cost_item: bpy.props.IntProperty() def _execute(self, context): - props = context.scene.BIMCostProperties - self.file = IfcStore.get_file() - ifcopenshell.api.run( - "cost.remove_cost_item", - self.file, - cost_item=self.file.by_id(self.cost_item), - ) - contracted_cost_items = json.loads(props.contracted_cost_items) - if props.active_cost_item_index in contracted_cost_items: - contracted_cost_items.remove(props.active_cost_item_index) - props.contracted_cost_items = json.dumps(contracted_cost_items) - bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id) - if props.active_cost_item_id == self.cost_item: - props.active_cost_item_id = 0 - return {"FINISHED"} + core.remove_cost_item(tool.Ifc, tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item)) class EnableEditingCostItem(bpy.types.Operator, tool.Ifc.Operator): - bl_idname = "bim.enable_editing_cost_item" + bl_idname = "bim.enable_editing_cost_item_attributes" bl_label = "Enable Editing Cost Item" bl_options = {"REGISTER", "UNDO"} cost_item: bpy.props.IntProperty() def _execute(self, context): - props = context.scene.BIMCostProperties - props.cost_item_attributes.clear() - - blenderbim.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.cost_item), props.cost_item_attributes) - props.active_cost_item_id = self.cost_item - props.cost_item_editing_type = "ATTRIBUTES" - return {"FINISHED"} + core.enable_editing_cost_item_attributes(tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item)) class DisableEditingCostItem(bpy.types.Operator, tool.Ifc.Operator): @@ -266,8 +173,7 @@ class DisableEditingCostItem(bpy.types.Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - context.scene.BIMCostProperties.active_cost_item_id = 0 - return {"FINISHED"} + core.disable_editing_cost_item(tool.Cost) class EditCostItem(bpy.types.Operator, tool.Ifc.Operator): @@ -276,16 +182,7 @@ class EditCostItem(bpy.types.Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - props = context.scene.BIMCostProperties - attributes = blenderbim.bim.helper.export_attributes(props.cost_item_attributes) - 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}, - ) - bpy.ops.bim.disable_editing_cost_item() - bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id) + core.edit_cost_item(tool.Ifc, tool.Cost) return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/cost/ui.py b/src/blenderbim/blenderbim/bim/module/cost/ui.py index 305edf219c..663b332aec 100644 --- a/src/blenderbim/blenderbim/bim/module/cost/ui.py +++ b/src/blenderbim/blenderbim/bim/module/cost/ui.py @@ -57,7 +57,8 @@ class BIM_PT_cost_schedules(Panel): op = row.operator("bim.select_cost_schedule_products", icon="RESTRICT_SELECT_OFF", text="") op.cost_schedule = cost_schedule["id"] row.prop(self.props, "should_show_column_ui", text="", icon="SHORTDISPLAY") - if self.props.is_editing == "COST_SCHEDULE": + row.operator("bim.export_cost_schedule", text="", icon="EXPORT").cost_schedule = cost_schedule["id"] + if self.props.is_editing == "COST_SCHEDULE_ATTRIBUTES": row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK") elif self.props.is_editing == "COST_ITEMS": row.operator("bim.add_summary_cost_item", text="", icon="ADD").cost_schedule = cost_schedule["id"] @@ -67,12 +68,12 @@ class BIM_PT_cost_schedules(Panel): 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" + "bim.enable_editing_cost_schedule_attributes", 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.is_editing == "COST_SCHEDULE": + if self.props.is_editing == "COST_SCHEDULE_ATTRIBUTES": self.draw_editable_cost_schedule_ui() elif self.props.is_editing == "COST_ITEMS": if self.props.should_show_column_ui: @@ -110,7 +111,7 @@ class BIM_PT_cost_schedules(Panel): row.operator("bim.edit_cost_item", text="", icon="CHECKMARK") row.operator("bim.disable_editing_cost_item", text="", icon="CANCEL") else: - op = row.operator("bim.enable_editing_cost_item", text="", icon="GREASEPENCIL") + op = row.operator("bim.enable_editing_cost_item_attributes", text="", icon="GREASEPENCIL") op.cost_item = ifc_definition_id row.operator("bim.remove_cost_item", text="", icon="X").cost_item = ifc_definition_id @@ -237,9 +238,7 @@ class BIM_PT_cost_item_types(Panel): def draw(self, context): self.props = context.scene.BIMCostProperties - cost_item = self.props.cost_items[self.props.active_cost_item_index] - grid = self.layout.grid_flow(columns=3, even_columns=True) # Column1 diff --git a/src/blenderbim/blenderbim/core/cost.py b/src/blenderbim/blenderbim/core/cost.py new file mode 100644 index 0000000000..77c963c65e --- /dev/null +++ b/src/blenderbim/blenderbim/core/cost.py @@ -0,0 +1,65 @@ +def add_cost_schedule(ifc): + ifc.run("cost.add_cost_schedule") + +def edit_cost_schedule(ifc, cost, cost_schedule): + attributes = cost.get_cost_schedule_attributes() + ifc.run("cost.edit_cost_schedule", cost_schedule=cost_schedule, attributes=attributes) + cost.disable_editing_cost_schedule() + +def disable_editing_cost_schedule(cost): + cost.disable_editing_cost_schedule() + +def remove_cost_schedule(ifc, cost_schedule): + ifc.run("cost.remove_cost_schedule", cost_schedule=cost_schedule) + +def enable_editing_cost_schedule_attributes(cost, cost_schedule): + cost.enable_editing_cost_schedule_attributes(cost_schedule) + cost.load_cost_items() + cost.play_chaching_sound() + +def enable_editing_cost_items(cost, cost_schedule): + cost.enable_editing_cost_items(cost_schedule) + cost.load_cost_items() + +def add_summary_cost_item(ifc, cost, cost_schedule): + ifc.run("cost.add_cost_item", cost_schedule=cost_schedule) + cost.load_cost_items() + +def add_cost_item(ifc, cost, cost_item): + ifc.run("cost.add_cost_item", cost_item=cost_item) + cost.load_cost_items() + # cost.enable_editing_cost_schedule_attributes(cost_schedule) + +def expand_cost_item(cost, cost_item): + cost.expand_cost_item(cost_item) + cost.load_cost_items() + +def expand_cost_items(cost): + cost.expand_cost_items() + cost.load_cost_items() + +def contract_cost_item(cost, cost_item): + cost.contract_cost_item(cost_item) + cost.load_cost_items() + +def contract_cost_items(cost): + cost.contract_cost_items() + cost.load_cost_items() + +def remove_cost_item(ifc, cost, cost_item): + ifc.run("cost.remove_cost_item", cost_item=cost_item) + cost.clean_up_cost_item_tree(cost_item) + cost.load_cost_items() + +def enable_editing_cost_item_attributes(cost, cost_item): + cost.enable_editing_cost_item_attributes(cost_item) + cost.load_cost_item_attributes(cost_item) + +def disable_editing_cost_item(cost): + cost.disable_editing_cost_item() + +def edit_cost_item(ifc, cost): + attributes = cost.get_cost_item_attributes() + ifc.run("cost.edit_cost_item", cost_item=cost.get_active_cost_item(), attributes=attributes) + cost.disable_editing_cost_item() + cost.load_cost_items() \ No newline at end of file diff --git a/src/blenderbim/blenderbim/core/tool.py b/src/blenderbim/blenderbim/core/tool.py index f06b36fc86..247376ed50 100644 --- a/src/blenderbim/blenderbim/core/tool.py +++ b/src/blenderbim/blenderbim/core/tool.py @@ -125,6 +125,25 @@ class Context: def import_attributes(cls): pass def set_context(cls, context): pass +@interface +class Cost: + def clean_up_cost_item_tree(cls, cost_item): pass + def contract_cost_item(cls, cost_item): pass + def contract_cost_items(cls): pass + def create_new_cost_item_li(cls, props, cost_item, level_index): pass + def disable_editing_cost_item(cls): pass + def disable_editing_cost_schedule(cls): pass + def enable_editing_cost_item_attributes(cls, cost_item): pass + def enable_editing_cost_items(cls, cost_schedule): pass + def enable_editing_cost_schedule_attributes(cls, cost_schedule): pass + def expand_cost_item(cls, cost_item): pass + def expand_cost_items(cls): pass + def get_active_cost_item(cls): pass + def get_cost_item_attributes(cls, cost_item): pass + def get_cost_schedule_attributes(cls): pass + def load_cost_items(cls): pass + def load_cost_item_attributes(cls): pass + def play_chaching_sound(cls): pass @interface class Debug: diff --git a/src/blenderbim/blenderbim/tool/__init__.py b/src/blenderbim/blenderbim/tool/__init__.py index c7101dc8ac..915953a095 100644 --- a/src/blenderbim/blenderbim/tool/__init__.py +++ b/src/blenderbim/blenderbim/tool/__init__.py @@ -50,3 +50,4 @@ from blenderbim.tool.surveyor import Surveyor from blenderbim.tool.system import System from blenderbim.tool.type import Type from blenderbim.tool.unit import Unit +from blenderbim.tool.cost import Cost \ No newline at end of file diff --git a/src/blenderbim/blenderbim/tool/cost.py b/src/blenderbim/blenderbim/tool/cost.py new file mode 100644 index 0000000000..9ab08465a0 --- /dev/null +++ b/src/blenderbim/blenderbim/tool/cost.py @@ -0,0 +1,158 @@ +import os +import bpy +import blenderbim.tool as tool +import ifcopenshell.util.date +import blenderbim.bim.helper +import json + + +class Cost(blenderbim.core.tool.Cost): + @classmethod + def get_cost_schedule_attributes(cls): + props = bpy.context.scene.BIMCostProperties + return blenderbim.bim.helper.export_attributes(props.cost_schedule_attributes) + + @classmethod + def disable_editing_cost_schedule(cls): + bpy.context.scene.BIMCostProperties.active_cost_schedule_id = 0 + + @classmethod + def enable_editing_cost_schedule_attributes(cls, cost_schedule): + def special_import(name, prop, data): + if name in ["SubmittedOn", "UpdateDate"]: + prop.string_value = "" if prop.is_null else ifcopenshell.util.date.ifc2datetime(data[name]).isoformat() + return True + + bpy.context.scene.BIMCostProperties.active_cost_schedule_id = cost_schedule.id() + bpy.context.scene.BIMCostProperties.is_editing = "COST_SCHEDULE_ATTRIBUTES" + + @classmethod + def load_cost_schedule_attributes(cls, cost_schedule): + props = bpy.context.scene.BIMCostProperties + props.cost_schedule_attributes.clear() + blenderbim.bim.helper.import_attributes(cost_schedule, props.cost_schedule_attributes) + + @classmethod + def play_chaching_sound(cls): + # TODO: make pitch higher as costs rise + try: + import aud + + device = aud.Device() + # chaching.mp3 is by Lucish_ CC-BY-3.0 https://freesound.org/people/Lucish_/sounds/554841/ + sound = aud.Sound(os.path.join(bpy.context.scene.BIMProperties.data_dir, "chaching.mp3")) + handle = device.play(sound) + sound_buffered = aud.Sound.buffer(sound) + handle_buffered = device.play(sound_buffered) + handle.stop() + handle_buffered.stop() + except: + pass # ah well + + @classmethod + def enable_editing_cost_items(cls, cost_schedule): + props = bpy.context.scene.BIMCostProperties + props.is_cost_update_enabled = False + props.active_cost_schedule_id = cost_schedule.id() + props.is_editing = "COST_ITEMS" + props.is_cost_update_enabled = True + + @classmethod + def play_chaching_sound(cls): + if bpy.context.preferences.addons["blenderbim"].preferences.should_play_chaching_sound: + cls.play_chaching_sound() # lol + + @classmethod + def load_cost_items(cls): + props = bpy.context.scene.BIMCostProperties + cost_schedule = tool.Ifc.get().by_id(props.active_cost_schedule_id) + props.cost_items.clear() + if not hasattr(cls, "contracted_cost_items"): + cls.contracted_cost_items = json.loads(props.contracted_cost_items) + for rel in cost_schedule.Controls or []: + for cost_item in rel.RelatedObjects: + cls.create_new_cost_item_li(props, cost_item, 0) + + @classmethod + def create_new_cost_item_li(cls, props, cost_item, level_index): + new = props.cost_items.add() + new.ifc_definition_id = cost_item.id() + new.name = cost_item.Name or "Unnamed" + new.identification = cost_item.Identification or "XXX" + new.is_expanded = cost_item.id() not in cls.contracted_cost_items + new.level_index = level_index + if cost_item.IsNestedBy: + new.has_children = True + if new.is_expanded: + for rel in cost_item.IsNestedBy: + for sub_cost_item in rel.RelatedObjects: + cls.create_new_cost_item_li(props, sub_cost_item, level_index + 1) + + @classmethod + def expand_cost_item(cls, cost_item): + props = bpy.context.scene.BIMCostProperties + cls.contracted_cost_items = json.loads(props.contracted_cost_items) + cls.contracted_cost_items.remove(cost_item.id()) + props.contracted_cost_items = json.dumps(cls.contracted_cost_items) + + @classmethod + def expand_cost_items(cls): + props = bpy.context.scene.BIMCostProperties + cls.contracted_cost_items = json.loads(props.contracted_cost_items) + for cost_item in props.cost_items: + if cost_item.ifc_definition_id in cls.contracted_cost_items: + cls.contracted_cost_items.remove(cost_item.ifc_definition_id) + props.contracted_cost_items = json.dumps(cls.contracted_cost_items) + + @classmethod + def contract_cost_item(cls, cost_item): + props = bpy.context.scene.BIMCostProperties + cls.contracted_cost_items = json.loads(props.contracted_cost_items) + cls.contracted_cost_items.append(cost_item.id()) + props.contracted_cost_items = json.dumps(cls.contracted_cost_items) + + @classmethod + def contract_cost_items(cls): + props = bpy.context.scene.BIMCostProperties + cls.contracted_cost_items = json.loads(props.contracted_cost_items) + for cost_item in props.cost_items: + if cost_item.ifc_definition_id not in cls.contracted_cost_items: + cls.contracted_cost_items.append(cost_item.ifc_definition_id) + props.contracted_cost_items = json.dumps(cls.contracted_cost_items) + + @classmethod + def clean_up_cost_item_tree(cls, cost_item): + props = bpy.context.scene.BIMCostProperties + cls.contracted_cost_items = json.loads(props.contracted_cost_items) + if props.active_cost_item_index in cls.contracted_cost_items: + cls.contracted_cost_items.remove(props.active_cost_item_index) + props.contracted_cost_items = json.dumps(cls.contracted_cost_items) + bpy.ops.bim.enable_editing_cost_items(cost_schedule=props.active_cost_schedule_id) + if props.active_cost_item_id == cost_item.id(): + props.active_cost_item_id = 0 + + @classmethod + def enable_editing_cost_item_attributes(cls, cost_item): + bpy.context.scene.BIMCostProperties.active_cost_item_id = cost_item.id() + bpy.context.scene.BIMCostProperties.cost_item_editing_type = "ATTRIBUTES" + + @classmethod + def load_cost_item_attributes(cls, cost_item): + props = bpy.context.scene.BIMCostProperties + props.cost_item_attributes.clear() + blenderbim.bim.helper.import_attributes2(cost_item, props.cost_item_attributes) + + @classmethod + def disable_editing_cost_item(cls): + bpy.context.scene.BIMCostProperties.active_cost_item_id = 0 + + @classmethod + def get_cost_item_attributes(cls): + props = bpy.context.scene.BIMCostProperties + return blenderbim.bim.helper.export_attributes(props.cost_item_attributes) + + @classmethod + def get_active_cost_item(cls): + if bpy.context.scene.BIMCostProperties.active_cost_item_id == 0: + return None + return tool.Ifc.get().by_id(bpy.context.scene.BIMCostProperties.active_cost_item_id) \ No newline at end of file diff --git a/src/blenderbim/test/bim/feature/cost.feature b/src/blenderbim/test/bim/feature/cost.feature index 4fc30b1e9a..9e4c778024 100644 --- a/src/blenderbim/test/bim/feature/cost.feature +++ b/src/blenderbim/test/bim/feature/cost.feature @@ -10,14 +10,14 @@ Scenario: Enable editing cost schedule Given an empty IFC project And I press "bim.add_cost_schedule" And the variable "cost_schedule" is "{ifc}.by_type('IfcCostSchedule')[0].id()" - When I press "bim.enable_editing_cost_schedule(cost_schedule={cost_schedule})" + When I press "bim.enable_editing_cost_schedule_attributes(cost_schedule={cost_schedule})" Then nothing happens Scenario: Disable editing cost schedule Given an empty IFC project And I press "bim.add_cost_schedule" And the variable "cost_schedule" is "{ifc}.by_type('IfcCostSchedule')[0].id()" - And I press "bim.enable_editing_cost_schedule(cost_schedule={cost_schedule})" + And I press "bim.enable_editing_cost_schedule_attributes(cost_schedule={cost_schedule})" When I press "bim.disable_editing_cost_schedule" Then nothing happens @@ -25,7 +25,7 @@ Scenario: Edit cost schedule Given an empty IFC project And I press "bim.add_cost_schedule" And the variable "cost_schedule" is "{ifc}.by_type('IfcCostSchedule')[0].id()" - And I press "bim.enable_editing_cost_schedule(cost_schedule={cost_schedule})" + And I press "bim.enable_editing_cost_schedule_attributes(cost_schedule={cost_schedule})" When I press "bim.edit_cost_schedule" Then nothing happens @@ -76,7 +76,7 @@ Scenario: Enable editing cost item And I press "bim.enable_editing_cost_items(cost_schedule={cost_schedule})" And I press "bim.add_summary_cost_item(cost_schedule={cost_schedule})" And the variable "cost_item" is "{ifc}.by_type('IfcCostItem')[0].id()" - When I press "bim.enable_editing_cost_item(cost_item={cost_item})" + When I press "bim.enable_editing_cost_item_attributes(cost_item={cost_item})" Then nothing happens Scenario: Disable editing cost item @@ -86,7 +86,7 @@ Scenario: Disable editing cost item And I press "bim.enable_editing_cost_items(cost_schedule={cost_schedule})" And I press "bim.add_summary_cost_item(cost_schedule={cost_schedule})" And the variable "cost_item" is "{ifc}.by_type('IfcCostItem')[0].id()" - And I press "bim.enable_editing_cost_item(cost_item={cost_item})" + And I press "bim.enable_editing_cost_item_attributes(cost_item={cost_item})" When I press "bim.disable_editing_cost_item" Then nothing happens @@ -97,7 +97,7 @@ Scenario: Edit cost item And I press "bim.enable_editing_cost_items(cost_schedule={cost_schedule})" And I press "bim.add_summary_cost_item(cost_schedule={cost_schedule})" And the variable "cost_item" is "{ifc}.by_type('IfcCostItem')[0].id()" - And I press "bim.enable_editing_cost_item(cost_item={cost_item})" + And I press "bim.enable_editing_cost_item_attributes(cost_item={cost_item})" When I press "bim.edit_cost_item" Then nothing happens