bugs squished

This commit is contained in:
xananax prozaxx 2023-04-22 03:08:05 +02:00
parent 24c4b98a5e
commit 17d8637156
13 changed files with 346 additions and 107 deletions

54
assets/play_small.svg Normal file
View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="13"
height="13"
viewBox="0 0 3.4395833 3.4395833"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="play_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="#ffffff"
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="6.3495909"
inkscape:cy="5.8263506"
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" />
</sodipodi:namedview>
<defs
id="defs2" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
id="rect11457"
style="fill:#ffffff;stroke-width:1.85208;paint-order:stroke markers fill;stop-color:#000000"
d="M 0.26458333,0.26458333 3.175,1.7197917 0.26458333,3.175 Z"
sodipodi:nodetypes="cccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/play_small.svg-6ecf1cf55097c1673c0917a7e7624a3c.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/play_small.svg"
dest_files=[ "res://.import/play_small.svg-6ecf1cf55097c1673c0917a7e7624a3c.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=1.0

View File

@ -86,6 +86,7 @@ window/per_pixel_transparency/enabled=true
window/energy_saving/keep_screen_on=false window/energy_saving/keep_screen_on=false
window/handheld/orientation="portrait" window/handheld/orientation="portrait"
window/ios/hide_home_indicator=false window/ios/hide_home_indicator=false
window/stretch/aspect="keep"
[rendering] [rendering]

View File

@ -1,8 +1,15 @@
class_name CMD class_name CMD
var command_line_arguments: Dictionary = {}
func unsurround(value: String, quotes := PoolStringArray(['"', "'"])) -> String: var _parsed := false
## @type Dictionary[String, String|bool]
var command_line_arguments: Dictionary = {} setget set_command_line_arguments, get_command_line_arguments
## Removes the first element find from the `quotes` array from the start and end of a string
## Also removes any whitespace resulting from removing the quoting elements
static func unsurround(value: String, quotes := PoolStringArray(['"', "'"])) -> String:
for quote_str in quotes: for quote_str in quotes:
if value.begins_with(quote_str) \ if value.begins_with(quote_str) \
and value.ends_with(quote_str) \ and value.ends_with(quote_str) \
@ -10,6 +17,7 @@ func unsurround(value: String, quotes := PoolStringArray(['"', "'"])) -> String:
return value.trim_prefix(quote_str).trim_suffix(quote_str).strip_edges() return value.trim_prefix(quote_str).trim_suffix(quote_str).strip_edges()
return value return value
## Returns a dictionary of all arguments passed after `--` on the command line ## Returns a dictionary of all arguments passed after `--` on the command line
## arguments take one of 2 forms: ## arguments take one of 2 forms:
## - `--arg` which is a boolean (using `--no-arg` for `false` is possible) ## - `--arg` which is a boolean (using `--no-arg` for `false` is possible)
@ -17,7 +25,7 @@ func unsurround(value: String, quotes := PoolStringArray(['"', "'"])) -> String:
## unsurround the string ## unsurround the string
## This function does no evaluation and does not attempt to guess the type of ## This function does no evaluation and does not attempt to guess the type of
## arguments. You will receive either bools, or strings. ## arguments. You will receive either bools, or strings.
func _read_arguments() -> Dictionary: static func parse_cmd_arguments() -> Dictionary:
var arguments := {} var arguments := {}
for arg in OS.get_cmdline_args(): for arg in OS.get_cmdline_args():
var argument: String = arg.lstrip("--").to_lower() var argument: String = arg.lstrip("--").to_lower()
@ -36,12 +44,27 @@ func _read_arguments() -> Dictionary:
return arguments return arguments
func set_command_line_arguments(_arguments: Dictionary) -> void:
printerr("get_command_line_arguments is a read only value")
func get_command_line_arguments() -> Dictionary:
if not _parsed:
_parsed = true
command_line_arguments = parse_cmd_arguments()
return command_line_arguments
## Returns a single argument passed after `--` on the command line
## if the argument does not exist, `default` is returned instead
## _parse_cmd_arguments() has to be called first
func get_argument(name: String, default = null): func get_argument(name: String, default = null):
if command_line_arguments.has(name): if get_command_line_arguments().has(name):
return command_line_arguments[name] return get_command_line_arguments()[name]
return default return default
## Verifies an argument exists on the command line
## _parse_cmd_arguments() has to be called first
func has_argument(name: String) -> bool: func has_argument(name: String) -> bool:
return command_line_arguments.has(name) return get_command_line_arguments().has(name)

View File

@ -1,25 +1,41 @@
## Reads the config, sets values. Acts a singleton because it proxies a const
## file path.
class_name ConfigManager extends Resource class_name ConfigManager extends Resource
signal file_changed
signal time_sheet_reloaded
const CONFIG_PATH := "user://settings.cfg" const CONFIG_PATH := "user://settings.cfg"
var timesheet: TimeSheet setget ,get_timesheet
var _config := ConfigFile.new() var _config := ConfigFile.new()
var _watcher: FileWatcher var _watcher: FileWatcher
###############################################################################
#
# SIGNAL
#
signal time_sheet_loaded
func emit_loaded() -> void:
emit_signal("time_sheet_loaded")
###############################################################################
#
# TIMESHEET FILE LOADING AND PARSING
#
var timesheet: TimeSheet setget ,get_timesheet
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_timesheet_file_path())
return timesheet return timesheet
func _load_timesheet(path: String) -> TimeSheet: func _load_timesheet(path: String) -> TimeSheet:
timesheet = TimeSheet.restore(path) var new_timesheet := TimeSheet.restore(path)
if timesheet == null: if new_timesheet == null:
return null return null
_watcher = FileWatcher.new() _watcher = FileWatcher.new()
_watcher.file_name = path _watcher.file_name = path
@ -30,72 +46,94 @@ func _load_timesheet(path: String) -> TimeSheet:
#timesheet.connect("entry_started", self, "_on_entry_started") #timesheet.connect("entry_started", self, "_on_entry_started")
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
#timesheet.connect("entry_stopped", self, "_on_entry_stopped") #timesheet.connect("entry_stopped", self, "_on_entry_stopped")
return timesheet return new_timesheet
func reload_timesheet() -> void: func reload_timesheet() -> void:
var new_timesheet = _load_timesheet(get_current_file()) var new_timesheet = _load_timesheet(get_current_timesheet_file_path())
if new_timesheet == null: if new_timesheet == null:
printerr("failed to load new timesheet") printerr("failed to load new timesheet")
return return
timesheet = new_timesheet timesheet = new_timesheet
emit_signal("time_sheet_reloaded") emit_loaded()
var current_file: String = "" setget set_current_file, get_current_file ###############################################################################
#
# TIMESHEET FILE PATH
#
var current_timesheet_file_path: String = "" setget set_current_timesheet_file_path, get_current_timesheet_file_path
func set_current_file(value: String) -> void: func set_current_timesheet_file_path(value: String) -> void:
timesheet = _load_timesheet(value) timesheet = _load_timesheet(value)
if timesheet == null: if timesheet == null:
return return
current_file = value current_timesheet_file_path = value
_config.set_value("MAIN", "file", value) _config.set_value("MAIN", "file", value)
emit_signal("file_changed") emit_loaded()
save() save()
func get_current_file() -> String: func get_current_timesheet_file_path() -> String:
var _default_path := OS.get_system_dir(OS.SYSTEM_DIR_DOCUMENTS, true).plus_file("mouse_timer.csv") var _default_path := OS.get_system_dir(OS.SYSTEM_DIR_DOCUMENTS, true).plus_file("mouse_timer.csv")
return _config.get_value("MAIN", "file", _default_path) return _config.get_value("MAIN", "file", _default_path)
###############################################################################
#
# THEME FILE LOADING AND PARSING
#
var theme: Theme setget , get_theme var theme: Theme setget , get_theme
func get_theme() -> Theme: func get_theme() -> Theme:
if theme == null: if theme == null:
theme = ResourceLoader.load(theme_path, "Theme") theme = ResourceLoader.load(theme_file_path, "Theme")
return theme return theme
###############################################################################
#
# THEME FILE PATH
#
signal theme_changed signal theme_changed
var theme_path: String = "" setget set_theme_path, get_theme_path var theme_file_path: String = "" setget set_theme_file_path, get_theme_file_path
func set_theme_path(value: String) -> void: func set_theme_file_path(value: String) -> void:
var new_theme: Theme = ResourceLoader.load(value, "Theme") var new_theme: Theme = ResourceLoader.load(value, "Theme")
if new_theme != null: if new_theme != null:
theme = new_theme theme = new_theme
theme_path = value theme_file_path = value
_config.set_value("MAIN", "theme", value) _config.set_value("MAIN", "theme", value)
emit_signal("theme_changed") emit_signal("theme_changed")
save() save()
func get_theme_path() -> String: func get_theme_file_path() -> String:
return _config.get_value("MAIN", "theme", preload("res://assets/default_theme.theme").resource_path) return _config.get_value("MAIN", "theme", preload("res://assets/default_theme.theme").resource_path)
var last_task_name: String = "" setget set_last_task_name, get_last_task_name #var current_task_name: String = "" setget set_current_task_name, get_current_task_name
#
#func set_current_task_name(value: String) -> void:
# current_task_name = value
# _config.set_value("MAIN", "current_task_name", value)
# save()
#
#func get_current_task_name() -> String:
# return _config.get_value("MAIN", "current_task_name", "")
func set_last_task_name(value: String) -> void:
last_task_name = value
_config.set_value("MAIN", "last_task_name", value)
save()
func get_last_task_name() -> String:
return _config.get_value("MAIN", "last_task_name", "")
###############################################################################
#
# SOUND OPTION
#
var sound_fx_on: bool = true setget set_sound_fx_on, get_sound_fx_on var sound_fx_on: bool = true setget set_sound_fx_on, get_sound_fx_on
@ -108,6 +146,30 @@ func get_sound_fx_on() -> bool:
return _config.get_value("MAIN", "sound_fx", true) return _config.get_value("MAIN", "sound_fx", true)
###############################################################################
#
# SOME SETTINGS CACHE
#
var current_task_name := "" setget set_current_task_name, get_current_task_name
func set_current_task_name(value: String) -> void:
current_task_name = value
_config.set_value("CACHE", "current_task_name", value)
save()
func get_current_task_name() -> String:
return _config.get_value("CACHE", "current_task_name", "")
###############################################################################
#
# BOOTSTRAP
#
func _init() -> void: func _init() -> void:
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
_config.load(CONFIG_PATH) _config.load(CONFIG_PATH)

