Task trees can now be sorted by any attribute independent of the WBS

This commit is contained in:
Dion Moult
2021-06-23 18:17:39 +10:00
parent 788a5a829e
commit 312de694b6
4 changed files with 74 additions and 24 deletions
@@ -75,6 +75,7 @@ classes = (
operator.BlenderBIM_RedrawDatePicker,
operator.AddTaskColumn,
operator.RemoveTaskColumn,
operator.SetTaskSortColumn,
prop.WorkPlan,
prop.BIMWorkPlanProperties,
prop.Task,
@@ -244,10 +244,14 @@ class EnableEditingTasks(bpy.types.Operator):
self.contracted_tasks = json.loads(self.props.contracted_tasks)
self.sort_keys = {
i: Data.tasks[i]["Identification"] or "" for i in Data.work_schedules[self.work_schedule]["RelatedObjects"]
i: self.get_sort_key(Data.tasks[i]) for i in Data.work_schedules[self.work_schedule]["RelatedObjects"]
}
for related_object_id in sorted(self.sort_keys, key=self.natural_sort_key):
related_object_ids = sorted(self.sort_keys, key=self.natural_sort_key)
if self.props.is_sort_reversed:
related_object_ids.reverse()
for related_object_id in related_object_ids:
self.create_new_task_li(related_object_id, 0)
bpy.ops.bim.load_task_properties()
self.props.editing_type = "TASKS"
@@ -262,10 +266,27 @@ class EnableEditingTasks(bpy.types.Operator):
if task["RelatedObjects"]:
new.has_children = True
if new.is_expanded:
self.sort_keys = {i: Data.tasks[i]["Identification"] or "" for i in task["RelatedObjects"]}
for related_object_id in sorted(self.sort_keys, key=self.natural_sort_key):
self.sort_keys = {i: self.get_sort_key(Data.tasks[i]) for i in task["RelatedObjects"]}
related_object_ids = sorted(self.sort_keys, key=self.natural_sort_key)
if self.props.is_sort_reversed:
related_object_ids.reverse()
for related_object_id in related_object_ids:
self.create_new_task_li(related_object_id, level_index + 1)
def get_sort_key(self, task):
# Sorting only applies to actual tasks, not the WBS
if task["RelatedObjects"]:
# Sorry for the hack
return "0000000000" + (task["Identification"] or "")
if not self.props.sort_column:
return task["Identification"] or ""
column_type, name = self.props.sort_column.split(".")
if column_type == "IfcTask":
return task.get(name)
elif column_type == "IfcTaskTime" and task.get("TaskTime"):
task_time = Data.task_times[task.get("TaskTime")].get(name)
return task["Identification"] or ""
def natural_sort_key(self, i, _nsre=re.compile("([0-9]+)")):
s = self.sort_keys[i]
return [int(text) if text.isdigit() else text.lower() for text in _nsre.split(s)]
@@ -1710,15 +1731,15 @@ class RecalculateSchedule(bpy.types.Operator):
class AddTaskColumn(bpy.types.Operator):
bl_idname = "bim.add_task_column"
bl_label = "Add Task Column"
type: bpy.props.StringProperty()
column_type: bpy.props.StringProperty()
name: bpy.props.StringProperty()
data_type: 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
new.name = f"{self.column_type}.{self.name}"
new.data_type = self.data_type
return {"FINISHED"}
@@ -1730,3 +1751,15 @@ class RemoveTaskColumn(bpy.types.Operator):
self.props = context.scene.BIMWorkScheduleProperties
self.props.columns.remove(self.props.active_column_index)
return {"FINISHED"}
class SetTaskSortColumn(bpy.types.Operator):
bl_idname = "bim.set_task_sort_column"
bl_label = "Set Task Sort Column"
column: bpy.props.StringProperty()
def execute(self, context):
self.props = context.scene.BIMWorkScheduleProperties
self.props.sort_column = self.column
bpy.ops.bim.enable_editing_tasks(work_schedule=self.props.active_work_schedule_id)
return {"FINISHED"}
@@ -256,6 +256,16 @@ class BIMWorkScheduleProperties(PropertyGroup):
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")
sort_column: StringProperty(name="Sort Column")
is_sort_reversed: BoolProperty(name="Is Sort Reversed")
column_types: EnumProperty(
items=[
("IfcTask", "IfcTask", ""),
("IfcTaskTime", "IfcTaskTime", ""),
("Special", "Special", ""),
],
name="Column Types",
)
task_columns: EnumProperty(items=getTaskColumns, name="Task Columns")
task_time_columns: EnumProperty(items=getTaskTimeColumns, name="Task Time Columns")
other_columns: EnumProperty(
@@ -138,23 +138,26 @@ class BIM_PT_work_schedules(Panel):
def draw_column_ui(self):
row = self.layout.row(align=True)
row.prop(self.props, "task_columns", text="")
row.prop(self.props, "column_types", text="")
column_type = self.props.column_types
if self.props.column_types == "IfcTask":
row.prop(self.props, "task_columns", text="")
name, data_type = self.props.task_columns.split("/")
elif self.props.column_types == "IfcTaskTime":
row.prop(self.props, "task_time_columns", text="")
name, data_type = self.props.task_time_columns.split("/")
elif self.props.column_types == "Special":
row.prop(self.props, "other_columns", text="")
column_type, name = self.props.other_columns.split(".")
data_type = "string"
row.operator("bim.set_task_sort_column", text="", icon="SORTALPHA").column = f"{column_type}.{name}"
row.prop(
self.props, "is_sort_reversed", text="", icon="SORT_DESC" if self.props.is_sort_reversed else "SORT_ASC"
)
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"
op.column_type = column_type
op.name = name
op.data_type = data_type
self.layout.template_list("BIM_UL_task_columns", "", self.props, "columns", self.props, "active_column_index")
@@ -285,9 +288,12 @@ class BIM_PT_work_schedules(Panel):
class BIM_UL_task_columns(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
props = context.scene.BIMWorkScheduleProperties
if item:
row = layout.row(align=True)
row.prop(item, "name", emboss=False, text="")
if props.sort_column == item.name:
row.label(text="", icon="SORTALPHA")
row.operator("bim.remove_task_column", text="", icon="X")