From 0293c133ab08dd3efbbe7d8a74e52874ba449602 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 2 Sep 2022 14:03:05 +1000 Subject: [PATCH] Fix #2364. Bug where classifications couldn't be added in IFC2X3. --- src/blenderbim/blenderbim/bim/ifc.py | 2 + .../bim/module/classification/__init__.py | 19 ++- .../bim/module/classification/data.py | 91 ++++++++++ .../bim/module/classification/operator.py | 155 ++++++++---------- .../bim/module/classification/prop.py | 47 +----- .../bim/module/classification/ui.py | 129 +++++++-------- .../blenderbim/bim/module/pset_template/ui.py | 1 - .../ifcopenshell/api/classification/data.py | 2 +- 8 files changed, 233 insertions(+), 213 deletions(-) create mode 100644 src/blenderbim/blenderbim/bim/module/classification/data.py diff --git a/src/blenderbim/blenderbim/bim/ifc.py b/src/blenderbim/blenderbim/bim/ifc.py index ca5b6438ae..8f020bfbe1 100644 --- a/src/blenderbim/blenderbim/bim/ifc.py +++ b/src/blenderbim/blenderbim/bim/ifc.py @@ -39,6 +39,8 @@ class IfcStore: edited_objs = set() pset_template_path = "" pset_template_file = None + classification_path = "" + classification_file = None library_path = "" library_file = None element_listeners = set() diff --git a/src/blenderbim/blenderbim/bim/module/classification/__init__.py b/src/blenderbim/blenderbim/bim/module/classification/__init__.py index 64d2a29a5a..9fdb326907 100644 --- a/src/blenderbim/blenderbim/bim/module/classification/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/classification/__init__.py @@ -20,18 +20,19 @@ import bpy from . import ui, prop, operator classes = ( - operator.LoadClassificationLibrary, operator.AddClassification, - operator.RemoveClassification, - operator.EnableEditingClassification, - operator.DisableEditingClassification, - operator.EditClassification, - operator.RemoveClassificationReference, - operator.EnableEditingClassificationReference, - operator.DisableEditingClassificationReference, - operator.EditClassificationReference, operator.AddClassificationReference, operator.ChangeClassificationLevel, + operator.DisableEditingClassification, + operator.DisableEditingClassificationReference, + operator.DisableEditingClassificationReferences, + operator.EditClassification, + operator.EditClassificationReference, + operator.EnableEditingClassification, + operator.EnableEditingClassificationReference, + operator.LoadClassificationLibrary, + operator.RemoveClassification, + operator.RemoveClassificationReference, prop.ClassificationReference, prop.BIMClassificationProperties, prop.BIMClassificationReferenceProperties, diff --git a/src/blenderbim/blenderbim/bim/module/classification/data.py b/src/blenderbim/blenderbim/bim/module/classification/data.py new file mode 100644 index 0000000000..52e5087b58 --- /dev/null +++ b/src/blenderbim/blenderbim/bim/module/classification/data.py @@ -0,0 +1,91 @@ +# BlenderBIM Add-on - OpenBIM Blender Add-on +# Copyright (C) 2022 Dion Moult +# +# This file is part of BlenderBIM Add-on. +# +# BlenderBIM Add-on is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# BlenderBIM Add-on 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with BlenderBIM Add-on. If not, see . + +import bpy +import ifcopenshell +import ifcopenshell.util.date +import ifcopenshell.util.classification +import blenderbim.tool as tool +from blenderbim.bim.ifc import IfcStore + + +def refresh(): + ClassificationsData.is_loaded = False + ClassificationReferencesData.is_loaded = False + + +class ClassificationsData: + data = {} + is_loaded = False + + @classmethod + def load(cls): + cls.is_loaded = True + cls.data["has_classification_file"] = cls.has_classification_file() + cls.data["classifications"] = cls.classifications() + cls.data["available_classifications"] = cls.available_classifications() + + @classmethod + def has_classification_file(cls): + return bool(IfcStore.classification_file) + + @classmethod + def classifications(cls): + results = [] + for element in tool.Ifc.get().by_type("IfcClassification"): + data = element.get_info() + if IfcStore.classification_file.schema == "IFC2X3" and element.EditionDate: + data["EditionDate"] = ifcopenshell.util.date.ifc2datetime(data["EditionDate"]) + results.append(data) + return results + + @classmethod + def available_classifications(cls): + if not IfcStore.classification_file: + return [] + return [(str(e.id()), e.Name, "") for e in IfcStore.classification_file.by_type("IfcClassification")] + + +class ClassificationReferencesData: + data = {} + is_loaded = False + + @classmethod + def load(cls): + cls.is_loaded = True + cls.data["references"] = cls.references() + cls.data["is_available_classification_added"] = cls.is_available_classification_added() + + @classmethod + def references(cls): + results = [] + element = tool.Ifc.get_entity(bpy.context.active_object) + if element: + for reference in ifcopenshell.util.classification.get_references(element): + data = reference.get_info() + del data["ReferencedSource"] + results.append(data) + return results + + @classmethod + def is_available_classification_added(cls): + if not IfcStore.classification_file or not IfcStore.classification_file.by_type("IfcClassification"): + return False + props = bpy.context.scene.BIMClassificationProperties + name = IfcStore.classification_file.by_id(int(props.available_classifications)).Name + return name in [e.Name for e in tool.Ifc.get().by_type("IfcClassification")] diff --git a/src/blenderbim/blenderbim/bim/module/classification/operator.py b/src/blenderbim/blenderbim/bim/module/classification/operator.py index 1db448c9c7..021078842c 100644 --- a/src/blenderbim/blenderbim/bim/module/classification/operator.py +++ b/src/blenderbim/blenderbim/bim/module/classification/operator.py @@ -1,5 +1,5 @@ # BlenderBIM Add-on - OpenBIM Blender Add-on -# Copyright (C) 2020, 2021 Dion Moult +# Copyright (C) 2020-2022 Dion Moult # # This file is part of BlenderBIM Add-on. # @@ -18,46 +18,40 @@ import bpy import json +import ifcopenshell import ifcopenshell.api +import blenderbim.tool as tool +import blenderbim.bim.helper from blenderbim.bim.ifc import IfcStore -from ifcopenshell.api.classification.data import Data -from blenderbim.bim.module.classification.prop import getClassifications, getReferences -class LoadClassificationLibrary(bpy.types.Operator): +class LoadClassificationLibrary(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.load_classification_library" bl_label = "Load Classification Library" filename_ext = ".ifc" filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"}) filepath: bpy.props.StringProperty(subtype="FILE_PATH") - def execute(self, context): - Data.load_library(self.filepath) - getClassifications(self, context) - return {"FINISHED"} - def invoke(self, context, event): context.window_manager.fileselect_add(self) return {"RUNNING_MODAL"} + def _execute(self, context): + IfcStore.classification_file = ifcopenshell.open(self.filepath) -class AddClassification(bpy.types.Operator): + +class AddClassification(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.add_classification" bl_label = "Add Classification" bl_options = {"REGISTER", "UNDO"} - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - def _execute(self, context): props = context.scene.BIMClassificationProperties ifcopenshell.api.run( "classification.add_classification", - IfcStore.get_file(), - **{"classification": Data.library_file.by_id(int(props.available_classifications))}, + tool.Ifc.get(), + classification=IfcStore.classification_file.by_id(int(props.available_classifications)), ) - Data.load(IfcStore.get_file()) - return {"FINISHED"} class EnableEditingClassification(bpy.types.Operator): @@ -67,19 +61,21 @@ class EnableEditingClassification(bpy.types.Operator): classification: bpy.props.IntProperty() def execute(self, context): + def callback(name, prop, data): + if name == "ReferenceTokens": + new = bpy.context.scene.BIMGeoreferenceProperties.projected_crs.add() + new.name = name + new.data_type = "string" + new.is_null = data[name] is None + new.is_optional = True + new.string_value = "" if new.is_null else json.dumps(data[name]) + return True + props = context.scene.BIMClassificationProperties props.classification_attributes.clear() - classification_data = Data.classifications[self.classification] - for attribute in IfcStore.get_schema().declaration_by_name("IfcClassification").all_attributes(): - new = props.classification_attributes.add() - new.name = attribute.name() - new.is_null = classification_data[attribute.name()] is None - new.is_optional = attribute.optional() - new.data_type = "string" - if attribute.name() == "ReferenceTokens": - new.string_value = "" if new.is_null else json.dumps(classification_data[attribute.name()]) - else: - new.string_value = "" if new.is_null else classification_data[attribute.name()] + blenderbim.bim.helper.import_attributes2( + tool.Ifc.get().by_id(self.classification), props.classification_attributes, callback + ) props.active_classification_id = self.classification return {"FINISHED"} @@ -94,34 +90,26 @@ class DisableEditingClassification(bpy.types.Operator): return {"FINISHED"} -class RemoveClassification(bpy.types.Operator): +class RemoveClassification(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.remove_classification" bl_label = "Remove Classification" bl_options = {"REGISTER", "UNDO"} classification: bpy.props.IntProperty() - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - def _execute(self, context): self.file = IfcStore.get_file() ifcopenshell.api.run( "classification.remove_classification", - self.file, - **{"classification": self.file.by_id(self.classification)}, + tool.Ifc.get(), + classification=self.file.by_id(self.classification), ) - Data.load(IfcStore.get_file()) - return {"FINISHED"} -class EditClassification(bpy.types.Operator): +class EditClassification(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.edit_classification" bl_label = "Edit Classification" bl_options = {"REGISTER", "UNDO"} - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - def _execute(self, context): props = context.scene.BIMClassificationProperties attributes = {} @@ -138,9 +126,7 @@ class EditClassification(bpy.types.Operator): self.file, **{"classification": self.file.by_id(props.active_classification_id), "attributes": attributes}, ) - Data.load(IfcStore.get_file()) bpy.ops.bim.disable_editing_classification() - return {"FINISHED"} class EnableEditingClassificationReference(bpy.types.Operator): @@ -154,16 +140,7 @@ class EnableEditingClassificationReference(bpy.types.Operator): obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object props = obj.BIMClassificationReferenceProperties props.reference_attributes.clear() - reference_data = Data.references[self.reference] - for attribute in IfcStore.get_schema().declaration_by_name("IfcClassificationReference").all_attributes(): - if attribute.name() == "ReferencedSource": - continue - new = props.reference_attributes.add() - new.name = attribute.name() - new.is_null = reference_data[attribute.name()] is None - new.is_optional = attribute.optional() - new.data_type = "string" - new.string_value = "" if new.is_null else reference_data[attribute.name()] + blenderbim.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.reference), props.reference_attributes) props.active_reference_id = self.reference return {"FINISHED"} @@ -180,41 +157,30 @@ class DisableEditingClassificationReference(bpy.types.Operator): return {"FINISHED"} -class RemoveClassificationReference(bpy.types.Operator): +class RemoveClassificationReference(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.remove_classification_reference" bl_label = "Remove Classification Reference" bl_options = {"REGISTER", "UNDO"} reference: bpy.props.IntProperty() obj: bpy.props.StringProperty() - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - def _execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object self.file = IfcStore.get_file() ifcopenshell.api.run( "classification.remove_reference", self.file, - **{ - "reference": self.file.by_id(self.reference), - "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), - }, + reference=self.file.by_id(self.reference), + product=self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), ) - Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) - Data.load(IfcStore.get_file()) - return {"FINISHED"} -class EditClassificationReference(bpy.types.Operator): +class EditClassificationReference(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.edit_classification_reference" bl_label = "Edit Classification Reference" bl_options = {"REGISTER", "UNDO"} obj: bpy.props.StringProperty() - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - def _execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object props = obj.BIMClassificationReferenceProperties @@ -228,48 +194,37 @@ class EditClassificationReference(bpy.types.Operator): ifcopenshell.api.run( "classification.edit_reference", self.file, - **{"reference": self.file.by_id(props.active_reference_id), "attributes": attributes}, + reference=self.file.by_id(props.active_reference_id), attributes=attributes, ) - Data.load(IfcStore.get_file()) bpy.ops.bim.disable_editing_classification_reference() - return {"FINISHED"} -class AddClassificationReference(bpy.types.Operator): +class AddClassificationReference(bpy.types.Operator, tool.Ifc.Operator): bl_idname = "bim.add_classification_reference" bl_label = "Add Classification Reference" bl_options = {"REGISTER", "UNDO"} reference: bpy.props.IntProperty() obj: bpy.props.StringProperty() - def execute(self, context): - return IfcStore.execute_ifc_operator(self, context) - def _execute(self, context): obj = bpy.data.objects.get(self.obj) if self.obj else context.active_object self.file = IfcStore.get_file() - classification = None - props = context.scene.BIMClassificationProperties - classification_name = Data.library_classifications[int(props.available_classifications)] - for classification_id, classification in Data.classifications.items(): - if classification["Name"] == classification_name: - classification = self.file.by_id(classification_id) + classification = None + classification_name = IfcStore.classification_file.by_id(int(props.available_classifications)).Name + for element in tool.Ifc.get().by_type("IfcClassification"): + if element.Name == classification_name: + classification = element break ifcopenshell.api.run( "classification.add_reference", self.file, - **{ - "reference": Data.library_file.by_id(self.reference), - "product": self.file.by_id(obj.BIMObjectProperties.ifc_definition_id), - "classification": classification, - }, + reference=IfcStore.classification_file.by_id(self.reference), + product=tool.Ifc.get_entity(obj), + classification=classification, ) - Data.load(IfcStore.get_file(), obj.BIMObjectProperties.ifc_definition_id) - Data.load(IfcStore.get_file()) - return {"FINISHED"} class ChangeClassificationLevel(bpy.types.Operator): @@ -279,5 +234,27 @@ class ChangeClassificationLevel(bpy.types.Operator): parent_id: bpy.props.IntProperty() def execute(self, context): - getReferences(self, context, parent_id=self.parent_id) + props = context.scene.BIMClassificationProperties + props.available_library_references.clear() + for reference in IfcStore.classification_file.by_id(self.parent_id).HasReferences: + new = props.available_library_references.add() + new.identification = reference.Identification or "" + new.name = reference.Name or "" + new.ifc_definition_id = reference.id() + new.has_references = bool(reference.HasReferences) + new.referenced_source + if reference.ReferencedSource.is_a("IfcClassificationReference"): + props.active_library_referenced_source = reference.ReferencedSource.ReferencedSource.id() + else: + props.active_library_referenced_source = 0 return {"FINISHED"} + + +class DisableEditingClassificationReferences(bpy.types.Operator): + bl_idname = "bim.disable_editing_classification_references" + bl_label = "Disable Editing Classification References" + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + props = context.scene.BIMClassificationProperties + props.available_library_references.clear() diff --git a/src/blenderbim/blenderbim/bim/module/classification/prop.py b/src/blenderbim/blenderbim/bim/module/classification/prop.py index 4b5c091763..71d8f7c53b 100644 --- a/src/blenderbim/blenderbim/bim/module/classification/prop.py +++ b/src/blenderbim/blenderbim/bim/module/classification/prop.py @@ -17,8 +17,9 @@ # along with BlenderBIM Add-on. If not, see . import bpy +from blenderbim.bim.ifc import IfcStore from blenderbim.bim.prop import StrProperty, Attribute -from ifcopenshell.api.classification.data import Data +from blenderbim.bim.module.classification.data import ClassificationsData from bpy.types import PropertyGroup from bpy.props import ( PointerProperty, @@ -31,42 +32,10 @@ from bpy.props import ( CollectionProperty, ) -classification_enum = [] - - -def purge(): - global classification_enum - classification_enum = [] - - -def getClassifications(self, context): - global classification_enum - if len(classification_enum) < 1: - classification_enum.clear() - classification_enum.extend([(str(i), n, "") for i, n in Data.library_classifications.items()]) - if classification_enum: - getReferences(self, context, parent_id=int(classification_enum[0][0])) - return classification_enum - - -def updateClassification(self, context): - getReferences(self, context, parent_id=int(self.available_classifications)) - - -def getReferences(self, context, parent_id=None): - props = context.scene.BIMClassificationProperties - props.available_library_references.clear() - for reference in Data.library_file.by_id(parent_id).HasReferences: - new = props.available_library_references.add() - new.identification = reference.Identification or "" - new.name = reference.Name or "" - new.ifc_definition_id = reference.id() - new.has_references = bool(reference.HasReferences) - new.referenced_source - if reference.ReferencedSource.is_a("IfcClassificationReference"): - props.active_library_referenced_source = reference.ReferencedSource.ReferencedSource.id() - else: - props.active_library_referenced_source = 0 +def get_available_classifications(self, context): + if not ClassificationsData.is_loaded: + ClassificationsData.load() + return ClassificationsData.data["available_classifications"] class ClassificationReference(PropertyGroup): @@ -78,9 +47,7 @@ class ClassificationReference(PropertyGroup): class BIMClassificationProperties(PropertyGroup): - available_classifications: EnumProperty( - items=getClassifications, name="Available Classifications", update=updateClassification - ) + available_classifications: EnumProperty(items=get_available_classifications, name="Available Classifications") classification_attributes: CollectionProperty(name="Classification Attributes", type=Attribute) active_classification_id: IntProperty(name="Active Classification Id") available_library_references: CollectionProperty(name="Available Library References", type=ClassificationReference) diff --git a/src/blenderbim/blenderbim/bim/module/classification/ui.py b/src/blenderbim/blenderbim/bim/module/classification/ui.py index dc395cb33d..5c1ae86b7d 100644 --- a/src/blenderbim/blenderbim/bim/module/classification/ui.py +++ b/src/blenderbim/blenderbim/bim/module/classification/ui.py @@ -16,10 +16,12 @@ # You should have received a copy of the GNU General Public License # along with BlenderBIM Add-on. If not, see . +import blenderbim.bim.helper +import blenderbim.tool as tool import blenderbim.bim.module.classification.prop as classification_prop from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore -from ifcopenshell.api.classification.data import Data +from blenderbim.bim.module.classification.data import ClassificationsData, ClassificationReferencesData class BIM_PT_classifications(Panel): @@ -33,15 +35,15 @@ class BIM_PT_classifications(Panel): @classmethod def poll(cls, context): - return IfcStore.get_file() + return tool.Ifc.get() def draw(self, context): - if not Data.is_loaded: - Data.load(IfcStore.get_file()) + if not ClassificationsData.is_loaded: + ClassificationsData.load() self.props = context.scene.BIMClassificationProperties - if Data.library_file: + if ClassificationsData.data["has_classification_file"]: row = self.layout.row(align=True) row.prop(self.props, "available_classifications", text="") row.operator("bim.load_classification_library", text="", icon="IMPORT") @@ -51,33 +53,25 @@ class BIM_PT_classifications(Panel): row.label(text="No Active Classification Library") row.operator("bim.load_classification_library", text="", icon="IMPORT") - for classification_id, classification in Data.classifications.items(): - if self.props.active_classification_id == classification_id: - self.draw_editable_ui(classification) + for classification in ClassificationsData.data["classifications"]: + if self.props.active_classification_id == classification["id"]: + self.draw_editable_ui() else: - self.draw_ui(classification_id, classification) + self.draw_ui(classification) - def draw_editable_ui(self, classification): + def draw_editable_ui(self): row = self.layout.row(align=True) - row.prop(self.props.classification_attributes.get("Name"), "string_value", text="", icon="ASSET_MANAGER") - row.operator("bim.edit_classification", text="", icon="CHECKMARK") + row.operator("bim.edit_classification", text="Save changes", icon="CHECKMARK") row.operator("bim.disable_editing_classification", text="", icon="CANCEL") + blenderbim.bim.helper.draw_attributes(self.props.classification_attributes, self.layout) - for attribute in self.props.classification_attributes: - if attribute.name == "Name": - continue - row = self.layout.row(align=True) - row.prop(attribute, "string_value", text=attribute.name) - if attribute.is_optional: - row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") - - def draw_ui(self, classification_id, classification): + def draw_ui(self, classification): row = self.layout.row(align=True) row.label(text=classification["Name"], icon="ASSET_MANAGER") if not self.props.active_classification_id: op = row.operator("bim.enable_editing_classification", text="", icon="GREASEPENCIL") - op.classification = classification_id - row.operator("bim.remove_classification", text="", icon="X").classification = classification_id + op.classification = classification["id"] + row.operator("bim.remove_classification", text="", icon="X").classification = classification["id"] class BIM_PT_classification_references(Panel): @@ -93,74 +87,63 @@ class BIM_PT_classification_references(Panel): def poll(cls, context): if not context.active_object: return False - if not IfcStore.get_element(context.active_object.BIMObjectProperties.ifc_definition_id): - return False - return bool(context.active_object.BIMObjectProperties.ifc_definition_id) + return bool(tool.Ifc.get_entity(context.active_object)) def draw(self, context): + if not ClassificationReferencesData.is_loaded: + ClassificationReferencesData.load() + obj = context.active_object self.oprops = obj.BIMObjectProperties self.sprops = context.scene.BIMClassificationProperties self.props = obj.BIMClassificationReferenceProperties self.file = IfcStore.get_file() - if not Data.is_loaded: - Data.load(IfcStore.get_file()) - if self.oprops.ifc_definition_id not in Data.products: - Data.load(IfcStore.get_file(), self.oprops.ifc_definition_id) self.draw_add_ui(context) - reference_ids = Data.products[self.oprops.ifc_definition_id] - if not reference_ids: + if not ClassificationReferencesData.data["references"]: row = self.layout.row(align=True) row.label(text="No References") - for reference_id in reference_ids: - reference = Data.references[reference_id] - if self.props.active_reference_id == reference_id: - self.draw_editable_ui(reference) + for reference in ClassificationReferencesData.data["references"]: + if self.props.active_reference_id == reference["id"]: + self.draw_editable_ui() else: - self.draw_ui(reference_id, reference) + self.draw_ui(reference) def draw_add_ui(self, context): - if not classification_prop.getClassifications(self.sprops, context): + if not ClassificationReferencesData.data["is_available_classification_added"]: return - - name = Data.library_classifications[int(self.sprops.available_classifications)] - if name in [c["Name"] for c in Data.classifications.values()]: - row = self.layout.row(align=True) - row.prop(self.sprops, "available_classifications", text="") - if self.sprops.active_library_referenced_source: - op = row.operator("bim.change_classification_level", text="", icon="FRAME_PREV") - op.parent_id = self.sprops.active_library_referenced_source - op = row.operator("bim.add_classification_reference", text="", icon="ADD") - op.reference = self.sprops.available_library_references[ - self.sprops.active_library_reference_index - ].ifc_definition_id - self.layout.template_list( - "BIM_UL_classifications", - "", - self.sprops, - "available_library_references", - self.sprops, - "active_library_reference_index", - ) - - def draw_editable_ui(self, reference): row = self.layout.row(align=True) - row.prop(self.props.reference_attributes.get("Name"), "string_value", text="", icon="ASSET_MANAGER") - row.operator("bim.edit_classification_reference", text="", icon="CHECKMARK") + row.prop(self.sprops, "available_classifications", text="") + if not self.sprops.available_library_references: + op = row.operator("bim.change_classification_level", text="", icon="IMPORT") + op.parent_id = int(self.sprops.available_classifications) + return + if self.sprops.active_library_referenced_source: + op = row.operator("bim.change_classification_level", text="", icon="FRAME_PREV") + op.parent_id = self.sprops.active_library_referenced_source + op = row.operator("bim.add_classification_reference", text="", icon="ADD") + op.reference = self.sprops.available_library_references[ + self.sprops.active_library_reference_index + ].ifc_definition_id + row.operator("bim.disable_editing_classification_references", text="", icon="CANCEL") + self.layout.template_list( + "BIM_UL_classifications", + "", + self.sprops, + "available_library_references", + self.sprops, + "active_library_reference_index", + ) + + def draw_editable_ui(self): + row = self.layout.row(align=True) + row.operator("bim.edit_classification_reference", text="Save changes", icon="CHECKMARK") row.operator("bim.disable_editing_classification_reference", text="", icon="CANCEL") + blenderbim.bim.helper.draw_attributes(self.props.reference_attributes, self.layout) - for attribute in self.props.reference_attributes: - if attribute.name == "Name": - continue - row = self.layout.row(align=True) - row.prop(attribute, "string_value", text=attribute.name) - if attribute.is_optional: - row.prop(attribute, "is_null", icon="RADIOBUT_OFF" if attribute.is_null else "RADIOBUT_ON", text="") - - def draw_ui(self, reference_id, reference): + def draw_ui(self, reference): row = self.layout.row(align=True) if self.file.schema == "IFC2X3": name = reference["ItemReference"] or "No Identification" @@ -170,8 +153,8 @@ class BIM_PT_classification_references(Panel): row.label(text=reference["Name"] or "") if not self.props.active_reference_id: op = row.operator("bim.enable_editing_classification_reference", text="", icon="GREASEPENCIL") - op.reference = reference_id - row.operator("bim.remove_classification_reference", text="", icon="X").reference = reference_id + op.reference = reference["id"] + row.operator("bim.remove_classification_reference", text="", icon="X").reference = reference["id"] class BIM_UL_classifications(UIList): diff --git a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py index a5b984268b..324aee459d 100644 --- a/src/blenderbim/blenderbim/bim/module/pset_template/ui.py +++ b/src/blenderbim/blenderbim/bim/module/pset_template/ui.py @@ -18,7 +18,6 @@ import bpy from bpy.types import Panel -from blenderbim.bim.ifc import IfcStore from blenderbim.bim.helper import prop_with_search from blenderbim.bim.module.pset_template.data import PsetTemplatesData diff --git a/src/ifcopenshell-python/ifcopenshell/api/classification/data.py b/src/ifcopenshell-python/ifcopenshell/api/classification/data.py index 6fe085ff48..8d38727014 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/classification/data.py +++ b/src/ifcopenshell-python/ifcopenshell/api/classification/data.py @@ -66,7 +66,7 @@ class Data: for classification in cls._file.by_type("IfcClassification"): data = classification.get_info() if cls._file.schema == "IFC2X3" and data["EditionDate"]: - data["EditionDate"] = ifcopenshell.util.date(data.EditionDate).isoformat() + data["EditionDate"] = ifcopenshell.util.date.ifc2datetime(data["EditionDate"]).isoformat() cls.classifications[classification.id()] = data @classmethod