View File

@ -37,6 +37,7 @@ func check() -> void:
var new_modified := _file.get_modified_time(file_name) var new_modified := _file.get_modified_time(file_name)
if new_modified != _last_modified: if new_modified != _last_modified:
_last_modified = new_modified _last_modified = new_modified
print("file changed")
emit_signal("file_changed") emit_signal("file_changed")

View File

@ -3,9 +3,6 @@
class_name TimeEntry class_name TimeEntry
signal end_time_updated
signal closed
var name := "" var name := ""
var is_closed := false var is_closed := false
var start_time := TimeStamp.new() var start_time := TimeStamp.new()
@ -13,20 +10,21 @@ var end_time := TimeStamp.new()
func start_recording() -> TimeEntry: func start_recording() -> TimeEntry:
start_time = start_time.from_current_time() # warning-ignore:return_value_discarded
end_time = end_time.from_current_time() start_time.from_current_time()
# warning-ignore:return_value_discarded
end_time.from_current_time()
return self return self
func update() -> void: func update() -> void:
end_time = end_time.from_current_time() # warning-ignore:return_value_discarded
emit_signal("end_time_updated") end_time.from_current_time()
func close() -> void: func close() -> void:
update() update()
is_closed = true is_closed = true
emit_signal("closed")
func get_elapsed_seconds() -> int: func get_elapsed_seconds() -> int:
@ -88,5 +86,6 @@ func to_dict() -> Dictionary:
closed = is_closed, closed = is_closed,
} }
func _to_string() -> String: func _to_string() -> String:
return "%s\t%s\t%s"%[name, tr(Consts.ONGOING) if is_closed == false else end_time.to_string(), start_time] return "%s\t%s\t%s"%[name, tr(Consts.ONGOING) if is_closed == false else end_time.to_string(), start_time]

