mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-02 05:27:41 -05:00
impr: Handle provider opening more centrally, switch to existing provider if same file is being opened again
(cherry picked from commit 89004574d3)
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;
|
||||
|
||||
@@ -79,6 +79,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;
|
||||
@@ -94,7 +153,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
|
||||
@@ -262,9 +321,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)...);
|
||||
@@ -296,8 +352,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) {
|
||||
|
||||
Reference in New Issue
Block a user