mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 17:31:45 +00:00
See #6570. Add a button to refresh an imported csv file
Now the imported csv filepath is stored so it is possible to refresh the cost schedule without the need of reimporting it
This commit is contained in:
committed by
Massimo Fabbro
parent
0608f92bc4
commit
f8e52c8a12
@@ -61,6 +61,7 @@ classes = (
|
||||
operator.ExportCostSchedules,
|
||||
operator.HighlightProductCostItem,
|
||||
operator.ImportCostScheduleCsv,
|
||||
operator.RefreshCostScheduleCsv,
|
||||
operator.LoadCostItemElementQuantities,
|
||||
operator.LoadCostItemQuantities,
|
||||
operator.LoadCostItemResourceQuantities,
|
||||
@@ -82,6 +83,7 @@ classes = (
|
||||
prop.CostItem,
|
||||
prop.CostItemQuantity,
|
||||
prop.CostItemType,
|
||||
prop.CostItemsMapping,
|
||||
prop.ScheduleColumn,
|
||||
prop.BIMCostProperties,
|
||||
ui.BIM_PT_cost_schedules,
|
||||
|
||||
@@ -552,9 +552,19 @@ class ImportCostScheduleCsv(bpy.types.Operator, ImportHelper, tool.Ifc.Operator)
|
||||
return True
|
||||
|
||||
def _execute(self, context):
|
||||
core.import_cost_schedule_csv(tool.Cost, self.filepath, self.is_schedule_of_rates)
|
||||
cost_schedule = core.import_cost_schedule_csv(tool.Cost, self.filepath, self.is_schedule_of_rates)
|
||||
core.add_csv_filepath(tool.Cost, self.filepath, self.is_schedule_of_rates, cost_schedule)
|
||||
return {"FINISHED"}
|
||||
|
||||
class RefreshCostScheduleCsv(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.refresh_cost_schedule_csv"
|
||||
bl_label = "Refresh Cost Schedule CSV"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@classmethod
|
||||
def _execute(self, context):
|
||||
core.refresh_cost_schedule_csv(tool.Ifc, tool.Cost)
|
||||
return {"FINISHED"}
|
||||
|
||||
class AddCostColumn(bpy.types.Operator):
|
||||
bl_idname = "bim.add_cost_column"
|
||||
|
||||
@@ -166,6 +166,13 @@ class CostItemQuantity(PropertyGroup):
|
||||
unit_symbol: str
|
||||
total_cost_quantity: float
|
||||
|
||||
class CostItemsMapping(PropertyGroup):
|
||||
cost_item_id: IntProperty(name="cost_item_id")
|
||||
csv_filepath: StringProperty(name="filepath")
|
||||
|
||||
if TYPE_CHECKING:
|
||||
cost_item_id: int
|
||||
csv_filepath: str
|
||||
|
||||
class CostItemType(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
@@ -272,6 +279,7 @@ class BIMCostProperties(PropertyGroup):
|
||||
custom_currency: StringProperty(
|
||||
name="Custom Currency", default="USD", description="Custom Currency in ISO 4217 format"
|
||||
)
|
||||
cost_schedule_files: CollectionProperty(name="Cost Schedule Files", type=CostItemsMapping)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
cost_schedule_predefined_types: str
|
||||
@@ -326,3 +334,4 @@ class BIMCostProperties(PropertyGroup):
|
||||
show_cost_item_operators: bool
|
||||
currency: str
|
||||
custom_currency: str
|
||||
cost_schedule_files: bpy.types.bpy_prop_collection_idprop[CostItemsMapping]
|
||||
|
||||
@@ -71,6 +71,19 @@ class BIM_PT_cost_schedules(Panel):
|
||||
text="Currently editing: {}[{}]".format(cost_schedule["name"], cost_schedule["predefined_type"]),
|
||||
icon="LINENUMBERS_ON",
|
||||
)
|
||||
|
||||
row0 = self.layout.row(align=True)
|
||||
col = row0.column()
|
||||
col.label(text="Linked CSV:")
|
||||
row_1 = col.row(align=True)
|
||||
if self.props.active_cost_schedule_id in [item.cost_item_id for item in self.props.cost_schedule_files]:
|
||||
file = next((item.csv_filepath for item in self.props.cost_schedule_files if item.cost_item_id == self.props.active_cost_schedule_id), None)
|
||||
row_1.label(text=file)
|
||||
row_1.operator("bim.refresh_cost_schedule_csv", icon="FILE_REFRESH", text="")
|
||||
else:
|
||||
row_1.label(text="No CSV file found")
|
||||
row_1.operator("bim.import_cost_schedule_csv", icon="IMPORT", text="")
|
||||
|
||||
grid = self.layout.grid_flow(columns=2, even_columns=True)
|
||||
col = grid.column()
|
||||
row1 = col.row(align=True)
|
||||
|
||||
@@ -42,6 +42,7 @@ def disable_editing_cost_schedule(cost: tool.Cost) -> None:
|
||||
|
||||
def remove_cost_schedule(ifc: tool.Ifc, cost: tool.Cost, cost_schedule: ifcopenshell.entity_instance) -> None:
|
||||
cost.remove_stored_schedule_columns(cost_schedule)
|
||||
cost.remove_csv_filepath(cost_schedule)
|
||||
ifc.run("cost.remove_cost_schedule", cost_schedule=cost_schedule)
|
||||
|
||||
|
||||
@@ -311,10 +312,20 @@ def select_cost_schedule_products(
|
||||
products = cost.get_cost_schedule_products(cost_schedule)
|
||||
spatial.select_products(products)
|
||||
|
||||
def import_cost_schedule_csv(cost: tool.Cost, file_path: str, is_schedule_of_rates: bool) -> ifcopenshell.entity_instance:
|
||||
cost_schedule = cost.import_cost_schedule_csv(file_path, is_schedule_of_rates)
|
||||
return cost_schedule
|
||||
|
||||
def import_cost_schedule_csv(cost: tool.Cost, file_path: str, is_schedule_of_rates: bool) -> None:
|
||||
cost.import_cost_schedule_csv(file_path, is_schedule_of_rates)
|
||||
def add_csv_filepath(cost: tool.Cost, file_path: str, is_schedule_of_rates: bool, cost_schedule) -> None:
|
||||
cost.add_csv_filepath(file_path, is_schedule_of_rates, cost_schedule)
|
||||
|
||||
def remove_csv_filepath(cost: tool.Cost, cost_schedule) -> None:
|
||||
cost.remove_csv_filepath(cost_schedule)
|
||||
|
||||
def refresh_cost_schedule_csv(ifc: tool.Ifc, cost:tool.Cost) -> None:
|
||||
cost.delete_all_cost_items()
|
||||
cost.refresh_cost_schedule_csv()
|
||||
cost.load_cost_schedule_tree()
|
||||
|
||||
def add_cost_column(cost: tool.Cost, name: str) -> None:
|
||||
cost.add_cost_column(name)
|
||||
|
||||
@@ -246,6 +246,10 @@ class Cost:
|
||||
def has_schedules(cls): pass
|
||||
def highlight_cost_item(cls, cost_item): pass
|
||||
def import_cost_schedule_csv(cls, file_path, is_schedule_of_rates): pass
|
||||
def add_csv_filepath(cls, file_path, is_schedule_of_rates, cost_schedule): pass
|
||||
def remove_csv_filepath(cls, cost_schedule): pass
|
||||
def delete_all_cost_items(cls): pass
|
||||
def refresh_cost_schedule_csv(cls): pass
|
||||
def is_active_schedule_of_rates(cls): pass
|
||||
def is_cost_schedule_active(cls, cost_schedule): pass
|
||||
def is_root_cost_item(cls, cost_item): pass
|
||||
|
||||
@@ -561,7 +561,7 @@ class Cost(bonsai.core.tool.Cost):
|
||||
return products
|
||||
|
||||
@classmethod
|
||||
def import_cost_schedule_csv(cls, file_path: Optional[str] = None, is_schedule_of_rates: bool = False) -> None:
|
||||
def import_cost_schedule_csv(cls, file_path: Optional[str] = None, is_schedule_of_rates: bool = False) -> ifcopenshell.entity_instance:
|
||||
if not file_path:
|
||||
return
|
||||
from ifc5d.csv2ifc import Csv2Ifc
|
||||
@@ -571,7 +571,67 @@ class Cost(bonsai.core.tool.Cost):
|
||||
csv2ifc = Csv2Ifc(file_path, tool.Ifc.get(), is_schedule_of_rates=is_schedule_of_rates)
|
||||
csv2ifc.execute()
|
||||
print("Import finished in {:.2f} seconds".format(time.time() - start))
|
||||
return csv2ifc.cost_schedule
|
||||
|
||||
@classmethod
|
||||
def add_csv_filepath(cls, file_path: Optional[str] = None, is_schedule_of_rates: bool = False, cost_schedule: ifcopenshell.entity_instance = None) -> None:
|
||||
if not file_path:
|
||||
return
|
||||
|
||||
props = cls.get_cost_props()
|
||||
if not props.active_cost_schedule_id in [item.cost_item_id for item in props.cost_schedule_files]:
|
||||
item = props.cost_schedule_files.add()
|
||||
item.cost_item_id = cost_schedule.id()
|
||||
item.csv_filepath = file_path
|
||||
else:
|
||||
return
|
||||
|
||||
@classmethod
|
||||
def remove_csv_filepath(cls, cost_schedule: ifcopenshell.entity_instance = None) -> None:
|
||||
if not cost_schedule:
|
||||
return
|
||||
|
||||
props = cls.get_cost_props()
|
||||
cost_schedule_id = cost_schedule.id()
|
||||
if cost_schedule_id in [item.cost_item_id for item in props.cost_schedule_files]:
|
||||
for i, item in enumerate(props.cost_schedule_files):
|
||||
if item.cost_item_id == cost_schedule_id:
|
||||
props.cost_schedule_files.remove(i)
|
||||
print(f"Cost schedule id={cost_schedule_id} csv filepath correctly removed")
|
||||
return
|
||||
else:
|
||||
return
|
||||
|
||||
@classmethod
|
||||
def delete_all_cost_items(cls):
|
||||
cost_schedule = tool.Cost.get_active_cost_schedule()
|
||||
items = ifcopenshell.util.cost.get_root_cost_items(cost_schedule)
|
||||
for item in items:
|
||||
cost_item_id = item.id()
|
||||
ifcopenshell.api.run("cost.remove_cost_item", tool.Ifc.get(), cost_item = item)
|
||||
tool.Cost.clean_up_cost_item_tree(cost_item_id)
|
||||
|
||||
@classmethod
|
||||
def refresh_cost_schedule_csv(cls):
|
||||
from ifc5d.csv2ifc import Csv2Ifc
|
||||
|
||||
props = cls.get_cost_props()
|
||||
cost_schedule_id = props.active_cost_schedule_id
|
||||
file_path = next((item.csv_filepath for item in props.cost_schedule_files if item.cost_item_id == cost_schedule_id), None)
|
||||
if not file_path:
|
||||
return
|
||||
|
||||
cost_schedule = tool.Ifc.get_entity_by_id(cost_schedule_id)
|
||||
|
||||
csv2ifc = Csv2Ifc()
|
||||
csv2ifc.csv = file_path
|
||||
csv2ifc.file = tool.Ifc.get()
|
||||
csv2ifc.cost_schedule = cost_schedule
|
||||
csv2ifc.is_schedule_of_rates = False
|
||||
csv2ifc.refresh()
|
||||
|
||||
print("Csv file correctly refreshed")
|
||||
|
||||
@classmethod
|
||||
def add_cost_column(cls, name: str) -> None:
|
||||
props = cls.get_cost_props()
|
||||
|
||||
@@ -127,6 +127,10 @@ class Csv2Ifc:
|
||||
self.parse_csv()
|
||||
self.create_ifc()
|
||||
|
||||
def refresh(self) -> None:
|
||||
self.parse_csv()
|
||||
self.create_cost_items(self.cost_items)
|
||||
|
||||
def parse_csv(self) -> None:
|
||||
"""Fill ``headers`` and ``cost_items`` based on data from csv file."""
|
||||
self.cost_items = []
|
||||
|
||||
Reference in New Issue
Block a user