1
0
mirror of synced 2024-11-24 07:40:17 +01:00

Refactored plugin system

This commit is contained in:
WerWolv 2021-01-12 16:50:15 +01:00
parent c09a8bca7f
commit 84a6fff034
15 changed files with 170 additions and 164 deletions

View File

@ -39,8 +39,12 @@ find_package(OpenGL REQUIRED)
find_package(Python COMPONENTS Development)
add_subdirectory(external/llvm)
# Plugins
add_subdirectory(plugins/libimhex)
add_subdirectory(plugins/example)
if(Python_VERSION LESS 3)
message(STATUS ${PYTHON_VERSION_MAJOR_MINOR})

View File

@ -15,20 +15,13 @@ namespace hex {
~Plugin();
void initializePlugin(SharedData &sharedData) const;
View* createView() const;
void drawToolsEntry() const;
private:
using InitializePluginFunc = void(*)(SharedData &sharedData);
using CreateViewFunc = View*(*)();
using DrawToolsEntryFunc = void(*)();
void *m_handle = nullptr;
InitializePluginFunc m_initializePluginFunction = nullptr;
CreateViewFunc m_createViewFunction = nullptr;
DrawToolsEntryFunc m_drawToolsEntryFunction = nullptr;
};
class PluginHandler {

View File

@ -14,18 +14,11 @@ namespace hex {
class Window {
public:
Window();
Window(int &argc, char **&argv);
~Window();
void loop();
template<derived_from<View> T, typename ... Args>
T* addView(Args&& ... args) {
this->m_views.emplace_back(new T(std::forward<Args>(args)...));
return static_cast<T*>(this->m_views.back());
}
friend void *ImHexSettingsHandler_ReadOpenFn(ImGuiContext *ctx, ImGuiSettingsHandler *, const char *);
friend void ImHexSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler *handler, void *, const char* line);
friend void ImHexSettingsHandler_ApplyAll(ImGuiContext *ctx, ImGuiSettingsHandler *handler);
@ -33,20 +26,18 @@ namespace hex {
bool setFont(const std::filesystem::path &font_path);
void initPlugins();
void deinitPlugins();
private:
void frameBegin();
void frameEnd();
void initGLFW();
void initImGui();
void initPlugins();
void deinitGLFW();
void deinitImGui();
void deinitPlugins();
GLFWwindow* m_window;
std::vector<View*> m_views;
std::vector<View*> m_pluginViews;
float m_globalScale = 1.0f, m_fontScale = 1.0f;
bool m_fpsVisible = false;

View File

@ -3,7 +3,9 @@ project(example)
set(CMAKE_CXX_STANDARD 20)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../libimhex ${CMAKE_CURRENT_BINARY_DIR}/plugins/libimhex)
if (NOT TARGET libimhex)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../libimhex ${CMAKE_CURRENT_BINARY_DIR}/plugins/libimhex)
endif()
set(CMAKE_SHARED_LIBRARY_PREFIX "plugin")

View File

@ -15,17 +15,9 @@ public:
}
};
IMHEX_PLUGIN {
IMHEX_PLUGIN_SETUP {
View* createView() {
return new ViewExample();
}
void drawToolsEntry() {
if (ImGui::CollapsingHeader("Example Tool")) {
ImGui::Text("Custom Plugin tool");
}
}
ContentRegistry::Views::add<ViewExample>();
}

View File

@ -2,6 +2,7 @@
#include <hex.hpp>
#include <concepts>
#include <functional>
#include <map>
#include <string>
@ -12,12 +13,19 @@
namespace hex {
class View;
namespace lang { class ASTNode; }
/*
The Content Registry is the heart of all features in ImHex that are in some way extendable by Plugins.
It allows you to add/register new content that will be picked up and used by the ImHex core or by other
plugins when needed.
*/
class ContentRegistry {
public:
ContentRegistry() = delete;
/* Settings Registry. Allows adding of new entries into the ImHex preferences window. */
struct Settings {
Settings() = delete;
@ -36,12 +44,14 @@ namespace hex {
static nlohmann::json& getSettingsData();
};
/* Events Registry. Allows to define new events that can be used by other plugins later on subscribe to */
struct Events {
Events() = delete;
static auto get(std::string_view name);
};
/* Command Palette Command Registry. Allows adding of new commands to the command palette */
struct CommandPaletteCommands {
CommandPaletteCommands() = delete;
@ -58,9 +68,10 @@ namespace hex {
};
static void add(Type type, std::string_view command, std::string_view description, const std::function<std::string(std::string)> &callback);
static std::vector<Entry> getEntries();
static std::vector<Entry>& getEntries();
};
/* Pattern Language Function Registry. Allows adding of new functions that may be used inside the pattern language */
struct PatternLanguageFunctions {
PatternLanguageFunctions() = delete;
@ -75,7 +86,31 @@ namespace hex {
};
static void add(std::string_view name, u32 parameterCount, const std::function<hex::lang::ASTNode*(std::vector<hex::lang::ASTNode*>)> &func);
static std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function> getEntries();
static std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function>& getEntries();
};
/* View Registry. Allows adding of new windows */
struct Views {
Views() = delete;
template<std::derived_from<View> T, typename ... Args>
static T* add(Args&& ... args) {
return static_cast<T*>(add(new T(std::forward<Args>(args)...)));
}
static std::vector<View*>& getEntries();
private:
static View* add(View *view);
};
/* Tools Registry. Allows adding new entries to the tools window */
struct Tools {
static void add(const std::function<void()> &function);
static std::vector<std::function<void()>>& getEntries();
};
};

View File

@ -5,8 +5,9 @@
#include <vector>
#include <map>
#include <helpers/event.hpp>
#include <helpers/content_registry.hpp>
#include <helpers/event.hpp>
#include <views/view.hpp>
#include <imgui.h>
#include <nlohmann/json.hpp>
@ -49,6 +50,9 @@ namespace hex {
private:
void initializeData() {
static int mainArgcStorage;
static char **mainArgvStorage;
static ImGuiContext *imGuiContextStorage;
static std::vector<EventHandler> eventHandlersStorage;
static std::vector<std::function<void()>> deferredCallsStorage;
static prv::Provider *currentProviderStorage;
@ -60,8 +64,10 @@ namespace hex {
static u32 customEventsLastIdStorage = u32(Events::Events_BuiltinEnd) + 1;
static std::vector<ContentRegistry::CommandPaletteCommands::Entry> commandPaletteCommandsStorage;
static std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function> patternLanguageFunctionsStorage;
static std::vector<View*> viewsStorage;
static std::vector<std::function<void()>> toolsStorage;
this->imguiContext = ImGui::GetCurrentContext();
this->imguiContext = &imGuiContextStorage;
this->eventHandlers = &eventHandlersStorage;
this->deferredCalls = &deferredCallsStorage;
this->currentProvider = &currentProviderStorage;
@ -74,6 +80,10 @@ namespace hex {
this->customEventsLastId = &customEventsLastIdStorage;
this->commandPaletteCommands = &commandPaletteCommandsStorage;
this->patternLanguageFunctions = &patternLanguageFunctionsStorage;
this->views = &viewsStorage;
this->tools = &toolsStorage;
this->mainArgc = &mainArgcStorage;
this->mainArgv = &mainArgvStorage;
}
void initializeData(const SharedData &other) {
@ -90,10 +100,14 @@ namespace hex {
this->customEventsLastId = other.customEventsLastId;
this->commandPaletteCommands = other.commandPaletteCommands;
this->patternLanguageFunctions = other.patternLanguageFunctions;
this->views = other.views;
this->tools = other.tools;
this->mainArgc = other.mainArgc;
this->mainArgv = other.mainArgv;
}
public:
ImGuiContext *imguiContext;
ImGuiContext **imguiContext;
std::vector<EventHandler> *eventHandlers;
std::vector<std::function<void()>> *deferredCalls;
prv::Provider **currentProvider;
@ -103,6 +117,11 @@ namespace hex {
u32 *customEventsLastId;
std::vector<ContentRegistry::CommandPaletteCommands::Entry> *commandPaletteCommands;
std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function> *patternLanguageFunctions;
std::vector<View*> *views;
std::vector<std::function<void()>> *tools;
int *mainArgc;
char ***mainArgv;
ImVec2 *windowPos;
ImVec2 *windowSize;

View File

@ -15,9 +15,6 @@ using s32 = std::int32_t;
using s64 = std::int64_t;
using s128 = __int128_t;
extern int mainArgc;
extern char **mainArgv;
#ifdef OS_WINDOWS
#define MAGIC_PATH_SEPARATOR ";"
#else

View File

@ -7,12 +7,17 @@
#include <views/view.hpp>
#include <providers/provider.hpp>
#include <helpers/shared_data.hpp>
#include <helpers/content_registry.hpp>
#define IMHEX_PLUGIN namespace hex::plugin::internal { \
void initializePlugin(SharedData &sharedData) { \
if (glGetString == NULL) \
gladLoadGL(); \
SharedData::get().initializeData(sharedData); \
} \
} \
namespace hex::plugin
#define IMHEX_PLUGIN_SETUP namespace hex::plugin { void setup(); } \
namespace hex::plugin::internal { \
void initializePlugin(SharedData &sharedData) { \
if (glGetString == NULL) \
gladLoadGL(); \
SharedData::get().initializeData(sharedData); \
ImGui::SetCurrentContext(*sharedData.imguiContext); \
hex::plugin::setup(); \
\
} \
} \
void hex::plugin::setup()

View File

@ -10,21 +10,21 @@ namespace hex {
/* Settings */
void ContentRegistry::Settings::load() {
std::ifstream settingsFile(std::filesystem::path(mainArgv[0]).parent_path() / "settings.json");
std::ifstream settingsFile(std::filesystem::path((*SharedData::get().mainArgv)[0]).parent_path() / "settings.json");
if (settingsFile.good())
settingsFile >> getSettingsData();
}
void ContentRegistry::Settings::store() {
std::ofstream settingsFile(std::filesystem::path(mainArgv[0]).parent_path() / "settings.json", std::ios::trunc);
std::ofstream settingsFile(std::filesystem::path((*SharedData::get().mainArgv)[0]).parent_path() / "settings.json", std::ios::trunc);
settingsFile << getSettingsData();
}
void ContentRegistry::Settings::add(std::string_view category, std::string_view name, s64 defaultValue, const std::function<bool(nlohmann::json&)> &callback) {
ContentRegistry::Settings::getEntries()[category.data()].emplace_back(Entry{ name.data(), callback });
auto &json = (*SharedData::get().settingsJson);
auto &json = getSettingsData();
if (!json.contains(category.data()))
json[category.data()] = nlohmann::json::object();
@ -35,8 +35,8 @@ namespace hex {
void ContentRegistry::Settings::add(std::string_view category, std::string_view name, std::string_view defaultValue, const std::function<bool(nlohmann::json&)> &callback) {
ContentRegistry::Settings::getEntries()[category.data()].emplace_back(Entry{ name.data(), callback });
(*SharedData::get().settingsJson)[category.data()] = nlohmann::json::object();
(*SharedData::get().settingsJson)[category.data()][name.data()] = defaultValue;
getSettingsData()[category.data()] = nlohmann::json::object();
getSettingsData()[category.data()][name.data()] = defaultValue;
}
std::map<std::string, std::vector<ContentRegistry::Settings::Entry>>& ContentRegistry::Settings::getEntries() {
@ -66,10 +66,10 @@ namespace hex {
/* Command Palette Commands */
void ContentRegistry::CommandPaletteCommands::add(ContentRegistry::CommandPaletteCommands::Type type, std::string_view command, std::string_view description, const std::function<std::string(std::string)> &callback) {
SharedData::get().commandPaletteCommands->push_back(ContentRegistry::CommandPaletteCommands::Entry{ type, command.data(), description.data(), callback });
getEntries().push_back(ContentRegistry::CommandPaletteCommands::Entry{ type, command.data(), description.data(), callback });
}
std::vector<ContentRegistry::CommandPaletteCommands::Entry> ContentRegistry::CommandPaletteCommands::getEntries() {
std::vector<ContentRegistry::CommandPaletteCommands::Entry>& ContentRegistry::CommandPaletteCommands::getEntries() {
return *SharedData::get().commandPaletteCommands;
}
@ -77,11 +77,37 @@ namespace hex {
/* Pattern Language Functions */
void ContentRegistry::PatternLanguageFunctions::add(std::string_view name, u32 parameterCount, const std::function<hex::lang::ASTNode*(std::vector<hex::lang::ASTNode*>)> &func) {
(*SharedData::get().patternLanguageFunctions)[name.data()] = Function{ parameterCount, func };
getEntries()[name.data()] = Function{ parameterCount, func };
}
std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function> ContentRegistry::PatternLanguageFunctions::getEntries() {
std::map<std::string, ContentRegistry::PatternLanguageFunctions::Function>& ContentRegistry::PatternLanguageFunctions::getEntries() {
return *SharedData::get().patternLanguageFunctions;
}
/* Views */
View* ContentRegistry::Views::add(View *view) {
auto &views = getEntries();
views.push_back(view);
return views.back();
}
std::vector<View*>& ContentRegistry::Views::getEntries() {
return *SharedData::get().views;
}
/* Tools */
void ContentRegistry::Tools::add(const std::function<void()> &function) {
getEntries().push_back(function);
}
std::vector<std::function<void()>>& ContentRegistry::Tools::getEntries() {
return *SharedData::get().tools;
}
}

View File

@ -179,10 +179,10 @@ namespace hex {
}
bool LoaderScript::processFile(std::string_view scriptPath) {
Py_SetProgramName(Py_DecodeLocale(mainArgv[0], nullptr));
Py_SetProgramName(Py_DecodeLocale((*SharedData::get().mainArgv)[0], nullptr));
if (std::filesystem::exists(std::filesystem::path(mainArgv[0]).parent_path().string() + "/lib/python" PYTHON_VERSION_MAJOR_MINOR))
Py_SetPythonHome(Py_DecodeLocale(std::filesystem::path(mainArgv[0]).parent_path().string().c_str(), nullptr));
if (std::filesystem::exists(std::filesystem::path((*SharedData::get().mainArgv)[0]).parent_path().string() + "/lib/python" PYTHON_VERSION_MAJOR_MINOR))
Py_SetPythonHome(Py_DecodeLocale(std::filesystem::path((*SharedData::get().mainArgv)[0]).parent_path().string().c_str(), nullptr));
PyImport_AppendInittab("_imhex", []() -> PyObject* {

View File

@ -5,12 +5,8 @@
namespace hex {
// hex::plugin::createView(void)
constexpr auto CreateViewSymbol = "_ZN3hex6plugin10createViewEv";
// hex::plugin::drawToolsEntry(void)
constexpr auto DrawToolsEntrySymbol = "_ZN3hex6plugin14drawToolsEntryEv";
// hex::plugin::internal::initializePlugin(SharedData&)
constexpr auto InitializePluginSymbol = "_ZN3hex6plugin8internal16initializePluginER10SharedData";
constexpr auto InitializePluginSymbol = "_ZN3hex6plugin8internal16initializePluginERNS_10SharedDataE";
Plugin::Plugin(std::string_view path) {
this->m_handle = dlopen(path.data(), RTLD_LAZY);
@ -18,8 +14,6 @@ namespace hex {
if (this->m_handle == nullptr)
return;
this->m_createViewFunction = reinterpret_cast<CreateViewFunc>(dlsym(this->m_handle, CreateViewSymbol));
this->m_drawToolsEntryFunction = reinterpret_cast<DrawToolsEntryFunc>(dlsym(this->m_handle, DrawToolsEntrySymbol));
this->m_initializePluginFunction = reinterpret_cast<InitializePluginFunc>(dlsym(this->m_handle, InitializePluginSymbol));
}
@ -33,19 +27,6 @@ namespace hex {
this->m_initializePluginFunction(sharedData);
}
View* Plugin::createView() const {
if (this->m_createViewFunction != nullptr)
return this->m_createViewFunction();
return nullptr;
}
void Plugin::drawToolsEntry() const {
if (this->m_drawToolsEntryFunction != nullptr)
this->m_drawToolsEntryFunction();
}
void PluginHandler::load(std::string_view pluginFolder) {
PluginHandler::unload();
@ -54,8 +35,10 @@ namespace hex {
PluginHandler::s_pluginFolder = pluginFolder;
for (auto& pluginPath : std::filesystem::directory_iterator(pluginFolder))
PluginHandler::s_plugins.emplace_back(pluginPath.path().string());
for (auto& pluginPath : std::filesystem::directory_iterator(pluginFolder)) {
if (pluginPath.is_regular_file())
PluginHandler::s_plugins.emplace_back(pluginPath.path().string());
}
}
void PluginHandler::unload() {

View File

@ -1,6 +1,9 @@
#include "helpers/utils.hpp"
#include "window.hpp"
#include <helpers/content_registry.hpp>
#include <providers/provider.hpp>
#include "lang/pattern_data.hpp"
#include "views/view_hexeditor.hpp"
#include "views/view_pattern.hpp"
@ -17,42 +20,39 @@
#include "views/view_command_palette.hpp"
#include "views/view_settings.hpp"
#include "providers/provider.hpp"
#include <vector>
int mainArgc;
char **mainArgv;
int main(int argc, char **argv) {
mainArgc = argc;
mainArgv = argv;
hex::Window window;
hex::Window window(argc, argv);
// Shared Data
std::vector<hex::lang::PatternData*> patternData;
// Create views
window.addView<hex::ViewHexEditor>(patternData);
window.addView<hex::ViewPattern>(patternData);
window.addView<hex::ViewPatternData>(patternData);
window.addView<hex::ViewDataInspector>();
window.addView<hex::ViewHashes>();
window.addView<hex::ViewInformation>();
window.addView<hex::ViewStrings>();
window.addView<hex::ViewDisassembler>();
window.addView<hex::ViewBookmarks>();
window.addView<hex::ViewPatches>();
window.addView<hex::ViewTools>();
window.addView<hex::ViewCommandPalette>();
window.addView<hex::ViewHelp>();
window.addView<hex::ViewSettings>();
hex::ContentRegistry::Views::add<hex::ViewHexEditor>(patternData);
hex::ContentRegistry::Views::add<hex::ViewPattern>(patternData);
hex::ContentRegistry::Views::add<hex::ViewPatternData>(patternData);
hex::ContentRegistry::Views::add<hex::ViewDataInspector>();
hex::ContentRegistry::Views::add<hex::ViewHashes>();
hex::ContentRegistry::Views::add<hex::ViewInformation>();
hex::ContentRegistry::Views::add<hex::ViewStrings>();
hex::ContentRegistry::Views::add<hex::ViewDisassembler>();
hex::ContentRegistry::Views::add<hex::ViewBookmarks>();
hex::ContentRegistry::Views::add<hex::ViewPatches>();
hex::ContentRegistry::Views::add<hex::ViewTools>();
hex::ContentRegistry::Views::add<hex::ViewCommandPalette>();
hex::ContentRegistry::Views::add<hex::ViewHelp>();
hex::ContentRegistry::Views::add<hex::ViewSettings>();
if (argc > 1)
hex::View::postEvent(hex::Events::FileDropped, argv[1]);
window.initPlugins();
window.loop();
return 0;
window.deinitPlugins();
return EXIT_SUCCESS;
}

View File

@ -313,8 +313,8 @@ namespace hex {
this->drawMathEvaluator();
this->drawColorPicker();
for (const auto& plugin : PluginHandler::getPlugins())
plugin.drawToolsEntry();
for (const auto& entries : ContentRegistry::Tools::getEntries())
entries();
}
ImGui::End();

View File

@ -26,46 +26,45 @@ namespace hex {
}
void ImHexSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler *handler, void *, const char* line) {
auto *window = reinterpret_cast<Window *>(handler->UserData);
for (auto &view : window->m_views) {
for (auto &view : ContentRegistry::Views::getEntries()) {
std::string format = view->getName() + "=%d";
sscanf(line, format.c_str(), &view->getWindowOpenState());
}
}
void ImHexSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler *handler, ImGuiTextBuffer *buf) {
auto *window = reinterpret_cast<Window *>(handler->UserData);
buf->reserve(buf->size() + 0x20); // Ballpark reserve
buf->appendf("[%s][General]\n", handler->TypeName);
for (auto &view : window->m_views) {
for (auto &view : ContentRegistry::Views::getEntries()) {
buf->appendf("%s=%d\n", view->getName().c_str(), view->getWindowOpenState());
}
buf->append("\n");
}
Window::Window() {
Window::Window(int &argc, char **&argv) {
SharedData::get().initializeData();
hex::SharedData::get().mainArgc = &argc;
hex::SharedData::get().mainArgv = &argv;
ContentRegistry::Settings::load();
View::postEvent(Events::SettingsChanged, nullptr);
this->initGLFW();
this->initImGui();
this->initPlugins();
}
Window::~Window() {
this->deinitImGui();
this->deinitGLFW();
this->deinitPlugins();
ContentRegistry::Settings::store();
for (auto &view : this->m_views)
for (auto &view : ContentRegistry::Views::getEntries())
delete view;
ContentRegistry::Views::getEntries().clear();
}
void Window::loop() {
@ -76,15 +75,7 @@ namespace hex {
call();
View::getDeferedCalls().clear();
for (auto &view : this->m_views) {
if (!view->getWindowOpenState())
continue;
ImGui::SetNextWindowSizeConstraints(view->getMinSize(), view->getMaxSize());
view->drawContent();
}
for (auto &view : this->m_pluginViews) {
for (auto &view : ContentRegistry::Views::getEntries()) {
if (!view->getWindowOpenState())
continue;
@ -160,30 +151,14 @@ namespace hex {
if (ImGui::BeginMenu(menu)) ImGui::EndMenu();
if (ImGui::BeginMenu("View")) {
for (auto &view : this->m_views) {
for (auto &view : ContentRegistry::Views::getEntries()) {
if (view->hasViewMenuItemEntry())
ImGui::MenuItem((view->getName() + " View").c_str(), "", &view->getWindowOpenState());
}
if (!this->m_pluginViews.empty()) {
if (ImGui::BeginMenu("Plugin Views")) {
for (auto &view : this->m_pluginViews) {
if (view->hasViewMenuItemEntry())
ImGui::MenuItem((view->getName() + " View").c_str(), "", &view->getWindowOpenState());
}
ImGui::EndMenu();
}
}
ImGui::EndMenu();
}
for (auto &view : this->m_views) {
view->drawMenu();
}
for (auto &view : this->m_pluginViews) {
for (auto &view : ContentRegistry::Views::getEntries()) {
view->drawMenu();
}
@ -208,22 +183,10 @@ namespace hex {
}
if (auto &[key, mods] = Window::s_currShortcut; key != -1) {
bool shortcutHandled = false;
for (auto &view : this->m_pluginViews) {
for (auto &view : ContentRegistry::Views::getEntries()) {
if (view->getWindowOpenState()) {
if (view->handleShortcut(key, mods)) {
shortcutHandled = true;
if (view->handleShortcut(key, mods))
break;
}
}
}
if (!shortcutHandled) {
for (auto &view : this->m_views) {
if (view->getWindowOpenState()) {
if (view->handleShortcut(key, mods))
break;
}
}
}
@ -232,7 +195,6 @@ namespace hex {
}
ImGui::End();
}
void Window::frameEnd() {
@ -343,7 +305,7 @@ namespace hex {
style.ScaleAllSizes(this->m_globalScale);
#ifdef __MINGW32__
std::filesystem::path resourcePath = std::filesystem::path(mainArgv[0]).parent_path();
std::filesystem::path resourcePath = std::filesystem::path((*SharedData::get().mainArgv)[0]).parent_path();
#elif defined(__linux__)
std::filesystem::path resourcePath = "/usr/share/ImHex";
#else
@ -382,15 +344,15 @@ namespace hex {
}
void Window::initPlugins() {
(*SharedData::get().imguiContext) = ImGui::GetCurrentContext();
try {
auto pluginFolderPath = std::filesystem::path(mainArgv[0]).parent_path() / "plugins";
auto pluginFolderPath = std::filesystem::path((*SharedData::get().mainArgv)[0]).parent_path() / "plugins";
PluginHandler::load(pluginFolderPath.string());
} catch (std::runtime_error &e) { return; }
for (const auto &plugin : PluginHandler::getPlugins()) {
plugin.initializePlugin(SharedData::get());
if (auto view = plugin.createView(); view != nullptr)
this->m_pluginViews.push_back(view);
}
}
@ -407,9 +369,6 @@ namespace hex {
void Window::deinitPlugins() {
PluginHandler::unload();
for (auto &view : this->m_pluginViews)
delete view;
}
}