From 89004574d32bbd41a49d2442da82c0e9e0c85f86 Mon Sep 17 00:00:00 2001 From: WerWolv Date: Wed, 17 Dec 2025 12:55:24 +0100 Subject: [PATCH] impr: Handle provider opening more centrally, switch to existing provider if same file is being opened again --- .../hex/api/events/events_provider.hpp | 2 +- .../hex/api/events/requests_provider.hpp | 5 ++ .../include/hex/api/imhex_api/provider.hpp | 6 ++ .../include/hex/providers/cached_provider.hpp | 2 +- .../include/hex/providers/memory_provider.hpp | 2 +- .../include/hex/providers/provider.hpp | 66 ++++++++++++++++-- lib/libimhex/source/api/imhex_api.cpp | 6 +- lib/libimhex/source/helpers/patches.cpp | 2 +- .../source/providers/cached_provider.cpp | 4 +- .../source/providers/memory_provider.cpp | 4 +- .../content/providers/command_provider.hpp | 2 +- .../content/providers/disk_provider.hpp | 2 +- .../content/providers/file_provider.hpp | 4 +- .../content/providers/gdb_provider.hpp | 2 +- .../content/providers/intel_hex_provider.hpp | 2 +- .../providers/memory_file_provider.hpp | 2 +- .../providers/motorola_srec_provider.hpp | 2 +- .../content/providers/null_provider.hpp | 2 +- .../providers/process_memory_provider.hpp | 2 +- .../content/providers/udp_provider.hpp | 2 +- .../content/providers/view_provider.hpp | 2 +- plugins/builtin/romfs/lang/en_US.json | 7 +- .../source/content/command_line_interface.cpp | 6 +- plugins/builtin/source/content/events.cpp | 69 +++++++++---------- .../source/content/main_menu_items.cpp | 4 +- plugins/builtin/source/content/providers.cpp | 5 +- .../content/providers/command_provider.cpp | 4 +- .../content/providers/disk_provider.cpp | 12 ++-- .../content/providers/file_provider.cpp | 23 +++---- .../source/content/providers/gdb_provider.cpp | 10 +-- .../content/providers/intel_hex_provider.cpp | 10 ++- .../providers/memory_file_provider.cpp | 6 +- .../providers/motorola_srec_provider.cpp | 10 ++- .../providers/process_memory_provider.cpp | 8 +-- .../source/content/providers/udp_provider.cpp | 4 +- .../content/providers/view_provider.cpp | 6 +- plugins/builtin/source/content/recent.cpp | 9 +-- plugins/builtin/source/content/ui_items.cpp | 5 +- .../fullscreen/view_fullscreen_file_info.cpp | 3 +- .../view_fullscreen_save_editor.cpp | 3 +- .../source/content/views/view_bookmarks.cpp | 7 +- .../source/content/views/view_hex_editor.cpp | 3 +- .../content/views/view_provider_settings.cpp | 9 +-- .../builtin/source/content/welcome_screen.cpp | 2 +- .../content/providers/ssh_provider.hpp | 2 +- plugins/remote/romfs/lang/en_US.json | 3 +- .../source/content/providers/ssh_provider.cpp | 14 ++-- .../support/c/source/script_api/v1/mem.cpp | 2 +- 48 files changed, 211 insertions(+), 158 deletions(-) diff --git a/lib/libimhex/include/hex/api/events/events_provider.hpp b/lib/libimhex/include/hex/api/events/events_provider.hpp index 11a64e57b..a0b12dba7 100644 --- a/lib/libimhex/include/hex/api/events/events_provider.hpp +++ b/lib/libimhex/include/hex/api/events/events_provider.hpp @@ -15,7 +15,7 @@ namespace hex { * This event is responsible for (optionally) initializing the provider and calling EventProviderOpened * (although the event can also be called manually without problem) */ - EVENT_DEF(EventProviderCreated, prv::Provider *); + EVENT_DEF(EventProviderCreated, std::shared_ptr); /** * @brief Called as a continuation of EventProviderCreated diff --git a/lib/libimhex/include/hex/api/events/requests_provider.hpp b/lib/libimhex/include/hex/api/events/requests_provider.hpp index 29b5f43aa..943b843e3 100644 --- a/lib/libimhex/include/hex/api/events/requests_provider.hpp +++ b/lib/libimhex/include/hex/api/events/requests_provider.hpp @@ -10,6 +10,11 @@ namespace hex { */ EVENT_DEF(RequestCreateProvider, std::string, bool, bool, std::shared_ptr *); + /** + * @brief Used internally when opening a provider through the API + */ + EVENT_DEF(RequestOpenProvider, std::shared_ptr); + /** * @brief Move the data from all PerProvider instances from one provider to another * diff --git a/lib/libimhex/include/hex/api/imhex_api/provider.hpp b/lib/libimhex/include/hex/api/imhex_api/provider.hpp index c5c684e71..c12a45fc9 100644 --- a/lib/libimhex/include/hex/api/imhex_api/provider.hpp +++ b/lib/libimhex/include/hex/api/imhex_api/provider.hpp @@ -117,6 +117,12 @@ EXPORT_MODULE namespace hex { bool select = true ); + /** + * @brief Opens a provider, making its data available to ImHex and handling any error that may occur + * @param provider The provider to open + */ + void openProvider(std::shared_ptr provider); + } } \ No newline at end of file diff --git a/lib/libimhex/include/hex/providers/cached_provider.hpp b/lib/libimhex/include/hex/providers/cached_provider.hpp index f92abfc85..972da7108 100644 --- a/lib/libimhex/include/hex/providers/cached_provider.hpp +++ b/lib/libimhex/include/hex/providers/cached_provider.hpp @@ -21,7 +21,7 @@ namespace hex::prv { CachedProvider(size_t cacheBlockSize = 4096, size_t maxBlocks = 1024); ~CachedProvider() override; - bool open() override; + OpenResult open() override; void close() override; void readRaw(u64 offset, void *buffer, size_t size) override; diff --git a/lib/libimhex/include/hex/providers/memory_provider.hpp b/lib/libimhex/include/hex/providers/memory_provider.hpp index 439e883b2..62af009f9 100644 --- a/lib/libimhex/include/hex/providers/memory_provider.hpp +++ b/lib/libimhex/include/hex/providers/memory_provider.hpp @@ -27,7 +27,7 @@ namespace hex::prv { [[nodiscard]] bool isSavable() const override { return m_name.empty(); } [[nodiscard]] bool isSavableAsRecent() const override { return false; } - [[nodiscard]] bool open() override; + [[nodiscard]] OpenResult open() override; void close() override { } void readRaw(u64 offset, void *buffer, size_t size) override; diff --git a/lib/libimhex/include/hex/providers/provider.hpp b/lib/libimhex/include/hex/providers/provider.hpp index dab48c9e9..82ca3e587 100644 --- a/lib/libimhex/include/hex/providers/provider.hpp +++ b/lib/libimhex/include/hex/providers/provider.hpp @@ -94,6 +94,65 @@ namespace hex::prv { public: constexpr static u64 MaxPageSize = 0xFFFF'FFFF'FFFF'FFFF; + class OpenResult { + public: + OpenResult() : m_result(std::monostate{}) {} + + [[nodiscard]] static OpenResult failure(std::string errorMessage) { + OpenResult result; + result.m_result = std::move(errorMessage); + return result; + } + + [[nodiscard]] static OpenResult warning(std::string warningMessage) { + OpenResult result; + result.m_result = std::move(warningMessage); + result.m_warning = true; + return result; + } + + [[nodiscard]] static OpenResult redirect(Provider *provider) { + OpenResult result; + result.m_result = provider; + return result; + } + + [[nodiscard]] bool isSuccess() const { + return std::holds_alternative(m_result); + } + + [[nodiscard]] bool isFailure() const { + return std::holds_alternative(m_result) && !m_warning; + } + + [[nodiscard]] bool isWarning() const { + return std::holds_alternative(m_result) && m_warning; + } + + [[nodiscard]] bool isRedirecting() const { + return std::holds_alternative(m_result); + } + + [[nodiscard]] Provider* getRedirectProvider() const { + if (std::holds_alternative(m_result)) { + return std::get(m_result); + } + return nullptr; + } + + [[nodiscard]] std::string_view getErrorMessage() const { + if (std::holds_alternative(m_result)) { + return std::get(m_result); + } + + return ""; + } + + private: + std::variant m_result; + bool m_warning = false; + }; + Provider(); virtual ~Provider(); Provider(const Provider&) = delete; @@ -109,7 +168,7 @@ namespace hex::prv { * @note This is not related to the EventProviderOpened event * @return true if the provider was opened successfully, else false */ - [[nodiscard]] virtual bool open() = 0; + [[nodiscard]] virtual OpenResult open() = 0; /** * @brief Closes this provider @@ -277,9 +336,6 @@ namespace hex::prv { void skipLoadInterface() { m_skipLoadInterface = true; } [[nodiscard]] bool shouldSkipLoadInterface() const { return m_skipLoadInterface; } - void setErrorMessage(const std::string &errorMessage) { m_errorMessage = errorMessage; } - [[nodiscard]] const std::string& getErrorMessage() const { return m_errorMessage; } - template T> bool addUndoableOperation(auto && ... args) { return m_undoRedoStack.add(std::forward(args)...); @@ -311,8 +367,6 @@ namespace hex::prv { */ bool m_skipLoadInterface = false; - std::string m_errorMessage = "Unspecified error"; - u64 m_pageSize = MaxPageSize; }; diff --git a/lib/libimhex/source/api/imhex_api.cpp b/lib/libimhex/source/api/imhex_api.cpp index e89fbfca9..357871094 100644 --- a/lib/libimhex/source/api/imhex_api.cpp +++ b/lib/libimhex/source/api/imhex_api.cpp @@ -391,7 +391,7 @@ namespace hex { if (skipLoadInterface) provider->skipLoadInterface(); - EventProviderCreated::post(provider.get()); + EventProviderCreated::post(provider); s_providers->emplace_back(std::move(provider)); if (select || s_providers->size() == 1) @@ -498,6 +498,10 @@ namespace hex { return result; } + void openProvider(std::shared_ptr provider) { + RequestOpenProvider::post(provider); + } + } namespace ImHexApi::System { diff --git a/lib/libimhex/source/helpers/patches.cpp b/lib/libimhex/source/helpers/patches.cpp index 42d1601d9..6c14d1552 100644 --- a/lib/libimhex/source/helpers/patches.cpp +++ b/lib/libimhex/source/helpers/patches.cpp @@ -24,7 +24,7 @@ namespace hex { [[nodiscard]] bool isSavable() const override { return false; } [[nodiscard]] bool isSavableAsRecent() const override { return false; } - [[nodiscard]] bool open() override { return true; } + [[nodiscard]] OpenResult open() override { return {}; } void close() override { } void readRaw(u64 offset, void *buffer, size_t size) override { diff --git a/lib/libimhex/source/providers/cached_provider.cpp b/lib/libimhex/source/providers/cached_provider.cpp index ea118d09d..423271c59 100644 --- a/lib/libimhex/source/providers/cached_provider.cpp +++ b/lib/libimhex/source/providers/cached_provider.cpp @@ -11,9 +11,9 @@ namespace hex::prv { clearCache(); } - bool CachedProvider::open() { + Provider::OpenResult CachedProvider::open() { clearCache(); - return true; + return {}; } void CachedProvider::close() { diff --git a/lib/libimhex/source/providers/memory_provider.cpp b/lib/libimhex/source/providers/memory_provider.cpp index 311e3fac6..b3c5caa99 100644 --- a/lib/libimhex/source/providers/memory_provider.cpp +++ b/lib/libimhex/source/providers/memory_provider.cpp @@ -4,12 +4,12 @@ namespace hex::prv { - bool MemoryProvider::open() { + Provider::OpenResult MemoryProvider::open() { if (m_data.empty()) { m_data.resize(1); } - return true; + return {}; } void MemoryProvider::readRaw(u64 offset, void *buffer, size_t size) { diff --git a/plugins/builtin/include/content/providers/command_provider.hpp b/plugins/builtin/include/content/providers/command_provider.hpp index 3bca3cbfc..a67036ca8 100644 --- a/plugins/builtin/include/content/providers/command_provider.hpp +++ b/plugins/builtin/include/content/providers/command_provider.hpp @@ -29,7 +29,7 @@ namespace hex::plugin::builtin { [[nodiscard]] std::string getName() const override; - [[nodiscard]] bool open() override; + [[nodiscard]] OpenResult open() override; void close() override; bool drawLoadInterface() override; diff --git a/plugins/builtin/include/content/providers/disk_provider.hpp b/plugins/builtin/include/content/providers/disk_provider.hpp index bd8e75d6f..7a44e633b 100644 --- a/plugins/builtin/include/content/providers/disk_provider.hpp +++ b/plugins/builtin/include/content/providers/disk_provider.hpp @@ -30,7 +30,7 @@ namespace hex::plugin::builtin { void setPath(const std::fs::path &path); - [[nodiscard]] bool open() override; + [[nodiscard]] OpenResult open() override; void close() override; [[nodiscard]] std::string getName() const override; diff --git a/plugins/builtin/include/content/providers/file_provider.hpp b/plugins/builtin/include/content/providers/file_provider.hpp index 40256b852..fd6d0900f 100644 --- a/plugins/builtin/include/content/providers/file_provider.hpp +++ b/plugins/builtin/include/content/providers/file_provider.hpp @@ -44,7 +44,7 @@ namespace hex::plugin::builtin { void setPath(const std::fs::path &path); - [[nodiscard]] bool open() override; + [[nodiscard]] OpenResult open() override; void close() override; void loadSettings(const nlohmann::json &settings) override; @@ -66,7 +66,7 @@ namespace hex::plugin::builtin { private: void handleFileChange(); - bool open(bool memoryMapped); + OpenResult open(bool memoryMapped); protected: std::fs::path m_path; diff --git a/plugins/builtin/include/content/providers/gdb_provider.hpp b/plugins/builtin/include/content/providers/gdb_provider.hpp index eec57c0df..b5573caeb 100644 --- a/plugins/builtin/include/content/providers/gdb_provider.hpp +++ b/plugins/builtin/include/content/providers/gdb_provider.hpp @@ -35,7 +35,7 @@ namespace hex::plugin::builtin { [[nodiscard]] std::string getName() const override; [[nodiscard]] std::vector getDataDescription() const override; - [[nodiscard]] bool open() override; + [[nodiscard]] OpenResult open() override; void close() override; [[nodiscard]] bool isConnected() const; diff --git a/plugins/builtin/include/content/providers/intel_hex_provider.hpp b/plugins/builtin/include/content/providers/intel_hex_provider.hpp index afbee08bb..b9a2dc48f 100644 --- a/plugins/builtin/include/content/providers/intel_hex_provider.hpp +++ b/plugins/builtin/include/content/providers/intel_hex_provider.hpp @@ -39,7 +39,7 @@ namespace hex::plugin::builtin { [[nodiscard]] u64 getActualSize() const override; void processMemoryRegions(wolv::util::Expected>, std::string> data); static bool memoryRegionFilter(const std::string &search, const MemoryRegion &memoryRegion); - bool open() override; + OpenResult open() override; void close() override; [[nodiscard]] std::string getName() const override; diff --git a/plugins/builtin/include/content/providers/memory_file_provider.hpp b/plugins/builtin/include/content/providers/memory_file_provider.hpp index 9e7df4542..f630db438 100644 --- a/plugins/builtin/include/content/providers/memory_file_provider.hpp +++ b/plugins/builtin/include/content/providers/memory_file_provider.hpp @@ -18,7 +18,7 @@ namespace hex::plugin::builtin { [[nodiscard]] bool isSavable() const override { return m_name.empty(); } [[nodiscard]] bool isSavableAsRecent() const override { return false; } - [[nodiscard]] bool open() override; + [[nodiscard]] OpenResult open() override; void close() override { } void readRaw(u64 offset, void *buffer, size_t size) override; diff --git a/plugins/builtin/include/content/providers/motorola_srec_provider.hpp b/plugins/builtin/include/content/providers/motorola_srec_provider.hpp index 8e973c6ba..3cfb760d9 100644 --- a/plugins/builtin/include/content/providers/motorola_srec_provider.hpp +++ b/plugins/builtin/include/content/providers/motorola_srec_provider.hpp @@ -9,7 +9,7 @@ namespace hex::plugin::builtin { MotorolaSRECProvider() = default; ~MotorolaSRECProvider() override = default; - bool open() override; + OpenResult open() override; void close() override; [[nodiscard]] std::string getName() const override; diff --git a/plugins/builtin/include/content/providers/null_provider.hpp b/plugins/builtin/include/content/providers/null_provider.hpp index 693774499..df57309ea 100644 --- a/plugins/builtin/include/content/providers/null_provider.hpp +++ b/plugins/builtin/include/content/providers/null_provider.hpp @@ -29,7 +29,7 @@ namespace hex::plugin::builtin { [[nodiscard]] bool isResizable() const override { return false; } [[nodiscard]] bool isSavable() const override { return false; } - [[nodiscard]] bool open() override { return true; } + [[nodiscard]] OpenResult open() override { return {}; } void close() override { } void readRaw(u64 offset, void *buffer, size_t size) override { diff --git a/plugins/builtin/include/content/providers/process_memory_provider.hpp b/plugins/builtin/include/content/providers/process_memory_provider.hpp index e22dbbca1..0fd06ecd4 100644 --- a/plugins/builtin/include/content/providers/process_memory_provider.hpp +++ b/plugins/builtin/include/content/providers/process_memory_provider.hpp @@ -59,7 +59,7 @@ namespace hex::plugin::builtin { }; } - [[nodiscard]] bool open() override; + [[nodiscard]] OpenResult open() override; void close() override; bool drawLoadInterface() override; diff --git a/plugins/builtin/include/content/providers/udp_provider.hpp b/plugins/builtin/include/content/providers/udp_provider.hpp index 4dd01f829..353c28078 100644 --- a/plugins/builtin/include/content/providers/udp_provider.hpp +++ b/plugins/builtin/include/content/providers/udp_provider.hpp @@ -30,7 +30,7 @@ namespace hex::plugin::builtin { [[nodiscard]] bool drawLoadInterface() override; void drawSidebarInterface() override; - [[nodiscard]] bool open() override; + [[nodiscard]] OpenResult open() override; void close() override; void loadSettings(const nlohmann::json &) override; diff --git a/plugins/builtin/include/content/providers/view_provider.hpp b/plugins/builtin/include/content/providers/view_provider.hpp index 1b23d0be4..8e74c6167 100644 --- a/plugins/builtin/include/content/providers/view_provider.hpp +++ b/plugins/builtin/include/content/providers/view_provider.hpp @@ -20,7 +20,7 @@ namespace hex::plugin::builtin { [[nodiscard]] bool isSavableAsRecent() const override; void save() override; - [[nodiscard]] bool open() override; + [[nodiscard]] OpenResult open() override; void close() override; void resizeRaw(u64 newSize) override; diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index 72b87d32f..a58378678 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -420,7 +420,7 @@ "hex.builtin.provider.rename": "Rename", "hex.builtin.provider.rename.desc": "Enter a name for this data source.", "hex.builtin.provider.tooltip.show_more": "Hold SHIFT for more information", - "hex.builtin.provider.error.open": "Failed to open data provider: {}", + "hex.builtin.provider.error.open": "Failed to open data source: {}", "hex.builtin.provider.base64": "Base64 File", "hex.builtin.provider.command": "Terminal Command", "hex.builtin.provider.command.name": "Command {0}", @@ -442,6 +442,7 @@ "hex.builtin.provider.disk.error.read_rw": "Failed to open disk {} in read/write mode: {}", "hex.builtin.provider.file": "Regular File", "hex.builtin.provider.file.error.open": "Failed to open file {}: {}", + "hex.builtin.provider.file.error.already_open": "Same file is already open", "hex.builtin.provider.file.access": "Last access time", "hex.builtin.provider.file.creation": "Creation time", "hex.builtin.provider.file.menu.direct_access": "Direct access file", @@ -460,6 +461,7 @@ "hex.builtin.provider.gdb.name": "GDB Server <{0}:{1}>", "hex.builtin.provider.gdb.port": "Port", "hex.builtin.provider.gdb.server": "Server", + "hex.builtin.provider.gdb.server.error.not_connected": "Failed to open connection to GDB Server", "hex.builtin.provider.intel_hex": "Intel Hex File", "hex.builtin.provider.intel_hex.name": "Intel Hex {0}", "hex.builtin.provider.mem_file": "In-Memory File", @@ -470,6 +472,8 @@ "hex.builtin.provider.opening": "Opening Data Source...", "hex.builtin.provider.process_memory": "Process Memory", "hex.builtin.provider.process_memory.enumeration_failed": "Failed to enumerate processes", + "hex.builtin.provider.process_memory.error.no_process_selected": "No process selected", + "hex.builtin.provider.process_memory.error.open_process": "Failed to attach to process", "hex.builtin.provider.process_memory.macos_limitations": "macOS doesn't properly allow reading memory from other processes, even when running as root. If System Integrity Protection (SIP) is enabled, it only works for applications that are unsigned or have the 'Get Task Allow' entitlement which generally only applies to applications compiled by yourself.", "hex.builtin.provider.process_memory.memory_regions": "Memory Regions", "hex.builtin.provider.process_memory.name": "'{0}' Process Memory", @@ -488,6 +492,7 @@ "hex.builtin.provider.udp.port": "Server Port", "hex.builtin.provider.udp.timestamp": "Timestamp", "hex.builtin.provider.view": "View", + "hex.builtin.provider.view.error.no_provider": "No data source has been attached to this view", "hex.builtin.setting.experiments": "Experiments", "hex.builtin.setting.experiments.description": "Experiments are features that are still in development and may not work correctly yet.\n\nFeel free to try them out and report any issues you encounter!", "hex.builtin.setting.folders": "Folders", diff --git a/plugins/builtin/source/content/command_line_interface.cpp b/plugins/builtin/source/content/command_line_interface.cpp index 208ffd47c..6c9cdadf8 100644 --- a/plugins/builtin/source/content/command_line_interface.cpp +++ b/plugins/builtin/source/content/command_line_interface.cpp @@ -360,10 +360,10 @@ namespace hex::plugin::builtin { std::fs::path filePath = reinterpret_cast(args[0].data()); FileProvider provider; - provider.setPath(filePath); - if (!provider.open()) { - log::println("Failed to open file '{}'", args[0]); + auto result = provider.open(); + if (!result.isFailure()) { + log::println("Failed to open file '{}': {}", args[0], result.getErrorMessage()); std::exit(EXIT_FAILURE); } diff --git a/plugins/builtin/source/content/events.cpp b/plugins/builtin/source/content/events.cpp index 0fdc55500..c912fbb23 100644 --- a/plugins/builtin/source/content/events.cpp +++ b/plugins/builtin/source/content/events.cpp @@ -52,15 +52,10 @@ namespace hex::plugin::builtin { auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true); if (auto *fileProvider = dynamic_cast(provider.get()); fileProvider != nullptr) { fileProvider->setPath(path); - if (!provider->open() || !provider->isAvailable()) { - ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage())); - TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider.get()); }); - return; - } - EventProviderOpened::post(fileProvider); + ImHexApi::Provider::openProvider(provider); + AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name"); - ImHexApi::Provider::setCurrentProvider(provider.get()); glfwRequestWindowAttention(ImHexApi::System::getMainWindowHandle()); glfwFocusWindow(ImHexApi::System::getMainWindowHandle()); @@ -182,11 +177,8 @@ namespace hex::plugin::builtin { RequestOpenWindow::subscribe([](const std::string &name) { if (name == "Create File") { - auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true); - if (newProvider != nullptr && !newProvider->open()) - hex::ImHexApi::Provider::remove(newProvider.get()); - else - EventProviderOpened::post(newProvider.get()); + auto newProvider = ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true); + ImHexApi::Provider::openProvider(newProvider); } else if (name == "Open File") { fs::openFileBrowser(fs::DialogMode::Open, { }, [](const auto &path) { if (path.extension() == ".hexproj") { @@ -204,12 +196,8 @@ namespace hex::plugin::builtin { return; newProvider->setPath(path); - if (!newProvider->open()) { - hex::ImHexApi::Provider::remove(newProvider); - } else { - EventProviderOpened::post(newProvider); - AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name"); - } + ImHexApi::Provider::openProvider(provider); + AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name"); }, {}, true); } else if (name == "Open Project") { fs::openFileBrowser(fs::DialogMode::Open, { {"Project File", "hexproj"} }, @@ -226,34 +214,20 @@ namespace hex::plugin::builtin { }); // Handles the provider initialization, and calls EventProviderOpened if successful - EventProviderCreated::subscribe([](hex::prv::Provider *provider) { + EventProviderCreated::subscribe([](std::shared_ptr provider) { if (provider->shouldSkipLoadInterface()) return; - if (auto *filePickerProvider = dynamic_cast(provider); filePickerProvider != nullptr) { + if (auto *filePickerProvider = dynamic_cast(provider.get()); filePickerProvider != nullptr) { if (!filePickerProvider->handleFilePicker()) { - TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); }); + TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider.get()); }); return; } - TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [provider]() { - if (!provider->open()) { - ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage())); - TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); }); - } else { - TaskManager::doLater([provider]{ EventProviderOpened::post(provider); }); - } - }); + ImHexApi::Provider::openProvider(provider); } - else if (dynamic_cast(provider) == nullptr) { - TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [provider]() { - if (!provider->open() || !provider->isAvailable()) { - ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage())); - TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); }); - } else { - TaskManager::doLater([provider]{ EventProviderOpened::post(provider); }); - } - }); + else if (dynamic_cast(provider.get()) == nullptr) { + ImHexApi::Provider::openProvider(provider); } }); @@ -419,6 +393,25 @@ namespace hex::plugin::builtin { }); }); + RequestOpenProvider::subscribe([](std::shared_ptr provider) { + TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [provider]() { + auto result = provider->open(); + if (result.isFailure()) { + ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, result.getErrorMessage())); + TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider.get()); }); + } else if (result.isRedirecting()) { + TaskManager::doLater([result, provider] { + ImHexApi::Provider::remove(provider.get()); + ImHexApi::Provider::setCurrentProvider(result.getRedirectProvider()); + }); + } else { + if (result.isWarning()) + ui::ToastWarning::open(std::string(result.getErrorMessage())); + TaskManager::doLater([provider]{ EventProviderOpened::post(provider.get()); }); + } + }); + }); + fs::setFileBrowserErrorCallback([](const std::string& errMsg){ #if defined(NFD_PORTAL) ui::PopupError::open(fmt::format("hex.builtin.popup.error.file_dialog.portal"_lang, errMsg)); diff --git a/plugins/builtin/source/content/main_menu_items.cpp b/plugins/builtin/source/content/main_menu_items.cpp index f42f9fbe2..fb4912837 100644 --- a/plugins/builtin/source/content/main_menu_items.cpp +++ b/plugins/builtin/source/content/main_menu_items.cpp @@ -377,7 +377,7 @@ namespace hex::plugin::builtin { /* Create File */ ContentRegistry::UserInterface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.create_file" }, ICON_VS_FILE, 1050, CTRLCMD + Keys::N + AllowWhileTyping + ShowOnWelcomeScreen, [] { auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true); - if (newProvider != nullptr && !newProvider->open()) + if (newProvider != nullptr && newProvider->open().isFailure()) hex::ImHexApi::Provider::remove(newProvider.get()); else EventProviderOpened::post(newProvider.get()); @@ -401,7 +401,7 @@ namespace hex::plugin::builtin { auto provider = ImHexApi::Provider::get(); provider->close(); - if (!provider->open()) + if (provider->open().isFailure()) ImHexApi::Provider::remove(provider, true); EventDataChanged::post(provider); diff --git a/plugins/builtin/source/content/providers.cpp b/plugins/builtin/source/content/providers.cpp index e7d933d92..a23cdac7b 100644 --- a/plugins/builtin/source/content/providers.cpp +++ b/plugins/builtin/source/content/providers.cpp @@ -92,8 +92,9 @@ namespace hex::plugin::builtin { providerWarnings[newProvider.get()] = e.what(); } if (loaded) { - if (!newProvider->open() || !newProvider->isAvailable() || !newProvider->isReadable()) { - providerWarnings[newProvider.get()] = newProvider->getErrorMessage(); + auto result = newProvider->open(); + if (result.isFailure() || !newProvider->isAvailable() || !newProvider->isReadable()) { + providerWarnings[newProvider.get()] = result.getErrorMessage(); } else { EventProviderOpened::post(newProvider.get()); } diff --git a/plugins/builtin/source/content/providers/command_provider.cpp b/plugins/builtin/source/content/providers/command_provider.cpp index 01f50eb22..1999e0ae4 100644 --- a/plugins/builtin/source/content/providers/command_provider.cpp +++ b/plugins/builtin/source/content/providers/command_provider.cpp @@ -242,9 +242,9 @@ namespace hex::plugin::builtin { return fmt::format("hex.builtin.provider.command.name"_lang, m_name); } - bool CommandProvider::open() { + prv::Provider::OpenResult CommandProvider::open() { m_open = true; - return true; + return {}; } void CommandProvider::close() { diff --git a/plugins/builtin/source/content/providers/disk_provider.cpp b/plugins/builtin/source/content/providers/disk_provider.cpp index 764a96970..46f41fa95 100644 --- a/plugins/builtin/source/content/providers/disk_provider.cpp +++ b/plugins/builtin/source/content/providers/disk_provider.cpp @@ -157,7 +157,7 @@ namespace hex::plugin::builtin { } #endif - bool DiskProvider::open() { + prv::Provider::OpenResult DiskProvider::open() { m_readable = true; m_writable = true; @@ -207,18 +207,16 @@ namespace hex::plugin::builtin { const auto &path = m_path.native(); m_diskHandle = ::open(path.c_str(), O_RDWR); + OpenResult result; if (m_diskHandle == -1) { - this->setErrorMessage(fmt::format("hex.builtin.provider.disk.error.read_rw"_lang, path, formatSystemError(errno))); - log::warn("{}", this->getErrorMessage()); + result = OpenResult::warning(fmt::format("hex.builtin.provider.disk.error.read_rw"_lang, path, formatSystemError(errno))); m_diskHandle = ::open(path.c_str(), O_RDONLY); m_writable = false; } if (m_diskHandle == -1) { - this->setErrorMessage(fmt::format("hex.builtin.provider.disk.error.read_ro"_lang, path, formatSystemError(errno))); - log::warn("{}", this->getErrorMessage()); m_readable = false; - return false; + return OpenResult::failure(fmt::format("hex.builtin.provider.disk.error.read_ro"_lang, path, formatSystemError(errno))); } u64 diskSize = 0; @@ -228,7 +226,7 @@ namespace hex::plugin::builtin { #endif - return true; + return result; } void DiskProvider::close() { diff --git a/plugins/builtin/source/content/providers/file_provider.cpp b/plugins/builtin/source/content/providers/file_provider.cpp index c955dc75b..ba32635a5 100644 --- a/plugins/builtin/source/content/providers/file_provider.cpp +++ b/plugins/builtin/source/content/providers/file_provider.cpp @@ -203,24 +203,23 @@ namespace hex::plugin::builtin { m_path.make_preferred(); } - bool FileProvider::open() { + prv::Provider::OpenResult FileProvider::open() { const size_t maxMemoryFileSize = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.max_mem_file_size", 128_MiB); size_t fileSize = 0x00; { wolv::io::File file(m_path, wolv::io::File::Mode::Read); if (!file.isValid()) { - this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0)))); - return false; + return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0)))); } fileSize = file.getSize(); } const bool directAccess = fileSize >= maxMemoryFileSize; - const bool result = open(directAccess); + const auto result = open(directAccess); - if (result && directAccess) { + if (result.isSuccess() && directAccess) { m_writable = false; ui::BannerButton::open(ICON_VS_WARNING, "hex.builtin.provider.file.too_large", ImColor(135, 116, 66), "hex.builtin.provider.file.too_large.allow_write", [this]{ @@ -232,7 +231,7 @@ namespace hex::plugin::builtin { return result; } - bool FileProvider::open(bool directAccess) { + prv::Provider::OpenResult FileProvider::open(bool directAccess) { m_readable = true; m_writable = true; @@ -243,8 +242,7 @@ namespace hex::plugin::builtin { file = wolv::io::File(m_path, wolv::io::File::Mode::Read); if (!file.isValid()) { m_readable = false; - this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0)))); - return false; + return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(file.getOpenError().value_or(0)))); } ui::ToastInfo::open("hex.builtin.popup.error.read_only"_lang); @@ -263,8 +261,7 @@ namespace hex::plugin::builtin { }); if (alreadyOpenedFileProvider != s_openedFiles.end()) { - ImHexApi::Provider::setCurrentProvider(*alreadyOpenedFileProvider); - return false; + return OpenResult::redirect(*alreadyOpenedFileProvider); } else { s_openedFiles.insert(this); } @@ -286,7 +283,7 @@ namespace hex::plugin::builtin { m_changeEventAcknowledgementPending = false; - return true; + return {}; } @@ -318,10 +315,6 @@ namespace hex::plugin::builtin { if (!wolv::io::fs::exists(fullPath)) fullPath = path; - if (!wolv::io::fs::exists(fullPath)) { - this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_path.string(), formatSystemError(ENOENT))); - } - path = std::move(fullPath); } diff --git a/plugins/builtin/source/content/providers/gdb_provider.cpp b/plugins/builtin/source/content/providers/gdb_provider.cpp index d097f8d17..07bf3b008 100644 --- a/plugins/builtin/source/content/providers/gdb_provider.cpp +++ b/plugins/builtin/source/content/providers/gdb_provider.cpp @@ -254,7 +254,7 @@ namespace hex::plugin::builtin { }; } - bool GDBProvider::open() { + prv::Provider::OpenResult GDBProvider::open() { std::scoped_lock lock(m_mutex); CachedProvider::open(); @@ -264,11 +264,11 @@ namespace hex::plugin::builtin { gdb::sendReceivePackage(m_socket, gdb::createPacket("!")); gdb::sendReceivePackage(m_socket, gdb::createPacket("Hg0")); - if (m_socket.isConnected()) { - return true; - } else { - return false; + if (!m_socket.isConnected()) { + return OpenResult::failure("hex.builtin.provider.gdb.server.error.not_connected"_lang); } + + return {}; } void GDBProvider::close() { diff --git a/plugins/builtin/source/content/providers/intel_hex_provider.cpp b/plugins/builtin/source/content/providers/intel_hex_provider.cpp index d7e5dd680..c0e3d5273 100644 --- a/plugins/builtin/source/content/providers/intel_hex_provider.cpp +++ b/plugins/builtin/source/content/providers/intel_hex_provider.cpp @@ -245,21 +245,19 @@ namespace hex::plugin::builtin { }); } - bool IntelHexProvider::open() { + prv::Provider::OpenResult IntelHexProvider::open() { auto file = wolv::io::File(m_sourceFilePath, wolv::io::File::Mode::Read); if (!file.isValid()) { - this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno))); - return false; + return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno))); } auto data = intel_hex::parseIntelHex(file.readString()); if (!data.has_value()) { - this->setErrorMessage(data.error()); - return false; + return OpenResult::failure(data.error()); } processMemoryRegions(data); - return true; + return {}; } void IntelHexProvider::close() { diff --git a/plugins/builtin/source/content/providers/memory_file_provider.cpp b/plugins/builtin/source/content/providers/memory_file_provider.cpp index f334bca76..b9edf4f56 100644 --- a/plugins/builtin/source/content/providers/memory_file_provider.cpp +++ b/plugins/builtin/source/content/providers/memory_file_provider.cpp @@ -16,12 +16,12 @@ namespace hex::plugin::builtin { - bool MemoryFileProvider::open() { + prv::Provider::OpenResult MemoryFileProvider::open() { if (m_data.empty()) { m_data.resize(1); } - return true; + return {}; } void MemoryFileProvider::readRaw(u64 offset, void *buffer, size_t size) { @@ -54,7 +54,7 @@ namespace hex::plugin::builtin { if (auto fileProvider = dynamic_cast(newProvider.get()); fileProvider != nullptr) { fileProvider->setPath(path); - if (!fileProvider->open()) { + if (fileProvider->open().isFailure()) { ImHexApi::Provider::remove(newProvider.get()); } else { MovePerProviderData::post(this, fileProvider); diff --git a/plugins/builtin/source/content/providers/motorola_srec_provider.cpp b/plugins/builtin/source/content/providers/motorola_srec_provider.cpp index 60ada419d..2b3aacb0b 100644 --- a/plugins/builtin/source/content/providers/motorola_srec_provider.cpp +++ b/plugins/builtin/source/content/providers/motorola_srec_provider.cpp @@ -170,21 +170,19 @@ namespace hex::plugin::builtin { } - bool MotorolaSRECProvider::open() { + prv::Provider::OpenResult MotorolaSRECProvider::open() { auto file = wolv::io::File(m_sourceFilePath, wolv::io::File::Mode::Read); if (!file.isValid()) { - this->setErrorMessage(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno))); - return false; + return OpenResult::failure(fmt::format("hex.builtin.provider.file.error.open"_lang, m_sourceFilePath.string(), formatSystemError(errno))); } auto data = motorola_srec::parseMotorolaSREC(file.readString()); if (!data.has_value()) { - this->setErrorMessage(data.error()); - return false; + return OpenResult::failure(data.error()); } processMemoryRegions(data); - return true; + return {}; } void MotorolaSRECProvider::close() { diff --git a/plugins/builtin/source/content/providers/process_memory_provider.cpp b/plugins/builtin/source/content/providers/process_memory_provider.cpp index bf83493da..db85fda42 100644 --- a/plugins/builtin/source/content/providers/process_memory_provider.cpp +++ b/plugins/builtin/source/content/providers/process_memory_provider.cpp @@ -102,21 +102,21 @@ namespace hex::plugin::builtin { #endif - bool ProcessMemoryProvider::open() { + prv::Provider::OpenResult ProcessMemoryProvider::open() { if (m_selectedProcess == nullptr) - return false; + return OpenResult::failure("hex.builtin.provider.process_memory.error.no_process_selected"_lang); #if defined(OS_WINDOWS) m_processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_selectedProcess->id); if (m_processHandle == nullptr) - return false; + return OpenResult::failure("hex.builtin.provider.process_memory.error.open_process"_lang); #else m_processId = pid_t(m_selectedProcess->id); #endif this->reloadProcessModules(); - return true; + return {}; } void ProcessMemoryProvider::close() { diff --git a/plugins/builtin/source/content/providers/udp_provider.cpp b/plugins/builtin/source/content/providers/udp_provider.cpp index 907929bbe..bf32c0bb0 100644 --- a/plugins/builtin/source/content/providers/udp_provider.cpp +++ b/plugins/builtin/source/content/providers/udp_provider.cpp @@ -7,13 +7,13 @@ namespace hex::plugin::builtin { - bool UDPProvider::open() { + prv::Provider::OpenResult UDPProvider::open() { m_udpServer = UDPServer(m_port, [this](std::span data) { this->receive(data); }); m_udpServer.start(); - return true; + return {}; } void UDPProvider::close() { diff --git a/plugins/builtin/source/content/providers/view_provider.cpp b/plugins/builtin/source/content/providers/view_provider.cpp index 69deffe95..a91e2494a 100644 --- a/plugins/builtin/source/content/providers/view_provider.cpp +++ b/plugins/builtin/source/content/providers/view_provider.cpp @@ -48,9 +48,9 @@ namespace hex::plugin::builtin { m_provider->save(); } - [[nodiscard]] bool ViewProvider::open() { + [[nodiscard]] prv::Provider::OpenResult ViewProvider::open() { if (m_provider == this) - return false; + return OpenResult::failure("hex.builtin.provider.view.error.no_provider"_lang); EventProviderClosing::subscribe(this, [this](const prv::Provider *provider, bool*) { if (m_provider == provider) { @@ -59,7 +59,7 @@ namespace hex::plugin::builtin { } }); - return true; + return {}; } void ViewProvider::close() { EventProviderClosing::unsubscribe(this); diff --git a/plugins/builtin/source/content/recent.cpp b/plugins/builtin/source/content/recent.cpp index 1e8f3598b..9c5cc6763 100644 --- a/plugins/builtin/source/content/recent.cpp +++ b/plugins/builtin/source/content/recent.cpp @@ -283,14 +283,7 @@ namespace hex::plugin::builtin::recent { if (provider != nullptr) { provider->loadSettings(recentEntry.data); - TaskManager::createBlockingTask("hex.builtin.provider.opening", TaskManager::NoProgress, [provider]() { - if (!provider->open() || !provider->isAvailable()) { - ui::ToastError::open(fmt::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage())); - TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider.get()); }); - } else { - TaskManager::doLater([provider]{ EventProviderOpened::post(provider.get()); }); - } - }); + ImHexApi::Provider::openProvider(provider); updateRecentEntries(); } diff --git a/plugins/builtin/source/content/ui_items.cpp b/plugins/builtin/source/content/ui_items.cpp index 8f00e4c9e..0a06db57c 100644 --- a/plugins/builtin/source/content/ui_items.cpp +++ b/plugins/builtin/source/content/ui_items.cpp @@ -539,7 +539,6 @@ namespace hex::plugin::builtin { flags |= ImGuiTabItemFlags_UnsavedDocument; if (i64(i) == selectedProviderIndex && providerJustChanged) { flags |= ImGuiTabItemFlags_SetSelected; - providerJustChanged = false; } static size_t lastSelectedProvider = 0; @@ -550,7 +549,7 @@ namespace hex::plugin::builtin { ImGui::EndTabItem(); } - if (isSelected && lastSelectedProvider != i) { + if (isSelected && lastSelectedProvider != i && !providerJustChanged) { ImHexApi::Provider::setCurrentProvider(i); lastSelectedProvider = i; } @@ -570,6 +569,8 @@ namespace hex::plugin::builtin { } } ImGui::EndTabBar(); + + providerJustChanged = false; } } ImGui::EndDisabled(); diff --git a/plugins/builtin/source/content/views/fullscreen/view_fullscreen_file_info.cpp b/plugins/builtin/source/content/views/fullscreen/view_fullscreen_file_info.cpp index c9d256315..c7c0b484f 100644 --- a/plugins/builtin/source/content/views/fullscreen/view_fullscreen_file_info.cpp +++ b/plugins/builtin/source/content/views/fullscreen/view_fullscreen_file_info.cpp @@ -15,8 +15,9 @@ namespace hex::plugin::builtin { ViewFullScreenFileInfo::ViewFullScreenFileInfo(std::fs::path filePath) : m_filePath(std::move(filePath)) { this->m_provider.setPath(m_filePath); - if (!this->m_provider.open()) { + if (this->m_provider.open().isFailure()) { ui::ToastError::open("hex.builtin.view.fullscreen.file_info.error.file_not_readable"_lang); + return; } m_analysisTask = TaskManager::createBlockingTask("hex.builtin.view.fullscreen.file_info.analyzing", TaskManager::NoProgress, [this](Task &task) { diff --git a/plugins/builtin/source/content/views/fullscreen/view_fullscreen_save_editor.cpp b/plugins/builtin/source/content/views/fullscreen/view_fullscreen_save_editor.cpp index d44287ba2..3048f15a0 100644 --- a/plugins/builtin/source/content/views/fullscreen/view_fullscreen_save_editor.cpp +++ b/plugins/builtin/source/content/views/fullscreen/view_fullscreen_save_editor.cpp @@ -67,8 +67,9 @@ namespace hex::plugin::builtin { if (ImGuiExt::DimmedButton(fmt::format("{} {}", ICON_VS_OPEN_PREVIEW, "hex.builtin.view.fullscreen.save_editor.select_file"_lang).c_str(), ImVec2(-1, 0))) { fs::openFileBrowser(fs::DialogMode::Open, {}, [this](const std::fs::path &path) { this->m_provider.setPath(path); - if (!this->m_provider.open()) { + if (this->m_provider.open().isFailure()) { ui::ToastError::open("hex.builtin.view.fullscreen.save_editor.error.not_readable"_lang); + return; } ContentRegistry::PatternLanguage::configureRuntime(m_runtime, &m_provider); diff --git a/plugins/builtin/source/content/views/view_bookmarks.cpp b/plugins/builtin/source/content/views/view_bookmarks.cpp index 2de63aad8..51bac3980 100644 --- a/plugins/builtin/source/content/views/view_bookmarks.cpp +++ b/plugins/builtin/source/content/views/view_bookmarks.cpp @@ -394,10 +394,9 @@ namespace hex::plugin::builtin { viewProvider->setProvider(region.getStartAddress(), region.getSize(), provider); viewProvider->setName(fmt::format("'{}' View", name)); - if (viewProvider->open()) { - EventProviderOpened::post(viewProvider); - AchievementManager::unlockAchievement("hex.builtin.achievement.hex_editor", "hex.builtin.achievement.hex_editor.open_new_view.name"); - } + ImHexApi::Provider::openProvider(newProvider); + + AchievementManager::unlockAchievement("hex.builtin.achievement.hex_editor", "hex.builtin.achievement.hex_editor.open_new_view.name"); } }); } diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index 85bb58271..7c3d3de0e 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -1170,8 +1170,7 @@ namespace hex::plugin::builtin { auto newProvider = ImHexApi::Provider::createProvider("hex.builtin.provider.view", true); if (auto *viewProvider = dynamic_cast(newProvider.get()); viewProvider != nullptr) { viewProvider->setProvider(selection->getStartAddress(), selection->getSize(), selection->getProvider()); - if (viewProvider->open()) - EventProviderOpened::post(viewProvider); + ImHexApi::Provider::openProvider(newProvider); } }, [] { return ImHexApi::HexEditor::isSelectionValid() && ImHexApi::Provider::isValid(); }, diff --git a/plugins/builtin/source/content/views/view_provider_settings.cpp b/plugins/builtin/source/content/views/view_provider_settings.cpp index ffce839e3..cef410963 100644 --- a/plugins/builtin/source/content/views/view_provider_settings.cpp +++ b/plugins/builtin/source/content/views/view_provider_settings.cpp @@ -11,8 +11,8 @@ namespace hex::plugin::builtin { ViewProviderSettings::ViewProviderSettings() : View::Modal("hex.builtin.view.provider_settings.name", ICON_VS_SETTINGS) { - EventProviderCreated::subscribe(this, [this](const hex::prv::Provider *provider) { - if (dynamic_cast(provider) != nullptr && !provider->shouldSkipLoadInterface()) + EventProviderCreated::subscribe(this, [this](std::shared_ptr provider) { + if (dynamic_cast(provider.get()) != nullptr && !provider->shouldSkipLoadInterface()) this->getWindowOpenState() = true; }); @@ -43,7 +43,8 @@ namespace hex::plugin::builtin { ImGui::BeginDisabled(!settingsValid); if (ImGui::Button("hex.ui.common.open"_lang)) { - if (provider->open()) { + auto result = provider->open(); + if (result.isSuccess()) { EventProviderOpened::post(provider); this->getWindowOpenState() = false; @@ -52,7 +53,7 @@ namespace hex::plugin::builtin { else { this->getWindowOpenState() = false; ImGui::CloseCurrentPopup(); - auto errorMessage = provider->getErrorMessage(); + auto errorMessage = result.getErrorMessage(); if (errorMessage.empty()) { ui::ToastError::open("hex.builtin.view.provider_settings.load_error"_lang); } else { diff --git a/plugins/builtin/source/content/welcome_screen.cpp b/plugins/builtin/source/content/welcome_screen.cpp index 30706584a..58d01c6b8 100644 --- a/plugins/builtin/source/content/welcome_screen.cpp +++ b/plugins/builtin/source/content/welcome_screen.cpp @@ -346,7 +346,7 @@ namespace hex::plugin::builtin { if (ImGuiExt::BeginSubWindow("hex.builtin.welcome.header.start"_lang, nullptr, ImVec2(), ImGuiChildFlags_AutoResizeX)) { if (ImGuiExt::IconHyperlink(ICON_VS_NEW_FILE, "hex.builtin.welcome.start.create_file"_lang)) { auto newProvider = hex::ImHexApi::Provider::createProvider("hex.builtin.provider.mem_file", true); - if (newProvider != nullptr && !newProvider->open()) + if (newProvider != nullptr && newProvider->open().isFailure()) hex::ImHexApi::Provider::remove(newProvider.get()); else EventProviderOpened::post(newProvider.get()); diff --git a/plugins/remote/include/content/providers/ssh_provider.hpp b/plugins/remote/include/content/providers/ssh_provider.hpp index 483d3ac85..9d5ef6425 100644 --- a/plugins/remote/include/content/providers/ssh_provider.hpp +++ b/plugins/remote/include/content/providers/ssh_provider.hpp @@ -15,7 +15,7 @@ namespace hex::plugin::remote { bool isResizable() const override { return false; } bool isSavable() const override { return isWritable(); } - bool open() override; + OpenResult open() override; void close() override; void save() override; diff --git a/plugins/remote/romfs/lang/en_US.json b/plugins/remote/romfs/lang/en_US.json index 186f5d4fe..3f6b30568 100644 --- a/plugins/remote/romfs/lang/en_US.json +++ b/plugins/remote/romfs/lang/en_US.json @@ -7,5 +7,6 @@ "hex.plugin.remote.ssh_provider.key_file": "Private Key Path", "hex.plugin.remote.ssh_provider.passphrase": "Passphrase", "hex.plugin.remote.ssh_provider.connect": "Connect", - "hex.plugin.remote.ssh_provider.ssh_access": "Access file using raw SSH" + "hex.plugin.remote.ssh_provider.ssh_access": "Access file using raw SSH", + "hex.plugin.remote.ssh_provider.error.open_failed": "Failed to open remote file" } diff --git a/plugins/remote/source/content/providers/ssh_provider.cpp b/plugins/remote/source/content/providers/ssh_provider.cpp index 79b3169e6..ed45d2f9e 100644 --- a/plugins/remote/source/content/providers/ssh_provider.cpp +++ b/plugins/remote/source/content/providers/ssh_provider.cpp @@ -11,7 +11,7 @@ namespace hex::plugin::remote { - bool SSHProvider::open() { + prv::Provider::OpenResult SSHProvider::open() { if (!m_sftpClient.isConnected()) { try { if (m_authMethod == AuthMethod::Password) { @@ -22,8 +22,7 @@ namespace hex::plugin::remote { m_sftpClient = std::move(client); } } catch (const std::exception& e) { - setErrorMessage(e.what()); - return false; + return OpenResult::failure(e.what()); } } @@ -33,11 +32,14 @@ namespace hex::plugin::remote { else m_remoteFile = m_sftpClient.openFileSFTP(m_remoteFilePath, SSHClient::OpenMode::ReadWrite); } catch (const std::exception& e) { - setErrorMessage(e.what()); - return false; + return OpenResult::failure(e.what()); } - return m_remoteFile->isOpen(); + if (!m_remoteFile->isOpen()) { + return OpenResult::failure("hex.plugin.remote.ssh_provider.error.open_failed"_lang); + } + + return {}; } void SSHProvider::close() { diff --git a/plugins/script_loader/support/c/source/script_api/v1/mem.cpp b/plugins/script_loader/support/c/source/script_api/v1/mem.cpp index c76077661..db9c0e6b8 100644 --- a/plugins/script_loader/support/c/source/script_api/v1/mem.cpp +++ b/plugins/script_loader/support/c/source/script_api/v1/mem.cpp @@ -60,7 +60,7 @@ public: using GetSizeFunction = u64(*)(); using GetNameFunction = std::string(*)(); - bool open() override { return true; } + OpenResult open() override { return {}; } void close() override { } [[nodiscard]] bool isAvailable() const override { return true; }