1
0
mirror of synced 2025-02-17 18:59:21 +01:00

Make File Dialogs less hacky

This commit is contained in:
WerWolv 2021-01-27 00:44:10 +01:00
parent ab2458bdf4
commit 8990fad85a
8 changed files with 119 additions and 97 deletions

View File

@ -30,7 +30,6 @@ namespace hex {
private: private:
MemoryEditor m_memoryEditor; MemoryEditor m_memoryEditor;
imgui_addons::ImGuiFileBrowser m_fileBrowser;
std::vector<lang::PatternData*> &m_patternData; std::vector<lang::PatternData*> &m_patternData;

View File

@ -32,7 +32,6 @@ namespace hex {
TextEditor m_textEditor; TextEditor m_textEditor;
std::vector<std::pair<lang::LogConsole::Level, std::string>> m_console; std::vector<std::pair<lang::LogConsole::Level, std::string>> m_console;
imgui_addons::ImGuiFileBrowser m_fileBrowser;
void loadPatternFile(std::string path); void loadPatternFile(std::string path);
void clearPatternData(); void clearPatternData();

View File

@ -12,6 +12,8 @@
#include <hex/views/view.hpp> #include <hex/views/view.hpp>
#include <imgui.h> #include <imgui.h>
#include <ImGuiFileBrowser.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
namespace hex { class SharedData; } namespace hex { class SharedData; }
@ -59,6 +61,12 @@ namespace hex {
static std::string errorPopupMessage; static std::string errorPopupMessage;
static std::list<ImHexApi::Bookmarks::Entry> bookmarkEntries; static std::list<ImHexApi::Bookmarks::Entry> bookmarkEntries;
static imgui_addons::ImGuiFileBrowser fileBrowser;
static imgui_addons::ImGuiFileBrowser::DialogMode fileBrowserDialogMode;
static std::string fileBrowserTitle;
static std::string fileBrowserValidExtensions;
static std::function<void(std::string)> fileBrowserCallback;
static int mainArgc; static int mainArgc;
static char **mainArgv; static char **mainArgv;

View File

@ -3,6 +3,7 @@
#include <hex.hpp> #include <hex.hpp>
#include <imgui.h> #include <imgui.h>
#include <ImGuiFileBrowser.h>
#include <hex/api/event.hpp> #include <hex/api/event.hpp>
@ -22,6 +23,7 @@ namespace hex {
virtual void drawMenu(); virtual void drawMenu();
virtual bool handleShortcut(int key, int mods); virtual bool handleShortcut(int key, int mods);
static void openFileBrowser(std::string title, imgui_addons::ImGuiFileBrowser::DialogMode mode, std::string validExtensions, const std::function<void(std::string)> &callback);
static void doLater(std::function<void()> &&function); static void doLater(std::function<void()> &&function);
static std::vector<std::function<void()>>& getDeferedCalls(); static std::vector<std::function<void()>>& getDeferedCalls();

View File

@ -18,6 +18,12 @@ namespace hex {
std::string SharedData::errorPopupMessage; std::string SharedData::errorPopupMessage;
std::list<ImHexApi::Bookmarks::Entry> SharedData::bookmarkEntries; std::list<ImHexApi::Bookmarks::Entry> SharedData::bookmarkEntries;
imgui_addons::ImGuiFileBrowser SharedData::fileBrowser;
imgui_addons::ImGuiFileBrowser::DialogMode SharedData::fileBrowserDialogMode;
std::string SharedData::fileBrowserTitle;
std::string SharedData::fileBrowserValidExtensions;
std::function<void(std::string)> SharedData::fileBrowserCallback;
int SharedData::mainArgc; int SharedData::mainArgc;
char **SharedData::mainArgv; char **SharedData::mainArgv;

View File

@ -24,6 +24,17 @@ namespace hex {
return EventManager::post(eventType, userData); return EventManager::post(eventType, userData);
} }
void View::openFileBrowser(std::string title, imgui_addons::ImGuiFileBrowser::DialogMode mode, std::string validExtensions, const std::function<void(std::string)> &callback) {
SharedData::fileBrowserTitle = title;
SharedData::fileBrowserDialogMode = mode;
SharedData::fileBrowserValidExtensions = std::move(validExtensions);
SharedData::fileBrowserCallback = callback;
View::doLater([title]{
ImGui::OpenPopup(title.c_str());
});
}
void View::drawCommonInterfaces() { void View::drawCommonInterfaces() {
if (ImGui::BeginPopupModal("Error", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { if (ImGui::BeginPopupModal("Error", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::NewLine(); ImGui::NewLine();
@ -38,6 +49,11 @@ namespace hex {
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
ImGui::EndPopup(); ImGui::EndPopup();
} }
if (SharedData::fileBrowser.showFileDialog(SharedData::fileBrowserTitle, SharedData::fileBrowserDialogMode, ImVec2(0, 0), SharedData::fileBrowserValidExtensions)) {
SharedData::fileBrowserCallback(SharedData::fileBrowser.selected_path);
SharedData::fileBrowserTitle = "";
}
} }
void View::showErrorPopup(std::string_view errorMessage) { void View::showErrorPopup(std::string_view errorMessage) {

View File

@ -124,7 +124,6 @@ namespace hex {
if (ProjectFile::hasUnsavedChanges()) { if (ProjectFile::hasUnsavedChanges()) {
glfwSetWindowShouldClose(window, GLFW_FALSE); glfwSetWindowShouldClose(window, GLFW_FALSE);
this->getWindowOpenState() = true;
View::doLater([] { ImGui::OpenPopup("Save Changes"); }); View::doLater([] { ImGui::OpenPopup("Save Changes"); });
} }
}); });
@ -210,23 +209,21 @@ namespace hex {
ImGui::NewLine(); ImGui::NewLine();
ImGui::InputText("##nolabel", this->m_loaderScriptScriptPath.data(), this->m_loaderScriptScriptPath.length(), ImGuiInputTextFlags_ReadOnly); ImGui::InputText("##nolabel", this->m_loaderScriptScriptPath.data(), this->m_loaderScriptScriptPath.length(), ImGuiInputTextFlags_ReadOnly);
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("Script")) if (ImGui::Button("Script")) {
ImGui::OpenPopup("Loader Script: Open Script"); View::openFileBrowser("Loader Script: Open Script", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ".py", [this](auto path) {
this->m_loaderScriptScriptPath = path;
});
}
ImGui::InputText("##nolabel", this->m_loaderScriptFilePath.data(), this->m_loaderScriptFilePath.length(), ImGuiInputTextFlags_ReadOnly); ImGui::InputText("##nolabel", this->m_loaderScriptFilePath.data(), this->m_loaderScriptFilePath.length(), ImGuiInputTextFlags_ReadOnly);
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("File")) if (ImGui::Button("File")) {
ImGui::OpenPopup("Loader Script: Open File"); View::openFileBrowser("Loader Script: Open File", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, "*.*", [this](auto path) {
this->m_loaderScriptFilePath = path;
});
}
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape))) if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
if (this->m_fileBrowser.showFileDialog("Loader Script: Open Script", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(0, 0), ".py")) {
this->m_loaderScriptScriptPath = this->m_fileBrowser.selected_path;
}
if (this->m_fileBrowser.showFileDialog("Loader Script: Open File", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN)) {
this->m_loaderScriptFilePath = this->m_fileBrowser.selected_path;
}
ImGui::NewLine(); ImGui::NewLine();
confirmButtons("Load", "Cancel", confirmButtons("Load", "Cancel",
@ -265,62 +262,17 @@ namespace hex {
ImGui::EndPopup(); ImGui::EndPopup();
} }
}
static void save() {
auto provider = SharedData::currentProvider;
for (const auto &[address, value] : provider->getPatches())
provider->writeRaw(address, &value, sizeof(u8));
}
if (this->m_fileBrowser.showFileDialog("Open File", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN)) { static void saveAs() {
this->openFile(this->m_fileBrowser.selected_path); View::openFileBrowser("Save As", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE, "*.*", [](auto path) {
} FILE *file = fopen(path.c_str(), "wb");
if (this->m_fileBrowser.showFileDialog("Open Base64 File", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN)) {
std::vector<u8> base64;
this->loadFromFile(this->m_fileBrowser.selected_path, base64);
if (!base64.empty()) {
this->m_dataToSave = decode64(base64);
if (this->m_dataToSave.empty())
View::showErrorPopup("File is not in a valid Base64 format!");
else
ImGui::OpenPopup("Save Data");
} else View::showErrorPopup("Failed to open file!");
}
if (this->m_fileBrowser.showFileDialog("Open Project", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(0, 0), ".hexproj")) {
ProjectFile::load(this->m_fileBrowser.selected_path);
View::postEvent(Events::ProjectFileLoad);
}
if (this->m_fileBrowser.showFileDialog("Save Project", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE, ImVec2(0, 0), ".hexproj")) {
ProjectFile::store(this->m_fileBrowser.selected_path);
}
if (this->m_fileBrowser.showFileDialog("Export File", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE)) {
this->saveToFile(this->m_fileBrowser.selected_path, this->m_dataToSave);
}
if (this->m_fileBrowser.showFileDialog("Apply IPS Patch", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN)) {
auto patchData = hex::readFile(this->m_fileBrowser.selected_path);
auto patch = hex::loadIPSPatch(patchData);
for (auto &[address, value] : patch) {
provider->write(address, &value, 1);
}
}
if (this->m_fileBrowser.showFileDialog("Apply IPS32 Patch", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN)) {
auto patchData = hex::readFile(this->m_fileBrowser.selected_path);
auto patch = hex::loadIPS32Patch(patchData);
for (auto &[address, value] : patch) {
provider->write(address, &value, 1);
}
}
if (this->m_fileBrowser.showFileDialog("Save As", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE)) {
FILE *file = fopen(this->m_fileBrowser.selected_path.c_str(), "wb");
if (file != nullptr) { if (file != nullptr) {
std::vector<u8> buffer(0xFF'FFFF, 0x00); std::vector<u8> buffer(0xFF'FFFF, 0x00);
@ -328,6 +280,7 @@ namespace hex {
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
auto provider = SharedData::currentProvider;
for (u64 offset = 0; offset < provider->getActualSize(); offset += bufferSize) { for (u64 offset = 0; offset < provider->getActualSize(); offset += bufferSize) {
if (bufferSize > provider->getActualSize() - offset) if (bufferSize > provider->getActualSize() - offset)
bufferSize = provider->getActualSize() - offset; bufferSize = provider->getActualSize() - offset;
@ -338,39 +291,47 @@ namespace hex {
fclose(file); fclose(file);
} }
} });
} };
void ViewHexEditor::drawMenu() { void ViewHexEditor::drawMenu() {
auto provider = SharedData::currentProvider; auto provider = SharedData::currentProvider;
if (ImGui::BeginMenu("File")) { if (ImGui::BeginMenu("File")) {
if (ImGui::MenuItem("Open File...", "CTRL + O")) { if (ImGui::MenuItem("Open File...", "CTRL + O")) {
this->getWindowOpenState() = true;
View::doLater([]{ ImGui::OpenPopup("Open File"); }); View::openFileBrowser("Open File", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, "*.*", [this](auto path) {
this->openFile(path);
this->getWindowOpenState() = true;
});
} }
if (ImGui::MenuItem("Save", "CTRL + S", false, provider != nullptr && provider->isWritable())) { if (ImGui::MenuItem("Save", "CTRL + S", false, provider != nullptr && provider->isWritable())) {
for (const auto &[address, value] : provider->getPatches()) save();
provider->writeRaw(address, &value, sizeof(u8));
} }
if (ImGui::MenuItem("Save As...", "CTRL + SHIFT + S", false, provider != nullptr && provider->isWritable())) { if (ImGui::MenuItem("Save As...", "CTRL + SHIFT + S", false, provider != nullptr && provider->isWritable())) {
View::doLater([]{ ImGui::OpenPopup("Save As"); }); saveAs();
} }
ImGui::Separator(); ImGui::Separator();
if (ImGui::MenuItem("Open Project", "")) { if (ImGui::MenuItem("Open Project", "")) {
this->getWindowOpenState() = true; View::openFileBrowser("Open Project", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ".hexproj", [this](auto path) {
View::doLater([]{ ImGui::OpenPopup("Open Project"); }); ProjectFile::load(path);
View::postEvent(Events::ProjectFileLoad);
this->getWindowOpenState() = true;
});
} }
if (ImGui::MenuItem("Save Project", "", false, provider != nullptr && provider->isWritable())) { if (ImGui::MenuItem("Save Project", "", false, provider != nullptr && provider->isWritable())) {
View::postEvent(Events::ProjectFileStore); View::postEvent(Events::ProjectFileStore);
if (ProjectFile::getProjectFilePath() == "") if (ProjectFile::getProjectFilePath() == "") {
View::doLater([] { ImGui::OpenPopup("Save Project"); }); View::openFileBrowser("Save Project", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE, ".hexproj", [](auto path) {
ProjectFile::store(path);
});
}
else else
ProjectFile::store(); ProjectFile::store();
} }
@ -379,24 +340,53 @@ namespace hex {
if (ImGui::BeginMenu("Import...")) { if (ImGui::BeginMenu("Import...")) {
if (ImGui::MenuItem("Base64 File")) { if (ImGui::MenuItem("Base64 File")) {
this->getWindowOpenState() = true;
View::doLater([]{ ImGui::OpenPopup("Open Base64 File"); }); View::openFileBrowser("Open Base64 File", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, "*.*", [this](auto path) {
std::vector<u8> base64;
this->loadFromFile(path, base64);
if (!base64.empty()) {
this->m_dataToSave = decode64(base64);
if (this->m_dataToSave.empty())
View::showErrorPopup("File is not in a valid Base64 format!");
else
ImGui::OpenPopup("Save Data");
this->getWindowOpenState() = true;
} else View::showErrorPopup("Failed to open file!");
});
} }
ImGui::Separator(); ImGui::Separator();
if (ImGui::MenuItem("IPS Patch")) { if (ImGui::MenuItem("IPS Patch")) {
this->getWindowOpenState() = true;
View::doLater([]{ ImGui::OpenPopup("Apply IPS Patch"); }); View::openFileBrowser("Apply IPS Patch", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, "*.*", [this](auto path) {
auto patchData = hex::readFile(path);
auto patch = hex::loadIPSPatch(patchData);
for (auto &[address, value] : patch) {
SharedData::currentProvider->write(address, &value, 1);
}
this->getWindowOpenState() = true;
});
} }
if (ImGui::MenuItem("IPS32 Patch")) { if (ImGui::MenuItem("IPS32 Patch")) {
this->getWindowOpenState() = true; View::openFileBrowser("Apply IPS32 Patch", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, "*.*", [this](auto path) {
View::doLater([]{ ImGui::OpenPopup("Apply IPS32 Patch"); }); auto patchData = hex::readFile(path);
auto patch = hex::loadIPS32Patch(patchData);
for (auto &[address, value] : patch) {
SharedData::currentProvider->write(address, &value, 1);
}
this->getWindowOpenState() = true;
});
} }
if (ImGui::MenuItem("File with Loader Script")) { if (ImGui::MenuItem("File with Loader Script")) {
this->getWindowOpenState() = true;
this->m_loaderScriptFilePath.clear(); this->m_loaderScriptFilePath.clear();
this->m_loaderScriptScriptPath.clear(); this->m_loaderScriptScriptPath.clear();
View::doLater([]{ ImGui::OpenPopup("Load File with Loader Script"); }); View::doLater([]{ ImGui::OpenPopup("Load File with Loader Script"); });
@ -415,7 +405,9 @@ namespace hex {
} }
this->m_dataToSave = generateIPSPatch(patches); this->m_dataToSave = generateIPSPatch(patches);
View::doLater([]{ ImGui::OpenPopup("Export File"); }); View::openFileBrowser("Export File", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE, "*.*", [this](auto path) {
this->saveToFile(path, this->m_dataToSave);
});
} }
if (ImGui::MenuItem("IPS32 Patch")) { if (ImGui::MenuItem("IPS32 Patch")) {
Patches patches = provider->getPatches(); Patches patches = provider->getPatches();
@ -426,7 +418,9 @@ namespace hex {
} }
this->m_dataToSave = generateIPS32Patch(patches); this->m_dataToSave = generateIPS32Patch(patches);
View::doLater([]{ ImGui::OpenPopup("Export File"); }); View::openFileBrowser("Export File", imgui_addons::ImGuiFileBrowser::DialogMode::SAVE, "*.*", [this](auto path) {
this->saveToFile(path, this->m_dataToSave);
});
} }
ImGui::EndMenu(); ImGui::EndMenu();
@ -457,12 +451,10 @@ namespace hex {
bool ViewHexEditor::handleShortcut(int key, int mods) { bool ViewHexEditor::handleShortcut(int key, int mods) {
if (mods == GLFW_MOD_CONTROL && key == GLFW_KEY_S) { if (mods == GLFW_MOD_CONTROL && key == GLFW_KEY_S) {
auto provider = SharedData::currentProvider; save();
for (const auto &[address, value] : provider->getPatches())
provider->writeRaw(address, &value, sizeof(u8));
return true; return true;
} else if (mods == (GLFW_MOD_CONTROL | GLFW_MOD_SHIFT) && key == GLFW_KEY_S) { } else if (mods == (GLFW_MOD_CONTROL | GLFW_MOD_SHIFT) && key == GLFW_KEY_S) {
ImGui::OpenPopup("Save As"); saveAs();
return true; return true;
} else if (mods == GLFW_MOD_CONTROL && key == GLFW_KEY_F) { } else if (mods == GLFW_MOD_CONTROL && key == GLFW_KEY_F) {
ImGui::OpenPopup("Search"); ImGui::OpenPopup("Search");

View File

@ -217,7 +217,9 @@ namespace hex {
void ViewPattern::drawMenu() { void ViewPattern::drawMenu() {
if (ImGui::BeginMenu("File")) { if (ImGui::BeginMenu("File")) {
if (ImGui::MenuItem("Load pattern...")) { if (ImGui::MenuItem("Load pattern...")) {
View::doLater([]{ ImGui::OpenPopup("Open Hex Pattern"); }); View::openFileBrowser("Open Hex Pattern", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ".hexpat", [this](auto path) {
this->loadPatternFile(path);
});
} }
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -272,9 +274,7 @@ namespace hex {
} }
ImGui::End(); ImGui::End();
if (this->m_fileBrowser.showFileDialog("Open Hex Pattern", imgui_addons::ImGuiFileBrowser::DialogMode::OPEN, ImVec2(0, 0), ".hexpat")) {
this->loadPatternFile(this->m_fileBrowser.selected_path);
}
if (ImGui::BeginPopupModal("Accept Pattern", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { if (ImGui::BeginPopupModal("Accept Pattern", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextWrapped("One or more patterns compatible with this data type has been found"); ImGui::TextWrapped("One or more patterns compatible with this data type has been found");