1
0
mirror of synced 2024-11-28 01:20:51 +01:00

impr: Update all of ImHex to the new popup system

This commit is contained in:
WerWolv 2023-04-08 00:58:53 +02:00
parent 9c9ac23818
commit 80edaea392
36 changed files with 578 additions and 478 deletions

View File

@ -183,10 +183,7 @@ namespace hex {
EVENT_DEF(RequestCreateProvider, std::string, bool, hex::prv::Provider **);
EVENT_DEF(RequestInitThemeHandlers);
EVENT_DEF(RequestShowInfoPopup, std::string);
EVENT_DEF(RequestShowErrorPopup, std::string);
EVENT_DEF(RequestShowFatalErrorPopup, std::string);
EVENT_DEF(RequestShowYesNoQuestionPopup, std::string, std::function<void()>, std::function<void()>);
EVENT_DEF(RequestShowFileChooserPopup, std::vector<std::fs::path>, std::vector<nfdfilteritem_t>, std::function<void(std::fs::path)>, bool);
EVENT_DEF(RequestOpenInfoPopup, const std::string);
EVENT_DEF(RequestOpenErrorPopup, const std::string);
EVENT_DEF(RequestOpenFatalPopup, const std::string);
}

View File

@ -108,6 +108,8 @@ namespace hex {
[[nodiscard]] bool wasInterrupted() const;
[[nodiscard]] bool shouldInterrupt() const;
[[nodiscard]] u32 getProgress() const;
void interrupt();
private:
std::weak_ptr<Task> m_task;

View File

@ -7,55 +7,88 @@
#include <vector>
#include <imgui.h>
#include <hex/ui/imgui_imhex_extensions.h>
#include <hex/helpers/utils.hpp>
#include <hex/api/task.hpp>
namespace hex {
class PopupBase {
public:
explicit PopupBase(std::string unlocalizedName, bool closeButton = true)
: m_unlocalizedName(std::move(unlocalizedName)), m_closeButton(closeButton) { }
namespace impl {
virtual ~PopupBase() = default;
class PopupBase {
public:
explicit PopupBase(std::string unlocalizedName, bool closeButton, bool modal)
: m_unlocalizedName(std::move(unlocalizedName)), m_closeButton(closeButton), m_modal(modal) { }
virtual void drawContent() = 0;
[[nodiscard]] virtual ImGuiPopupFlags getFlags() const { return ImGuiPopupFlags_None; }
virtual ~PopupBase() = default;
virtual void drawContent() = 0;
[[nodiscard]] virtual ImGuiWindowFlags getFlags() const { return ImGuiWindowFlags_None; }
[[nodiscard]] static std::vector<std::unique_ptr<PopupBase>> &getOpenPopups() {
return s_openPopups;
}
[[nodiscard]] virtual ImVec2 getMinSize() const {
return { 0, 0 };
}
[[nodiscard]] const std::string &getUnlocalizedName() const {
return this->m_unlocalizedName;
}
[[nodiscard]] virtual ImVec2 getMaxSize() const {
return { FLT_MAX, FLT_MAX };
}
[[nodiscard]] bool hasCloseButton() const {
return this->m_closeButton;
}
[[nodiscard]] static std::vector<std::unique_ptr<PopupBase>> &getOpenPopups() {
return s_openPopups;
}
protected:
static void close() {
ImGui::CloseCurrentPopup();
s_openPopups.pop_back();
}
[[nodiscard]] const std::string &getUnlocalizedName() const {
return this->m_unlocalizedName;
}
static std::vector<std::unique_ptr<PopupBase>> s_openPopups;
private:
[[nodiscard]] bool hasCloseButton() const {
return this->m_closeButton;
}
[[nodiscard]] bool isModal() const {
return this->m_modal;
}
static void close() {
if (s_openPopups.empty())
return;
TaskManager::doLater([]{
std::lock_guard lock(s_mutex);
ImGui::CloseCurrentPopup();
s_openPopups.pop_back();
});
}
static std::mutex& getMutex() {
return s_mutex;
}
protected:
static std::vector<std::unique_ptr<PopupBase>> s_openPopups;
static std::mutex s_mutex;
private:
std::string m_unlocalizedName;
bool m_closeButton, m_modal;
};
}
std::string m_unlocalizedName;
bool m_closeButton;
};
template<typename T>
class Popup : public PopupBase {
class Popup : public impl::PopupBase {
protected:
explicit Popup(std::string unlocalizedName, bool closeButton = true) : PopupBase(std::move(unlocalizedName), closeButton) { }
explicit Popup(std::string unlocalizedName, bool closeButton = true, bool modal = true) : PopupBase(std::move(unlocalizedName), closeButton, modal) { }
public:
virtual ~Popup() = default;
template<typename ...Args>
static void open(Args && ... args) {
std::lock_guard lock(s_mutex);
auto popup = std::make_unique<T>(std::forward<Args>(args)...);
s_openPopups.emplace_back(std::move(popup));

View File

@ -34,13 +34,6 @@ namespace hex {
[[nodiscard]] virtual bool isAvailable() const;
[[nodiscard]] virtual bool shouldProcess() const { return this->isAvailable() && this->getWindowOpenState(); }
static void showInfoPopup(const std::string &message);
static void showErrorPopup(const std::string &message);
static void showFatalPopup(const std::string &message);
static void showYesNoQuestionPopup(const std::string &message, const std::function<void()> &yesCallback, const std::function<void()> &noCallback);
static void showFileChooserPopup(const std::vector<std::fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, bool multiple, const std::function<void(std::fs::path)> &callback);
[[nodiscard]] virtual bool hasViewMenuItemEntry() const;
[[nodiscard]] virtual ImVec2 getMinSize() const;
[[nodiscard]] virtual ImVec2 getMaxSize() const;

View File

@ -165,6 +165,14 @@ namespace hex {
task->interrupt();
}
u32 TaskHolder::getProgress() const {
if (this->m_task.expired())
return 0;
auto task = this->m_task.lock();
return (u32)((task->getValue() * 100) / task->getMaxValue());
}
void TaskManager::init() {
for (u32 i = 0; i < std::thread::hardware_concurrency(); i++)

View File

@ -1,7 +1,8 @@
#include <hex/ui/popup.hpp>
namespace hex {
namespace hex::impl {
std::vector<std::unique_ptr<PopupBase>> PopupBase::s_openPopups;
std::mutex PopupBase::s_mutex;
}

View File

@ -17,33 +17,6 @@ namespace hex {
return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isAvailable();
}
void View::showInfoPopup(const std::string &message) {
EventManager::post<RequestShowInfoPopup>(message);
}
void View::showErrorPopup(const std::string &message) {
EventManager::post<RequestShowErrorPopup>(message);
}
void View::showFatalPopup(const std::string &message) {
EventManager::post<RequestShowFatalErrorPopup>(message);
}
void View::showYesNoQuestionPopup(const std::string &message, const std::function<void()> &yesCallback, const std::function<void()> &noCallback) {
EventManager::post<RequestShowYesNoQuestionPopup>(message, yesCallback, noCallback);
}
void View::showFileChooserPopup(const std::vector<std::fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, bool multiple, const std::function<void(std::fs::path)> &callback) {
if (paths.empty()) {
fs::openFileBrowser(fs::DialogMode::Open, validExtensions, [callback](const auto &path) {
callback(path);
}, {}, multiple);
} else {
EventManager::post<RequestShowFileChooserPopup>(paths, validExtensions, callback, multiple);
}
}
bool View::hasViewMenuItemEntry() const {
return true;
}

View File

@ -525,7 +525,8 @@ namespace hex {
// Draw popup stack
{
if (auto &popups = PopupBase::getOpenPopups(); !popups.empty()) {
std::scoped_lock lock(impl::PopupBase::getMutex());
if (auto &popups = impl::PopupBase::getOpenPopups(); !popups.empty()) {
auto &currPopup = popups.back();
const auto &name = LangEntry(currPopup->getUnlocalizedName());
@ -533,10 +534,24 @@ namespace hex {
ImGui::OpenPopup(name);
bool open = true;
if (ImGui::BeginPopupModal(name, currPopup->hasCloseButton() ? &open : nullptr, currPopup->getFlags())) {
currPopup->drawContent();
ImGui::SetNextWindowSizeConstraints(currPopup->getMinSize(), currPopup->getMaxSize());
ImGui::EndPopup();
auto closeButton = currPopup->hasCloseButton() ? &open : nullptr;
auto flags = currPopup->getFlags();
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
if (currPopup->isModal()) {
if (ImGui::BeginPopupModal(name, closeButton, flags)) {
currPopup->drawContent();
ImGui::EndPopup();
}
} else {
if (ImGui::BeginPopup(name, flags)) {
currPopup->drawContent();
ImGui::EndPopup();
}
}
if (!open)

View File

@ -0,0 +1,80 @@
#include <hex/ui/popup.hpp>
#include <hex/api/localization.hpp>
#include <functional>
#include <string>
namespace hex::plugin::builtin {
class PopupFileChooser : public Popup<PopupFileChooser> {
public:
PopupFileChooser(const std::vector<std::fs::path> &files, const std::vector<nfdfilteritem_t> &validExtensions, bool multiple, const std::function<void(std::fs::path)> &callback)
: hex::Popup<PopupFileChooser>("hex.builtin.common.choose_file", false),
m_indices({ }), m_files(files),
m_openCallback(callback),
m_validExtensions(validExtensions), m_multiple(multiple) { }
void drawContent() override {
bool doubleClicked = false;
if (ImGui::BeginListBox("##files", scaled(ImVec2(500, 400)))) {
u32 index = 0;
for (auto &path : this->m_files) {
ImGui::PushID(index);
bool selected = this->m_indices.contains(index);
if (ImGui::Selectable(wolv::util::toUTF8String(path.filename()).c_str(), selected, ImGuiSelectableFlags_DontClosePopups)) {
if (!this->m_multiple) {
this->m_indices.clear();
this->m_indices.insert(index);
} else {
if (selected) {
this->m_indices.erase(index);
} else {
this->m_indices.insert(index);
}
}
}
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0))
doubleClicked = true;
ImGui::InfoTooltip(wolv::util::toUTF8String(path).c_str());
ImGui::PopID();
index++;
}
ImGui::EndListBox();
}
if (ImGui::Button("hex.builtin.common.open"_lang) || doubleClicked) {
for (const auto &index : this->m_indices)
this->m_openCallback(this->m_files[index]);
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("hex.builtin.common.browse"_lang)) {
fs::openFileBrowser(fs::DialogMode::Open, this->m_validExtensions, [this](const auto &path) {
this->m_openCallback(path);
ImGui::CloseCurrentPopup();
}, {}, this->m_multiple);
}
}
[[nodiscard]] ImGuiWindowFlags getFlags() const override {
return ImGuiWindowFlags_AlwaysAutoResize;
}
private:
std::set<u32> m_indices;
std::vector<std::fs::path> m_files;
std::function<void(std::fs::path)> m_openCallback;
std::vector<nfdfilteritem_t> m_validExtensions;
bool m_multiple = false;
};
}

View File

@ -0,0 +1,74 @@
#include <hex/ui/popup.hpp>
#include <hex/api/localization.hpp>
#include <functional>
#include <string>
namespace hex::plugin::builtin {
namespace impl {
template<typename T>
class PopupNotification : public Popup<T> {
public:
PopupNotification(std::string unlocalizedName, std::string message, std::function<void()> function)
: hex::Popup<T>(std::move(unlocalizedName), false),
m_message(std::move(message)), m_function(std::move(function)) { }
void drawContent() override {
ImGui::TextFormattedWrapped("{}", this->m_message.c_str());
ImGui::NewLine();
ImGui::Separator();
if (ImGui::Button("hex.builtin.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape))
this->m_function();
ImGui::SetWindowPos((ImHexApi::System::getMainWindowSize() - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
}
[[nodiscard]] ImGuiWindowFlags getFlags() const override {
return ImGuiWindowFlags_AlwaysAutoResize;
}
[[nodiscard]] ImVec2 getMinSize() const override {
return scaled({ 400, 100 });
}
[[nodiscard]] ImVec2 getMaxSize() const override {
return scaled({ 600, 300 });
}
private:
std::string m_message;
std::function<void()> m_function;
};
}
class PopupInfo : public impl::PopupNotification<PopupInfo> {
public:
explicit PopupInfo(std::string message)
: PopupNotification("hex.builtin.common.info", std::move(message), []() {
Popup::close();
}) { }
};
class PopupError : public impl::PopupNotification<PopupError> {
public:
explicit PopupError(std::string message)
: PopupNotification("hex.builtin.common.error", std::move(message), []() {
Popup::close();
}) { }
};
class PopupFatal : public impl::PopupNotification<PopupFatal> {
public:
explicit PopupFatal(std::string message)
: PopupNotification("hex.builtin.common.fatal", std::move(message), []() {
ImHexApi::System::closeImHex();
Popup::close();
}) { }
};
}

View File

@ -0,0 +1,51 @@
#include <hex/ui/popup.hpp>
#include <hex/api/localization.hpp>
#include <functional>
#include <string>
namespace hex::plugin::builtin {
class PopupQuestion : public Popup<PopupQuestion> {
public:
PopupQuestion(std::string message, std::function<void()> yesFunction, std::function<void()> noFunction)
: hex::Popup<PopupQuestion>("hex.builtin.common.question", false),
m_message(std::move(message)),
m_yesFunction(std::move(yesFunction)), m_noFunction(std::move(noFunction)) { }
void drawContent() override {
ImGui::TextFormattedWrapped("{}", this->m_message.c_str());
ImGui::NewLine();
ImGui::Separator();
auto width = ImGui::GetWindowWidth();
ImGui::SetCursorPosX(width / 9);
if (ImGui::Button("hex.builtin.common.yes"_lang, ImVec2(width / 3, 0)))
this->m_yesFunction();
ImGui::SameLine();
ImGui::SetCursorPosX(width / 9 * 5);
if (ImGui::Button("hex.builtin.common.no"_lang, ImVec2(width / 3, 0)))
this->m_noFunction();
ImGui::SetWindowPos((ImHexApi::System::getMainWindowSize() - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
}
[[nodiscard]] ImGuiWindowFlags getFlags() const override {
return ImGuiWindowFlags_AlwaysAutoResize;
}
[[nodiscard]] ImVec2 getMinSize() const override {
return scaled({ 400, 100 });
}
[[nodiscard]] ImVec2 getMaxSize() const override {
return scaled({ 600, 300 });
}
private:
std::string m_message;
std::function<void()> m_yesFunction, m_noFunction;
};
}

View File

@ -0,0 +1,37 @@
#include <hex/ui/popup.hpp>
#include <hex/api/localization.hpp>
#include <functional>
#include <string>
namespace hex::plugin::builtin {
class PopupTasksWaiting : public Popup<PopupTasksWaiting> {
public:
PopupTasksWaiting()
: hex::Popup<PopupTasksWaiting>("hex.builtin.popup.waiting_for_tasks.title", false) { }
void drawContent() override {
ImGui::TextUnformatted("hex.builtin.popup.waiting_for_tasks.desc"_lang);
ImGui::Separator();
ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize("[-]").x) / 2);
ImGui::TextSpinner("");
ImGui::NewLine();
ImGui::SetCursorPosX((ImGui::GetWindowWidth() - 150_scaled) / 2);
if (ImGui::ButtonEx("hex.builtin.common.cancel"_lang, ImVec2(150, 0)) || ImGui::IsKeyDown(ImGuiKey_Escape))
ImGui::CloseCurrentPopup();
if (TaskManager::getRunningTaskCount() == 0 && TaskManager::getRunningBackgroundTaskCount() == 0) {
ImGui::CloseCurrentPopup();
ImHexApi::System::closeImHex();
}
}
[[nodiscard]] ImGuiWindowFlags getFlags() const override {
return ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove;
}
};
}

View File

@ -1,14 +1,18 @@
#pragma once
#include <hex/ui/view.hpp>
#include <hex/providers/provider.hpp>
#include <hex/ui/popup.hpp>
#include <pl/pattern_language.hpp>
#include <pl/core/errors/error.hpp>
#include <hex/providers/provider.hpp>
#include <content/helpers/provider_extra_data.hpp>
#include <content/providers/memory_file_provider.hpp>
#include <ui/hex_editor.hpp>
#include <ui/pattern_drawer.hpp>
#include <content/providers/memory_file_provider.hpp>
#include <cstring>
#include <filesystem>
@ -38,6 +42,54 @@ namespace hex::plugin::builtin {
Deny
};
class PopupAcceptPattern : public Popup<PopupAcceptPattern> {
public:
PopupAcceptPattern(ViewPatternEditor *view) : Popup("hex.builtin.view.pattern_editor.accept_pattern"), m_view(view) {}
void drawContent() override {
ImGui::TextFormattedWrapped("{}", static_cast<const char *>("hex.builtin.view.pattern_editor.accept_pattern.desc"_lang));
std::vector<std::string> entries;
entries.resize(this->m_view->m_possiblePatternFiles.size());
for (u32 i = 0; i < entries.size(); i++) {
entries[i] = wolv::util::toUTF8String(this->m_view->m_possiblePatternFiles[i].filename());
}
if (ImGui::BeginListBox("##patterns_accept", ImVec2(-FLT_MIN, 0))) {
u32 index = 0;
for (auto &path : this->m_view->m_possiblePatternFiles) {
if (ImGui::Selectable(wolv::util::toUTF8String(path.filename()).c_str(), index == this->m_view->m_selectedPatternFile))
this->m_view->m_selectedPatternFile = index;
index++;
}
ImGui::EndListBox();
}
ImGui::NewLine();
ImGui::TextUnformatted("hex.builtin.view.pattern_editor.accept_pattern.question"_lang);
auto provider = ImHexApi::Provider::get();
confirmButtons(
"hex.builtin.common.yes"_lang, "hex.builtin.common.no"_lang, [this, provider] {
this->m_view->loadPatternFile(this->m_view->m_possiblePatternFiles[this->m_view->m_selectedPatternFile], provider);
Popup::close();
},
[] {
Popup::close();
}
);
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))
Popup::close();
}
private:
ViewPatternEditor *m_view;
};
private:
using PlData = ProviderExtraData::Data::PatternLanguage;

View File

@ -764,8 +764,8 @@
"hex.builtin.view.store.row.name",
"hex.builtin.view.store.tab.constants",
"hex.builtin.view.store.tab.encodings",
"hex.builtin.view.store.tab.libraries",
"hex.builtin.view.store.tab.magics",
"hex.builtin.view.store.tab.includes",
"hex.builtin.view.store.tab.magic",
"hex.builtin.view.store.tab.patterns",
"hex.builtin.view.store.tab.yara",
"hex.builtin.view.store.update",

View File

@ -806,8 +806,8 @@
"hex.builtin.view.store.row.name": "Name",
"hex.builtin.view.store.tab.constants": "Konstanten",
"hex.builtin.view.store.tab.encodings": "Encodings",
"hex.builtin.view.store.tab.libraries": "Libraries",
"hex.builtin.view.store.tab.magics": "Magic Files",
"hex.builtin.view.store.tab.includes": "Libraries",
"hex.builtin.view.store.tab.magic": "Magic Files",
"hex.builtin.view.store.tab.nodes": "",
"hex.builtin.view.store.tab.patterns": "Patterns",
"hex.builtin.view.store.tab.themes": "",

View File

@ -814,8 +814,8 @@
"hex.builtin.view.store.row.name": "Name",
"hex.builtin.view.store.tab.constants": "Constants",
"hex.builtin.view.store.tab.encodings": "Encodings",
"hex.builtin.view.store.tab.libraries": "Libraries",
"hex.builtin.view.store.tab.magics": "Magic Files",
"hex.builtin.view.store.tab.includes": "Libraries",
"hex.builtin.view.store.tab.magic": "Magic Files",
"hex.builtin.view.store.tab.nodes": "Nodes",
"hex.builtin.view.store.tab.patterns": "Patterns",
"hex.builtin.view.store.tab.themes": "Themes",

View File

@ -806,8 +806,8 @@
"hex.builtin.view.store.row.name": "Nome",
"hex.builtin.view.store.tab.constants": "Costanti",
"hex.builtin.view.store.tab.encodings": "Encodings",
"hex.builtin.view.store.tab.libraries": "Librerie",
"hex.builtin.view.store.tab.magics": "File Magici",
"hex.builtin.view.store.tab.includes": "Librerie",
"hex.builtin.view.store.tab.magic": "File Magici",
"hex.builtin.view.store.tab.nodes": "",
"hex.builtin.view.store.tab.patterns": "Modelli",
"hex.builtin.view.store.tab.themes": "",

View File

@ -806,8 +806,8 @@
"hex.builtin.view.store.row.name": "名前",
"hex.builtin.view.store.tab.constants": "定数",
"hex.builtin.view.store.tab.encodings": "エンコード",
"hex.builtin.view.store.tab.libraries": "ライブラリ",
"hex.builtin.view.store.tab.magics": "Magicファイル",
"hex.builtin.view.store.tab.includes": "ライブラリ",
"hex.builtin.view.store.tab.magic": "Magicファイル",
"hex.builtin.view.store.tab.nodes": "",
"hex.builtin.view.store.tab.patterns": "パターン",
"hex.builtin.view.store.tab.themes": "",

View File

@ -806,8 +806,8 @@
"hex.builtin.view.store.row.name": "이름",
"hex.builtin.view.store.tab.constants": "상수",
"hex.builtin.view.store.tab.encodings": "인코딩",
"hex.builtin.view.store.tab.libraries": "라이브러리",
"hex.builtin.view.store.tab.magics": "Magic 파일",
"hex.builtin.view.store.tab.includes": "라이브러리",
"hex.builtin.view.store.tab.magic": "Magic 파일",
"hex.builtin.view.store.tab.nodes": "",
"hex.builtin.view.store.tab.patterns": "패턴",
"hex.builtin.view.store.tab.themes": "",

View File

@ -806,8 +806,8 @@
"hex.builtin.view.store.row.name": "Nome",
"hex.builtin.view.store.tab.constants": "Constantes",
"hex.builtin.view.store.tab.encodings": "Codificações",
"hex.builtin.view.store.tab.libraries": "Bibliotecas",
"hex.builtin.view.store.tab.magics": "Arquivos Mágicos",
"hex.builtin.view.store.tab.includes": "Bibliotecas",
"hex.builtin.view.store.tab.magic": "Arquivos Mágicos",
"hex.builtin.view.store.tab.nodes": "",
"hex.builtin.view.store.tab.patterns": "Padrões",
"hex.builtin.view.store.tab.themes": "",

View File

@ -770,8 +770,8 @@
"hex.builtin.view.store.row.name": "名称",
"hex.builtin.view.store.tab.constants": "常量",
"hex.builtin.view.store.tab.encodings": "编码",
"hex.builtin.view.store.tab.libraries": "库",
"hex.builtin.view.store.tab.magics": "LibMagic 数据库",
"hex.builtin.view.store.tab.includes": "库",
"hex.builtin.view.store.tab.magic": "LibMagic 数据库",
"hex.builtin.view.store.tab.patterns": "模式",
"hex.builtin.view.store.tab.yara": "Yara 规则",
"hex.builtin.view.store.update": "更新",

View File

@ -806,8 +806,8 @@
"hex.builtin.view.store.row.name": "名稱",
"hex.builtin.view.store.tab.constants": "常數",
"hex.builtin.view.store.tab.encodings": "編碼",
"hex.builtin.view.store.tab.libraries": "程式庫",
"hex.builtin.view.store.tab.magics": "Magic Files",
"hex.builtin.view.store.tab.includes": "程式庫",
"hex.builtin.view.store.tab.magic": "Magic Files",
"hex.builtin.view.store.tab.nodes": "",
"hex.builtin.view.store.tab.patterns": "模式",
"hex.builtin.view.store.tab.themes": "",

View File

@ -14,6 +14,10 @@
#include <wolv/io/fs.hpp>
#include <content/popups/popup_notification.hpp>
#include <content/popups/popup_question.hpp>
#include <content/popups/popup_tasks_waiting.hpp>
namespace hex::plugin::builtin {
static void openFile(const std::fs::path &path) {
@ -30,13 +34,21 @@ namespace hex::plugin::builtin {
EventManager::subscribe<EventWindowClosing>([](GLFWwindow *window) {
if (ImHexApi::Provider::isDirty()) {
glfwSetWindowShouldClose(window, GLFW_FALSE);
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.popup.exit_application.title"_lang); });
PopupQuestion::open("hex.builtin.popup.exit_application.desc"_lang,
[]{
ImHexApi::Provider::resetDirty();
ImHexApi::System::closeImHex();
},
[]{
PopupQuestion::close();
}
);
} else if (TaskManager::getRunningTaskCount() > 0 || TaskManager::getRunningBackgroundTaskCount() > 0) {
glfwSetWindowShouldClose(window, GLFW_FALSE);
TaskManager::doLater([] {
for (auto &task : TaskManager::getRunningTasks())
task->interrupt();
ImGui::OpenPopup("hex.builtin.popup.waiting_for_tasks.title"_lang);
PopupTasksWaiting::open();
});
}
});
@ -44,7 +56,15 @@ namespace hex::plugin::builtin {
EventManager::subscribe<EventProviderClosing>([](hex::prv::Provider *provider, bool *shouldClose) {
if (provider->isDirty()) {
*shouldClose = false;
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.popup.close_provider.title"_lang); });
PopupQuestion::open("hex.builtin.popup.close_provider.desc",
[]{
ImHexApi::Provider::remove(ImHexApi::Provider::impl::getClosingProvider(), true);
PopupQuestion::close();
},
[]{
PopupQuestion::close();
}
);
}
});
@ -75,7 +95,7 @@ namespace hex::plugin::builtin {
fs::openFileBrowser(fs::DialogMode::Open, { {"Project File", "hexproj"} },
[](const auto &path) {
if (!ProjectFile::load(path)) {
View::showErrorPopup("hex.builtin.popup.error.project.load"_lang);
PopupError::open("hex.builtin.popup.error.project.load"_lang);
}
});
}
@ -95,7 +115,7 @@ namespace hex::plugin::builtin {
return;
}
if (!provider->open()) {
View::showErrorPopup("hex.builtin.popup.error.open"_lang);
PopupError::open("hex.builtin.popup.error.open"_lang);
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
return;
}
@ -106,7 +126,7 @@ namespace hex::plugin::builtin {
EventManager::post<RequestOpenPopup>(View::toWindowName("hex.builtin.view.provider_settings.load_popup"));
else {
if (!provider->open() || !provider->isAvailable()) {
View::showErrorPopup("hex.builtin.popup.error.open"_lang);
PopupError::open("hex.builtin.popup.error.open"_lang);
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
return;
}
@ -123,11 +143,23 @@ namespace hex::plugin::builtin {
ImHexApi::HexEditor::impl::setCurrentSelection(region);
});
EventManager::subscribe<RequestOpenInfoPopup>([](const std::string &message) {
PopupInfo::open(message);
});
EventManager::subscribe<RequestOpenErrorPopup>([](const std::string &message) {
PopupError::open(message);
});
EventManager::subscribe<RequestOpenFatalPopup>([](const std::string &message) {
PopupFatal::open(message);
});
fs::setFileBrowserErrorCallback([](const std::string& errMsg){
#if defined(NFD_PORTAL)
View::showErrorPopup(hex::format("hex.builtin.popup.error.file_dialog.portal"_lang, errMsg));
PopupError::open(hex::format("hex.builtin.popup.error.file_dialog.portal"_lang, errMsg));
#else
View::showErrorPopup(hex::format("hex.builtin.popup.error.file_dialog.common"_lang, errMsg));
PopupError::open(hex::format("hex.builtin.popup.error.file_dialog.common"_lang, errMsg));
#endif
});

View File

@ -3,6 +3,7 @@
#include <hex/api/project_file_manager.hpp>
#include <hex/helpers/logger.hpp>
#include <content/popups/popup_notification.hpp>
namespace hex::plugin::builtin {
@ -10,7 +11,7 @@ namespace hex::plugin::builtin {
fs::openFileBrowser(fs::DialogMode::Open, { {"Project File", "hexproj"} },
[](const auto &path) {
if (!ProjectFile::load(path)) {
View::showErrorPopup("hex.builtin.popup.error.project.load"_lang);
PopupError::open("hex.builtin.popup.error.project.load"_lang);
}
});
}
@ -18,7 +19,7 @@ namespace hex::plugin::builtin {
void saveProject() {
if (ImHexApi::Provider::isValid() && ProjectFile::hasPath()) {
if (!ProjectFile::store()) {
View::showErrorPopup("hex.builtin.popup.error.project.save"_lang);
PopupError::open("hex.builtin.popup.error.project.save"_lang);
} else {
log::debug("Project saved");
}
@ -33,7 +34,7 @@ namespace hex::plugin::builtin {
}
if (!ProjectFile::store(path)) {
View::showErrorPopup("hex.builtin.popup.error.project.save"_lang);
PopupError::open("hex.builtin.popup.error.project.save"_lang);
}
});
}

View File

@ -11,6 +11,7 @@
#include <hex/helpers/patches.hpp>
#include "content/global_actions.hpp"
#include <content/popups/popup_notification.hpp>
#include <wolv/io/file.hpp>
@ -38,19 +39,19 @@ namespace hex::plugin::builtin {
TaskManager::doLater([error]{
switch (error) {
case IPSError::InvalidPatchHeader:
View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.invalid_patch_header_error"_lang);
PopupError::open("hex.builtin.menu.file.export.ips.popup.invalid_patch_header_error"_lang);
break;
case IPSError::AddressOutOfRange:
View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.address_out_of_range_error"_lang);
PopupError::open("hex.builtin.menu.file.export.ips.popup.address_out_of_range_error"_lang);
break;
case IPSError::PatchTooLarge:
View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.patch_too_large_error"_lang);
PopupError::open("hex.builtin.menu.file.export.ips.popup.patch_too_large_error"_lang);
break;
case IPSError::InvalidPatchFormat:
View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.invalid_patch_format_error"_lang);
PopupError::open("hex.builtin.menu.file.export.ips.popup.invalid_patch_format_error"_lang);
break;
case IPSError::MissingEOF:
View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.missing_eof_error"_lang);
PopupError::open("hex.builtin.menu.file.export.ips.popup.missing_eof_error"_lang);
break;
}
});
@ -65,7 +66,7 @@ namespace hex::plugin::builtin {
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
wolv::io::File inputFile(path, wolv::io::File::Mode::Read);
if (!inputFile.isValid()) {
View::showErrorPopup("hex.builtin.menu.file.import.base64.popup.open_error"_lang);
PopupError::open("hex.builtin.menu.file.import.base64.popup.open_error"_lang);
return;
}
@ -75,19 +76,19 @@ namespace hex::plugin::builtin {
auto data = crypt::decode64(base64);
if (data.empty())
View::showErrorPopup("hex.builtin.menu.file.import.base64.popup.import_error"_lang);
PopupError::open("hex.builtin.menu.file.import.base64.popup.import_error"_lang);
else {
fs::openFileBrowser(fs::DialogMode::Save, {}, [&data](const std::fs::path &path) {
wolv::io::File outputFile(path, wolv::io::File::Mode::Create);
if (!outputFile.isValid())
View::showErrorPopup("hex.builtin.menu.file.import.base64.popup.import_error"_lang);
PopupError::open("hex.builtin.menu.file.import.base64.popup.import_error"_lang);
outputFile.writeVector(data);
});
}
} else {
View::showErrorPopup("hex.builtin.popup.file_open_error"_lang);
PopupError::open("hex.builtin.popup.file_open_error"_lang);
}
});
}
@ -151,7 +152,7 @@ namespace hex::plugin::builtin {
auto patchData = wolv::io::File(path, wolv::io::File::Mode::Read).readVector();
if (patchData.size() != provider->getActualSize()) {
View::showErrorPopup("hex.builtin.menu.file.import.modified_file.popup.invalid_size"_lang);
PopupError::open("hex.builtin.menu.file.import.modified_file.popup.invalid_size"_lang);
return;
}
@ -191,7 +192,7 @@ namespace hex::plugin::builtin {
wolv::io::File outputFile(path, wolv::io::File::Mode::Create);
if (!outputFile.isValid()) {
TaskManager::doLater([] {
View::showErrorPopup("hex.builtin.menu.file.export.base64.popup.export_error"_lang);
PopupError::open("hex.builtin.menu.file.export.base64.popup.export_error"_lang);
});
return;
}
@ -227,7 +228,7 @@ namespace hex::plugin::builtin {
fs::openFileBrowser(fs::DialogMode::Save, {}, [&data](const auto &path) {
auto file = wolv::io::File(path, wolv::io::File::Mode::Create);
if (!file.isValid()) {
View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.export_error"_lang);
PopupError::open("hex.builtin.menu.file.export.ips.popup.export_error"_lang);
return;
}
@ -260,7 +261,7 @@ namespace hex::plugin::builtin {
fs::openFileBrowser(fs::DialogMode::Save, {}, [&data](const auto &path) {
auto file = wolv::io::File(path, wolv::io::File::Mode::Create);
if (!file.isValid()) {
View::showErrorPopup("hex.builtin.menu.file.export.ips.popup.export_error"_lang);
PopupError::open("hex.builtin.menu.file.export.ips.popup.export_error"_lang);
return;
}

View File

@ -18,6 +18,7 @@
#include <llvm/Demangle/Demangle.h>
#include <content/helpers/math_evaluator.hpp>
#include <content/popups/popup_notification.hpp>
#include <imgui.h>
#define IMGUI_DEFINE_MATH_OPERATORS
@ -646,11 +647,11 @@ namespace hex::plugin::builtin {
json["data"]["file"]["metadata"]["size"]["readable"]
});
} catch (...) {
View::showErrorPopup("hex.builtin.tools.file_uploader.invalid_response"_lang);
PopupError::open("hex.builtin.tools.file_uploader.invalid_response"_lang);
}
} else if (response.getStatusCode() == 0) {
// Canceled by user, no action needed
} else View::showErrorPopup(hex::format("hex.builtin.tools.file_uploader.error"_lang, response.getStatusCode()));
} else PopupError::open(hex::format("hex.builtin.tools.file_uploader.error"_lang, response.getStatusCode()));
uploadProcess = {};
currFile.clear();
@ -772,7 +773,7 @@ namespace hex::plugin::builtin {
wolv::io::File file(selectedFile, wolv::io::File::Mode::Write);
if (!file.isValid()) {
View::showErrorPopup("hex.builtin.tools.file_tools.shredder.error.open"_lang);
PopupError::open("hex.builtin.tools.file_tools.shredder.error.open"_lang);
return;
}
@ -846,7 +847,7 @@ namespace hex::plugin::builtin {
file.remove();
View::showInfoPopup("hex.builtin.tools.file_tools.shredder.success"_lang);
PopupInfo::open("hex.builtin.tools.file_tools.shredder.success"_lang);
});
}
}
@ -937,12 +938,12 @@ namespace hex::plugin::builtin {
wolv::io::File file(selectedFile, wolv::io::File::Mode::Read);
if (!file.isValid()) {
View::showErrorPopup("hex.builtin.tools.file_tools.splitter.picker.error.open"_lang);
PopupError::open("hex.builtin.tools.file_tools.splitter.picker.error.open"_lang);
return;
}
if (file.getSize() < splitSize) {
View::showErrorPopup("hex.builtin.tools.file_tools.splitter.picker.error.size"_lang);
PopupError::open("hex.builtin.tools.file_tools.splitter.picker.error.size"_lang);
return;
}
@ -958,7 +959,7 @@ namespace hex::plugin::builtin {
wolv::io::File partFile(path, wolv::io::File::Mode::Create);
if (!partFile.isValid()) {
View::showErrorPopup(hex::format("hex.builtin.tools.file_tools.splitter.picker.error.create"_lang, index));
PopupError::open(hex::format("hex.builtin.tools.file_tools.splitter.picker.error.create"_lang, index));
return;
}
@ -971,7 +972,7 @@ namespace hex::plugin::builtin {
index++;
}
View::showInfoPopup("hex.builtin.tools.file_tools.splitter.picker.success"_lang);
PopupInfo::open("hex.builtin.tools.file_tools.splitter.picker.success"_lang);
});
}
}
@ -1071,7 +1072,7 @@ namespace hex::plugin::builtin {
wolv::io::File output(outputPath, wolv::io::File::Mode::Create);
if (!output.isValid()) {
View::showErrorPopup("hex.builtin.tools.file_tools.combiner.error.open_output"_lang);
PopupError::open("hex.builtin.tools.file_tools.combiner.error.open_output"_lang);
return;
}
@ -1084,7 +1085,7 @@ namespace hex::plugin::builtin {
wolv::io::File input(file, wolv::io::File::Mode::Read);
if (!input.isValid()) {
View::showErrorPopup(hex::format("hex.builtin.tools.file_tools.combiner.open_input"_lang, wolv::util::toUTF8String(file)));
PopupError::open(hex::format("hex.builtin.tools.file_tools.combiner.open_input"_lang, wolv::util::toUTF8String(file)));
return;
}
@ -1100,7 +1101,7 @@ namespace hex::plugin::builtin {
selectedIndex = 0;
outputPath.clear();
View::showInfoPopup("hex.builtin.tools.file_tools.combiner.success"_lang);
PopupInfo::open("hex.builtin.tools.file_tools.combiner.success"_lang);
});
}
}

View File

@ -12,193 +12,16 @@
#include <imgui_internal.h>
#include <hex/ui/imgui_imhex_extensions.h>
#include <content/popups/popup_tasks_waiting.hpp>
#include <content/popups/popup_notification.hpp>
namespace hex::plugin::builtin {
static std::string s_popupMessage;
static std::function<void()> s_yesCallback, s_noCallback;
static std::set<u32> s_selectableFileIndices;
static std::vector<std::fs::path> s_selectableFiles;
static std::function<void(std::fs::path)> s_selectableFileOpenCallback;
static std::vector<nfdfilteritem_t> s_selectableFilesValidExtensions;
static bool s_selectableFileMultiple;
static void drawGlobalPopups() {
// "Are you sure you want to exit?" Popup
if (ImGui::BeginPopupModal("hex.builtin.popup.exit_application.title"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::NewLine();
ImGui::TextUnformatted("hex.builtin.popup.exit_application.desc"_lang);
ImGui::NewLine();
View::confirmButtons("hex.builtin.common.yes"_lang, "hex.builtin.common.no"_lang,
[] {
ImHexApi::Provider::resetDirty();
ImHexApi::System::closeImHex();
},
[] { ImGui::CloseCurrentPopup(); }
);
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
}
// "Are you sure you want to close provider?" Popup
if (ImGui::BeginPopupModal("hex.builtin.popup.close_provider.title"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::NewLine();
ImGui::TextUnformatted("hex.builtin.popup.close_provider.desc"_lang);
ImGui::NewLine();
View::confirmButtons("hex.builtin.common.yes"_lang, "hex.builtin.common.no"_lang,
[] { ImHexApi::Provider::remove(ImHexApi::Provider::impl::getClosingProvider(), true); ImGui::CloseCurrentPopup(); },
[] { ImGui::CloseCurrentPopup(); }
);
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
}
if (ImGui::BeginPopupModal("hex.builtin.popup.waiting_for_tasks.title"_lang, nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) {
ImGui::TextUnformatted("hex.builtin.popup.waiting_for_tasks.desc"_lang);
ImGui::Separator();
ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize("[-]").x) / 2);
ImGui::TextSpinner("");
ImGui::NewLine();
ImGui::SetCursorPosX((ImGui::GetWindowWidth() - 150_scaled) / 2);
if (ImGui::ButtonEx("hex.builtin.common.cancel"_lang, ImVec2(150, 0)) || ImGui::IsKeyDown(ImGuiKey_Escape))
ImGui::CloseCurrentPopup();
if (TaskManager::getRunningTaskCount() == 0 && TaskManager::getRunningBackgroundTaskCount() == 0) {
ImGui::CloseCurrentPopup();
ImHexApi::System::closeImHex();
}
ImGui::EndPopup();
}
auto windowSize = ImHexApi::System::getMainWindowSize();
// Info popup
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
if (ImGui::BeginPopupModal("hex.builtin.common.info"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
ImGui::NewLine();
ImGui::Separator();
if (ImGui::Button("hex.builtin.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape))
ImGui::CloseCurrentPopup();
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
ImGui::EndPopup();
}
// Error popup
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
if (ImGui::BeginPopupModal("hex.builtin.common.error"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
ImGui::NewLine();
ImGui::Separator();
if (ImGui::Button("hex.builtin.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape))
ImGui::CloseCurrentPopup();
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
ImGui::EndPopup();
}
// Fatal error popup
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
if (ImGui::BeginPopupModal("hex.builtin.common.fatal"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
ImGui::NewLine();
ImGui::Separator();
if (ImGui::Button("hex.builtin.common.okay"_lang) || ImGui::IsKeyDown(ImGuiKey_Escape)) {
ImHexApi::System::closeImHex();
ImGui::CloseCurrentPopup();
}
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
ImGui::EndPopup();
}
// Yes/No question popup
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
if (ImGui::BeginPopupModal("hex.builtin.common.question"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextFormattedWrapped("{}", s_popupMessage.c_str());
ImGui::NewLine();
ImGui::Separator();
View::confirmButtons(
"hex.builtin.common.yes"_lang, "hex.builtin.common.no"_lang, [] {
s_yesCallback();
ImGui::CloseCurrentPopup(); }, [] {
s_noCallback();
ImGui::CloseCurrentPopup(); });
ImGui::SetWindowPos((windowSize - ImGui::GetWindowSize()) / 2, ImGuiCond_Appearing);
ImGui::EndPopup();
}
// File chooser popup
bool opened = true;
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
if (ImGui::BeginPopupModal("hex.builtin.common.choose_file"_lang, &opened, ImGuiWindowFlags_AlwaysAutoResize)) {
bool doubleClicked = false;
if (ImGui::BeginListBox("##files", scaled(ImVec2(500, 400)))) {
u32 index = 0;
for (auto &path : s_selectableFiles) {
ImGui::PushID(index);
bool selected = s_selectableFileIndices.contains(index);
if (ImGui::Selectable(wolv::util::toUTF8String(path.filename()).c_str(), selected, ImGuiSelectableFlags_DontClosePopups)) {
if (!s_selectableFileMultiple) {
s_selectableFileIndices.clear();
s_selectableFileIndices.insert(index);
} else {
if (selected) {
s_selectableFileIndices.erase(index);
} else {
s_selectableFileIndices.insert(index);
}
}
}
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0))
doubleClicked = true;
ImGui::InfoTooltip(wolv::util::toUTF8String(path).c_str());
ImGui::PopID();
index++;
}
ImGui::EndListBox();
}
if (ImGui::Button("hex.builtin.common.open"_lang) || doubleClicked) {
for (auto &index : s_selectableFileIndices)
s_selectableFileOpenCallback(s_selectableFiles[index]);
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("hex.builtin.common.browse"_lang)) {
fs::openFileBrowser(fs::DialogMode::Open, s_selectableFilesValidExtensions, [](const auto &path) {
s_selectableFileOpenCallback(path);
ImGui::CloseCurrentPopup();
}, {}, s_selectableFileMultiple);
}
ImGui::EndPopup();
}
// Task exception popup
for (const auto &task : TaskManager::getRunningTasks()) {
if (task->hadException()) {
EventManager::post<RequestShowErrorPopup>(hex::format("hex.builtin.popup.error.task_exception"_lang, LangEntry(task->getUnlocalizedName()), task->getExceptionMessage()));
PopupError::open(hex::format("hex.builtin.popup.error.task_exception"_lang, LangEntry(task->getUnlocalizedName()), task->getExceptionMessage()));
task->clearException();
break;
}
@ -207,49 +30,6 @@ namespace hex::plugin::builtin {
void addGlobalUIItems() {
EventManager::subscribe<EventFrameEnd>(drawGlobalPopups);
EventManager::subscribe<RequestShowInfoPopup>([](const std::string &message) {
s_popupMessage = message;
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.info"_lang); });
});
EventManager::subscribe<RequestShowErrorPopup>([](const std::string &message) {
s_popupMessage = message;
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.error"_lang); });
});
EventManager::subscribe<RequestShowFatalErrorPopup>([](const std::string &message) {
s_popupMessage = message;
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.fatal"_lang); });
});
EventManager::subscribe<RequestShowYesNoQuestionPopup>([](const std::string &message, const std::function<void()> &yesCallback, const std::function<void()> &noCallback) {
s_popupMessage = message;
s_yesCallback = yesCallback;
s_noCallback = noCallback;
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.question"_lang); });
});
EventManager::subscribe<RequestShowFileChooserPopup>([](const std::vector<std::fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback, bool multiple) {
s_selectableFileIndices = { };
s_selectableFiles = paths;
std::sort(s_selectableFiles.begin(), s_selectableFiles.end(),
[](const auto &a, const auto &b) {
return a.filename() < b.filename();
}
);
s_selectableFilesValidExtensions = validExtensions;
s_selectableFileOpenCallback = callback;
s_selectableFileMultiple = multiple;
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.choose_file"_lang); });
});
}
void addFooterItems() {

View File

@ -9,6 +9,7 @@
#include <content/providers/view_provider.hpp>
#include <content/helpers/math_evaluator.hpp>
#include <content/popups/popup_file_chooser.hpp>
#include <imgui_internal.h>
#include <nlohmann/json.hpp>
@ -1013,7 +1014,7 @@ namespace hex::plugin::builtin {
}
}
View::showFileChooserPopup(paths, { {"Thingy Table File", "tbl"} }, false,
PopupFileChooser::open(paths, std::vector<nfdfilteritem_t>{ {"Thingy Table File", "tbl"} }, false,
[this](const auto &path) {
TaskManager::createTask("Loading encoding file", 0, [this, path](auto&) {
auto encoding = EncodingFile(EncodingFile::Type::Thingy, path);

View File

@ -15,6 +15,8 @@
#include <implot.h>
#include <content/popups/popup_notification.hpp>
namespace hex::plugin::builtin {
using namespace hex::literals;
@ -47,7 +49,7 @@ namespace hex::plugin::builtin {
ContentRegistry::FileHandler::add({ ".mgc" }, [](const auto &path) {
for (const auto &destPath : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
if (wolv::io::fs::copyFile(path, destPath / path.filename(), std::fs::copy_options::overwrite_existing)) {
View::showInfoPopup("hex.builtin.view.information.magic_db_added"_lang);
PopupInfo::open("hex.builtin.view.information.magic_db_added"_lang);
return true;
}
}

View File

@ -15,6 +15,8 @@
#include <hex/helpers/magic.hpp>
#include <content/helpers/provider_extra_data.hpp>
#include <content/popups/popup_file_chooser.hpp>
#include <content/popups/popup_question.hpp>
#include <nlohmann/json.hpp>
#include <chrono>
@ -83,7 +85,6 @@ namespace hex::plugin::builtin {
return langDef;
}
ViewPatternEditor::ViewPatternEditor() : View("hex.builtin.view.pattern_editor.name") {
this->m_parserRuntime = std::make_unique<pl::PatternLanguage>();
ContentRegistry::PatternLanguage::configureRuntime(*this->m_parserRuntime, nullptr);
@ -196,25 +197,18 @@ namespace hex::plugin::builtin {
if (this->m_dangerousFunctionCalled && !ImGui::IsPopupOpen(View::toWindowName("hex.builtin.view.pattern_editor.dangerous_function.name").c_str())) {
ImGui::OpenPopup(View::toWindowName("hex.builtin.view.pattern_editor.dangerous_function.name").c_str());
this->m_dangerousFunctionCalled = false;
}
if (ImGui::BeginPopupModal(View::toWindowName("hex.builtin.view.pattern_editor.dangerous_function.name").c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::NewLine();
ImGui::TextUnformatted("hex.builtin.view.pattern_editor.dangerous_function.desc"_lang);
ImGui::NewLine();
View::confirmButtons(
"hex.builtin.common.yes"_lang, "hex.builtin.common.no"_lang,
PopupQuestion::open("hex.builtin.view.pattern_editor.dangerous_function.desc"_lang,
[this] {
this->m_dangerousFunctionsAllowed = DangerousFunctionPerms::Allow;
ImGui::CloseCurrentPopup();
}, [this] {
this->m_dangerousFunctionsAllowed = DangerousFunctionPerms::Deny;
ImGui::CloseCurrentPopup();
});
}
);
ImGui::EndPopup();
this->m_dangerousFunctionCalled = false;
}
View::discardNavigationRequests();
@ -501,42 +495,6 @@ namespace hex::plugin::builtin {
void ViewPatternEditor::drawAlwaysVisible() {
auto provider = ImHexApi::Provider::get();
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
if (ImGui::BeginPopupModal("hex.builtin.view.pattern_editor.accept_pattern"_lang, &this->m_acceptPatternWindowOpen, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextFormattedWrapped("{}", static_cast<const char *>("hex.builtin.view.pattern_editor.accept_pattern.desc"_lang));
std::vector<std::string> entries;
entries.resize(this->m_possiblePatternFiles.size());
for (u32 i = 0; i < entries.size(); i++) {
entries[i] = wolv::util::toUTF8String(this->m_possiblePatternFiles[i].filename());
}
if (ImGui::BeginListBox("##patterns_accept", ImVec2(-FLT_MIN, 0))) {
u32 index = 0;
for (auto &path : this->m_possiblePatternFiles) {
if (ImGui::Selectable(wolv::util::toUTF8String(path.filename()).c_str(), index == this->m_selectedPatternFile))
this->m_selectedPatternFile = index;
index++;
}
ImGui::EndListBox();
}
ImGui::NewLine();
ImGui::TextUnformatted("hex.builtin.view.pattern_editor.accept_pattern.question"_lang);
confirmButtons(
"hex.builtin.common.yes"_lang, "hex.builtin.common.no"_lang, [this, provider] {
this->loadPatternFile(this->m_possiblePatternFiles[this->m_selectedPatternFile], provider);
ImGui::CloseCurrentPopup(); }, [] { ImGui::CloseCurrentPopup(); });
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
}
auto open = this->m_sectionWindowDrawer.contains(provider);
if (open) {
ImGui::SetNextWindowSize(scaled(ImVec2(600, 700)), ImGuiCond_Appearing);
@ -828,7 +786,7 @@ namespace hex::plugin::builtin {
if (!this->m_possiblePatternFiles.empty()) {
this->m_selectedPatternFile = 0;
EventManager::post<RequestOpenPopup>("hex.builtin.view.pattern_editor.accept_pattern"_lang);
PopupAcceptPattern::open(this);
this->m_acceptPatternWindowOpen = true;
}
});
@ -903,7 +861,7 @@ namespace hex::plugin::builtin {
}
}
View::showFileChooserPopup(paths, { { "Pattern File", "hexpat" } }, false,
PopupFileChooser::open(paths, std::vector<nfdfilteritem_t>{ { "Pattern File", "hexpat" } }, false,
[this, provider](const std::fs::path &path) {
this->loadPatternFile(path, provider);
});

View File

@ -1,5 +1,7 @@
#include "content/views/view_provider_settings.hpp"
#include <content/popups/popup_notification.hpp>
namespace hex::plugin::builtin {
ViewProviderSettings::ViewProviderSettings() : hex::View("hex.builtin.view.provider_settings.name") {
@ -43,9 +45,9 @@ namespace hex::plugin::builtin {
else {
auto errorMessage = provider->getErrorMessage();
if (errorMessage.empty()) {
View::showErrorPopup("hex.builtin.view.provider_settings.load_error"_lang);
PopupError::open("hex.builtin.view.provider_settings.load_error"_lang);
} else {
View::showErrorPopup(hex::format("hex.builtin.view.provider_settings.load_error_details"_lang, errorMessage));
PopupError::open(hex::format("hex.builtin.view.provider_settings.load_error_details"_lang, errorMessage));
}
TaskManager::doLater([=] { ImHexApi::Provider::remove(provider); });
}

View File

@ -1,11 +1,12 @@
#include "content/views/view_settings.hpp"
#include <hex/api/content_registry.hpp>
#include <hex/helpers/logger.hpp>
#include <nlohmann/json.hpp>
#include <content/popups/popup_question.hpp>
namespace hex::plugin::builtin {
ViewSettings::ViewSettings() : View("hex.builtin.view.settings.name") {
@ -87,7 +88,7 @@ namespace hex::plugin::builtin {
this->getWindowOpenState() = false;
if (!this->getWindowOpenState() && this->m_restartRequested) {
View::showYesNoQuestionPopup("hex.builtin.view.settings.restart_question"_lang, ImHexApi::System::restartImHex, [] {});
PopupQuestion::open("hex.builtin.view.settings.restart_question"_lang, ImHexApi::System::restartImHex, [] {});
}
}

View File

@ -8,6 +8,9 @@
#include "content/helpers/provider_extra_data.hpp"
#include <content/popups/popup_notification.hpp>
#include <content/popups/popup_file_chooser.hpp>
// <yara/types.h>'s RE type has a zero-sized array, which is not allowed in ISO C++.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
@ -32,7 +35,7 @@ namespace hex::plugin::builtin {
ContentRegistry::FileHandler::add({ ".yar", ".yara" }, [](const auto &path) {
for (const auto &destPath : fs::getDefaultPaths(fs::ImHexPath::Yara)) {
if (wolv::io::fs::copyFile(path, destPath / path.filename(), std::fs::copy_options::overwrite_existing)) {
View::showInfoPopup("hex.builtin.view.yara.rule_added"_lang);
PopupInfo::open("hex.builtin.view.yara.rule_added"_lang);
return true;
}
}
@ -132,7 +135,7 @@ namespace hex::plugin::builtin {
}
}
View::showFileChooserPopup(paths, { { "Yara File", "yara" }, { "Yara File", "yar" } }, true,
PopupFileChooser::open(paths, std::vector<nfdfilteritem_t>{ { "Yara File", "yara" }, { "Yara File", "yar" } }, true,
[&](const auto &path) {
rules.push_back({ path.filename(), path });
});

View File

@ -23,6 +23,9 @@
#include <fonts/codicons_font.h>
#include <content/popups/popup_notification.hpp>
#include <content/popups/popup_question.hpp>
#include <string>
#include <list>
#include <unordered_set>
@ -59,6 +62,59 @@ namespace hex::plugin::builtin {
};
class PopupRestoreBackup : public Popup<PopupRestoreBackup> {
public:
PopupRestoreBackup() : Popup("hex.builtin.popup.safety_backup.title") { }
void drawContent() override {
ImGui::TextUnformatted("hex.builtin.welcome.safety_backup.desc"_lang);
ImGui::NewLine();
auto width = ImGui::GetWindowWidth();
ImGui::SetCursorPosX(width / 9);
if (ImGui::Button("hex.builtin.welcome.safety_backup.restore"_lang, ImVec2(width / 3, 0))) {
ProjectFile::load(s_safetyBackupPath);
ProjectFile::clearPath();
for (const auto &provider : ImHexApi::Provider::getProviders())
provider->markDirty();
wolv::io::fs::remove(s_safetyBackupPath);
Popup::close();
}
ImGui::SameLine();
ImGui::SetCursorPosX(width / 9 * 5);
if (ImGui::Button("hex.builtin.welcome.safety_backup.delete"_lang, ImVec2(width / 3, 0))) {
wolv::io::fs::remove(s_safetyBackupPath);
Popup::close();
}
}
};
class PopupTipOfTheDay : public Popup<PopupTipOfTheDay> {
public:
PopupTipOfTheDay() : Popup("hex.builtin.popup.tip_of_the_day.title", true, false) { }
void drawContent() override {
ImGui::Header("hex.builtin.welcome.tip_of_the_day"_lang, true);
ImGui::TextFormattedWrapped("{}", s_tipOfTheDay.c_str());
ImGui::NewLine();
static bool dontShowAgain = false;
if (ImGui::Checkbox("hex.builtin.common.dont_show_again"_lang, &dontShowAgain)) {
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.show_tips", !dontShowAgain);
}
ImGui::SameLine((ImGui::GetMainViewport()->Size / 3 - ImGui::CalcTextSize("hex.builtin.common.close"_lang) - ImGui::GetStyle().FramePadding).x);
if (ImGui::Button("hex.builtin.common.close"_lang))
Popup::close();
}
};
static std::atomic<bool> s_recentProvidersUpdating = false;
static std::list<RecentProvider> s_recentProviders;
@ -124,7 +180,7 @@ namespace hex::plugin::builtin {
provider->loadSettings(recentProvider.data);
if (!provider->open() || !provider->isAvailable()) {
View::showErrorPopup("hex.builtin.popup.error.open"_lang);
PopupError::open("hex.builtin.popup.error.open"_lang);
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
return;
}
@ -160,60 +216,6 @@ namespace hex::plugin::builtin {
});
}
static void drawPopups() {
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
ImGui::SetNextWindowSize(ImGui::GetMainViewport()->Size / 3, ImGuiCond_Appearing);
if (ImGui::BeginPopup("hex.builtin.welcome.tip_of_the_day"_lang)) {
ImGui::Header("hex.builtin.welcome.tip_of_the_day"_lang, true);
ImGui::TextFormattedWrapped("{}", s_tipOfTheDay.c_str());
ImGui::NewLine();
static bool dontShowAgain = false;
if (ImGui::Checkbox("hex.builtin.common.dont_show_again"_lang, &dontShowAgain)) {
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.show_tips", !dontShowAgain);
}
ImGui::SameLine((ImGui::GetMainViewport()->Size / 3 - ImGui::CalcTextSize("hex.builtin.common.close"_lang) - ImGui::GetStyle().FramePadding).x);
if (ImGui::Button("hex.builtin.common.close"_lang))
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
}
// Popup for if there is a safety backup present because ImHex crashed
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
if (ImGui::BeginPopupModal("hex.builtin.welcome.safety_backup.title"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) {
ImGui::TextUnformatted("hex.builtin.welcome.safety_backup.desc"_lang);
ImGui::NewLine();
auto width = ImGui::GetWindowWidth();
ImGui::SetCursorPosX(width / 9);
if (ImGui::Button("hex.builtin.welcome.safety_backup.restore"_lang, ImVec2(width / 3, 0))) {
ProjectFile::load(s_safetyBackupPath);
ProjectFile::clearPath();
for (const auto &provider : ImHexApi::Provider::getProviders())
provider->markDirty();
wolv::io::fs::remove(s_safetyBackupPath);
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
ImGui::SetCursorPosX(width / 9 * 5);
if (ImGui::Button("hex.builtin.welcome.safety_backup.delete"_lang, ImVec2(width / 3, 0))) {
wolv::io::fs::remove(s_safetyBackupPath);
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
}
static void drawWelcomeScreenContent() {
const auto availableSpace = ImGui::GetContentRegionAvail();
@ -406,8 +408,6 @@ namespace hex::plugin::builtin {
}
}
ImGui::End();
drawPopups();
}
static void drawNoViewsBackground() {
@ -515,8 +515,8 @@ namespace hex::plugin::builtin {
// documentation of the value above the setting definition
int showCheckForUpdates = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.check_for_updates", 2);
if (showCheckForUpdates == 2) {
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.check_for_updates", 0);
View::showYesNoQuestionPopup("hex.builtin.welcome.check_for_updates_text"_lang,
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.check_for_updates", 0);
PopupQuestion::open("hex.builtin.welcome.check_for_updates_text"_lang,
[] { // yes
ContentRegistry::Settings::write("hex.builtin.setting.general", "hex.builtin.setting.general.check_for_updates", 1);
ImGui::CloseCurrentPopup();
@ -526,7 +526,7 @@ namespace hex::plugin::builtin {
}
});
// clear project context if we go back to the welcome screen
// Clear project context if we go back to the welcome screen
EventManager::subscribe<EventProviderChanged>([](hex::prv::Provider *oldProvider, hex::prv::Provider *newProvider) {
hex::unused(oldProvider);
if (newProvider == nullptr) {
@ -559,14 +559,16 @@ namespace hex::plugin::builtin {
}
});
// Check for crash backup
constexpr static auto CrashBackupFileName = "crash_backup.hexproj";
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Config)) {
if (auto filePath = std::fs::path(path) / CrashBackupFileName; wolv::io::fs::exists(filePath)) {
s_safetyBackupPath = filePath;
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.safety_backup.title"_lang); });
PopupRestoreBackup::open();
}
}
// Tip of the day
auto tipsData = romfs::get("tips.json");
if(s_safetyBackupPath.empty() && tipsData.valid()){
auto tipsCategories = nlohmann::json::parse(tipsData.string());
@ -581,7 +583,7 @@ namespace hex::plugin::builtin {
bool showTipOfTheDay = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.show_tips", 1);
if (showTipOfTheDay)
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.tip_of_the_day"_lang); });
PopupTipOfTheDay::open();
}
}

View File

@ -215,7 +215,7 @@ namespace hex::plugin::windows {
if (loadLibraryW != nullptr) {
if (auto threadHandle = CreateRemoteThread(this->m_processHandle, nullptr, 0, loadLibraryW, pathAddress, 0, nullptr); threadHandle != nullptr) {
WaitForSingleObject(threadHandle, INFINITE);
hex::View::showInfoPopup(hex::format("hex.windows.provider.process_memory.utils.inject_dll.success"_lang, path.filename().string()));
EventManager::post<RequestOpenErrorPopup>(hex::format("hex.windows.provider.process_memory.utils.inject_dll.success"_lang, path.filename().string()));
this->reloadProcessModules();
CloseHandle(threadHandle);
return;
@ -224,7 +224,7 @@ namespace hex::plugin::windows {
}
}
hex::View::showErrorPopup(hex::format("hex.windows.provider.process_memory.utils.inject_dll.failure"_lang, path.filename().string()));
EventManager::post<RequestOpenErrorPopup>(hex::format("hex.windows.provider.process_memory.utils.inject_dll.failure"_lang, path.filename().string()));
});
}
}

View File

@ -87,7 +87,7 @@ namespace hex::plugin::windows {
if (this->m_portHandle == INVALID_HANDLE_VALUE) {
if (ImGui::Button("hex.windows.view.tty_console.connect"_lang))
if (!this->connect())
View::showErrorPopup("hex.windows.view.tty_console.connect_error"_lang);
EventManager::post<RequestOpenErrorPopup>("hex.windows.view.tty_console.connect_error"_lang);
} else {
if (ImGui::Button("hex.windows.view.tty_console.disconnect"_lang))
this->disconnect();
@ -190,7 +190,7 @@ namespace hex::plugin::windows {
bool ViewTTYConsole::connect() {
if (this->m_comPorts.empty() || static_cast<size_t>(this->m_selectedPort) >= this->m_comPorts.size()) {
View::showErrorPopup("hex.windows.view.tty_console.no_available_port"_lang);
EventManager::post<RequestOpenErrorPopup>("hex.windows.view.tty_console.no_available_port"_lang);
return true; // If false, connect_error error popup will override this error popup
}
this->m_portHandle = ::CreateFile((R"(\\.\)" + this->m_comPorts[this->m_selectedPort].first).c_str(),