mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-12 02:23:34 +00:00
BBIM D: Copy cost items, export Cost Schedules individually, start improving Cost Schedule UI
This commit is contained in:
@@ -76,6 +76,7 @@ classes = (
|
|||||||
operator.LoadCostItemTaskQuantities,
|
operator.LoadCostItemTaskQuantities,
|
||||||
operator.LoadCostItemResourceQuantities,
|
operator.LoadCostItemResourceQuantities,
|
||||||
operator.ChangeParentCostItem,
|
operator.ChangeParentCostItem,
|
||||||
|
operator.CopyCostItem,
|
||||||
prop.CostItem,
|
prop.CostItem,
|
||||||
prop.CostItemQuantity,
|
prop.CostItemQuantity,
|
||||||
prop.CostItemType,
|
prop.CostItemType,
|
||||||
|
|||||||
@@ -97,10 +97,9 @@ class AddSummaryCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
bl_label = "Add Cost Item"
|
bl_label = "Add Cost Item"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
bl_description = "Add a summary cost item"
|
bl_description = "Add a summary cost item"
|
||||||
cost_schedule: bpy.props.IntProperty()
|
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
core.add_summary_cost_item(tool.Ifc, tool.Cost, cost_schedule=tool.Ifc.get().by_id(self.cost_schedule))
|
core.add_summary_cost_item(tool.Ifc, tool.Cost, cost_schedule=tool.Cost.get_active_cost_schedule())
|
||||||
|
|
||||||
|
|
||||||
class AddCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
class AddCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -114,6 +113,16 @@ class AddCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
core.add_cost_item(tool.Ifc, tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
|
core.add_cost_item(tool.Ifc, tool.Cost, cost_item=tool.Ifc.get().by_id(self.cost_item))
|
||||||
|
|
||||||
|
|
||||||
|
class CopyCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
bl_idname = "bim.copy_cost_item"
|
||||||
|
bl_label = "Copy Cost Item"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
bl_description = "Copy a cost item"
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
core.copy_cost_item(tool.Ifc, tool.Cost)
|
||||||
|
|
||||||
|
|
||||||
class ExpandCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
class ExpandCostItem(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
bl_idname = "bim.expand_cost_item"
|
bl_idname = "bim.expand_cost_item"
|
||||||
bl_label = "Expand Cost Item"
|
bl_label = "Expand Cost Item"
|
||||||
@@ -214,8 +223,9 @@ class UnassignCostItemType(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
core.unassign_cost_item_type(
|
core.unassign_cost_item_type(
|
||||||
tool.Ifc,
|
tool.Ifc,
|
||||||
tool.Cost,
|
tool.Cost,
|
||||||
self.cost_item,
|
tool.Spatial,
|
||||||
products=[tool.Ifc.get().by_id(self.related_object)] if self.related_object else [],
|
cost_item=tool.Ifc.get().by_id(self.cost_item),
|
||||||
|
product_types=[tool.Ifc.get().by_id(self.related_object)] if self.related_object else [],
|
||||||
)
|
)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
@@ -491,7 +501,7 @@ class AddCostColumn(bpy.types.Operator):
|
|||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
name: bpy.props.StringProperty()
|
name: bpy.props.StringProperty()
|
||||||
|
|
||||||
def _execute(self, context):
|
def execute(self, context):
|
||||||
core.add_cost_column(tool.Cost, self.name)
|
core.add_cost_column(tool.Cost, self.name)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
@@ -619,10 +629,12 @@ class ExportCostSchedules(bpy.types.Operator):
|
|||||||
bl_label = "Export Cost Schedule"
|
bl_label = "Export Cost Schedule"
|
||||||
bl_options = {"REGISTER", "UNDO"}
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
bl_description = "Export a cost schedule to a CSV, XSLX OR ODS file"
|
bl_description = "Export a cost schedule to a CSV, XSLX OR ODS file"
|
||||||
|
cost_schedule: bpy.props.IntProperty()
|
||||||
format: bpy.props.EnumProperty("Format", items=(("CSV", "CSV", ""), ("XLSX", "XLSX", ""), ("ODS", "ODS", "")))
|
format: bpy.props.EnumProperty("Format", items=(("CSV", "CSV", ""), ("XLSX", "XLSX", ""), ("ODS", "ODS", "")))
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
core.export_cost_schedules(tool.Cost, format=self.format)
|
cost_schedule = tool.Ifc.get().by_id(self.cost_schedule) if self.cost_schedule else None
|
||||||
|
core.export_cost_schedules(tool.Cost, format=self.format, cost_schedule=cost_schedule)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
def invoke(self, context, event):
|
def invoke(self, context, event):
|
||||||
@@ -667,7 +679,9 @@ class LoadProductCostItems(bpy.types.Operator):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
core.load_product_cost_items(tool.Cost, product=tool.Ifc.get().by_id(context.active_object.BIMObjectProperties.ifc_definition_id))
|
core.load_product_cost_items(
|
||||||
|
tool.Cost, product=tool.Ifc.get().by_id(context.active_object.BIMObjectProperties.ifc_definition_id)
|
||||||
|
)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -213,3 +213,4 @@ class BIMCostProperties(PropertyGroup):
|
|||||||
name="Show Nested Tasks", default=False, update=update_active_cost_item_resources
|
name="Show Nested Tasks", default=False, update=update_active_cost_item_resources
|
||||||
)
|
)
|
||||||
change_cost_item_parent: BoolProperty(name="Change Cost Item Parent", default=False, update=update_cost_item_parent)
|
change_cost_item_parent: BoolProperty(name="Change Cost Item Parent", default=False, update=update_cost_item_parent)
|
||||||
|
show_cost_item_operators: BoolProperty(name="Show Cost Item Operators", default=False)
|
||||||
|
|||||||
@@ -43,43 +43,54 @@ class BIM_PT_cost_schedules(Panel):
|
|||||||
|
|
||||||
self.props = context.scene.BIMCostProperties
|
self.props = context.scene.BIMCostProperties
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
if CostSchedulesData.data["total_cost_schedules"]:
|
if not self.props.active_cost_schedule_id:
|
||||||
row.label(text=f"{CostSchedulesData.data['total_cost_schedules']} Cost Schedules Found", icon="TEXT")
|
if CostSchedulesData.data["total_cost_schedules"]:
|
||||||
row.operator("bim.export_cost_schedules", text="Export as spreadsheet", icon="EXPORT")
|
row.label(text=f"{CostSchedulesData.data['total_cost_schedules']} Cost Schedules Found", icon="TEXT")
|
||||||
else:
|
row.operator("bim.export_cost_schedules", text="Export as spreadsheet", icon="EXPORT")
|
||||||
row.label(text="No Cost Schedules Found found.", icon="COMMUNITY")
|
else:
|
||||||
|
row.label(text="No Cost Schedules Found found.", icon="COMMUNITY")
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.prop(self.props, "cost_schedule_predefined_types")
|
row.prop(self.props, "cost_schedule_predefined_types")
|
||||||
row.operator("bim.add_cost_schedule", icon="ADD", text="Add")
|
row.operator("bim.add_cost_schedule", icon="ADD", text="Add")
|
||||||
|
|
||||||
for schedule in CostSchedulesData.data["schedules"]:
|
for schedule in CostSchedulesData.data["schedules"]:
|
||||||
self.draw_cost_schedule_ui(schedule)
|
self.draw_cost_schedule_ui(schedule)
|
||||||
|
|
||||||
def draw_cost_schedule_ui(self, cost_schedule):
|
def draw_cost_schedule_ui(self, cost_schedule):
|
||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.label(text=cost_schedule["name"], icon="LINENUMBERS_ON")
|
|
||||||
|
|
||||||
if self.props.active_cost_schedule_id and self.props.active_cost_schedule_id == cost_schedule["id"]:
|
if self.props.active_cost_schedule_id and self.props.active_cost_schedule_id == cost_schedule["id"]:
|
||||||
op = row.operator("bim.select_cost_schedule_products", icon="RESTRICT_SELECT_OFF", text="Assigned")
|
row.label(text="Currently editing: {}".format(cost_schedule["name"]), icon="LINENUMBERS_ON")
|
||||||
|
grid = self.layout.grid_flow(columns=2, even_columns=True)
|
||||||
|
col = grid.column()
|
||||||
|
row1 = col.row(align=True)
|
||||||
|
row1.alignment = "LEFT"
|
||||||
|
row1.label(text="Schedule tools")
|
||||||
|
row1 = col.row(align=True)
|
||||||
|
row1.alignment = "RIGHT"
|
||||||
|
row1.operator("bim.export_cost_schedules", text="Export", icon="EXPORT").cost_schedule = cost_schedule["id"]
|
||||||
|
row2 = col.row(align=True)
|
||||||
|
row2.alignment = "RIGHT"
|
||||||
|
op = row2.operator("bim.select_cost_schedule_products", icon="RESTRICT_SELECT_OFF", text="Assigned")
|
||||||
op.cost_schedule = cost_schedule["id"]
|
op.cost_schedule = cost_schedule["id"]
|
||||||
row.operator("bim.select_unassigned_products", icon="RESTRICT_SELECT_OFF", text="Unassigned")
|
row2.operator("bim.select_unassigned_products", icon="RESTRICT_SELECT_OFF", text="Unassigned")
|
||||||
|
|
||||||
row.prop(self.props, "should_show_column_ui", text="", icon="SHORTDISPLAY")
|
col = grid.column()
|
||||||
|
row1 = col.row(align=True)
|
||||||
|
row1.alignment = "LEFT"
|
||||||
|
row1.label(text="Settings")
|
||||||
|
row1 = col.row(align=True)
|
||||||
|
row1.alignment = "RIGHT"
|
||||||
|
row1.prop(self.props, "should_show_column_ui", text="Schedule Columns", icon="SHORTDISPLAY")
|
||||||
if self.props.is_editing == "COST_SCHEDULE_ATTRIBUTES":
|
if self.props.is_editing == "COST_SCHEDULE_ATTRIBUTES":
|
||||||
row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK")
|
row.operator("bim.edit_cost_schedule", text="", icon="CHECKMARK")
|
||||||
elif self.props.is_editing == "COST_ITEMS":
|
row.operator("bim.disable_editing_cost_schedule", text="Disable Editing", icon="CANCEL")
|
||||||
row.operator("bim.add_summary_cost_item", text="", icon="ADD").cost_schedule = cost_schedule["id"]
|
|
||||||
row.operator("bim.disable_editing_cost_schedule", text="", icon="CANCEL")
|
|
||||||
elif self.props.active_cost_schedule_id:
|
|
||||||
row.operator("bim.remove_cost_schedule", text="", icon="X").cost_schedule = cost_schedule["id"]
|
|
||||||
else:
|
else:
|
||||||
|
row.label(text=cost_schedule["name"], icon="LINENUMBERS_ON")
|
||||||
row.operator("bim.enable_editing_cost_items", text="", icon="OUTLINER").cost_schedule = cost_schedule["id"]
|
row.operator("bim.enable_editing_cost_items", text="", icon="OUTLINER").cost_schedule = cost_schedule["id"]
|
||||||
row.operator(
|
row.operator(
|
||||||
"bim.enable_editing_cost_schedule_attributes", text="", icon="GREASEPENCIL"
|
"bim.enable_editing_cost_schedule_attributes", text="", icon="GREASEPENCIL"
|
||||||
).cost_schedule = cost_schedule["id"]
|
).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"]
|
||||||
|
|
||||||
if self.props.active_cost_schedule_id == cost_schedule["id"]:
|
if self.props.active_cost_schedule_id == cost_schedule["id"]:
|
||||||
if self.props.is_editing == "COST_SCHEDULE_ATTRIBUTES":
|
if self.props.is_editing == "COST_SCHEDULE_ATTRIBUTES":
|
||||||
self.draw_editable_cost_schedule_ui()
|
self.draw_editable_cost_schedule_ui()
|
||||||
@@ -101,30 +112,39 @@ class BIM_PT_cost_schedules(Panel):
|
|||||||
row = self.layout.row(align=True)
|
row = self.layout.row(align=True)
|
||||||
row.alignment = "RIGHT"
|
row.alignment = "RIGHT"
|
||||||
ifc_definition_id = None
|
ifc_definition_id = None
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.label(text="Cost Item Tools")
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.alignment = "RIGHT"
|
||||||
|
row.operator("bim.add_summary_cost_item", text="Add Summary Cost", icon="ADD")
|
||||||
|
row.operator("bim.expand_all_tasks", text="Expand All")
|
||||||
|
row.operator("bim.contract_all_tasks", text="Contract All")
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.alignment = "RIGHT"
|
||||||
if self.props.cost_items and self.props.active_cost_item_index < len(self.props.cost_items):
|
if self.props.cost_items and self.props.active_cost_item_index < len(self.props.cost_items):
|
||||||
ifc_definition_id = self.props.cost_items[self.props.active_cost_item_index].ifc_definition_id
|
ifc_definition_id = self.props.cost_items[self.props.active_cost_item_index].ifc_definition_id
|
||||||
if ifc_definition_id:
|
if ifc_definition_id:
|
||||||
row.prop(self.props, "change_cost_item_parent", text="", icon="LINKED")
|
row.prop(self.props, "show_cost_item_operators", text="Edit", icon="DOWNARROW_HLT")
|
||||||
row.prop(self.props, "enable_reorder", text="", icon="SORTALPHA")
|
row.operator("bim.add_cost_item", text="Add", icon="ADD").cost_item = ifc_definition_id
|
||||||
if not CostSchedulesData.data["is_editing_rates"]:
|
row.operator("bim.copy_cost_item", text="Copy", icon="ADD")
|
||||||
op = row.operator("bim.enable_editing_cost_item_quantities", text="", icon="PROPERTIES")
|
row.operator("bim.remove_cost_item", text="Delete", icon="X").cost_item = ifc_definition_id
|
||||||
|
if self.props.show_cost_item_operators:
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.alignment = "RIGHT"
|
||||||
|
row.prop(self.props, "change_cost_item_parent", text="", icon="LINKED")
|
||||||
|
row.prop(self.props, "enable_reorder", text="", icon="SORTALPHA")
|
||||||
|
if not CostSchedulesData.data["is_editing_rates"]:
|
||||||
|
op = row.operator("bim.enable_editing_cost_item_quantities", text="", icon="PROPERTIES")
|
||||||
|
op.cost_item = ifc_definition_id
|
||||||
|
op = row.operator("bim.enable_editing_cost_item_values", text="", icon="DISC")
|
||||||
op.cost_item = ifc_definition_id
|
op.cost_item = ifc_definition_id
|
||||||
|
if self.props.active_cost_item_id == ifc_definition_id:
|
||||||
op = row.operator("bim.enable_editing_cost_item_values", text="", icon="DISC")
|
if self.props.cost_item_editing_type == "ATTRIBUTES":
|
||||||
op.cost_item = ifc_definition_id
|
row.operator("bim.edit_cost_item", text="", icon="CHECKMARK")
|
||||||
|
row.operator("bim.disable_editing_cost_item", text="", icon="CANCEL")
|
||||||
row.operator("bim.add_cost_item", text="", icon="ADD").cost_item = ifc_definition_id
|
else:
|
||||||
|
op = row.operator("bim.enable_editing_cost_item_attributes", text="", icon="GREASEPENCIL")
|
||||||
if self.props.active_cost_item_id == ifc_definition_id:
|
op.cost_item = ifc_definition_id
|
||||||
if self.props.cost_item_editing_type == "ATTRIBUTES":
|
|
||||||
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_attributes", text="", icon="GREASEPENCIL")
|
|
||||||
op.cost_item = ifc_definition_id
|
|
||||||
|
|
||||||
row.operator("bim.remove_cost_item", text="", icon="X").cost_item = ifc_definition_id
|
|
||||||
|
|
||||||
self.layout.template_list(
|
self.layout.template_list(
|
||||||
"BIM_UL_cost_items",
|
"BIM_UL_cost_items",
|
||||||
"",
|
"",
|
||||||
@@ -698,9 +718,7 @@ class BIM_PT_Costing_Tools(Panel):
|
|||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
self.props = context.scene.BIMCostProperties
|
self.props = context.scene.BIMCostProperties
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.operator(
|
row.operator("bim.load_product_cost_items", icon="FILE_REFRESH")
|
||||||
"bim.load_product_cost_items", icon="FILE_REFRESH"
|
|
||||||
)
|
|
||||||
row = self.layout.row()
|
row = self.layout.row()
|
||||||
row.template_list(
|
row.template_list(
|
||||||
"BIM_UL_product_cost_items",
|
"BIM_UL_product_cost_items",
|
||||||
|
|||||||
@@ -236,8 +236,8 @@ def calculate_cost_item_resource_value(ifc, cost_item):
|
|||||||
ifc.run("cost.calculate_cost_item_resource_value", cost_item=cost_item)
|
ifc.run("cost.calculate_cost_item_resource_value", cost_item=cost_item)
|
||||||
|
|
||||||
|
|
||||||
def export_cost_schedules(cost, format):
|
def export_cost_schedules(cost, format, cost_schedule=None):
|
||||||
cost.export_cost_schedules(format)
|
cost.export_cost_schedules(format, cost_schedule)
|
||||||
|
|
||||||
|
|
||||||
def clear_cost_item_assignments(ifc, cost, cost_item, related_object_type):
|
def clear_cost_item_assignments(ifc, cost, cost_item, related_object_type):
|
||||||
@@ -277,3 +277,10 @@ def change_parent_cost_item(ifc, cost, new_parent):
|
|||||||
ifc.run("nest.change_nest", item=cost_item, new_parent=new_parent)
|
ifc.run("nest.change_nest", item=cost_item, new_parent=new_parent)
|
||||||
cost.disable_editing_cost_item_parent()
|
cost.disable_editing_cost_item_parent()
|
||||||
cost.load_cost_schedule_tree()
|
cost.load_cost_schedule_tree()
|
||||||
|
|
||||||
|
def copy_cost_item(ifc, cost):
|
||||||
|
cost_item = cost.get_highlighted_cost_item()
|
||||||
|
if cost_item:
|
||||||
|
cost_item = ifc.run("cost.copy_cost_item", cost_item=cost_item)
|
||||||
|
cost.disable_editing_cost_item_parent()
|
||||||
|
cost.load_cost_schedule_tree()
|
||||||
|
|||||||
@@ -498,24 +498,23 @@ class Cost(blenderbim.core.tool.Cost):
|
|||||||
props.is_cost_update_enabled = True
|
props.is_cost_update_enabled = True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def export_cost_schedules(cls, format=None):
|
def export_cost_schedules(cls, format=None, cost_schedule=None):
|
||||||
path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "build", "cost_schedules")
|
path = os.path.join(bpy.context.scene.BIMProperties.data_dir, "build", "cost_schedules")
|
||||||
if format == "CSV":
|
if format == "CSV":
|
||||||
from ifc5d.ifc5Dspreadsheet import Ifc5DCsvWriter
|
from ifc5d.ifc5Dspreadsheet import Ifc5DCsvWriter
|
||||||
|
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
os.makedirs(path)
|
os.makedirs(path)
|
||||||
writer = Ifc5DCsvWriter(file=tool.Ifc.get(), output=path)
|
writer = Ifc5DCsvWriter(file=tool.Ifc.get(), output=path, cost_schedule=cost_schedule)
|
||||||
writer.write()
|
writer.write()
|
||||||
elif format == "ODS":
|
elif format == "ODS":
|
||||||
from ifc5d.ifc5Dspreadsheet import Ifc5DOdsWriter
|
from ifc5d.ifc5Dspreadsheet import Ifc5DOdsWriter
|
||||||
|
|
||||||
writer = Ifc5DOdsWriter(file=tool.Ifc.get(), output=path)
|
writer = Ifc5DOdsWriter(file=tool.Ifc.get(), output=path, cost_schedule=cost_schedule)
|
||||||
writer.write()
|
writer.write()
|
||||||
elif format == "XLSX":
|
elif format == "XLSX":
|
||||||
from ifc5d.ifc5Dspreadsheet import Ifc5DXlsxWriter
|
from ifc5d.ifc5Dspreadsheet import Ifc5DXlsxWriter
|
||||||
|
|
||||||
writer = Ifc5DXlsxWriter(file=tool.Ifc.get(), output=path)
|
writer = Ifc5DXlsxWriter(file=tool.Ifc.get(), output=path, cost_schedule=cost_schedule )
|
||||||
writer.write()
|
writer.write()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -195,12 +195,13 @@ class IfcDataGetter:
|
|||||||
|
|
||||||
|
|
||||||
class Ifc5Dwriter:
|
class Ifc5Dwriter:
|
||||||
def __init__(self, file=None, output=None):
|
def __init__(self, file=None, output=None, cost_schedule=None):
|
||||||
self.output = output
|
self.output = output
|
||||||
if isinstance(file, str):
|
if isinstance(file, str):
|
||||||
self.file = ifcopenshell.open(file)
|
self.file = ifcopenshell.open(file)
|
||||||
else:
|
else:
|
||||||
self.file = file
|
self.file = file
|
||||||
|
self.cost_schedule = cost_schedule
|
||||||
self.cost_schedules = []
|
self.cost_schedules = []
|
||||||
self.sheet_data = {}
|
self.sheet_data = {}
|
||||||
self.column_indexes = []
|
self.column_indexes = []
|
||||||
@@ -220,6 +221,10 @@ class Ifc5Dwriter:
|
|||||||
self.used_names = []
|
self.used_names = []
|
||||||
for i in range(26):
|
for i in range(26):
|
||||||
self.column_indexes.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % 26])
|
self.column_indexes.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % 26])
|
||||||
|
if self.cost_schedule:
|
||||||
|
for cost_schedule in self.cost_schedules:
|
||||||
|
if cost_schedule.id() != self.cost_schedule.id():
|
||||||
|
self.cost_schedules.remove(cost_schedule)
|
||||||
for cost_schedule in self.cost_schedules:
|
for cost_schedule in self.cost_schedules:
|
||||||
sheet_id = cost_schedule.id()
|
sheet_id = cost_schedule.id()
|
||||||
self.sheet_data[sheet_id] = {}
|
self.sheet_data[sheet_id] = {}
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
# IfcOpenShell - IFC toolkit and geometry engine
|
||||||
|
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
|
#
|
||||||
|
# This file is part of IfcOpenShell.
|
||||||
|
#
|
||||||
|
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import ifcopenshell
|
||||||
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
|
def __init__(self, file, cost_item=None):
|
||||||
|
"""Copies all cost items and related relationships
|
||||||
|
|
||||||
|
The following relationships are also duplicated:
|
||||||
|
|
||||||
|
* The copy will have the same attributes and property sets as the original cost item
|
||||||
|
* The copy will be assigned to the parent cost schedule
|
||||||
|
* The copy will have duplicated nested cost items
|
||||||
|
|
||||||
|
:param cost_item: The cost item to be duplicated
|
||||||
|
:type cost_item: ifcopenshell.entity_instance.entity_instance
|
||||||
|
:return: The duplicated cost item or the list of duplicated cost items if the latter has children
|
||||||
|
:rtype: ifcopenshell.entity_instance.entity_instance or list of ifcopenshell.entity_instance.entity_instance
|
||||||
|
|
||||||
|
Example:
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
# We have a cost item
|
||||||
|
cost_item = CostItem(name="Design new feature", deadline="2023-03-01")
|
||||||
|
|
||||||
|
# And now we have two
|
||||||
|
duplicated_cost_item = project.duplicate_cost_item(cost_item)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.file = file
|
||||||
|
self.settings = {"cost_item": cost_item}
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
self.new_cost_items = []
|
||||||
|
self.duplicate_cost_item(self.settings["cost_item"])
|
||||||
|
|
||||||
|
def duplicate_cost_item(self, cost_item):
|
||||||
|
new_cost_item = ifcopenshell.util.element.copy_deep(self.file, cost_item)
|
||||||
|
self.new_cost_items.append(new_cost_item)
|
||||||
|
self.copy_indirect_attributes(cost_item, new_cost_item)
|
||||||
|
return new_cost_item
|
||||||
|
|
||||||
|
def copy_indirect_attributes(self, from_element, to_element):
|
||||||
|
for inverse in self.file.get_inverse(from_element):
|
||||||
|
if inverse.is_a("IfcRelDefinesByProperties"):
|
||||||
|
inverse = ifcopenshell.util.element.copy(self.file, inverse)
|
||||||
|
inverse.RelatedObjects = [to_element]
|
||||||
|
pset = ifcopenshell.util.element.copy_deep(
|
||||||
|
self.file, inverse.RelatingPropertyDefinition
|
||||||
|
)
|
||||||
|
inverse.RelatingPropertyDefinition = pset
|
||||||
|
elif inverse.is_a("IfcRelNests") and inverse.RelatingObject == from_element:
|
||||||
|
nested_cost_items = [e for e in inverse.RelatedObjects]
|
||||||
|
if nested_cost_items:
|
||||||
|
new_cost_items = []
|
||||||
|
for cost_item in nested_cost_items:
|
||||||
|
new_cost_item = self.duplicate_cost_item(cost_item)
|
||||||
|
new_cost_items.append(new_cost_item)
|
||||||
|
inverse = ifcopenshell.util.element.copy(self.file, inverse)
|
||||||
|
inverse.RelatingObject = to_element
|
||||||
|
inverse.RelatedObjects = new_cost_items
|
||||||
|
for cost_item in new_cost_items:
|
||||||
|
ifcopenshell.api.run(
|
||||||
|
"nest.unassign_object", self.file, related_object=cost_item
|
||||||
|
)
|
||||||
|
rel = ifcopenshell.api.run(
|
||||||
|
"nest.assign_object",
|
||||||
|
self.file,
|
||||||
|
related_object=cost_item,
|
||||||
|
relating_object=to_element,
|
||||||
|
)
|
||||||
|
# elif inverse.is_a("IfcRelAssignsToProduct"):
|
||||||
|
# continue
|
||||||
|
# to_element.IsDefinedBy = inverse.RelatingOrder
|
||||||
|
# elif inverse.is_a("IfcRelAssignsToProcess"):
|
||||||
|
# to_element.IsDefinedBy = inverse.RelatingProcess
|
||||||
|
# elif inverse.is_a("IfcRelAssignsToResource"):
|
||||||
|
# continue
|
||||||
|
# elif inverse.is_a("IfcRelAssignsToControl"):
|
||||||
|
# continue
|
||||||
|
# elif inverse.is_a("IfcRelDefinesByObject"):
|
||||||
|
# continue
|
||||||
|
else:
|
||||||
|
for i, value in enumerate(inverse):
|
||||||
|
if value == from_element:
|
||||||
|
new_inverse = ifcopenshell.util.element.copy(self.file, inverse)
|
||||||
|
new_inverse[i] = to_element
|
||||||
|
elif isinstance(value, (tuple, list)) and from_element in value:
|
||||||
|
new_value = list(value)
|
||||||
|
new_value.append(to_element)
|
||||||
|
inverse[i] = new_value
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# IfcOpenShell - IFC toolkit and geometry engine
|
||||||
|
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||||
|
#
|
||||||
|
# This file is part of IfcOpenShell.
|
||||||
|
#
|
||||||
|
# IfcOpenShell is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# IfcOpenShell is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with IfcOpenShell. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
class Usecase:
|
||||||
|
def __init__(self, file, material=None, attributes=None):
|
||||||
|
"""Edits the attributes of an IfcMaterial"""
|
||||||
|
|
||||||
|
self.file = file
|
||||||
|
self.settings = {"material": material, "attributes": attributes or {}}
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
for name, value in self.settings["attributes"].items():
|
||||||
|
setattr(self.settings["material"], name, value)
|
||||||
Reference in New Issue
Block a user