From e0d93a94dfa043b8c8d90db8a3b3423c643a6647 Mon Sep 17 00:00:00 2001 From: Boris Kaus Date: Fri, 25 Sep 2026 10:28:11 +0200 Subject: [PATCH] Fix saving picks breaking picking; make file dialogs replaceable - "Save Picks..." assigned the saved NamedTuple to `picks`, overwriting the global Observable used for picking. After saving once, adding/dragging picks and "Load Picks..." no longer worked until the GUI was restarted. - the native file dialogs are called through the PICK_FILE/SAVE_FILE Refs, so that tests can replace them. By default they are pick_file/save_file. Co-Authored-By: Claude Opus 5.5 (1M context) --- src/AdA_VizPickTool_V1.jl | 15 ++++++++------- src/FileIO/fileIO_utils.jl | 7 ++++++- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/AdA_VizPickTool_V1.jl b/src/AdA_VizPickTool_V1.jl index 6a07b43..0aedf3a 100644 --- a/src/AdA_VizPickTool_V1.jl +++ b/src/AdA_VizPickTool_V1.jl @@ -87,7 +87,7 @@ function start_AdA_Picker(;data=nothing) ############################################################ # LOAD PROFILE DATA @async begin - fn = fetch(Threads.@spawn pick_file("")) + fn = fetch(Threads.@spawn PICK_FILE[]("")) data = load(fn,"Profile") # we need to make this more foolproof, I don't think we can rely on people calling hteir profile structure Profile println(fn*" loaded") @@ -362,7 +362,7 @@ function start_AdA_Picker(;data=nothing) elseif s == "Load Picks..." # load picks from a text file, these will be modifyable @async begin - fn = fetch(Threads.@spawn pick_file("")) + fn = fetch(Threads.@spawn PICK_FILE[]("")) println(fn) @@ -410,7 +410,7 @@ function start_AdA_Picker(;data=nothing) elseif s == "Load Picks (not modifyable)..." # load the picks as point data, these will be treated in a similar way as e.g. the seismicity data @async begin - fn = fetch(Threads.@spawn pick_file("")) + fn = fetch(Threads.@spawn PICK_FILE[]("")) # test plot in ax1 #lines!(ax1, [0,100],[0,-200], color = :red,linewidth = 3) @@ -476,19 +476,20 @@ function start_AdA_Picker(;data=nothing) lat_pick = interp_linear_lat(x_pick) lon_pick = interp_linear_lon(x_pick) - picks = (x = x_pick, depth = y_pick, lat = lat_pick, lon = lon_pick) + # use a new name here: `picks` is the (global) Observable used for picking + pick_data = (x = x_pick, depth = y_pick, lat = lat_pick, lon = lon_pick) pick_info = (user_name = pick_name.stored_string[], date = now(), units = (x = "km", depth = "km", lat = "deg", lon = "deg")) profile_info = (start_lonlat = data.start_lonlat, end_lonlat = data.end_lonlat) @async begin - fn_save = fetch(Threads.@spawn save_file("")) # open native file dialog and choose a filename + fn_save = fetch(Threads.@spawn SAVE_FILE[]("")) # open native file dialog and choose a filename filetype = split(fn_save,".")[end] # get the ending # save depending on file ending if filetype == "jld2" # file should contain: profile information, picker information, picks, lat and lon of the picked points # save as jld2 file - jldsave(fn_save; picks=picks, pick_info=pick_info, profile_info=profile_info) + jldsave(fn_save; picks=pick_data, pick_info=pick_info, profile_info=profile_info) println("... "*fn_save*" saved") elseif filetype == "csv" println("Saving as csv is not implemented yet") @@ -503,7 +504,7 @@ function start_AdA_Picker(;data=nothing) elseif s == "Save Screenshot..." # save a screen shot of the makie window @async begin - fn_screen = fetch(Threads.@spawn save_file("")) + fn_screen = fetch(Threads.@spawn SAVE_FILE[]("")) save(fn_screen, fig, px_per_unit = 2) println(fn_screen*" saved") end diff --git a/src/FileIO/fileIO_utils.jl b/src/FileIO/fileIO_utils.jl index 0410907..dc7f12d 100644 --- a/src/FileIO/fileIO_utils.jl +++ b/src/FileIO/fileIO_utils.jl @@ -4,11 +4,16 @@ using FileIO using NativeFileDialog using JLD2 +# The GUI opens the native file dialogs through these Refs, so that the tests can +# replace them by functions that return a fixed filename (there is no user on CI) +const PICK_FILE = Ref{Function}(pick_file) +const SAVE_FILE = Ref{Function}(save_file) + # function for fileIO menu response function menu_fileIO_response(s) if s == "Load Profile..." @async begin - filename = fetch(Threads.@spawn pick_file("")) + filename = fetch(Threads.@spawn PICK_FILE[]("")) println(filename) #data = load_GMG(filename) # load the profile data, this did not work properly data = load(filename,"Profile")