mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-03-27 23:37:05 -05:00
impr: Handle provider opening more centrally, switch to existing provider if same file is being opened again
This commit is contained in:
@@ -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<prv::Provider>);
|
||||
|
||||
/**
|
||||
* @brief Called as a continuation of EventProviderCreated
|
||||
|
||||
@@ -10,6 +10,11 @@ namespace hex {
|
||||
*/
|
||||
EVENT_DEF(RequestCreateProvider, std::string, bool, bool, std::shared_ptr<hex::prv::Provider> *);
|
||||
|
||||
/**
|
||||
* @brief Used internally when opening a provider through the API
|
||||
*/
|
||||
EVENT_DEF(RequestOpenProvider, std::shared_ptr<prv::Provider>);
|
||||
|
||||
/**
|
||||
* @brief Move the data from all PerProvider instances from one provider to another
|
||||
*
|
||||
|
||||
@@ -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<prv::Provider> provider);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<std::monostate>(m_result);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isFailure() const {
|
||||
return std::holds_alternative<std::string>(m_result) && !m_warning;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isWarning() const {
|
||||
return std::holds_alternative<std::string>(m_result) && m_warning;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isRedirecting() const {
|
||||
return std::holds_alternative<Provider*>(m_result);
|
||||
}
|
||||
|
||||
[[nodiscard]] Provider* getRedirectProvider() const {
|
||||
if (std::holds_alternative<Provider*>(m_result)) {
|
||||
return std::get<Provider*>(m_result);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string_view getErrorMessage() const {
|
||||
if (std::holds_alternative<std::string>(m_result)) {
|
||||
return std::get<std::string>(m_result);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private:
|
||||
std::variant<std::monostate, std::string, Provider*> 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<std::derived_from<undo::Operation> T>
|
||||
bool addUndoableOperation(auto && ... args) {
|
||||
return m_undoRedoStack.add<T>(std::forward<decltype(args)...>(args)...);
|
||||
@@ -311,8 +367,6 @@ namespace hex::prv {
|
||||
*/
|
||||
bool m_skipLoadInterface = false;
|
||||
|
||||
std::string m_errorMessage = "Unspecified error";
|
||||
|
||||
u64 m_pageSize = MaxPageSize;
|
||||
};
|
||||
|
||||
|
||||
@@ -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<prv::Provider> provider) {
|
||||
RequestOpenProvider::post(provider);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ImHexApi::System {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -11,9 +11,9 @@ namespace hex::prv {
|
||||
clearCache();
|
||||
}
|
||||
|
||||
bool CachedProvider::open() {
|
||||
Provider::OpenResult CachedProvider::open() {
|
||||
clearCache();
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
void CachedProvider::close() {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace hex::plugin::builtin {
|
||||
[[nodiscard]] std::string getName() const override;
|
||||
[[nodiscard]] std::vector<Description> getDataDescription() const override;
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
[[nodiscard]] OpenResult open() override;
|
||||
void close() override;
|
||||
|
||||
[[nodiscard]] bool isConnected() const;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace hex::plugin::builtin {
|
||||
[[nodiscard]] u64 getActualSize() const override;
|
||||
void processMemoryRegions(wolv::util::Expected<std::map<u64, std::vector<u8>>, 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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace hex::plugin::builtin {
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] bool open() override;
|
||||
[[nodiscard]] OpenResult open() override;
|
||||
void close() override;
|
||||
|
||||
bool drawLoadInterface() override;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -360,10 +360,10 @@ namespace hex::plugin::builtin {
|
||||
std::fs::path filePath = reinterpret_cast<const char8_t*>(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);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,15 +52,10 @@ namespace hex::plugin::builtin {
|
||||
auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true);
|
||||
if (auto *fileProvider = dynamic_cast<FileProvider*>(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<prv::Provider> provider) {
|
||||
if (provider->shouldSkipLoadInterface())
|
||||
return;
|
||||
|
||||
if (auto *filePickerProvider = dynamic_cast<prv::IProviderFilePicker*>(provider); filePickerProvider != nullptr) {
|
||||
if (auto *filePickerProvider = dynamic_cast<prv::IProviderFilePicker*>(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<prv::IProviderLoadInterface*>(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<prv::IProviderLoadInterface*>(provider.get()) == nullptr) {
|
||||
ImHexApi::Provider::openProvider(provider);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -419,6 +393,25 @@ namespace hex::plugin::builtin {
|
||||
});
|
||||
});
|
||||
|
||||
RequestOpenProvider::subscribe([](std::shared_ptr<prv::Provider> 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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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<u64>("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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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<FileProvider*>(newProvider.get()); fileProvider != nullptr) {
|
||||
fileProvider->setPath(path);
|
||||
|
||||
if (!fileProvider->open()) {
|
||||
if (fileProvider->open().isFailure()) {
|
||||
ImHexApi::Provider::remove(newProvider.get());
|
||||
} else {
|
||||
MovePerProviderData::post(this, fileProvider);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
bool UDPProvider::open() {
|
||||
prv::Provider::OpenResult UDPProvider::open() {
|
||||
m_udpServer = UDPServer(m_port, [this](std::span<const u8> data) {
|
||||
this->receive(data);
|
||||
});
|
||||
m_udpServer.start();
|
||||
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
void UDPProvider::close() {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1170,8 +1170,7 @@ namespace hex::plugin::builtin {
|
||||
auto newProvider = ImHexApi::Provider::createProvider("hex.builtin.provider.view", true);
|
||||
if (auto *viewProvider = dynamic_cast<ViewProvider*>(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(); },
|
||||
|
||||
@@ -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<const prv::IProviderLoadInterface*>(provider) != nullptr && !provider->shouldSkipLoadInterface())
|
||||
EventProviderCreated::subscribe(this, [this](std::shared_ptr<prv::Provider> provider) {
|
||||
if (dynamic_cast<const prv::IProviderLoadInterface*>(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 {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user