View File

@ -6,7 +6,9 @@ var time_entry: TimeEntry
var children := {} var children := {}
var time_entries := [] var time_entries := []
func get_child(parts: Array, or_create := false): func get_child(parts: Array, or_create := false):
# workaround for cyclic dependencies bug
var TimeEntryTreeItem = load("res://scripts/time_entry_tree_item.gd") var TimeEntryTreeItem = load("res://scripts/time_entry_tree_item.gd")
if parts.size() == 0: if parts.size() == 0:
return self return self
@ -21,14 +23,23 @@ func get_child(parts: Array, or_create := false):
return children[part].get_child(parts, or_create) return children[part].get_child(parts, or_create)
func find_active_time_entry() -> TimeEntry:
for _time_entry_tree_item in time_entries:
var time_entry_tree_item := _time_entry_tree_item as TimeEntryTreeItem
var current_time_entry := time_entry_tree_item.time_entry
if not current_time_entry.is_closed:
return current_time_entry
return null
func append(new_time_entry: TimeEntry) -> void: func append(new_time_entry: TimeEntry) -> void:
var TimeEntryTreeItem = load("res://scripts/time_entry_tree_item.gd") var TimeEntryTreeItem = load("res://scripts/time_entry_tree_item.gd")
var time_entry_tree_item = TimeEntryTreeItem.new() var time_entry_tree_item = TimeEntryTreeItem.new()
time_entry_tree_item.time_entry = new_time_entry time_entry_tree_item.time_entry = new_time_entry
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
new_time_entry.connect("end_time_updated", time_entry_tree_item, "_on_end_time_updated") # new_time_entry.connect("end_time_updated", time_entry_tree_item, "_on_end_time_updated")
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
time_entry_tree_item.connect("end_time_updated", self, "_on_end_time_updated") # time_entry_tree_item.connect("end_time_updated", self, "_on_end_time_updated")
time_entries.append(time_entry_tree_item) time_entries.append(time_entry_tree_item)

