mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-12 06:32:09 +00:00
Implement cost identification numbers and big cleanup to cost schedule UI
This commit is contained in:
@@ -103,6 +103,7 @@ class EnableEditingCostItems(bpy.types.Operator):
|
|||||||
if context.preferences.addons["blenderbim"].preferences.should_play_chaching_sound:
|
if context.preferences.addons["blenderbim"].preferences.should_play_chaching_sound:
|
||||||
self.play_chaching_sound() # lol
|
self.play_chaching_sound() # lol
|
||||||
self.props = context.scene.BIMCostProperties
|
self.props = context.scene.BIMCostProperties
|
||||||
|
self.props.is_cost_update_enabled = False
|
||||||
self.props.active_cost_schedule_id = self.cost_schedule
|
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)
|
||||||
@@ -111,6 +112,7 @@ class EnableEditingCostItems(bpy.types.Operator):
|
|||||||
for related_object_id in Data.cost_schedules[self.cost_schedule]["Controls"]:
|
for related_object_id in Data.cost_schedules[self.cost_schedule]["Controls"]:
|
||||||
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"
|
self.props.is_editing = "COST_ITEMS"
|
||||||
|
self.props.is_cost_update_enabled = True
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
def play_chaching_sound(self):
|
def play_chaching_sound(self):
|
||||||
@@ -134,6 +136,7 @@ class EnableEditingCostItems(bpy.types.Operator):
|
|||||||
new = self.props.cost_items.add()
|
new = self.props.cost_items.add()
|
||||||
new.ifc_definition_id = related_object_id
|
new.ifc_definition_id = related_object_id
|
||||||
new.name = cost_item["Name"] or "Unnamed"
|
new.name = cost_item["Name"] or "Unnamed"
|
||||||
|
new.identification = cost_item["Identification"] or "XXX"
|
||||||
new.is_expanded = related_object_id not in self.contracted_cost_items
|
new.is_expanded = related_object_id not in self.contracted_cost_items
|
||||||
new.level_index = level_index
|
new.level_index = level_index
|
||||||
if cost_item["IsNestedBy"]:
|
if cost_item["IsNestedBy"]:
|
||||||
|
|||||||
@@ -128,11 +128,27 @@ def update_cost_item_index(self, context):
|
|||||||
bpy.ops.bim.load_cost_item_quantities()
|
bpy.ops.bim.load_cost_item_quantities()
|
||||||
|
|
||||||
|
|
||||||
def updateCostItemName(self, context):
|
def updateCostItemIdentification(self, context):
|
||||||
if self.name == "Unnamed":
|
props = context.scene.BIMCostProperties
|
||||||
|
if not props.is_cost_update_enabled or self.identification == "XXX":
|
||||||
return
|
return
|
||||||
self.file = IfcStore.get_file()
|
self.file = IfcStore.get_file()
|
||||||
|
ifcopenshell.api.run(
|
||||||
|
"cost.edit_cost_item",
|
||||||
|
self.file,
|
||||||
|
**{"cost_item": self.file.by_id(self.ifc_definition_id), "attributes": {"Identification": self.identification}},
|
||||||
|
)
|
||||||
|
Data.load(self.file)
|
||||||
|
if props.active_cost_item_id == self.ifc_definition_id:
|
||||||
|
attribute = props.cost_item_attributes.get("Identification")
|
||||||
|
attribute.string_value = self.identification
|
||||||
|
|
||||||
|
|
||||||
|
def updateCostItemName(self, context):
|
||||||
props = context.scene.BIMCostProperties
|
props = context.scene.BIMCostProperties
|
||||||
|
if not props.is_cost_update_enabled or self.name == "Unnamed":
|
||||||
|
return
|
||||||
|
self.file = IfcStore.get_file()
|
||||||
ifcopenshell.api.run(
|
ifcopenshell.api.run(
|
||||||
"cost.edit_cost_item",
|
"cost.edit_cost_item",
|
||||||
self.file,
|
self.file,
|
||||||
@@ -146,6 +162,7 @@ def updateCostItemName(self, context):
|
|||||||
|
|
||||||
class CostItem(PropertyGroup):
|
class CostItem(PropertyGroup):
|
||||||
name: StringProperty(name="Name", update=updateCostItemName)
|
name: StringProperty(name="Name", update=updateCostItemName)
|
||||||
|
identification: StringProperty(name="Identification", update=updateCostItemIdentification)
|
||||||
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")
|
||||||
@@ -159,6 +176,7 @@ class CostItemQuantity(PropertyGroup):
|
|||||||
|
|
||||||
|
|
||||||
class BIMCostProperties(PropertyGroup):
|
class BIMCostProperties(PropertyGroup):
|
||||||
|
is_cost_update_enabled: BoolProperty(name="Is Cost Update Enabled", default=True)
|
||||||
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")
|
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")
|
||||||
|
|||||||
@@ -76,6 +76,32 @@ class BIM_PT_cost_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="")
|
||||||
|
|
||||||
def draw_editable_cost_item_ui(self, cost_schedule_id):
|
def draw_editable_cost_item_ui(self, cost_schedule_id):
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.alignment = "RIGHT"
|
||||||
|
ifc_definition_id = None
|
||||||
|
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
|
||||||
|
if ifc_definition_id:
|
||||||
|
|
||||||
|
if Data.cost_schedules[self.props.active_cost_schedule_id]["PredefinedType"] != "SCHEDULEOFRATES":
|
||||||
|
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
|
||||||
|
|
||||||
|
row.operator("bim.add_cost_item", text="", icon="ADD").cost_item = ifc_definition_id
|
||||||
|
|
||||||
|
if self.props.active_cost_item_id == 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", 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",
|
||||||
"",
|
"",
|
||||||
@@ -348,7 +374,7 @@ class BIM_PT_cost_item_quantities(Panel):
|
|||||||
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
|
self.props = context.scene.BIMCostProperties
|
||||||
cost_item = Data.cost_items[item.ifc_definition_id]
|
cost_item = Data.cost_items[item.ifc_definition_id]
|
||||||
row = layout.row(align=True)
|
row = layout.row(align=True)
|
||||||
|
|
||||||
@@ -366,40 +392,30 @@ class BIM_UL_cost_items(UIList):
|
|||||||
else:
|
else:
|
||||||
row.label(text="", icon="DOT")
|
row.label(text="", icon="DOT")
|
||||||
|
|
||||||
split1 = row.split(factor=0.7)
|
split1 = row.split(factor=0.1)
|
||||||
split1.prop(item, "name", emboss=False, text="")
|
split1.prop(item, "identification", emboss=False, text="")
|
||||||
|
split2 = split1.split(factor=0.5)
|
||||||
|
split2.alignment = "RIGHT"
|
||||||
|
split2.prop(item, "name", emboss=False, text="")
|
||||||
|
|
||||||
if Data.cost_schedules[props.active_cost_schedule_id]["PredefinedType"] != "SCHEDULEOFRATES":
|
if Data.cost_schedules[self.props.active_cost_schedule_id]["PredefinedType"] != "SCHEDULEOFRATES":
|
||||||
op = row.operator("bim.enable_editing_cost_item_quantities", text="", icon="PROPERTIES")
|
split2.label(text="{0:.2f}".format(cost_item["TotalCostQuantity"]) + f" ({cost_item['UnitSymbol'] or '?'})")
|
||||||
op.cost_item = item.ifc_definition_id
|
|
||||||
row.label(text="{0:.2f}".format(cost_item["TotalCostQuantity"]) + f" ({cost_item['UnitSymbol']})")
|
|
||||||
|
|
||||||
op = row.operator("bim.enable_editing_cost_item_values", text="", icon="DISC")
|
split2.label(text="{0:.2f}".format(cost_item["TotalAppliedValue"]))
|
||||||
op.cost_item = item.ifc_definition_id
|
|
||||||
row.label(text="{0:.2f}".format(cost_item["TotalAppliedValue"]))
|
|
||||||
|
|
||||||
for column in props.columns:
|
for column in self.props.columns:
|
||||||
row.label(text=str(cost_item["CategoryValues"].get(column.name, "-")))
|
split2.label(text=str(cost_item["CategoryValues"].get(column.name, "-")))
|
||||||
|
|
||||||
row.label(text="{0:.2f}".format(cost_item["TotalCostValue"]), icon="CON_TRANSLIKE")
|
split2.label(text="{0:.2f}".format(cost_item["TotalCostValue"]))
|
||||||
|
self.draw_buttons(split2, item, cost_item)
|
||||||
|
|
||||||
if props.active_cost_item_id == item.ifc_definition_id:
|
def draw_buttons(self, row, item, cost_item):
|
||||||
if props.cost_item_editing_type == "ATTRIBUTES":
|
pass # TODO: reimplement somewhere with better UX
|
||||||
row.operator("bim.edit_cost_item", text="", icon="CHECKMARK")
|
# elif self.props.active_cost_item_id:
|
||||||
row.operator("bim.disable_editing_cost_item", text="", icon="CANCEL")
|
# if self.props.cost_item_editing_type == "VALUES":
|
||||||
elif props.active_cost_item_id:
|
# op = row.operator("bim.copy_cost_item_values", text="", icon="COPYDOWN")
|
||||||
if props.cost_item_editing_type == "VALUES":
|
# op.source = self.props.active_cost_item_id
|
||||||
op = row.operator("bim.copy_cost_item_values", text="", icon="COPYDOWN")
|
# op.destination = item.ifc_definition_id
|
||||||
op.source = props.active_cost_item_id
|
|
||||||
op.destination = 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
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
class BIM_UL_cost_columns(UIList):
|
class BIM_UL_cost_columns(UIList):
|
||||||
|
|||||||
@@ -60,18 +60,20 @@ class Csv2Ifc:
|
|||||||
|
|
||||||
def get_row_cost_data(self, row):
|
def get_row_cost_data(self, row):
|
||||||
name = row[self.headers["Name"]]
|
name = row[self.headers["Name"]]
|
||||||
|
identification = row[self.headers["Identification"]] if "Identification" in self.headers else None
|
||||||
cost_quantities = row[self.headers["Quantity"]]
|
cost_quantities = row[self.headers["Quantity"]]
|
||||||
cost_quantities_unit = row[self.headers["Unit"]]
|
cost_quantities_unit = row[self.headers["Unit"]]
|
||||||
if self.has_categories:
|
if self.has_categories:
|
||||||
cost_values = {
|
cost_values = {
|
||||||
k: float(row[v])
|
k: float(row[v])
|
||||||
for k, v in self.headers.items()
|
for k, v in self.headers.items()
|
||||||
if k not in ["Hierarchy", "Name", "Quantity", "Unit", "Subtotal"] and row[v]
|
if k not in ["Hierarchy", "Identification", "Name", "Quantity", "Unit", "Subtotal"] and row[v]
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
cost_values = row[self.headers["Value"]]
|
cost_values = row[self.headers["Value"]]
|
||||||
cost_values = float(cost_values) if cost_values else None
|
cost_values = float(cost_values) if cost_values else None
|
||||||
return {
|
return {
|
||||||
|
"Identification": str(identification) if identification else None,
|
||||||
"Name": str(name) if name else None,
|
"Name": str(name) if name else None,
|
||||||
"CostQuantities": float(cost_quantities) if cost_quantities else None,
|
"CostQuantities": float(cost_quantities) if cost_quantities else None,
|
||||||
"CostQuantitiesUnit": str(cost_quantities_unit) if cost_quantities_unit else None,
|
"CostQuantitiesUnit": str(cost_quantities_unit) if cost_quantities_unit else None,
|
||||||
@@ -99,6 +101,7 @@ class Csv2Ifc:
|
|||||||
cost_item["ifc"] = ifcopenshell.api.run("cost.add_cost_item", self.file, cost_item=parent)
|
cost_item["ifc"] = ifcopenshell.api.run("cost.add_cost_item", self.file, cost_item=parent)
|
||||||
|
|
||||||
cost_item["ifc"].Name = cost_item["Name"]
|
cost_item["ifc"].Name = cost_item["Name"]
|
||||||
|
cost_item["ifc"].Identification = cost_item["Identification"]
|
||||||
|
|
||||||
if not cost_item["CostValues"]:
|
if not cost_item["CostValues"]:
|
||||||
cost_value = ifcopenshell.api.run("cost.add_cost_value", self.file, parent=cost_item["ifc"])
|
cost_value = ifcopenshell.api.run("cost.add_cost_value", self.file, parent=cost_item["ifc"])
|
||||||
|
|||||||
+14
-14
@@ -1,14 +1,14 @@
|
|||||||
"Hierarchy","Name","Quantity","Unit","Foo","Bar","Baz","Subtotal"
|
"Hierarchy","Identification","Name","Quantity","Unit","Foo","Bar","Baz","Subtotal"
|
||||||
1,"Demolition",,,,,,301
|
1,1,"Demolition",,,,,,301
|
||||||
,,,,,,,
|
,,,,,,,,
|
||||||
2,"Building A",,,,,,96
|
2,1.1,"Building A",,,,,,96
|
||||||
,,,,,,,
|
,,,,,,,,
|
||||||
3,"Soft strip",1,"m",5,4,3,12
|
3,"1.1.1","Soft strip",1,"m",5,4,3,12
|
||||||
3,"Hard Strip",2,"m2",6,5,4,30
|
3,"1.1.2","Hard Strip",2,"m2",6,5,4,30
|
||||||
3,"Hazmat",3,"m3",7,6,5,54
|
3,"1.1.3","Hazmat",3,"m3",7,6,5,54
|
||||||
,,,,,,,
|
,,,,,,,,
|
||||||
2,"Building B",,,,,,205
|
2,1.2,"Building B",,,,,,205
|
||||||
,,,,,,,
|
,,,,,,,,
|
||||||
3,"Soft strip",4,"hr",8,7,,60
|
3,"1.2.1","Soft strip",4,"hr",8,7,,60
|
||||||
3,"Hard Strip",5,,9,,8,85
|
3,"1.2.2","Hard Strip",5,,9,,8,85
|
||||||
3,"Hazmat",6,"kg",10,,,60
|
3,"1.2.3","Hazmat",6,"kg",10,,,60
|
||||||
|
|||||||
|
Reference in New Issue
Block a user