tasks list working
This commit is contained in:
parent
66b25bae97
commit
24c4b98a5e
57
assets/stop_small.svg
Normal file
57
assets/stop_small.svg
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="22"
|
||||||
|
height="22"
|
||||||
|
viewBox="0 0 5.8208333 5.8208333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
sodipodi:docname="stop_small.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#323232"
|
||||||
|
bordercolor="#111111"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="1"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:zoom="35.356609"
|
||||||
|
inkscape:cx="12.402208"
|
||||||
|
inkscape:cy="11.115319"
|
||||||
|
inkscape:window-width="1896"
|
||||||
|
inkscape:window-height="1029"
|
||||||
|
inkscape:window-x="12"
|
||||||
|
inkscape:window-y="39"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid7036"
|
||||||
|
originx="0"
|
||||||
|
originy="0"
|
||||||
|
empspacing="8" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:0.994836;stroke-width:4;stroke-linecap:round;stroke-opacity:0;paint-order:stroke markers fill;stop-color:#000000"
|
||||||
|
id="rect341"
|
||||||
|
width="4.7624998"
|
||||||
|
height="4.7624998"
|
||||||
|
x="0.52916664"
|
||||||
|
y="0.5291667" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
35
assets/stop_small.svg.import
Normal file
35
assets/stop_small.svg.import
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="StreamTexture"
|
||||||
|
path="res://.import/stop_small.svg-d7819f3a82ff689d7390798487abb123.stex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/stop_small.svg"
|
||||||
|
dest_files=[ "res://.import/stop_small.svg-d7819f3a82ff689d7390798487abb123.stex" ]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_mode=0
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
flags/repeat=0
|
||||||
|
flags/filter=true
|
||||||
|
flags/mipmaps=false
|
||||||
|
flags/anisotropic=false
|
||||||
|
flags/srgb=2
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/HDR_as_SRGB=false
|
||||||
|
process/invert_color=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
stream=false
|
||||||
|
size_limit=0
|
||||||
|
detect_3d=true
|
||||||
|
svg/scale=0.6
|
@ -40,6 +40,11 @@ _global_script_classes=[ {
|
|||||||
"path": "res://scripts/time_entry.gd"
|
"path": "res://scripts/time_entry.gd"
|
||||||
}, {
|
}, {
|
||||||
"base": "Reference",
|
"base": "Reference",
|
||||||
|
"class": "TimeEntryTreeItem",
|
||||||
|
"language": "GDScript",
|
||||||
|
"path": "res://scripts/time_entry_tree_item.gd"
|
||||||
|
}, {
|
||||||
|
"base": "Reference",
|
||||||
"class": "TimeSheet",
|
"class": "TimeSheet",
|
||||||
"language": "GDScript",
|
"language": "GDScript",
|
||||||
"path": "res://scripts/time_sheet.gd"
|
"path": "res://scripts/time_sheet.gd"
|
||||||
@ -56,6 +61,7 @@ _global_script_class_icons={
|
|||||||
"FileWatcher": "",
|
"FileWatcher": "",
|
||||||
"TimeEntriesItemsTree": "",
|
"TimeEntriesItemsTree": "",
|
||||||
"TimeEntry": "",
|
"TimeEntry": "",
|
||||||
|
"TimeEntryTreeItem": "",
|
||||||
"TimeSheet": "",
|
"TimeSheet": "",
|
||||||
"TimeStamp": ""
|
"TimeStamp": ""
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
class_name ConfigManager extends Resource
|
class_name ConfigManager extends Resource
|
||||||
|
|
||||||
|
|
||||||
signal entry_started
|
|
||||||
signal entry_stopped
|
|
||||||
signal file_changed
|
signal file_changed
|
||||||
|
signal time_sheet_reloaded
|
||||||
|
|
||||||
const CONFIG_PATH := "user://settings.cfg"
|
const CONFIG_PATH := "user://settings.cfg"
|
||||||
var _config := ConfigFile.new()
|
|
||||||
var _watcher: FileWatcher
|
|
||||||
|
|
||||||
var timesheet: TimeSheet setget ,get_timesheet
|
var timesheet: TimeSheet setget ,get_timesheet
|
||||||
|
|
||||||
|
var _config := ConfigFile.new()
|
||||||
|
var _watcher: FileWatcher
|
||||||
|
|
||||||
func get_timesheet() -> TimeSheet:
|
func get_timesheet() -> TimeSheet:
|
||||||
if timesheet == null:
|
if timesheet == null:
|
||||||
timesheet = _load_timesheet(get_current_file())
|
timesheet = _load_timesheet(get_current_file())
|
||||||
@ -20,29 +20,26 @@ func get_timesheet() -> TimeSheet:
|
|||||||
func _load_timesheet(path: String) -> TimeSheet:
|
func _load_timesheet(path: String) -> TimeSheet:
|
||||||
timesheet = TimeSheet.restore(path)
|
timesheet = TimeSheet.restore(path)
|
||||||
if timesheet == null:
|
if timesheet == null:
|
||||||
_watcher = null
|
|
||||||
return null
|
return null
|
||||||
_watcher = FileWatcher.new()
|
_watcher = FileWatcher.new()
|
||||||
_watcher.file_name = path
|
_watcher.file_name = path
|
||||||
|
# warning-ignore:return_value_discarded
|
||||||
|
_watcher.connect("file_changed", self, "reload_timesheet")
|
||||||
_watcher.start()
|
_watcher.start()
|
||||||
# warning-ignore:return_value_discarded
|
# warning-ignore:return_value_discarded
|
||||||
_watcher.connect("file_changed", self, "_on_file_changed")
|
#timesheet.connect("entry_started", self, "_on_entry_started")
|
||||||
# warning-ignore:return_value_discarded
|
# warning-ignore:return_value_discarded
|
||||||
timesheet.connect("entry_started", self, "_on_entry_started")
|
#timesheet.connect("entry_stopped", self, "_on_entry_stopped")
|
||||||
# warning-ignore:return_value_discarded
|
|
||||||
timesheet.connect("entry_stopped", self, "_on_entry_stopped")
|
|
||||||
return timesheet
|
return timesheet
|
||||||
|
|
||||||
|
|
||||||
func _on_entry_started() -> void:
|
func reload_timesheet() -> void:
|
||||||
emit_signal("entry_started")
|
var new_timesheet = _load_timesheet(get_current_file())
|
||||||
|
if new_timesheet == null:
|
||||||
func _on_entry_stopped() -> void:
|
printerr("failed to load new timesheet")
|
||||||
emit_signal("entry_stopped")
|
return
|
||||||
|
timesheet = new_timesheet
|
||||||
|
emit_signal("time_sheet_reloaded")
|
||||||
func _on_file_changed() -> void:
|
|
||||||
emit_signal("file_changed")
|
|
||||||
|
|
||||||
|
|
||||||
var current_file: String = "" setget set_current_file, get_current_file
|
var current_file: String = "" setget set_current_file, get_current_file
|
||||||
|
@ -2,11 +2,14 @@
|
|||||||
## Has a beginning and an end
|
## Has a beginning and an end
|
||||||
class_name TimeEntry
|
class_name TimeEntry
|
||||||
|
|
||||||
|
|
||||||
|
signal end_time_updated
|
||||||
|
signal closed
|
||||||
|
|
||||||
var name := ""
|
var name := ""
|
||||||
var closed := false
|
var is_closed := false
|
||||||
var start_time := TimeStamp.new()
|
var start_time := TimeStamp.new()
|
||||||
var end_time := TimeStamp.new()
|
var end_time := TimeStamp.new()
|
||||||
var previous_total := 0
|
|
||||||
|
|
||||||
|
|
||||||
func start_recording() -> TimeEntry:
|
func start_recording() -> TimeEntry:
|
||||||
@ -17,6 +20,13 @@ func start_recording() -> TimeEntry:
|
|||||||
|
|
||||||
func update() -> void:
|
func update() -> void:
|
||||||
end_time = end_time.from_current_time()
|
end_time = end_time.from_current_time()
|
||||||
|
emit_signal("end_time_updated")
|
||||||
|
|
||||||
|
|
||||||
|
func close() -> void:
|
||||||
|
update()
|
||||||
|
is_closed = true
|
||||||
|
emit_signal("closed")
|
||||||
|
|
||||||
|
|
||||||
func get_elapsed_seconds() -> int:
|
func get_elapsed_seconds() -> int:
|
||||||
@ -24,21 +34,11 @@ func get_elapsed_seconds() -> int:
|
|||||||
return elapsed
|
return elapsed
|
||||||
|
|
||||||
|
|
||||||
func get_total_elapsed_seconds() -> int:
|
|
||||||
var elapsed := get_elapsed_seconds() + previous_total
|
|
||||||
return elapsed
|
|
||||||
|
|
||||||
|
|
||||||
func get_period() -> String:
|
func get_period() -> String:
|
||||||
var time_in_secs := get_elapsed_seconds()
|
var time_in_secs := get_elapsed_seconds()
|
||||||
return time_to_period(time_in_secs)
|
return time_to_period(time_in_secs)
|
||||||
|
|
||||||
|
|
||||||
func get_total_period() -> String:
|
|
||||||
var time_in_secs := get_total_elapsed_seconds()
|
|
||||||
return time_to_period(time_in_secs)
|
|
||||||
|
|
||||||
|
|
||||||
static func time_to_period(time_in_secs: int) -> String:
|
static func time_to_period(time_in_secs: int) -> String:
|
||||||
# warning-ignore:integer_division
|
# warning-ignore:integer_division
|
||||||
var seconds := time_in_secs%60
|
var seconds := time_in_secs%60
|
||||||
@ -48,14 +48,16 @@ static func time_to_period(time_in_secs: int) -> String:
|
|||||||
var hours := (time_in_secs/60)/60
|
var hours := (time_in_secs/60)/60
|
||||||
return "%02d:%02d:%02d" % [hours, minutes, seconds]
|
return "%02d:%02d:%02d" % [hours, minutes, seconds]
|
||||||
|
|
||||||
|
|
||||||
func to_csv_line() -> PoolStringArray:
|
func to_csv_line() -> PoolStringArray:
|
||||||
return PoolStringArray([
|
return PoolStringArray([
|
||||||
name,
|
name,
|
||||||
start_time,
|
start_time,
|
||||||
end_time,
|
end_time,
|
||||||
str(get_elapsed_seconds()) if closed else tr(Consts.ONGOING)
|
str(get_elapsed_seconds()) if is_closed else tr(Consts.ONGOING)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
static func is_csv_line_valid(line: PoolStringArray) -> bool:
|
static func is_csv_line_valid(line: PoolStringArray) -> bool:
|
||||||
return line.size() > 3
|
return line.size() > 3
|
||||||
|
|
||||||
@ -68,9 +70,9 @@ func from_csv_line(line: PoolStringArray) -> TimeEntry:
|
|||||||
start_time.from_string(start_time_string)
|
start_time.from_string(start_time_string)
|
||||||
|
|
||||||
var elapsed_seconds = int(line[3]) if line[3].is_valid_integer() else 0
|
var elapsed_seconds = int(line[3]) if line[3].is_valid_integer() else 0
|
||||||
closed = elapsed_seconds > 0
|
is_closed = elapsed_seconds > 0
|
||||||
|
|
||||||
if closed == true:
|
if is_closed == true:
|
||||||
var end_time_string = line[2]
|
var end_time_string = line[2]
|
||||||
# warning-ignore:return_value_discarded
|
# warning-ignore:return_value_discarded
|
||||||
end_time.from_string(end_time_string)
|
end_time.from_string(end_time_string)
|
||||||
@ -79,5 +81,12 @@ func from_csv_line(line: PoolStringArray) -> TimeEntry:
|
|||||||
end_time.from_current_time()
|
end_time.from_current_time()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
func to_dict() -> Dictionary:
|
||||||
|
return {
|
||||||
|
start_time = start_time,
|
||||||
|
closed = is_closed,
|
||||||
|
}
|
||||||
|
|
||||||
func _to_string() -> String:
|
func _to_string() -> String:
|
||||||
return "%s\t%s\t%s"%[name, Consts.ONGOING if closed == false else "", start_time]
|
return "%s\t%s\t%s"%[name, tr(Consts.ONGOING) if is_closed == false else end_time.to_string(), start_time]
|
||||||
|
70
scripts/time_entry_tree_item.gd
Normal file
70
scripts/time_entry_tree_item.gd
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
class_name TimeEntryTreeItem
|
||||||
|
|
||||||
|
signal end_time_updated
|
||||||
|
|
||||||
|
var time_entry: TimeEntry
|
||||||
|
var children := {}
|
||||||
|
var time_entries := []
|
||||||
|
|
||||||
|
func get_child(parts: Array, or_create := false):
|
||||||
|
var TimeEntryTreeItem = load("res://scripts/time_entry_tree_item.gd")
|
||||||
|
if parts.size() == 0:
|
||||||
|
return self
|
||||||
|
var part: String = parts.pop_front()
|
||||||
|
if not children.has(part):
|
||||||
|
if or_create == false:
|
||||||
|
return null
|
||||||
|
var time_entry_tree_item = TimeEntryTreeItem.new()
|
||||||
|
# warning-ignore:return_value_discarded
|
||||||
|
time_entry_tree_item.connect("end_time_updated", self, "_on_end_time_updated")
|
||||||
|
children[part] = time_entry_tree_item
|
||||||
|
return children[part].get_child(parts, or_create)
|
||||||
|
|
||||||
|
|
||||||
|
func append(new_time_entry: TimeEntry) -> void:
|
||||||
|
var TimeEntryTreeItem = load("res://scripts/time_entry_tree_item.gd")
|
||||||
|
var time_entry_tree_item = TimeEntryTreeItem.new()
|
||||||
|
time_entry_tree_item.time_entry = new_time_entry
|
||||||
|
# warning-ignore:return_value_discarded
|
||||||
|
new_time_entry.connect("end_time_updated", time_entry_tree_item, "_on_end_time_updated")
|
||||||
|
# warning-ignore:return_value_discarded
|
||||||
|
time_entry_tree_item.connect("end_time_updated", self, "_on_end_time_updated")
|
||||||
|
time_entries.append(time_entry_tree_item)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_end_time_updated() -> void:
|
||||||
|
emit_signal("end_time_updated")
|
||||||
|
|
||||||
|
|
||||||
|
func get_elapsed_seconds() -> int:
|
||||||
|
var seconds := time_entry.get_elapsed_seconds() if time_entry != null else 0
|
||||||
|
for child_name in children:
|
||||||
|
var child = children[child_name]
|
||||||
|
seconds += child.get_elapsed_seconds()
|
||||||
|
for entry in time_entries:
|
||||||
|
seconds += entry.get_elapsed_seconds()
|
||||||
|
return seconds
|
||||||
|
|
||||||
|
|
||||||
|
func get_period() -> String:
|
||||||
|
var time_in_secs := get_elapsed_seconds()
|
||||||
|
return TimeEntry.time_to_period(time_in_secs)
|
||||||
|
|
||||||
|
|
||||||
|
func to_dict() -> Dictionary:
|
||||||
|
var json := {}
|
||||||
|
var times := []
|
||||||
|
if time_entries.size() > 0:
|
||||||
|
for entry in time_entries:
|
||||||
|
times.append(entry.to_dict())
|
||||||
|
json["__time"] = times
|
||||||
|
if children.size() > 0:
|
||||||
|
for name in children:
|
||||||
|
json[name] = children[name].to_dict()
|
||||||
|
return json
|
||||||
|
|
||||||
|
|
||||||
|
func _to_string() -> String:
|
||||||
|
var json := to_dict()
|
||||||
|
var json_string := JSON.print(json, "\t")
|
||||||
|
return json_string
|
@ -1,13 +1,9 @@
|
|||||||
class_name TimeSheet
|
class_name TimeSheet
|
||||||
|
|
||||||
signal entry_started
|
|
||||||
signal entry_stopped
|
|
||||||
|
|
||||||
var source_path := ""
|
var source_path := ""
|
||||||
var entries := []
|
var entries := []
|
||||||
var entries_names := {}
|
var tree := TimeEntryTreeItem.new()
|
||||||
var current_entry: TimeEntry
|
|
||||||
|
|
||||||
|
|
||||||
## Loads the data file
|
## Loads the data file
|
||||||
func load_file() -> bool:
|
func load_file() -> bool:
|
||||||
@ -19,6 +15,7 @@ func load_file() -> bool:
|
|||||||
printerr("Failed to open file %s"%[ProjectSettings.globalize_path(source_path)])
|
printerr("Failed to open file %s"%[ProjectSettings.globalize_path(source_path)])
|
||||||
return false
|
return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
while not file.eof_reached():
|
while not file.eof_reached():
|
||||||
var line := file.get_csv_line()
|
var line := file.get_csv_line()
|
||||||
if line.size() == 0 or "".join(line).length() == 0:
|
if line.size() == 0 or "".join(line).length() == 0:
|
||||||
@ -28,22 +25,32 @@ func load_file() -> bool:
|
|||||||
continue
|
continue
|
||||||
var entry := TimeEntry.new().from_csv_line(line)
|
var entry := TimeEntry.new().from_csv_line(line)
|
||||||
entries.append(entry)
|
entries.append(entry)
|
||||||
if entry.closed == false:
|
# warning-ignore:return_value_discarded
|
||||||
current_entry = entry
|
entry.connect("closed", self, "save")
|
||||||
if not entries_names.has(entry.name):
|
|
||||||
entries_names[entry.name] = 0
|
|
||||||
entries_names[entry.name] += entry.get_elapsed_seconds()
|
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
|
entries.sort_custom(self, "_sort_entries")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for entry_index in entries.size():
|
||||||
|
var entry: TimeEntry = entries[entry_index]
|
||||||
|
var parts: PoolStringArray = entry.name.split("/")
|
||||||
|
var repo: TimeEntryTreeItem = tree.get_child(parts, true)
|
||||||
|
repo.append(entry)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
|
func _sort_entries(a: TimeEntry, b: TimeEntry) -> bool:
|
||||||
|
return a.name < b.name
|
||||||
|
|
||||||
|
|
||||||
## Adds a new time entry to the tree and to the data file
|
## Adds a new time entry to the tree and to the data file
|
||||||
func start_entry(entry_name: String) -> void:
|
func start_entry(entry_name: String) -> void:
|
||||||
current_entry = TimeEntry.new().start_recording()
|
var current_entry := TimeEntry.new().start_recording()
|
||||||
current_entry.name = entry_name
|
current_entry.name = entry_name
|
||||||
current_entry.closed = false
|
current_entry.closed = false
|
||||||
if entry_name in entries_names:
|
|
||||||
current_entry.previous_total = entries_names[entry_name]
|
|
||||||
var file := File.new()
|
var file := File.new()
|
||||||
var success := file.open(source_path, File.READ_WRITE)
|
var success := file.open(source_path, File.READ_WRITE)
|
||||||
if success != OK:
|
if success != OK:
|
||||||
@ -55,22 +62,10 @@ func start_entry(entry_name: String) -> void:
|
|||||||
|
|
||||||
|
|
||||||
func update() -> void:
|
func update() -> void:
|
||||||
current_entry.update()
|
for entry in entries:
|
||||||
entries_names[current_entry.name] = current_entry.get_total_elapsed_seconds()
|
var time_entry := entry as TimeEntry
|
||||||
|
if time_entry.is_closed == false:
|
||||||
|
time_entry.update()
|
||||||
func close_entry() -> void:
|
|
||||||
current_entry.closed = true
|
|
||||||
save()
|
|
||||||
emit_signal("entry_stopped")
|
|
||||||
|
|
||||||
|
|
||||||
func get_period() -> String:
|
|
||||||
return current_entry.get_period()
|
|
||||||
|
|
||||||
|
|
||||||
func get_total_elapsed_seconds() -> int:
|
|
||||||
return current_entry.get_total_elapsed_seconds()
|
|
||||||
|
|
||||||
|
|
||||||
func save() -> void:
|
func save() -> void:
|
||||||
@ -90,5 +85,3 @@ static func restore(file_path: String) -> TimeSheet:
|
|||||||
if success:
|
if success:
|
||||||
return timesheet
|
return timesheet
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
|
||||||
|
6
test.gd
Normal file
6
test.gd
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
tool
|
||||||
|
extends EditorScript
|
||||||
|
|
||||||
|
|
||||||
|
func _run():
|
||||||
|
print ("c" < "b")
|
112
ui/tasks_list.gd
112
ui/tasks_list.gd
@ -7,55 +7,91 @@ enum COL{
|
|||||||
|
|
||||||
var config: ConfigManager = preload("res://config_manager.tres")
|
var config: ConfigManager = preload("res://config_manager.tres")
|
||||||
|
|
||||||
var current_item: TreeItem
|
var _timer := Timer.new()
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
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
|
# warning-ignore:return_value_discarded
|
||||||
config.connect("file_changed", self, "populate_entries")
|
config.connect("file_changed", self, "populate_entries")
|
||||||
|
# warning-ignore:return_value_discarded
|
||||||
|
config.connect("time_sheet_reloaded", self, "populate_entries")
|
||||||
populate_entries()
|
populate_entries()
|
||||||
|
|
||||||
|
|
||||||
func populate_entries() -> void:
|
func populate_entries() -> void:
|
||||||
clear()
|
clear()
|
||||||
var _root := create_item()
|
var tree_items_root := create_item()
|
||||||
var entries_names := config.timesheet.entries_names
|
var item_entries_tree := config.timesheet.tree
|
||||||
for entry_name in entries_names:
|
_populate_from_entry(tree_items_root, item_entries_tree)
|
||||||
|
_timer.start()
|
||||||
|
#for item in entries:
|
||||||
# warning-ignore:return_value_discarded
|
# warning-ignore:return_value_discarded
|
||||||
append_name_to_tree(entry_name, entries_names[entry_name])
|
# set_entry(entry)
|
||||||
|
|
||||||
|
|
||||||
|
# warning-ignore:unused_argument
|
||||||
func set_time_elapsed(total_elapsed: int) -> void:
|
func set_time_elapsed(total_elapsed: int) -> void:
|
||||||
current_item.set_text(COL.TIME, TimeEntry.time_to_period(total_elapsed))
|
#current_item.set_text(COL.TIME, TimeEntry.time_to_period(total_elapsed))
|
||||||
current_item.set_metadata(COL.TIME, total_elapsed)
|
#current_item.set_metadata(COL.TIME, total_elapsed)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
func set_current_item(task_name: String) -> void:
|
func set_current_item(_task_name: String) -> void:
|
||||||
current_item = append_name_to_tree(task_name, 0)
|
#current_item = append_name_to_tree(task_name, 0)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
func _on_timer_timeout() -> void:
|
||||||
func get_current_text() -> String:
|
config.timesheet.update()
|
||||||
var item := get_selected()
|
|
||||||
if not item:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
var resp = item.get_metadata(COL.TEXT)
|
|
||||||
if resp is String:
|
|
||||||
return resp
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
## Adds a new item to the tree, or returns the old item if it exists
|
func _populate_from_entry(tree_item_root: TreeItem, time_entry_item_root: TimeEntryTreeItem):
|
||||||
func append_name_to_tree(task_name: String, total_elapsed := 0) -> TreeItem:
|
var children := time_entry_item_root.children
|
||||||
var item := get_root()
|
for time_entry_name in children:
|
||||||
for item_name in task_name.split("/"):
|
var time_entry_item: TimeEntryTreeItem = children[time_entry_name]
|
||||||
item.collapsed = false
|
var item := find_or_create_item(tree_item_root, time_entry_name)
|
||||||
item = find_item(item, item_name, true)
|
item.set_metadata(COL.TEXT, time_entry_item)
|
||||||
item.set_metadata(COL.TEXT, task_name)
|
item.set_text(COL.TIME, time_entry_item.get_period())
|
||||||
item.set_text(COL.TIME, TimeEntry.time_to_period(total_elapsed))
|
# warning-ignore:return_value_discarded
|
||||||
item.set_metadata(COL.TIME, total_elapsed)
|
time_entry_item.connect("end_time_updated", self, "_on_time_entry_changed_update_item", [time_entry_item, item])
|
||||||
scroll_to_item(item)
|
_populate_from_entry(item, time_entry_item)
|
||||||
return item
|
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_text(COL.TEXT, time_entry.start_time.to_string())
|
||||||
|
item.set_metadata(COL.TEXT, time_entry_item)
|
||||||
|
item.set_text(COL.TIME, time_entry_item.get_period())
|
||||||
|
if time_entry.is_closed == false:
|
||||||
|
var texture := preload("res://assets/stop_small.svg")
|
||||||
|
item.add_button(COL.TIME, texture)
|
||||||
|
# warning-ignore:return_value_discarded
|
||||||
|
time_entry_item.connect("end_time_updated", self, "_on_time_entry_changed_update_item", [time_entry_item, item])
|
||||||
|
|
||||||
|
|
||||||
|
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 time_entry_tree_item: TimeEntryTreeItem = item.get_metadata(COL.TEXT)
|
||||||
|
if time_entry_tree_item == null:
|
||||||
|
return
|
||||||
|
var time_entry := time_entry_tree_item.time_entry
|
||||||
|
if time_entry == null:
|
||||||
|
return
|
||||||
|
if time_entry.is_closed:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
time_entry.close()
|
||||||
|
item.erase_button(COL.TIME, 0)
|
||||||
|
|
||||||
|
|
||||||
## Unecessary in Godot 4, can bre replaced with get_children()
|
## Unecessary in Godot 4, can bre replaced with get_children()
|
||||||
@ -73,13 +109,17 @@ static func _get_tree_item_children(item: TreeItem):
|
|||||||
|
|
||||||
|
|
||||||
## Finds an item in the tree by text
|
## Finds an item in the tree by text
|
||||||
func find_item(root: TreeItem, item_name: String, or_create: bool) -> TreeItem:
|
func find_item(root: TreeItem, item_name: String) -> TreeItem:
|
||||||
for child in _get_tree_item_children(root):
|
for child in _get_tree_item_children(root):
|
||||||
if child.get_text(COL.TEXT) == item_name:
|
if child.get_text(COL.TEXT) == item_name:
|
||||||
return child
|
return child
|
||||||
if or_create:
|
|
||||||
var child := create_item(root)
|
|
||||||
child.set_text(COL.TEXT, item_name)
|
|
||||||
child.set_text(COL.TIME, Consts.NO_TIME)
|
|
||||||
return child
|
|
||||||
return null
|
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
|
||||||
|
@ -14,7 +14,7 @@ onready var audio_stream_player := $"%AudioStreamPlayer" as AudioStreamPlayer
|
|||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
# warning-ignore:return_value_discarded
|
# warning-ignore:return_value_discarded
|
||||||
timer.connect("timeout", self, "_on_timer_timeout")
|
timer.connect("timeout", self, "_on_timer_timeout")
|
||||||
start_button.tooltip_text = tr(Consts.START)
|
start_button.hint_tooltip = tr(Consts.START)
|
||||||
start_button.toggle_mode = true
|
start_button.toggle_mode = true
|
||||||
# warning-ignore:return_value_discarded
|
# warning-ignore:return_value_discarded
|
||||||
start_button.connect("toggled", self, "_on_start_button_toggled")
|
start_button.connect("toggled", self, "_on_start_button_toggled")
|
||||||
@ -57,7 +57,7 @@ func _on_task_name_line_edit_text_changed(new_text: String) -> void:
|
|||||||
|
|
||||||
func set_button_as_stopped() -> void:
|
func set_button_as_stopped() -> void:
|
||||||
start_button.set_pressed_no_signal(false)
|
start_button.set_pressed_no_signal(false)
|
||||||
start_button.tooltip_text = tr(Consts.START)
|
start_button.hint_tooltip = tr(Consts.START)
|
||||||
time_label.text = Consts.NO_TIME
|
time_label.text = Consts.NO_TIME
|
||||||
start_button.theme_type_variation = Consts.THEME_OVERRIDE_START
|
start_button.theme_type_variation = Consts.THEME_OVERRIDE_START
|
||||||
timer.stop()
|
timer.stop()
|
||||||
@ -67,7 +67,7 @@ func set_button_as_started() -> void:
|
|||||||
## TODO: make this independent
|
## TODO: make this independent
|
||||||
# time_entries_items_tree.set_current_item(config.timesheet.current_entry.name)
|
# time_entries_items_tree.set_current_item(config.timesheet.current_entry.name)
|
||||||
start_button.set_pressed_no_signal(true)
|
start_button.set_pressed_no_signal(true)
|
||||||
start_button.tooltip_text = tr(Consts.STOP)
|
start_button.hint_tooltip = tr(Consts.STOP)
|
||||||
start_button.theme_type_variation = Consts.THEME_OVERRIDE_STOP
|
start_button.theme_type_variation = Consts.THEME_OVERRIDE_STOP
|
||||||
timer.start()
|
timer.start()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user