View File

@ -3,7 +3,8 @@ class_name TimeSheet
var source_path := "" var source_path := ""
var entries := [] var entries := []
var tree := TimeEntryTreeItem.new() # warning-ignore:integer_division
var _last_update := Time.get_ticks_msec() / 1000
## Loads the data file ## Loads the data file
func load_file() -> bool: func load_file() -> bool:
@ -25,20 +26,10 @@ 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)
# warning-ignore:return_value_discarded
entry.connect("closed", self, "save")
file.close() file.close()
entries.sort_custom(self, "_sort_entries") 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
@ -46,22 +37,56 @@ func _sort_entries(a: TimeEntry, b: TimeEntry) -> bool:
return a.name < b.name return a.name < b.name
func get_active_entry_from_name(task_name: String) -> TimeEntry:
for _entry in entries:
var current_time_entry := _entry as TimeEntry
if current_time_entry.name == task_name and not current_time_entry.is_closed:
return current_time_entry
return null
## 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 add_entry(entry_name: String) -> TimeEntry:
var 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.is_closed = false
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:
printerr("Could not open file") printerr("Could not open file")
return return null
file.seek_end()
entries.append(current_entry) entries.append(current_entry)
file.store_csv_line(current_entry.to_csv_line()) file.store_csv_line(current_entry.to_csv_line())
emit_signal("entry_started") return current_entry
func stop_entry(entry_name: String, do_save := true) -> bool:
prints("stopping", entry_name)
for _entry in entries:
var current_time_entry := _entry as TimeEntry
if current_time_entry.name == entry_name and not current_time_entry.is_closed:
current_time_entry.close()
if do_save:
save()
return true
return false
func toggle_entry(entry_name: String, do_save := true) -> void:
if stop_entry(entry_name, do_save):
return
else:
# warning-ignore:return_value_discarded
add_entry(entry_name)
func update() -> void: func update() -> void:
# warning-ignore:integer_division
var current_time := Time.get_ticks_msec() / 1000
if current_time == _last_update:
return
_last_update = current_time
for entry in entries: for entry in entries:
var time_entry := entry as TimeEntry var time_entry := entry as TimeEntry
if time_entry.is_closed == false: if time_entry.is_closed == false:
@ -74,10 +99,21 @@ func save() -> void:
if success != OK: if success != OK:
printerr("Could not open file") printerr("Could not open file")
return return
prints("saving")
for time_entry in entries: for time_entry in entries:
file.store_csv_line(time_entry.to_csv_line()) file.store_csv_line(time_entry.to_csv_line())
func make_items_tree() -> TimeEntryTreeItem:
var tree := TimeEntryTreeItem.new()
for entry_index in entries.size():
var entry := entries[entry_index] as TimeEntry
var parts := entry.name.split("/")
var repo: TimeEntryTreeItem = tree.get_child(parts, true)
repo.append(entry)
return tree
static func restore(file_path: String) -> TimeSheet: static func restore(file_path: String) -> TimeSheet:
var timesheet = load("res://scripts/time_sheet.gd").new() var timesheet = load("res://scripts/time_sheet.gd").new()
timesheet.source_path = file_path timesheet.source_path = file_path

View File

