You can now customise the data columns shown in the work task tree

This commit is contained in:
Dion Moult
2021-06-22 19:32:59 +10:00
parent 2c49b3bde8
commit e863015e85
4 changed files with 150 additions and 35 deletions
@@ -73,6 +73,8 @@ classes = (
operator.BlenderBIM_DatePicker,
operator.BlenderBIM_DatePickerSetDate,
operator.BlenderBIM_RedrawDatePicker,
operator.AddTaskColumn,
operator.RemoveTaskColumn,
prop.WorkPlan,
prop.BIMWorkPlanProperties,
prop.Task,
@@ -85,6 +87,7 @@ classes = (
ui.BIM_PT_work_plans,
ui.BIM_PT_work_schedules,
ui.BIM_PT_work_calendars,
ui.BIM_UL_task_columns,
ui.BIM_UL_tasks,
)
@@ -1705,3 +1705,28 @@ class RecalculateSchedule(bpy.types.Operator):
)
Data.load(self.file)
return {"FINISHED"}
class AddTaskColumn(bpy.types.Operator):
bl_idname = "bim.add_task_column"
bl_label = "Add Task Column"
type: bpy.props.StringProperty()
name: bpy.props.StringProperty()
def execute(self, context):
self.props = context.scene.BIMWorkScheduleProperties
new = self.props.columns.add()
name, data_type = self.name.split("/")
new.name = f"{self.type}.{name}"
new.data_type = data_type
return {"FINISHED"}
class RemoveTaskColumn(bpy.types.Operator):
bl_idname = "bim.remove_task_column"
bl_label = "Remove Task Column"
def execute(self, context):
self.props = context.scene.BIMWorkScheduleProperties
self.props.columns.remove(self.props.active_column_index)
return {"FINISHED"}
@@ -1,5 +1,6 @@
import bpy
import ifcopenshell.api
import ifcopenshell.util.attribute
from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.sequence.data import Data
from blenderbim.bim.prop import StrProperty, Attribute
@@ -17,6 +18,53 @@ from bpy.props import (
)
taskcolumns_enum = []
tasktimecolumns_enum = []
def purge():
global taskcolumns_enum
global tasktimecolumns_enum
taskcolumns_enum = []
tasktimecolumns_enum = []
def getTaskColumns(self, context):
global taskcolumns_enum
if not len(taskcolumns_enum) and IfcStore.get_schema():
taskcolumns_enum.extend(
[
(a.name() + "/" + ifcopenshell.util.attribute.get_primitive_type(a), a.name(), "")
for a in IfcStore.get_schema().declaration_by_name("IfcTask").all_attributes()
if ifcopenshell.util.attribute.get_primitive_type(a)
in ["string", "float", "integer", "boolean", "enum"]
]
)
return taskcolumns_enum
def getTaskTimeColumns(self, context):
global tasktimecolumns_enum
if not len(tasktimecolumns_enum) and IfcStore.get_schema():
tasktimecolumns_enum.extend(
[
(a.name() + "/" + ifcopenshell.util.attribute.get_primitive_type(a), a.name(), "")
for a in IfcStore.get_schema().declaration_by_name("IfcTaskTime").all_attributes()
if ifcopenshell.util.attribute.get_primitive_type(a)
in ["string", "float", "integer", "boolean", "enum"]
]
)
return tasktimecolumns_enum
def getWorkSchedules(self, context):
return [(str(k), v["Name"], "") for k, v in Data.work_schedules.items()]
def getWorkCalendars(self, context):
return [(str(k), v["Name"], "") for k, v in Data.work_calendars.items()]
def updateTaskName(self, context):
props = context.scene.BIMWorkScheduleProperties
if not props.is_task_update_enabled or self.name == "Unnamed":
@@ -160,17 +208,6 @@ def updateVisualisationStartFinish(self, context, startfinish):
setattr(self, startfinish, canonical_value)
workschedule_enum = []
def getWorkSchedules(self, context):
return [(str(k), v["Name"], "") for k, v in Data.work_schedules.items()]
def getWorkCalendars(self, context):
return [(str(k), v["Name"], "") for k, v in Data.work_calendars.items()]
class Task(PropertyGroup):
name: StringProperty(name="Name", update=updateTaskName)
identification: StringProperty(name="Identification", update=updateTaskIdentification)
@@ -216,8 +253,17 @@ class BIMWorkScheduleProperties(PropertyGroup):
active_task_id: IntProperty(name="Active Task Id")
task_attributes: CollectionProperty(name="Task Attributes", type=Attribute)
should_show_visualisation_ui: BoolProperty(name="Should Show Visualisation UI", default=False)
should_show_times: BoolProperty(name="Should Show Times", default=False)
should_show_calendars: BoolProperty(name="Should Show Calendars", default=False)
should_show_column_ui: BoolProperty(name="Should Show Column UI", default=False)
columns: CollectionProperty(name="Columns", type=Attribute)
active_column_index: IntProperty(name="Active Column Index")
task_columns: EnumProperty(items=getTaskColumns, name="Task Columns")
task_time_columns: EnumProperty(items=getTaskTimeColumns, name="Task Time Columns")
other_columns: EnumProperty(
items=[
("Controls.Calendar", "Calendar", ""),
],
name="Special Columns",
)
active_task_time_id: IntProperty(name="Active Task Id")
task_time_attributes: CollectionProperty(name="Task Time Attributes", type=Attribute)
contracted_tasks: StringProperty(name="Contracted Task Items", default="[]")
@@ -111,8 +111,7 @@ class BIM_PT_work_schedules(Panel):
if self.props.editing_type == "WORK_SCHEDULE":
row.operator("bim.edit_work_schedule", text="", icon="CHECKMARK")
elif self.props.editing_type == "TASKS":
row.prop(self.props, "should_show_times", text="", icon="TIME")
row.prop(self.props, "should_show_calendars", text="", icon="VIEW_ORTHO")
row.prop(self.props, "should_show_column_ui", text="", icon="SHORTDISPLAY")
row.prop(self.props, "should_show_visualisation_ui", text="", icon="CAMERA_STEREO")
row.operator("bim.generate_gantt_chart", text="", icon="NLA").work_schedule = work_schedule_id
row.operator("bim.recalculate_schedule", text="", icon="FILE_REFRESH").work_schedule = work_schedule_id
@@ -128,6 +127,8 @@ class BIM_PT_work_schedules(Panel):
row.operator("bim.remove_work_schedule", text="", icon="X").work_schedule = work_schedule_id
if self.props.active_work_schedule_id == work_schedule_id:
if self.props.should_show_column_ui:
self.draw_column_ui()
if self.props.should_show_visualisation_ui:
self.draw_visualisation_ui()
if self.props.editing_type == "WORK_SCHEDULE":
@@ -135,6 +136,28 @@ class BIM_PT_work_schedules(Panel):
elif self.props.editing_type == "TASKS":
self.draw_editable_task_ui(work_schedule_id)
def draw_column_ui(self):
row = self.layout.row(align=True)
row.prop(self.props, "task_columns", text="")
op = row.operator("bim.add_task_column", text="", icon="ADD")
op.type = "IfcTask"
op.name = self.props.task_columns
row = self.layout.row(align=True)
row.prop(self.props, "task_time_columns", text="")
op = row.operator("bim.add_task_column", text="", icon="ADD")
op.type = "IfcTaskTime"
op.name = self.props.task_time_columns
row = self.layout.row(align=True)
row.prop(self.props, "other_columns", text="")
op = row.operator("bim.add_task_column", text="", icon="ADD")
type, name = self.props.other_columns.split(".")
op.type = type
op.name = f"{name}/string"
self.layout.template_list("BIM_UL_task_columns", "", self.props, "columns", self.props, "active_column_index")
def draw_visualisation_ui(self):
row = self.layout.row(align=True)
target_prop = "BIMWorkScheduleProperties.visualisation_start"
@@ -260,10 +283,19 @@ class BIM_PT_work_schedules(Panel):
blenderbim.bim.helper.draw_attributes(self.props.task_time_attributes, self.layout)
class BIM_UL_task_columns(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item:
row = layout.row(align=True)
row.prop(item, "name", emboss=False, text="")
row.operator("bim.remove_task_column", text="", icon="X")
class BIM_UL_tasks(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
if item:
props = context.scene.BIMWorkScheduleProperties
task = IfcStore.get_file().by_id(item.ifc_definition_id)
row = layout.row(align=True)
for i in range(0, item.level_index):
row.label(text="", icon="BLANK1")
@@ -281,27 +313,36 @@ class BIM_UL_tasks(UIList):
row.prop(item, "identification", emboss=False, text="")
row.prop(item, "name", emboss=False, text="")
if props.should_show_times:
if item.derived_start:
row.label(text=item.derived_start + "*")
for column in props.columns:
if column.name == "IfcTaskTime.ScheduleStart":
if item.derived_start:
row.label(text=item.derived_start + "*")
else:
row.prop(item, "start", emboss=False, text="")
elif column.name == "IfcTaskTime.ScheduleFinish":
if item.derived_finish:
row.label(text=item.derived_finish + "*")
else:
row.prop(item, "finish", emboss=False, text="")
elif column.name == "IfcTaskTime.ScheduleDuration":
if item.derived_duration:
row.label(text=item.derived_duration + "*")
else:
row.prop(item, "duration", emboss=False, text="")
elif column.name == "Controls.Calendar":
if item.derived_calendar:
row.label(text=item.derived_calendar + "*")
else:
row.label(text=item.calendar or "-")
else:
row.prop(item, "start", emboss=False, text="")
if item.derived_finish:
row.label(text=item.derived_finish + "*")
else:
row.prop(item, "finish", emboss=False, text="")
if item.derived_duration:
row.label(text=item.derived_duration + "*")
else:
row.prop(item, "duration", emboss=False, text="")
if props.should_show_calendars:
if item.derived_calendar:
row.label(text=item.derived_calendar + "*")
else:
row.label(text=item.calendar or "-")
ifc_class, name = column.name.split(".")
if ifc_class == "IfcTask":
value = getattr(task, name)
elif ifc_class == "IfcTaskTime":
value = getattr(task.TaskTime, name) if task.TaskTime else None
if value is None:
value = "-"
row.label(text=str(value))
if context.active_object:
oprops = context.active_object.BIMObjectProperties