#include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace hex::plugin::builtin { static void openFile(const std::fs::path &path) { auto provider = ImHexApi::Provider::createProvider("hex.builtin.provider.file", true); if (auto *fileProvider = dynamic_cast(provider); fileProvider != nullptr) { fileProvider->setPath(path); if (!provider->open() || !provider->isAvailable()) { PopupError::open(hex::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage())); TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); }); } else { EventManager::post(fileProvider); } } } void registerEventHandlers() { static bool imhexClosing = false; EventManager::subscribe([](GLFWwindow *window) { if (ImHexApi::Provider::isDirty() && !imhexClosing) { glfwSetWindowShouldClose(window, GLFW_FALSE); PopupQuestion::open("hex.builtin.popup.exit_application.desc"_lang, [] { imhexClosing = true; for (const auto &provider : auto(ImHexApi::Provider::getProviders())) ImHexApi::Provider::remove(provider); }, [] { } ); } else if (TaskManager::getRunningTaskCount() > 0 || TaskManager::getRunningBackgroundTaskCount() > 0) { glfwSetWindowShouldClose(window, GLFW_FALSE); TaskManager::doLater([] { for (auto &task : TaskManager::getRunningTasks()) task->interrupt(); PopupTasksWaiting::open(); }); } }); EventManager::subscribe([](const hex::prv::Provider *provider, bool *shouldClose) { if (provider->isDirty()) { *shouldClose = false; PopupUnsavedChanges::open("hex.builtin.popup.close_provider.desc"_lang, []{ for (const auto &provider : ImHexApi::Provider::impl::getClosingProviders()) ImHexApi::Provider::remove(provider, true); }, [] { ImHexApi::Provider::impl::resetClosingProvider(); imhexClosing = false; } ); } }); EventManager::subscribe([](hex::prv::Provider *oldProvider, hex::prv::Provider *newProvider) { hex::unused(oldProvider); hex::unused(newProvider); EventManager::post(); }); EventManager::subscribe([](hex::prv::Provider *provider) { if (provider != nullptr && ImHexApi::Provider::get() == provider) EventManager::post(); EventManager::post(nullptr, provider); }); EventManager::subscribe(openFile); EventManager::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); else EventManager::post(newProvider); } else if (name == "Open File") { fs::openFileBrowser(fs::DialogMode::Open, { }, [](const auto &path) { if (path.extension() == ".hexproj") { if (!ProjectFile::load(path)) { PopupError::open(hex::format("hex.builtin.popup.error.project.load"_lang, wolv::util::toUTF8String(path))); } } else { FileProvider* newProvider = static_cast( ImHexApi::Provider::createProvider("hex.builtin.provider.file", true) ); if (newProvider == nullptr) return; newProvider->setPath(path); if (!newProvider->open()) hex::ImHexApi::Provider::remove(newProvider); else { EventManager::post(newProvider); AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.open_file.name"); } } }); } else if (name == "Open Project") { fs::openFileBrowser(fs::DialogMode::Open, { {"Project File", "hexproj"} }, [](const auto &path) { if (!ProjectFile::load(path)) { PopupError::open(hex::format("hex.builtin.popup.error.project.load"_lang, wolv::util::toUTF8String(path))); } }); } }); EventManager::subscribe([](auto, auto) { EventManager::post(); }); // Handles the provider initialization, and calls EventProviderOpened if successful EventManager::subscribe([](hex::prv::Provider *provider) { if (provider->shouldSkipLoadInterface()) return; if (provider->hasFilePicker()) { if (!provider->handleFilePicker()) { TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); }); return; } if (!provider->open()) { PopupError::open(hex::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage())); TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); }); return; } EventManager::post(provider); } else if (provider->hasLoadInterface()) EventManager::post(View::toWindowName("hex.builtin.view.provider_settings.load_popup")); else { if (!provider->open() || !provider->isAvailable()) { PopupError::open(hex::format("hex.builtin.provider.error.open"_lang, provider->getErrorMessage())); TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); }); return; } EventManager::post(provider); } }); EventManager::subscribe([](const ImHexApi::HexEditor::ProviderRegion ®ion) { ImHexApi::HexEditor::impl::setCurrentSelection(region); }); EventManager::subscribe([](const std::string &message) { PopupInfo::open(message); }); EventManager::subscribe([](const std::string &message) { PopupError::open(message); }); EventManager::subscribe([](const std::string &message) { PopupFatal::open(message); }); fs::setFileBrowserErrorCallback([](const std::string& errMsg){ #if defined(NFD_PORTAL) PopupError::open(hex::format("hex.builtin.popup.error.file_dialog.portal"_lang, errMsg)); #else PopupError::open(hex::format("hex.builtin.popup.error.file_dialog.common"_lang, errMsg)); #endif }); } }