@ -1,4 +1,4 @@
extends PanelContainer extends Control
var config: ConfigManager = preload("res://config_manager.tres") var config: ConfigManager = preload("res://config_manager.tres")
@ -26,11 +26,13 @@ func _ready() -> void:
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
file_path_file_dialog.connect("file_selected", self, "_on_current_file_selected") file_path_file_dialog.connect("file_selected", self, "_on_current_file_selected")
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
file_path_line_edit.connect("text_submitted", self, "_on_current_file_selected") file_path_line_edit.connect("text_entered", self, "_on_current_file_selected")
theme_path_button.connected("pressed", self, "_on_theme_path_button_pressed") # warning-ignore:return_value_discarded
theme_path_button.connect("pressed", self, "_on_theme_path_button_pressed")
theme_path_file_dialog.connected("file_selected", self, "_on_new_theme_selected") # warning-ignore:return_value_discarded
theme_path_file_dialog.connect("file_selected", self, "_on_new_theme_selected")
theme_path_file_dialog.hide() theme_path_file_dialog.hide()
file_path_file_dialog.hide() file_path_file_dialog.hide()
@ -46,6 +48,7 @@ func _ready() -> void:
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
open_data_dir_button.connect("pressed", self, "_on_open_data_dir_button_pressed") open_data_dir_button.connect("pressed", self, "_on_open_data_dir_button_pressed")
_on_current_file_changed()
func _on_current_file_changed() -> void: func _on_current_file_changed() -> void:

View File

@ -116,19 +116,31 @@ This game uses Godot Engine, available under the following license:
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
" "
[node name="FilePathFileDialog" type="FileDialog" parent="."] [node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="FilePathFileDialog" type="FileDialog" parent="CanvasLayer"]
unique_name_in_owner = true unique_name_in_owner = true
margin_right = 442.0 anchor_right = 1.0
margin_bottom = 760.0 anchor_bottom = 1.0
size_flags_horizontal = 3
size_flags_vertical = 3
window_title = "Pick a file" window_title = "Pick a file"
resizable = true
dialog_hide_on_ok = true
mode_overrides_title = false
access = 2 access = 2
filters = PoolStringArray( "*.csv ; Comma Separated Files" ) filters = PoolStringArray( "*.csv ; Comma Separated Files" )
[node name="ThemePathFileDialog" type="FileDialog" parent="."] [node name="ThemePathFileDialog" type="FileDialog" parent="CanvasLayer"]
unique_name_in_owner = true unique_name_in_owner = true
margin_right = 360.0 anchor_right = 1.0
margin_bottom = 760.0 anchor_bottom = 1.0
size_flags_horizontal = 3
size_flags_vertical = 3
window_title = "Open a File" window_title = "Open a File"
resizable = true
dialog_hide_on_ok = true
mode_overrides_title = false
mode = 0 mode = 0
access = 2 access = 2
filters = PoolStringArray( "*.theme ; Theme Files" ) filters = PoolStringArray( "*.theme ; Theme Files" )

View File

