add file input for changing opened file view

This commit is contained in:
Rokas Puzonas 2025-04-10 00:23:53 +03:00
parent da7a580e55
commit faa0a534d5
5 changed files with 72 additions and 17 deletions

View File

@ -626,7 +626,8 @@ pub const Command = union(enum) {
load_project,
stop_output: Id, // Channel id
start_output: Id, // Channel id
add_file_from_picker
add_file_from_picker,
reload_file: Id, // File id
};
pub const CollectionTask = struct {
@ -742,7 +743,7 @@ fn deinitUI(self: *App) void {
}
fn loadProject(self: *App) !void {
if (self.isCollectionInProgress()) {
if (self.isNiDaqInUse()) {
log.warn("Attempt to load while collection is still in progress. Loading canceled", .{});
return;
}
@ -786,7 +787,7 @@ fn loadProject(self: *App) !void {
}
fn saveProject(self: *App) !void {
if (self.isCollectionInProgress()) {
if (self.isNiDaqInUse()) {
log.warn("Attempt to save while collection is still in progress. Saving canceled", .{});
return;
}
@ -933,6 +934,11 @@ pub fn tick(self: *App) !void {
},
.stop_output => |channel_id| {
self.stopOutput(channel_id);
},
.reload_file => |file_id| {
self.loadFile(file_id) catch |e| {
log.err("Failed to load file: {}", .{ e });
};
}
}
}
@ -1105,6 +1111,20 @@ pub fn isCollectionInProgress(self: *App) bool {
return self.collection_task != null;
}
pub fn isOutputingInProgress(self: *App) bool {
var channel_iter = self.project.channels.idIterator();
while (channel_iter.next()) |channel_id| {
if (self.isChannelOutputing(channel_id)) {
return true;
}
}
return false;
}
fn isNiDaqInUse(self: *App) bool {
return self.isCollectionInProgress() or self.isOutputingInProgress();
}
pub fn collectionThreadCallback(self: *App) void {
while (!self.should_close) {
@ -1214,6 +1234,7 @@ pub fn loadFile(self: *App, id: Id) !void {
file.clear(self.allocator);
const cwd = std.fs.cwd();
const samples_file = try cwd.openFile(file.path, .{ .mode = .read_only });
defer samples_file.close();
@ -1244,9 +1265,24 @@ pub fn addChannel(self: *App, channel_name: []const u8) !Id {
const channel = self.project.channels.get(id).?;
channel.* = Channel{
.name = try utils.initBoundedStringZ(Channel.Name, channel_name)
.name = try utils.initBoundedStringZ(Channel.Name, channel_name),
};
if (self.project.save_location) |project_file_path| {
if (std.fs.path.dirname(project_file_path)) |project_dir| {
var clean_channel_name_buff = channel.name;
const clean_channel_name = utils.getBoundedStringZ(&clean_channel_name_buff);
// Sanitize the channel name, because it will be used as a filename
std.mem.replaceScalar(u8, clean_channel_name, '/', '_');
const filename = try std.mem.concat(self.allocator, u8, &.{ clean_channel_name, ".bin" });
defer self.allocator.free(filename);
channel.saved_collected_samples = try std.fs.path.join(self.allocator, &.{ project_dir, filename });
}
}
self.loadChannel(id) catch |e| {
log.err("Failed to load channel: {}", .{ e });
};

View File

@ -103,6 +103,15 @@ pub fn main() !void {
defer app.deinit();
if (builtin.mode == .Debug) {
var cwd_realpath_buff: [std.fs.MAX_PATH_BYTES]u8 = undefined;
const cwd_realpath = try std.fs.cwd().realpath(".", &cwd_realpath_buff);
const save_location = try std.fs.path.join(allocator, &.{ cwd_realpath, "project.proj" });
errdefer allocator.free(save_location);
app.project.save_location = save_location;
app.project.sample_rate = 5000;
_ = try app.addView(.{
.channel = try app.addChannel("Dev1/ai0")
});
@ -137,15 +146,6 @@ pub fn main() !void {
// .file = try app.addFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_I.bin")
// });
var cwd_realpath_buff: [std.fs.MAX_PATH_BYTES]u8 = undefined;
const cwd_realpath = try std.fs.cwd().realpath(".", &cwd_realpath_buff);
const save_location = try std.fs.path.join(allocator, &.{ cwd_realpath, "project.proj" });
errdefer allocator.free(allocator);
app.project.save_location = save_location;
app.project.sample_rate = 5000;
// try app.appendChannelFromDevice("Dev1/ai0");
// try app.appendChannelFromDevice("Dev3/ao0");
// try app.appendChannelFromFile("samples/HeLa Cx37_ 40nM GFX + 35uM Propofol_18-Sep-2024_0003_I.bin");

View File

@ -37,6 +37,7 @@ parsed_sample_rate: ?f64 = null,
// View settings
channel_save_file_picker: ?Platform.FilePickerId = null,
file_save_file_picker: ?Platform.FilePickerId = null,
pub fn init(app: *App) !MainScreen {
const allocator = app.allocator;
@ -336,7 +337,8 @@ fn showViewSettings(self: *MainScreen, view_id: Id) !void {
.key = ui.keyFromString("Save location"),
.allocator = self.app.allocator,
.file_picker = &self.channel_save_file_picker,
.path = channel.saved_collected_samples
.path = channel.saved_collected_samples,
.open_dialog = false
})) |path| {
if (channel.saved_collected_samples) |current_path| {
self.app.allocator.free(current_path);
@ -353,6 +355,17 @@ fn showViewSettings(self: *MainScreen, view_id: Id) !void {
if (file.samples) |samples| {
sample_count = samples.len;
}
if (ui.fileInput(.{
.key = ui.keyFromString("Filename"),
.allocator = self.app.allocator,
.file_picker = &self.file_save_file_picker,
.path = file.path
})) |path| {
self.app.allocator.free(file.path);
file.path = path;
self.app.pushCommand(.{ .reload_file = file_id });
}
}
}

View File

@ -2277,6 +2277,7 @@ pub const FileInputOptions = struct {
key: Key,
allocator: std.mem.Allocator,
file_picker: *?Platform.FilePickerId,
open_dialog: bool = true,
path: ?[]const u8 = null
};
@ -2819,8 +2820,13 @@ pub fn fileInput(self: *UI, opts: FileInputOptions) ?[]u8 {
const container_signal = self.signal(container);
if (container_signal.clicked()) {
var file_open_options: Platform.OpenFileOptions = .{};
file_open_options.style = .save;
file_open_options.prompt_overwrite = true;
if (opts.open_dialog) {
file_open_options.style = .open;
file_open_options.file_must_exist = true;
} else {
file_open_options.style = .save;
file_open_options.prompt_overwrite = true;
}
file_open_options.appendFilter("All", "*") catch unreachable;
file_open_options.appendFilter("Binary", "*.bin") catch unreachable;

View File

@ -74,7 +74,7 @@ pub fn initBoundedStringZ(comptime BoundedString: type, text: []const u8) !Bound
return bounded_string;
}
pub fn getBoundedStringZ(bounded_array: anytype) [:0]const u8 {
pub fn getBoundedStringZ(bounded_array: anytype) [:0]u8 {
return bounded_array.buffer[0..(bounded_array.len-1) :0];
}