From 15aeb8366104e2df5affa28c0aed168bf427efbc Mon Sep 17 00:00:00 2001 From: Jamie Vital Date: Sun, 24 Sep 2023 09:14:16 -0400 Subject: [PATCH] Rework file widget to prevent partial hang --- .../common/dsp_source_sink/file_source.cpp | 2 +- src-core/core/params.cpp | 4 +- src-core/imgui/pfd/widget.cpp | 140 ++++++++++++++++++ src-core/imgui/pfd/widget.h | 131 ++-------------- src-interface/offline.cpp | 9 +- src-interface/recorder/recorder_proc.cpp | 2 +- src-interface/viewer/image_handler.cpp | 4 + src-interface/viewer/viewer_projection.cpp | 4 +- 8 files changed, 168 insertions(+), 128 deletions(-) create mode 100644 src-core/imgui/pfd/widget.cpp diff --git a/src-core/common/dsp_source_sink/file_source.cpp b/src-core/common/dsp_source_sink/file_source.cpp index d92401a1a..8830f95da 100644 --- a/src-core/common/dsp_source_sink/file_source.cpp +++ b/src-core/common/dsp_source_sink/file_source.cpp @@ -8,7 +8,7 @@ FileSource::FileSource(dsp::SourceDescriptor source) : DSPSampleSource(source) { - file_input.default_dir = satdump::config::main_cfg["satdump_directories"]["default_input_directory"]["value"].get(); + file_input.setPath(satdump::config::main_cfg["satdump_directories"]["default_input_directory"]["value"].get()); should_run = true; work_thread = std::thread(&FileSource::run_thread, this); } diff --git a/src-core/core/params.cpp b/src-core/core/params.cpp index c17b88705..72c0b61ab 100644 --- a/src-core/core/params.cpp +++ b/src-core/core/params.cpp @@ -81,7 +81,7 @@ namespace satdump d_type = PARAM_PATH; file_select = std::make_shared(p_json["name"], p_json["name"], p_json["is_directory"]); - file_select->path = p_json["value"]; + file_select->setPath(p_json["value"]); } else if (type_str == "timestamp") { @@ -173,7 +173,7 @@ namespace satdump } } else if (d_type == PARAM_PATH) - file_select->path = v.get(); + file_select->setPath(v.get()); else if (d_type == PARAM_TIMESTAMP) date_time_picker->set(v.get()); else if (d_type == PARAM_NOTATED_INT) diff --git a/src-core/imgui/pfd/widget.cpp b/src-core/imgui/pfd/widget.cpp new file mode 100644 index 000000000..d4b497cd9 --- /dev/null +++ b/src-core/imgui/pfd/widget.cpp @@ -0,0 +1,140 @@ +#include +#include "widget.h" +#include "core/style.h" +#include "imgui/imgui.h" +#include "imgui/imgui_stdlib.h" +#include "android_dialogs.h" + +#ifdef _MSC_VER +#include +#endif + +FileSelectWidget::FileSelectWidget(std::string label, std::string selection_text, bool directory) + : label(label), selection_text(selection_text), directory(directory) +{ + fileselect = nullptr; + dirselect = nullptr; + waiting_for_res = false; + default_dir = "."; + id = "##filepathselection" + label; + btnid = u8"\ufc6e Open##filepathselectionbutton" + label; +} + +FileSelectWidget::~FileSelectWidget() +{ + delete fileselect; + delete dirselect; +} + +bool FileSelectWidget::draw(std::string hint) +{ + bool changed = false; + bool disabled = waiting_for_res; + bool is_dir = std::filesystem::is_directory(path); + file_valid = std::filesystem::exists(path) && (directory ? is_dir : !is_dir); + +#ifdef _MSC_VER + if (default_dir == ".") + { + char* cwd; + cwd = _getcwd(NULL, 0); + if (cwd != 0) + default_dir = cwd; + } +#endif + if (disabled) + style::beginDisabled(); + if (!file_valid) + ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255)); + changed |= ImGui::InputTextWithHint(id.c_str(), hint.c_str(), &path); + if (!file_valid) + ImGui::PopStyleColor(); + ImGui::SameLine(); + if (ImGui::Button(btnid.c_str())) + { + if (!directory) + { +#ifdef __ANDROID__ + show_select_file_dialog(); +#else + fileselect = new pfd::open_file(selection_text.c_str(), default_dir, { "All Files", "*" }, pfd::opt::force_path); +#endif + } + else + { +#ifdef __ANDROID__ + show_select_directory_dialog(); +#else + dirselect = new pfd::select_folder(selection_text.c_str(), default_dir, pfd::opt::force_path); +#endif + } + + waiting_for_res = true; + } + if (disabled) + style::endDisabled(); + + if (waiting_for_res) + { + std::string get = ""; +#ifdef __ANDROID__ + if (!directory) + get = get_select_file_dialog_result(); + else + get = get_select_directory_dialog_result(); + if (get != "") + { + { +#else + bool is_ready = (directory ? dirselect->ready(0) : fileselect->ready(0)); + if (is_ready) + { + if (!directory) + { + get = (fileselect->result().size() == 0 ? "" : fileselect->result()[0]); + delete fileselect; + fileselect = nullptr; + } + + else + { + get = dirselect->result(); + delete dirselect; + dirselect = nullptr; + } + + if (get == "") + waiting_for_res = false; + else + { +#endif + path = get; + changed = true; + file_valid = std::filesystem::exists(path) && (directory ? is_dir : !is_dir); + waiting_for_res = false; + } + } + } + + return file_valid && changed; +} + +std::string FileSelectWidget::getPath() +{ + return path; +} + +void FileSelectWidget::setPath(std::string new_path) +{ + path = new_path; +} + +void FileSelectWidget::setDefaultDir(std::string new_path) +{ + default_dir = new_path; +} + +bool FileSelectWidget::isValid() +{ + return file_valid; +} \ No newline at end of file diff --git a/src-core/imgui/pfd/widget.h b/src-core/imgui/pfd/widget.h index e140b7fa8..6509e01bf 100644 --- a/src-core/imgui/pfd/widget.h +++ b/src-core/imgui/pfd/widget.h @@ -1,124 +1,21 @@ #pragma once - -#include "imgui/imgui.h" -#include #include "portable-file-dialogs.h" -#include "imgui/imgui_stdlib.h" -#include "android_dialogs.h" -#ifdef _MSC_VER -#include -#endif - -struct FileSelectWidget +class FileSelectWidget { - std::string label; - std::string selection_text; - std::string id; - std::string btnid; +public: + FileSelectWidget(std::string label, std::string selection_text, bool directory = false); + ~FileSelectWidget(); + bool draw(std::string hint = ""); + bool isValid(); + std::string getPath(); + void setPath(std::string new_path); + void setDefaultDir(std::string new_path); - std::string path; +private: + std::string label, selection_text, id, btnid, default_dir, path; + bool directory, waiting_for_res; + pfd::open_file *fileselect; + pfd::select_folder *dirselect; bool file_valid; - - bool directory; - -#ifdef __ANDROID__ - bool waiting_for_res = false; -#endif - - std::string default_dir = "."; - - bool draw(std::string hint = "") - { - bool changed = false; - - bool is_dir = std::filesystem::is_directory(path); - file_valid = std::filesystem::exists(path) && (directory ? is_dir : !is_dir); - -#ifdef _MSC_VER - if (default_dir == ".") - { - char* cwd; - cwd = _getcwd(NULL, 0); - if (cwd != 0) - default_dir = cwd; - } -#endif - - if (!file_valid) - ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255)); - changed |= ImGui::InputTextWithHint(id.c_str(), hint.c_str(), &path); - if (!file_valid) - ImGui::PopStyleColor(); - ImGui::SameLine(); - if (ImGui::Button(btnid.c_str())) - { - if (!directory) - { -#ifdef __ANDROID__ - show_select_file_dialog(); -#else - auto fileselect = pfd::open_file(selection_text.c_str(), default_dir, { "All Files", "*" }, pfd::opt::force_path); - - while (!fileselect.ready(1000)) - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - - if (fileselect.result().size() > 0) - path = fileselect.result()[0]; -#endif - } - else - { -#ifdef __ANDROID__ - show_select_directory_dialog(); -#else - auto dirselect = pfd::select_folder(selection_text.c_str(), default_dir, pfd::opt::force_path); - - while (!dirselect.ready(1000)) - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - - if (dirselect.result().size() > 0) - path = dirselect.result(); -#endif - } - - changed = true; -#ifdef __ANDROID__ - waiting_for_res = true; -#endif - file_valid = std::filesystem::exists(path) && (directory ? is_dir : !is_dir); - } - -#ifdef __ANDROID__ - if (waiting_for_res) - { - std::string get; - if (!directory) - get = get_select_file_dialog_result(); - else - get = get_select_directory_dialog_result(); - if (get != "") - { - path = get; - changed = true; - file_valid = std::filesystem::exists(path) && (directory ? is_dir : !is_dir); - waiting_for_res = false; - } - } -#endif - - return file_valid && changed; - } - - FileSelectWidget(std::string label, std::string selection_text, bool directory = false) - : label(label), selection_text(selection_text), directory(directory) - { - id = "##filepathselection" + label; - btnid = u8"\ufc6e Open##filepathselectionbutton" + label; - } - - std::string getPath() - { - return path; - } }; \ No newline at end of file diff --git a/src-interface/offline.cpp b/src-interface/offline.cpp index d0c460726..e617a726d 100644 --- a/src-interface/offline.cpp +++ b/src-interface/offline.cpp @@ -16,9 +16,8 @@ namespace satdump void setup() { pipeline_selector = std::make_unique(false); - - pipeline_selector->inputfileselect.default_dir = config::main_cfg["satdump_directories"]["default_input_directory"]["value"].get(); - pipeline_selector->outputdirselect.default_dir = config::main_cfg["satdump_directories"]["default_output_directory"]["value"].get(); + pipeline_selector->inputfileselect.setDefaultDir(config::main_cfg["satdump_directories"]["default_input_directory"]["value"].get()); + pipeline_selector->outputdirselect.setDefaultDir(config::main_cfg["satdump_directories"]["default_output_directory"]["value"].get()); #ifndef _MSC_VER pipeline_selector->inputfileselect.default_dir += "/"; @@ -46,9 +45,9 @@ namespace satdump { nlohmann::json params2 = pipeline_selector->getParameters(); - if (!pipeline_selector->inputfileselect.file_valid) + if (!pipeline_selector->inputfileselect.isValid()) error_message = "Input file is invalid!"; - else if (!pipeline_selector->outputdirselect.file_valid) + else if (!pipeline_selector->outputdirselect.isValid()) error_message = "Output folder is invalid!"; else ui_thread_pool.push([&, params2](int) diff --git a/src-interface/recorder/recorder_proc.cpp b/src-interface/recorder/recorder_proc.cpp index 4ec70ebac..80ea003a4 100644 --- a/src-interface/recorder/recorder_proc.cpp +++ b/src-interface/recorder/recorder_proc.cpp @@ -145,7 +145,7 @@ namespace satdump void RecorderApplication::start_processing() { - if (pipeline_selector.outputdirselect.file_valid || automated_live_output_dir) + if (pipeline_selector.outputdirselect.isValid() || automated_live_output_dir) { logger->trace("Start pipeline..."); pipeline_params = pipeline_selector.getParameters(); diff --git a/src-interface/viewer/image_handler.cpp b/src-interface/viewer/image_handler.cpp index 1735ae0fa..772b60da7 100644 --- a/src-interface/viewer/image_handler.cpp +++ b/src-interface/viewer/image_handler.cpp @@ -14,6 +14,10 @@ #include "core/opencl.h" #include "common/widgets/switch.h" +#ifdef _MSC_VER +#include +#endif + namespace satdump { void ImageViewerHandler::init() diff --git a/src-interface/viewer/viewer_projection.cpp b/src-interface/viewer/viewer_projection.cpp index a18e3025d..4ce261125 100644 --- a/src-interface/viewer/viewer_projection.cpp +++ b/src-interface/viewer/viewer_projection.cpp @@ -205,8 +205,8 @@ namespace satdump projection_new_layer_cfg.draw("Projection Config File"); } - if (ImGui::Button("Add layer") && (selected_external_type == 2 || (projection_new_layer_file.file_valid && - (selected_external_type == 0 ? 1 : projection_new_layer_cfg.file_valid)))) + if (ImGui::Button("Add layer") && (selected_external_type == 2 || (projection_new_layer_file.isValid() && + (selected_external_type == 0 ? 1 : projection_new_layer_cfg.isValid())))) { if (re_matchp(osm_url_regex, mapurl.c_str(), &osm_url_regex_len) || selected_external_type != 2) {