@ -18,16 +18,14 @@ 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")
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
config.connect("file_changed", self, "populate_entries") config.connect("time_sheet_loaded", 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 tree_items_root := create_item() var tree_items_root := create_item()
var item_entries_tree := config.timesheet.tree var item_entries_tree := config.timesheet.make_items_tree()
_populate_from_entry(tree_items_root, item_entries_tree) _populate_from_entry(tree_items_root, item_entries_tree)
_timer.start() _timer.start()
#for item in entries: #for item in entries:
@ -56,18 +54,23 @@ func _populate_from_entry(tree_item_root: TreeItem, time_entry_item_root: TimeEn
for time_entry_name in children: for time_entry_name in children:
var time_entry_item: TimeEntryTreeItem = children[time_entry_name] var time_entry_item: TimeEntryTreeItem = children[time_entry_name]
var item := find_or_create_item(tree_item_root, time_entry_name) var item := find_or_create_item(tree_item_root, time_entry_name)
item.set_metadata(COL.TEXT, time_entry_item) item.set_metadata(COL.TEXT, time_entry_name)
item.set_text(COL.TIME, time_entry_item.get_period()) item.set_text(COL.TIME, time_entry_item.get_period())
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
time_entry_item.connect("end_time_updated", self, "_on_time_entry_changed_update_item", [time_entry_item, item]) 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) _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 var entries = time_entry_item_root.time_entries
for entry_item in entries: for entry_item in entries:
var time_entry_item := entry_item as TimeEntryTreeItem var time_entry_item := entry_item as TimeEntryTreeItem
var item := create_item(tree_item_root) var item := create_item(tree_item_root)
var time_entry := time_entry_item.time_entry var time_entry := time_entry_item.time_entry
item.set_text(COL.TEXT, time_entry.start_time.to_string()) item.set_text(COL.TEXT, time_entry.start_time.to_string())
item.set_metadata(COL.TEXT, time_entry_item) item.set_metadata(COL.TEXT, time_entry_item.time_entry.name)
item.set_text(COL.TIME, time_entry_item.get_period()) item.set_text(COL.TIME, time_entry_item.get_period())
if time_entry.is_closed == false: if time_entry.is_closed == false:
var texture := preload("res://assets/stop_small.svg") var texture := preload("res://assets/stop_small.svg")
@ -81,17 +84,10 @@ func _on_time_entry_changed_update_item(time_entry_item: TimeEntryTreeItem, item
func _on_button_pressed(item: TreeItem, _column: int, _id: int) -> void: func _on_button_pressed(item: TreeItem, _column: int, _id: int) -> void:
var time_entry_tree_item: TimeEntryTreeItem = item.get_metadata(COL.TEXT) var task_name: String = item.get_metadata(COL.TEXT)
if time_entry_tree_item == null: if task_name == "":
return return
var time_entry := time_entry_tree_item.time_entry config.timesheet.toggle_entry(task_name)
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()

View File

@ -10,6 +10,7 @@ onready var start_button := $"%StartButton" as Button
onready var timer := $"%Timer" as Timer onready var timer := $"%Timer" as Timer
onready var audio_stream_player := $"%AudioStreamPlayer" as AudioStreamPlayer onready var audio_stream_player := $"%AudioStreamPlayer" as AudioStreamPlayer
var current_time_entry: TimeEntry
func _ready() -> void: func _ready() -> void:
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
@ -18,13 +19,16 @@ func _ready() -> void:
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")
task_name_line_edit.text = config.last_task_name task_name_line_edit.text = config.current_task_name
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
task_name_line_edit.connect("text_changed", self, "_on_task_name_line_edit_text_changed") task_name_line_edit.connect("text_changed", self, "_on_task_name_line_edit_text_changed")
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
config.connect("entry_started", self, "set_button_as_started") config.connect("time_sheet_loaded", self, "_on_time_sheet_loaded")
update_timer_state()
# warning-ignore:return_value_discarded # warning-ignore:return_value_discarded
config.connect("entry_stopped", self, "set_button_as_stopped") #config.connect("entry_started", self, "set_button_as_started")
# warning-ignore:return_value_discarded
#config.connect("entry_stopped", self, "set_button_as_stopped")
# TODO: connect this: # TODO: connect this:
#time_entries_items_tree.item_selected.connect( #time_entries_items_tree.item_selected.connect(
# func item_selected() -> void: # func item_selected() -> void:
@ -34,25 +38,33 @@ func _ready() -> void:
func _on_timer_timeout() -> void: func _on_timer_timeout() -> void:
config.timesheet.update() config.timesheet.update()
time_label.text = current_time_entry.get_period()
time_label.text = config.timesheet.get_period()
## TODO: change this
# var total_elapsed: int = config.timesheet.get_total_elapsed_seconds()
# time_entries_items_tree.set_time_elapsed(total_elapsed)
func _on_start_button_toggled(is_on: bool) -> void: func _on_start_button_toggled(_is_on: bool) -> void:
if config.sound_fx_on: if config.sound_fx_on:
audio_stream_player.play() audio_stream_player.play()
if is_on: if current_time_entry != null:
config.timesheet.start_entry(task_name_line_edit.text) config.timesheet.stop_entry(task_name_line_edit.text)
else: else:
config.timesheet.close_entry() config.timesheet.add_entry(task_name_line_edit.text)
func _on_task_name_line_edit_text_changed(new_text: String) -> void: func _on_task_name_line_edit_text_changed(new_text: String) -> void:
config.last_task_name = new_text config.current_task_name = new_text
update_timer_state()
func _on_time_sheet_loaded():
print("loaded")
update_timer_state()
func update_timer_state() -> void:
current_time_entry = config.timesheet.get_active_entry_from_name(config.current_task_name)
if current_time_entry:
set_button_as_started()
else:
set_button_as_stopped()
func set_button_as_stopped() -> void: func set_button_as_stopped() -> void:
@ -70,9 +82,3 @@ func set_button_as_started() -> void:
start_button.hint_tooltip = 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()
func set_initial_state() -> void:
if config.timesheet.current_entry != null and config.timesheet.current_entry.closed == false:
start_button.set_pressed_no_signal(true)
set_button_as_started()