From 05d835410daa23c2116d691db3d277e61bfea5e6 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 19 Dec 2020 21:48:23 +1100 Subject: [PATCH] Reimplement basic BCF metadata editing and further improve BCF UI --- .../blenderbim/bim/__init__.py | 5 + .../blenderbim/bim/operator.py | 59 +++++- src/ifcblenderexport/blenderbim/bim/prop.py | 48 +++-- src/ifcblenderexport/blenderbim/bim/ui.py | 170 +++++++++++------- 4 files changed, 199 insertions(+), 83 deletions(-) diff --git a/src/ifcblenderexport/blenderbim/bim/__init__.py b/src/ifcblenderexport/blenderbim/bim/__init__.py index 075f00d236..66e6a42635 100644 --- a/src/ifcblenderexport/blenderbim/bim/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/__init__.py @@ -29,6 +29,10 @@ if bpy is not None: operator.LoadBcfProject, operator.LoadBcfTopics, operator.LoadBcfComments, + operator.EditBcfProjectName, + operator.EditBcfAuthor, + operator.EditBcfTopicName, + operator.EditBcfTopic, operator.SaveBcfProject, operator.AddBcfTopic, operator.ViewBcfTopic, @@ -297,6 +301,7 @@ if bpy is not None: ui.BIM_PT_ifccsv, ui.BIM_PT_ifcclash, ui.BIM_PT_bcf, + ui.BIM_PT_bcf_metadata, ui.BIM_PT_bcf_comments, ui.BIM_PT_owner, ui.BIM_PT_people, diff --git a/src/ifcblenderexport/blenderbim/bim/operator.py b/src/ifcblenderexport/blenderbim/bim/operator.py index aa2ccc7d77..ed8f122da3 100644 --- a/src/ifcblenderexport/blenderbim/bim/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/operator.py @@ -527,7 +527,6 @@ class LoadBcfProject(bpy.types.Operator): bcfxml = bcfstore.BcfStore.get_bcfxml() if self.filepath: bcfxml.get_project(self.filepath) - bpy.context.scene.BCFProperties.is_editable = False bpy.context.scene.BCFProperties.name = bcfxml.project.name bpy.ops.bim.load_bcf_topics() bpy.context.scene.BCFProperties.is_loaded = True @@ -627,6 +626,64 @@ class LoadBcfComments(bpy.types.Operator): return {"FINISHED"} +class EditBcfProjectName(bpy.types.Operator): + bl_idname = "bim.edit_bcf_project_name" + bl_label = "Edit BCF Project Name" + + def execute(self, context): + bcfxml = bcfstore.BcfStore.get_bcfxml() + bcfxml.project.name = bpy.context.scene.BCFProperties.name + bcfxml.edit_project() + return {"FINISHED"} + + +class EditBcfAuthor(bpy.types.Operator): + bl_idname = "bim.edit_bcf_author" + bl_label = "Edit BCF Author" + + def execute(self, context): + bcfxml = bcfstore.BcfStore.get_bcfxml() + bcfxml.author = bpy.context.scene.BCFProperties.author + return {"FINISHED"} + + +class EditBcfTopicName(bpy.types.Operator): + bl_idname = "bim.edit_bcf_topic_name" + bl_label = "Edit BCF Topic Name" + + def execute(self, context): + props = bpy.context.scene.BCFProperties + blender_topic = props.topics[props.active_topic_index] + bcfxml = bcfstore.BcfStore.get_bcfxml() + topic = bcfxml.topics[blender_topic.name] + topic.title = blender_topic.title + bcfxml.edit_topic(topic) + return {"FINISHED"} + + +class EditBcfTopic(bpy.types.Operator): + bl_idname = "bim.edit_bcf_topic" + bl_label = "Edit BCF Topic" + + def execute(self, context): + props = bpy.context.scene.BCFProperties + blender_topic = props.topics[props.active_topic_index] + bcfxml = bcfstore.BcfStore.get_bcfxml() + + topic = bcfxml.topics[blender_topic.name] + topic.title = blender_topic.title or None + topic.priority = blender_topic.priority or None + topic.due_date = blender_topic.due_date or None + topic.assigned_to = blender_topic.assigned_to or None + topic.stage = blender_topic.stage or None + topic.description = blender_topic.description or None + topic.topic_status = blender_topic.status or None + topic.topic_type = blender_topic.type or None + + bcfxml.edit_topic(topic) + return {"FINISHED"} + + class SaveBcfProject(bpy.types.Operator): bl_idname = "bim.save_bcf_project" bl_label = "Save BCF Project" diff --git a/src/ifcblenderexport/blenderbim/bim/prop.py b/src/ifcblenderexport/blenderbim/bim/prop.py index 1d3f421664..7fd0c5e456 100644 --- a/src/ifcblenderexport/blenderbim/bim/prop.py +++ b/src/ifcblenderexport/blenderbim/bim/prop.py @@ -540,6 +540,35 @@ def refreshFontSize(self, context): annotation.Annotator.resize_text(context.active_object) +def updateBcfProjectName(self, context): + bpy.ops.bim.edit_bcf_project_name() + + +def updateBcfAuthor(self, context): + bpy.ops.bim.edit_bcf_author() + + +def updateBcfTopicName(self, context): + bpy.ops.bim.edit_bcf_topic_name() + + +def updateBcfTopicIsEditable(self, context): + if not self.is_editable: + print("EDITING!") + bpy.ops.bim.edit_bcf_topic() + + +def refreshBcfTopic(self, context): + global bcfviewpoints_enum + bcfviewpoints_enum = None + + props = bpy.context.scene.BCFProperties + bcfxml = bcfstore.BcfStore.get_bcfxml() + topic = props.topics[props.active_topic_index] + header = bcfxml.get_header(topic.name) + getBcfViewpoints(self, context) + + class StrProperty(PropertyGroup): pass @@ -948,7 +977,7 @@ class BcfComment(PropertyGroup): class BcfTopic(PropertyGroup): name: StringProperty(name="GUID") - title: StringProperty(default="", name="Title") + title: StringProperty(default="", name="Title", update=updateBcfTopicName) type: StringProperty(default="", name="Type") status: StringProperty(default="", name="Status") priority: StringProperty(default="", name="Priority") @@ -968,17 +997,7 @@ class BcfTopic(PropertyGroup): document_references: CollectionProperty(name="Document References", type=BcfDocumentReference) related_topics: CollectionProperty(name="Related Topics", type=StrProperty) comments: CollectionProperty(name="Comments", type=BcfComment) - - -def refreshBcfTopic(self, context): - global bcfviewpoints_enum - bcfviewpoints_enum = None - - props = bpy.context.scene.BCFProperties - bcfxml = bcfstore.BcfStore.get_bcfxml() - topic = props.topics[props.active_topic_index] - header = bcfxml.get_header(topic.name) - getBcfViewpoints(self, context) + is_editable: BoolProperty(name="Is Editable", default=False, update=updateBcfTopicIsEditable) class PropertySetTemplate(PropertyGroup): @@ -1487,11 +1506,10 @@ class BIMProperties(PropertyGroup): class BCFProperties(PropertyGroup): - is_editable: BoolProperty(name="Is Editable", default=False) is_loaded: BoolProperty(name="Is Loaded", default=False) comment_text_width: IntProperty(name="Comment Text Width", default=40) - name: StringProperty(default="", name="Project Name") - author: StringProperty(default="john@doe.com", name="Author Email") + name: StringProperty(default="", name="Project Name", update=updateBcfProjectName) + author: StringProperty(default="john@doe.com", name="Author Email", update=updateBcfAuthor) topics: CollectionProperty(name="BCF Topics", type=BcfTopic) active_topic_index: IntProperty(name="Active BCF Topic Index", update=refreshBcfTopic) diff --git a/src/ifcblenderexport/blenderbim/bim/ui.py b/src/ifcblenderexport/blenderbim/bim/ui.py index 12c0ee2278..61058397f5 100644 --- a/src/ifcblenderexport/blenderbim/bim/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/ui.py @@ -1658,6 +1658,7 @@ class BIM_PT_bcf(Panel): def draw(self, context): layout = self.layout layout.use_property_split = True + layout.use_property_decorate = False scene = context.scene props = bpy.context.scene.BCFProperties @@ -1682,10 +1683,14 @@ class BIM_PT_bcf(Panel): row.template_list("BIM_UL_topics", "", props, "topics", props, "active_topic_index") col = row.column(align=True) col.operator("bim.add_bcf_topic", icon="ADD", text="") + if props.active_topic_index < len(props.topics): + topic = props.topics[props.active_topic_index] + col.prop(topic, "is_editable", icon="CHECKMARK" if topic.is_editable else "GREASEPENCIL", icon_only=True) if props.active_topic_index < len(props.topics): topic = props.topics[props.active_topic_index] row = layout.row() + row.enabled = topic.is_editable row.prop(topic, "description", text="") row = layout.row() @@ -1693,85 +1698,115 @@ class BIM_PT_bcf(Panel): row.operator("bim.activate_bcf_viewpoint", icon="SCENE", text="") col = layout.column(align=True) - col.prop(topic, "type") - col.prop(topic, "status") - col.prop(topic, "priority") - col.prop(topic, "stage") - col.prop(topic, "assigned_to") - col.prop(topic, "due_date") + if topic.type: + col.prop(topic, "type", emboss=topic.is_editable) + if topic.status: + col.prop(topic, "status", emboss=topic.is_editable) + if topic.priority: + col.prop(topic, "priority", emboss=topic.is_editable) + if topic.stage: + col.prop(topic, "stage", emboss=topic.is_editable) + if topic.assigned_to: + col.prop(topic, "assigned_to", emboss=topic.is_editable) + if topic.due_date: + col.prop(topic, "due_date", emboss=topic.is_editable) col = layout.column(align=True) - col.enabled = False - col.prop(topic, "creation_date") - col.prop(topic, "creation_author") - col.prop(topic, "modified_date") - col.prop(topic, "modified_author") + if topic.modified_date: + col.prop(topic, "modified_date", emboss=False) + col.prop(topic, "modified_author", emboss=False) + else: + col.prop(topic, "creation_date", emboss=False) + col.prop(topic, "creation_author", emboss=False) - bcfxml = bcfstore.BcfStore.get_bcfxml() - bcf_topic = bcfxml.topics[topic.name] - if bcf_topic.header: - layout.label(text="Header Files:") - for index, f in enumerate(bcf_topic.header.files): - box = self.layout.box() - row = box.row(align=True) - row.label(text=f.filename, icon="FILE_BLANK") - if f.is_external: - row.operator("bim.open_uri", icon="URL", text="").uri = f.reference - else: - op = row.operator("bim.open_uri", icon="FILE_FOLDER", text="") - op.uri = os.path.join(bcfxml.filepath, topic.name, f.reference) - box.label(text=f.date) - #box.label(text=f.ifc_project) - #box.label(text=f.ifc_spatial_structure_element) +class BIM_PT_bcf_metadata(Panel): + bl_label = "BCF Metadata" + bl_idname = "BIM_PT_bcf_metadata" + bl_options = {"DEFAULT_CLOSED"} + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "scene" + bl_parent_id = "BIM_PT_bcf" - if topic.reference_links: - layout.label(text="Reference Links:") - for index, link in enumerate(topic.reference_links): - row = layout.row(align=True) - row.prop(link, "name") - row.operator("bim.open_uri", icon="URL", text="").uri = link.name + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False - if topic.labels: - layout.label(text="Labels:") - for index, label in enumerate(topic.labels): - row = layout.row(align=True) - row.prop(label, "name", text="") + scene = context.scene + props = bpy.context.scene.BCFProperties - if topic.bim_snippet.schema: - layout.label(text="BIM Snippet:") - row = layout.row(align=True) - row.prop(topic.bim_snippet, "type") - if topic.bim_snippet.schema: - row.operator("bim.open_uri", icon="URL", text="").uri = topic.bim_snippet.schema + if props.active_topic_index >= len(props.topics): + layout.label(text="No BCF project is loaded") + return - row = layout.row(align=True) - row.prop(topic.bim_snippet, "reference") - if topic.bim_snippet.is_external: - row.operator("bim.open_uri", icon="URL", text="").uri = topic.bim_snippet.reference + topic = props.topics[props.active_topic_index] + bcfxml = bcfstore.BcfStore.get_bcfxml() + bcf_topic = bcfxml.topics[topic.name] + + if bcf_topic.header: + layout.label(text="Header Files:") + for index, f in enumerate(bcf_topic.header.files): + box = self.layout.box() + row = box.row(align=True) + row.label(text=f.filename, icon="FILE_BLANK") + if f.is_external: + row.operator("bim.open_uri", icon="URL", text="").uri = f.reference else: op = row.operator("bim.open_uri", icon="FILE_FOLDER", text="") - op.uri = os.path.join(bcfxml.filepath, topic.name, topic.bim_snippet.reference) + op.uri = os.path.join(bcfxml.filepath, topic.name, f.reference) + box.label(text=f.date) + #box.label(text=f.ifc_project) + #box.label(text=f.ifc_spatial_structure_element) - if topic.document_references: - layout.label(text="Document References:") - for index, doc in enumerate(topic.document_references): - box = self.layout.box() - row = box.row(align=True) - row.prop(doc, "reference") - if doc.is_external: - row.operator("bim.open_uri", icon="URL", text="").uri = doc.reference - else: - op = row.operator("bim.open_uri", icon="FILE_FOLDER", text="") - op.uri = os.path.join(bcfxml.filepath, topic.name, doc.reference) - row = box.row(align=True) - row.prop(doc, "description") + if topic.reference_links: + layout.label(text="Reference Links:") + for index, link in enumerate(topic.reference_links): + row = layout.row(align=True) + row.prop(link, "name") + row.operator("bim.open_uri", icon="URL", text="").uri = link.name - if topic.related_topics: - layout.label(text="Related Topics:") - for related_topic in topic.related_topics: - row = layout.row(align=True) - row.operator("bim.view_bcf_topic", text=related_topic.name).topic_guid = related_topic.name + if topic.labels: + layout.label(text="Labels:") + for index, label in enumerate(topic.labels): + row = layout.row(align=True) + row.prop(label, "name", text="") + + if topic.bim_snippet.schema: + layout.label(text="BIM Snippet:") + row = layout.row(align=True) + row.prop(topic.bim_snippet, "type") + if topic.bim_snippet.schema: + row.operator("bim.open_uri", icon="URL", text="").uri = topic.bim_snippet.schema + + row = layout.row(align=True) + row.prop(topic.bim_snippet, "reference") + if topic.bim_snippet.is_external: + row.operator("bim.open_uri", icon="URL", text="").uri = topic.bim_snippet.reference + else: + op = row.operator("bim.open_uri", icon="FILE_FOLDER", text="") + op.uri = os.path.join(bcfxml.filepath, topic.name, topic.bim_snippet.reference) + + if topic.document_references: + layout.label(text="Document References:") + for index, doc in enumerate(topic.document_references): + box = self.layout.box() + row = box.row(align=True) + row.prop(doc, "reference") + if doc.is_external: + row.operator("bim.open_uri", icon="URL", text="").uri = doc.reference + else: + op = row.operator("bim.open_uri", icon="FILE_FOLDER", text="") + op.uri = os.path.join(bcfxml.filepath, topic.name, doc.reference) + row = box.row(align=True) + row.prop(doc, "description") + + if topic.related_topics: + layout.label(text="Related Topics:") + for related_topic in topic.related_topics: + row = layout.row(align=True) + row.operator("bim.view_bcf_topic", text=related_topic.name).topic_guid = related_topic.name class BIM_PT_bcf_comments(Panel): @@ -1786,6 +1821,7 @@ class BIM_PT_bcf_comments(Panel): def draw(self, context): layout = self.layout layout.use_property_split = True + layout.use_property_decorate = False scene = context.scene props = bpy.context.scene.BCFProperties