From 0da508594b2d0997ca216b1bb030f36355e7339d Mon Sep 17 00:00:00 2001 From: WerWolv Date: Fri, 19 Feb 2021 13:22:12 +0100 Subject: [PATCH] ui/api: Added loaded plugin information to welcome screen --- include/helpers/plugin_handler.hpp | 24 ++++++++-- plugins/builtin/source/lang/en_US.cpp | 4 ++ plugins/builtin/source/plugin_builtin.cpp | 2 +- plugins/example/source/plugin_example.cpp | 2 +- plugins/libimhex/include/hex/plugin.hpp | 15 ++++--- source/helpers/plugin_handler.cpp | 53 ++++++++++++++++++----- source/views/view_information.cpp | 2 +- source/window.cpp | 45 +++++++++++++++++++ 8 files changed, 125 insertions(+), 22 deletions(-) diff --git a/include/helpers/plugin_handler.hpp b/include/helpers/plugin_handler.hpp index 128b39d02..5375c4600 100644 --- a/include/helpers/plugin_handler.hpp +++ b/include/helpers/plugin_handler.hpp @@ -4,8 +4,10 @@ #include #include +#include #include +#include namespace hex { @@ -13,17 +15,33 @@ namespace hex { public: Plugin(std::string_view path); Plugin(const Plugin&) = delete; - Plugin(Plugin &&other); + Plugin(Plugin &&other) noexcept; ~Plugin(); void initializePlugin() const; + std::string getPluginName() const; + std::string getPluginAuthor() const; + std::string getPluginDescription() const; + private: - using InitializePluginFunc = void(*)(); + using InitializePluginFunc = void(*)(); + using GetPluginNameFunc = const char*(*)(); + using GetPluginAuthorFunc = const char*(*)(); + using GetPluginDescriptionFunc = const char*(*)(); void *m_handle = nullptr; - InitializePluginFunc m_initializePluginFunction = nullptr; + InitializePluginFunc m_initializePluginFunction = nullptr; + GetPluginNameFunc m_getPluginNameFunction = nullptr; + GetPluginAuthorFunc m_getPluginAuthorFunction = nullptr; + GetPluginDescriptionFunc m_getPluginDescriptionFunction = nullptr; + + template + auto getPluginFunction(std::string_view pluginName, std::string_view symbol) { + auto symbolName = hex::format(symbol.data(), pluginName.length(), pluginName.data()); + return reinterpret_cast(dlsym(this->m_handle, symbolName.c_str())); + }; }; class PluginHandler { diff --git a/plugins/builtin/source/lang/en_US.cpp b/plugins/builtin/source/lang/en_US.cpp index 9deb15df0..2b564bfcf 100644 --- a/plugins/builtin/source/lang/en_US.cpp +++ b/plugins/builtin/source/lang/en_US.cpp @@ -24,6 +24,10 @@ namespace hex::plugin::builtin { { "hex.welcome.help.repo.link", "https://github.com/WerWolv/ImHex" }, { "hex.welcome.help.gethelp", "Get Help" }, { "hex.welcome.help.gethelp.link", "https://github.com/WerWolv/ImHex/discussions/categories/get-help" }, + { "hex.welcome.header.plugins", "Loaded Plugins" }, + { "hex.welcome.plugins.plugin", "Plugin" }, + { "hex.welcome.plugins.author", "Author" }, + { "hex.welcome.plugins.desc", "Description" }, { "hex.welcome.header.customize", "Customize" }, { "hex.welcome.customize.settings.title", "Settings" }, { "hex.welcome.customize.settings.desc", "Change preferences of ImHex" }, diff --git a/plugins/builtin/source/plugin_builtin.cpp b/plugins/builtin/source/plugin_builtin.cpp index eab411f4b..0bf7457ed 100644 --- a/plugins/builtin/source/plugin_builtin.cpp +++ b/plugins/builtin/source/plugin_builtin.cpp @@ -13,7 +13,7 @@ namespace hex::plugin::builtin { } -IMHEX_PLUGIN_SETUP { +IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") { using namespace hex::plugin::builtin; diff --git a/plugins/example/source/plugin_example.cpp b/plugins/example/source/plugin_example.cpp index 9eb586170..28b54d436 100644 --- a/plugins/example/source/plugin_example.cpp +++ b/plugins/example/source/plugin_example.cpp @@ -15,7 +15,7 @@ public: } }; -IMHEX_PLUGIN_SETUP { +IMHEX_PLUGIN_SETUP("Example", "WerWolv", "Example plugin used as template for plugin devs") { ContentRegistry::Views::add(); diff --git a/plugins/libimhex/include/hex/plugin.hpp b/plugins/libimhex/include/hex/plugin.hpp index 9b26133b6..19758d7f2 100644 --- a/plugins/libimhex/include/hex/plugin.hpp +++ b/plugins/libimhex/include/hex/plugin.hpp @@ -11,9 +11,14 @@ #include #include -#define IMHEX_PLUGIN_SETUP IMHEX_PLUGIN_SETUP_IMPL(IMHEX_PLUGIN_NAME) +#define IMHEX_PLUGIN_SETUP(name, author, description) IMHEX_PLUGIN_SETUP_IMPL(IMHEX_PLUGIN_NAME, name, author, description) -#define IMHEX_PLUGIN_SETUP_IMPL(name) namespace hex::plugin::name::internal { \ - [[gnu::visibility("default")]] void initializePlugin(); \ - } \ - void hex::plugin::name::internal::initializePlugin() +#define IMHEX_PLUGIN_SETUP_IMPL(namespaceName, name, author, description) \ + namespace hex::plugin::namespaceName::internal { \ + [[gnu::visibility("default")]] void initializePlugin(); \ + \ + [[gnu::visibility("default")]] const char* getPluginName() { return name; } \ + [[gnu::visibility("default")]] const char* getPluginAuthor() { return author; } \ + [[gnu::visibility("default")]] const char* getPluginDescription() { return description; } \ + } \ + void hex::plugin::namespaceName::internal::initializePlugin() diff --git a/source/helpers/plugin_handler.cpp b/source/helpers/plugin_handler.cpp index f209eb640..7be860c0a 100644 --- a/source/helpers/plugin_handler.cpp +++ b/source/helpers/plugin_handler.cpp @@ -1,7 +1,5 @@ #include "helpers/plugin_handler.hpp" -#include - #include namespace hex { @@ -9,24 +7,37 @@ namespace hex { namespace fs = std::filesystem; // hex::plugin::::internal::initializePlugin() - constexpr auto InitializePluginSymbol = "_ZN3hex6plugin%d%s8internal16initializePluginEv"; + constexpr auto InitializePluginSymbol = "_ZN3hex6plugin%d%s8internal16initializePluginEv"; + constexpr auto GetPluginNameSymbol = "_ZN3hex6plugin%d%s8internal13getPluginNameEv"; + constexpr auto GetPluginAuthorSymbol = "_ZN3hex6plugin%d%s8internal15getPluginAuthorEv"; + constexpr auto GetPluginDescriptionSymbol = "_ZN3hex6plugin%d%s8internal20getPluginDescriptionEv"; Plugin::Plugin(std::string_view path) { - auto fileName = fs::path(path).stem(); - auto symbolName = hex::format(InitializePluginSymbol, fileName.string().length(), fileName.string().c_str()); this->m_handle = dlopen(path.data(), RTLD_LAZY); + if (this->m_handle == nullptr) return; - this->m_initializePluginFunction = reinterpret_cast(dlsym(this->m_handle, symbolName.c_str())); + auto pluginName = fs::path(path).stem().string(); + + this->m_initializePluginFunction = getPluginFunction(pluginName, InitializePluginSymbol); + this->m_getPluginNameFunction = getPluginFunction(pluginName, GetPluginNameSymbol); + this->m_getPluginAuthorFunction = getPluginFunction(pluginName, GetPluginAuthorSymbol); + this->m_getPluginDescriptionFunction = getPluginFunction(pluginName, GetPluginDescriptionSymbol); } - Plugin::Plugin(Plugin &&other) { + Plugin::Plugin(Plugin &&other) noexcept { this->m_handle = other.m_handle; - this->m_initializePluginFunction = other.m_initializePluginFunction; + this->m_initializePluginFunction = other.m_initializePluginFunction; + this->m_getPluginNameFunction = other.m_getPluginNameFunction; + this->m_getPluginAuthorFunction = other.m_getPluginAuthorFunction; + this->m_getPluginDescriptionFunction = other.m_getPluginDescriptionFunction; other.m_handle = nullptr; - other.m_initializePluginFunction = nullptr; + other.m_initializePluginFunction = nullptr; + other.m_getPluginNameFunction = nullptr; + other.m_getPluginAuthorFunction = nullptr; + other.m_getPluginDescriptionFunction = nullptr; } Plugin::~Plugin() { @@ -34,9 +45,29 @@ namespace hex { } void Plugin::initializePlugin() const { - if (this->m_initializePluginFunction != nullptr) { + if (this->m_initializePluginFunction != nullptr) this->m_initializePluginFunction(); - } + } + + std::string Plugin::getPluginName() const { + if (this->m_getPluginNameFunction != nullptr) + return this->m_getPluginNameFunction(); + else + return hex::format("Unknown Plugin @ 0x016llX", this->m_handle); + } + + std::string Plugin::getPluginAuthor() const { + if (this->m_getPluginAuthorFunction != nullptr) + return this->m_getPluginAuthorFunction(); + else + return "Unknown"; + } + + std::string Plugin::getPluginDescription() const { + if (this->m_getPluginDescriptionFunction != nullptr) + return this->m_getPluginDescriptionFunction(); + else + return ""; } void PluginHandler::load(std::string_view pluginFolder) { diff --git a/source/views/view_information.cpp b/source/views/view_information.cpp index 1a88e25a3..beefa955e 100644 --- a/source/views/view_information.cpp +++ b/source/views/view_information.cpp @@ -177,7 +177,7 @@ namespace hex { if (this->m_averageEntropy > 0.83 && this->m_highestBlockEntropy > 0.9) { ImGui::NewLine(); - ImGui::TextColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F),"hex.view.information.encrypted"_lang); + ImGui::TextColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "hex.view.information.encrypted"_lang); } } diff --git a/source/window.cpp b/source/window.cpp index 27c8e912e..c2beee10f 100644 --- a/source/window.cpp +++ b/source/window.cpp @@ -364,6 +364,7 @@ namespace hex { if (ImGui::BulletHyperlink("hex.welcome.start.open_project"_lang)) EventManager::post(Events::OpenWindow, "Open Project"); } + ImGui::TableNextRow(ImGuiTableRowFlags_None, rowHeight); ImGui::TableNextColumn(); ImGui::TextUnformatted("hex.welcome.start.recent"_lang); @@ -377,6 +378,7 @@ namespace hex { } } } + ImGui::TableNextRow(ImGuiTableRowFlags_None, rowHeight); ImGui::TableNextColumn(); ImGui::TextUnformatted("hex.welcome.header.help"_lang); @@ -385,6 +387,49 @@ namespace hex { if (ImGui::BulletHyperlink("hex.welcome.help.gethelp"_lang)) hex::openWebpage("hex.welcome.help.gethelp.link"_lang); } + ImGui::TableNextRow(ImGuiTableRowFlags_None, rowHeight); + ImGui::TableNextColumn(); + ImGui::TextUnformatted("hex.welcome.header.plugins"_lang); + { + const auto &plugins = PluginHandler::getPlugins(); + + if (plugins.empty()) { + // Intentionally left untranslated so it will be readable even if no plugin with translations is loaded + ImGui::TextColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), + "No plugins loaded! To use ImHex properly, " + "make sure at least the builtin plugin is in the /plugins folder next to the executable"); + } else { + if (ImGui::BeginTable("plugins", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY | ImGuiTableFlags_SizingFixedFit, ImVec2((ImGui::GetContentRegionAvail().x * 5) / 6, ImGui::GetTextLineHeightWithSpacing() * 4))) { + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("hex.welcome.plugins.plugin"_lang); + ImGui::TableSetupColumn("hex.welcome.plugins.author"_lang); + ImGui::TableSetupColumn("hex.welcome.plugins.desc"_lang); + + ImGui::TableHeadersRow(); + + ImGuiListClipper clipper; + clipper.Begin(plugins.size()); + + while (clipper.Step()) { + for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::TextUnformatted((plugins[i].getPluginName() + " ").c_str()); + ImGui::TableNextColumn(); + ImGui::TextUnformatted((plugins[i].getPluginAuthor() + " ").c_str()); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(plugins[i].getPluginDescription().c_str()); + } + } + + clipper.End(); + + ImGui::EndTable(); + } + } + } + + ImGui::EndTable(); } ImGui::SameLine();