diff --git a/lib/libimhex/include/hex/api/event.hpp b/lib/libimhex/include/hex/api/event.hpp index 9d3618770..cca425e02 100644 --- a/lib/libimhex/include/hex/api/event.hpp +++ b/lib/libimhex/include/hex/api/event.hpp @@ -163,8 +163,23 @@ namespace hex { EVENT_DEF(EventSettingsChanged); EVENT_DEF(EventAbnormalTermination, int); EVENT_DEF(EventOSThemeChanged); + + /** + * @brief Called when the provider is created. + * 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(EventProviderChanged, prv::Provider *, prv::Provider *); + + /** + * @brief Called as a continuation of EventProviderCreated + * this event is normally called immediately after EventProviderCreated successfully initialized the provider. + * If no initialization (Provider::skipLoadInterface() has been set), this event should be called manually + * If skipLoadInterface failed, this event is not called + * + * @note this is not related to Provider::open() + */ EVENT_DEF(EventProviderOpened, prv::Provider *); EVENT_DEF(EventProviderClosing, prv::Provider *, bool *); EVENT_DEF(EventProviderClosed, prv::Provider *); @@ -195,6 +210,10 @@ namespace hex { EVENT_DEF(RequestOpenFile, std::fs::path); EVENT_DEF(RequestChangeTheme, std::string); EVENT_DEF(RequestOpenPopup, std::string); + + /** + * @brief Creates a provider from it's unlocalized name, and add it to the provider list + */ EVENT_DEF(RequestCreateProvider, std::string, bool, hex::prv::Provider **); EVENT_DEF(RequestInitThemeHandlers); diff --git a/lib/libimhex/include/hex/api/imhex_api.hpp b/lib/libimhex/include/hex/api/imhex_api.hpp index 1cf899566..2ce07414e 100644 --- a/lib/libimhex/include/hex/api/imhex_api.hpp +++ b/lib/libimhex/include/hex/api/imhex_api.hpp @@ -225,7 +225,11 @@ namespace hex { } - /* Functions to interact with the loaded data provider */ + /** + * Helper methods about the providers + * @note the "current provider" or "currently selected provider" refers to the currently selected provider in the UI; + * the provider the user is actually editing. + */ namespace Provider { namespace impl { @@ -237,7 +241,7 @@ namespace hex { /** * @brief Gets the currently selected data provider - * @return The currently selected data provider + * @return The currently selected data provider, or nullptr is there is none */ prv::Provider *get(); @@ -261,26 +265,26 @@ namespace hex { /** - * @brief Marks the currently selected data provider as dirty + * @brief Marks the **currently selected** data provider as dirty */ void markDirty(); /** - * @brief Marks the currently selected data provider as clean + * @brief Marks **all data providers** as clean */ void resetDirty(); /** - * @brief Checks whether the currently selected data provider is dirty - * @return Whether the currently selected data provider is dirty + * @brief Checks whether **any of the data providers** is dirty + * @return Whether any data provider is dirty */ bool isDirty(); /** - * @brief Adds a newly created provider to the list of providers + * @brief Adds a newly created provider to the list of providers, and mark it as the selected one. * @param provider The provider to add - * @param skipLoadInterface Whether to skip loading the provider's loading interface + * @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation) */ void add(prv::Provider *provider, bool skipLoadInterface = false); @@ -302,9 +306,9 @@ namespace hex { void remove(prv::Provider *provider, bool noQuestions = false); /** - * @brief Creates a new provider using its unlocalized name + * @brief Creates a new provider using its unlocalized name and add it to the list of providers * @param unlocalizedName The unlocalized name of the provider to create - * @param skipLoadInterface Whether to skip loading the provider's loading interface + * @param skipLoadInterface Whether to skip the provider's loading interface (see property documentation) */ prv::Provider* createProvider(const std::string &unlocalizedName, bool skipLoadInterface = false); diff --git a/lib/libimhex/include/hex/providers/provider.hpp b/lib/libimhex/include/hex/providers/provider.hpp index ff9650d42..71421d51e 100644 --- a/lib/libimhex/include/hex/providers/provider.hpp +++ b/lib/libimhex/include/hex/providers/provider.hpp @@ -17,7 +17,7 @@ namespace hex::prv { /** - * @brief Represent the data source for a tab + * @brief Represent the data source for a tab in the UI */ class Provider { public: @@ -96,6 +96,13 @@ namespace hex::prv { [[nodiscard]] virtual std::vector> getDataDescription() const = 0; [[nodiscard]] virtual std::variant queryInformation(const std::string &category, const std::string &argument); + /** + * @brief Opens this provider + * the return value of this function allows to ensure the provider is available, + * so calling Provider::isAvailable() just after a call to open() that returned true is dedundant. + * @note This is not related to the EventProviderOpened event + * @return true if the provider was opened sucessfully, else false + */ [[nodiscard]] virtual bool open() = 0; virtual void close() = 0; @@ -145,7 +152,19 @@ namespace hex::prv { u32 m_id; + /** + * @brief true if there is any data that needs to be saved + */ bool m_dirty = false; + + /** + * @brief Control whetever to skip provider initialization + * initialization may be asking the user for information related to the provider, + * e.g. a process ID for the process memory provider + * this is used mainly when restoring a provider with already known initialization information + * for example when loading a project or loading a provider from the "recent" lsit + * + */ bool m_skipLoadInterface = false; std::string m_errorMessage; diff --git a/plugins/builtin/source/content/events.cpp b/plugins/builtin/source/content/events.cpp index 00e223135..0f099d634 100644 --- a/plugins/builtin/source/content/events.cpp +++ b/plugins/builtin/source/content/events.cpp @@ -99,7 +99,8 @@ namespace hex::plugin::builtin { EventManager::post(); }); - EventManager::subscribe([](hex::prv::Provider *provider) { + // Handles the provider initialization, and calls EventProviderOpened if successful + EventManager::subscribe([](hex::prv::Provider *provider) { if (provider->shouldSkipLoadInterface()) return; diff --git a/plugins/builtin/source/content/welcome_screen.cpp b/plugins/builtin/source/content/welcome_screen.cpp index 9fc8a6118..ed411e251 100644 --- a/plugins/builtin/source/content/welcome_screen.cpp +++ b/plugins/builtin/source/content/welcome_screen.cpp @@ -409,7 +409,9 @@ namespace hex::plugin::builtin { } ImGui::End(); } - + /** + * @brief Draw some default background if there are no views avaialble in the current layout + */ static void drawNoViewsBackground() { if (ImGui::Begin("ImHexDockSpace")) { static char title[256]; @@ -444,10 +446,16 @@ namespace hex::plugin::builtin { ImGui::End(); } + /** + * @brief Registers the event handlers related to the welcome screen + * should only be called once, at startup + */ void createWelcomeScreen() { updateRecentProviders(); (void)EventManager::subscribe(drawWelcomeScreen); + + // Sets a background when they are no views (void)EventManager::subscribe([]{ if (ImHexApi::Provider::isValid() && !isAnyViewOpen()) drawNoViewsBackground(); @@ -496,10 +504,13 @@ namespace hex::plugin::builtin { } }); + + // Save every opened provider as a "recent" shortcut (void)EventManager::subscribe([](prv::Provider *provider) { if (ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.save_recent_providers", 1) == 1) { + auto fileName = hex::format("{:%y%m%d_%H%M%S}.json", fmt::gmtime(std::chrono::system_clock::now())); + // The recent provider is saved to every "recent" directory for (const auto &recentPath : fs::getDefaultPaths(fs::ImHexPath::Recent)) { - auto fileName = hex::format("{:%y%m%d_%H%M%S}.json", fmt::gmtime(std::chrono::system_clock::now())); wolv::io::File recentFile(recentPath / fileName, wolv::io::File::Mode::Create); if (!recentFile.isValid()) continue;