class_name TimeEntriesItemsTree extends Tree enum COL{ TEXT, TIME } const META_KEY = "time_entry" var config: ConfigManager = preload("res://config_manager.tres") var _timer := Timer.new() func _ready() -> void: hide_root = true add_child(_timer) # warning-ignore:return_value_discarded connect("button_pressed", self, "_on_button_pressed") # warning-ignore:return_value_discarded _timer.connect("timeout", self, "_on_timer_timeout") # warning-ignore:return_value_discarded config.connect("time_sheet_loaded", self, "populate_entries") # warning-ignore:return_value_discarded connect("item_edited", self, "on_Tree_item_edited") populate_entries() func on_Tree_item_edited(): var tree_item := get_edited() var time_entry := tree_item.get_meta(META_KEY) as TimeEntry if time_entry == null: return var edited_start_time_str := tree_item.get_text(COL.TEXT) var edited_start_time := TimeStamp.new().from_string(edited_start_time_str) if edited_start_time.year == 1970: _update_from_time_entry(time_entry, tree_item) return var edited_duration_str := tree_item.get_text(COL.TIME) var edited_duration := TimeEntry.period_to_time(edited_duration_str) if edited_duration == -1: _update_from_time_entry(time_entry, tree_item) return var edited_end_time_unix := edited_start_time.unix + edited_duration var edited_end_time := TimeStamp.new().from_unix_time(edited_end_time_unix) if edited_start_time.equals(time_entry.start_time) \ and edited_end_time.equals(time_entry.end_time): _update_from_time_entry(time_entry, tree_item) return time_entry.start_time = edited_start_time time_entry.end_time = edited_end_time config.timesheet.save() func populate_entries() -> void: clear() var tree_items_root := create_item() var item_entries_tree := config.timesheet.make_items_tree() _populate_from_entry(tree_items_root, item_entries_tree) _timer.start() func _on_timer_timeout() -> void: config.timesheet.update() func _populate_from_entry(tree_item_root: TreeItem, time_entry_item_root: TimeEntryTreeItem): var children := time_entry_item_root.children for time_entry_name in children: var time_entry_item: TimeEntryTreeItem = children[time_entry_name] var item := find_or_create_item(tree_item_root, time_entry_name) item.set_metadata(COL.TEXT, time_entry_name) item.set_text(COL.TIME, time_entry_item.get_period()) # warning-ignore:return_value_discarded time_entry_item.connect("end_time_updated", self, "_on_time_entry_changed_update_item", [time_entry_item, item]) _populate_from_entry(item, time_entry_item) var has_at_least_one_running_entry := time_entry_item.find_active_time_entry() != null var texture := preload("res://assets/stop_small.svg") \ if has_at_least_one_running_entry \ else preload("res://assets/play_small.svg") item.add_button(COL.TIME, texture) var entries = time_entry_item_root.time_entries for entry_item in entries: var time_entry_item := entry_item as TimeEntryTreeItem var item := create_item(tree_item_root) var time_entry := time_entry_item.time_entry item.set_meta(META_KEY, time_entry) item.set_metadata(COL.TEXT, time_entry.name) item.set_editable(COL.TEXT, true) item.set_editable(COL.TIME, true) _update_from_time_entry(time_entry, item) # warning-ignore:return_value_discarded time_entry_item.connect("end_time_updated", self, "_on_time_entry_changed_update_item", [time_entry_item, item]) func _update_from_time_entry(time_entry: TimeEntry, item: TreeItem) -> void: item.set_text(COL.TEXT, time_entry.start_time.to_string()) item.set_text(COL.TIME, time_entry.get_period()) if time_entry.is_closed == false: if item.get_button_count(COL.TIME) < 1: var texture := preload("res://assets/stop_small.svg") item.add_button(COL.TIME, texture, 0) else: if item.get_button_count(COL.TIME) > 0: item.erase_button(COL.TIME, 0) func _on_time_entry_changed_update_item(time_entry_item: TimeEntryTreeItem, item: TreeItem) -> void: item.set_text(COL.TIME, time_entry_item.get_period()) func _on_button_pressed(item: TreeItem, _column: int, _id: int) -> void: var task_name: String = item.get_metadata(COL.TEXT) if task_name == "": return config.timesheet.toggle_entry(task_name) ## Unecessary in Godot 4, can bre replaced with get_children() static func _get_tree_item_children(item: TreeItem): var children = [] var child = item.get_children() if child == null: return children children.append(child) child = child.get_next() while child != null: children.append(child) child = child.get_next() return children ## Finds an item in the tree by text func find_item(root: TreeItem, item_name: String) -> TreeItem: for child in _get_tree_item_children(root): if child.get_text(COL.TEXT) == item_name: return child return null func find_or_create_item(root: TreeItem, item_name: String) -> TreeItem: var child := find_item(root, item_name) if child != null: return child child = create_item(root) child.set_text(COL.TEXT, item_name) return child