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

feat: Allow multiple yara files to be selected at once

This commit is contained in:
WerWolv 2023-01-28 00:01:53 +01:00
parent 800ffb5e56
commit 29c1a0cb78
9 changed files with 61 additions and 30 deletions

View File

@ -139,6 +139,6 @@ namespace hex {
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)>);
EVENT_DEF(RequestShowFileChooserPopup, std::vector<std::fs::path>, std::vector<nfdfilteritem_t>, std::function<void(std::fs::path)>, bool);
}

View File

@ -84,7 +84,7 @@ namespace hex::fs {
};
void setFileBrowserErrorCallback(const std::function<void()> &callback);
bool openFileBrowser(DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback, const std::string &defaultPath = {});
bool openFileBrowser(DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback, const std::string &defaultPath = {}, bool multiple = false);
enum class ImHexPath : u32 {
Patterns = 0,

View File

@ -39,7 +39,7 @@ namespace hex {
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, const std::function<void(std::fs::path)> &callback);
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;

View File

@ -81,20 +81,24 @@ namespace hex::fs {
s_fileBrowserErrorCallback = callback;
}
bool openFileBrowser(DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback, const std::string &defaultPath) {
bool openFileBrowser(DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback, const std::string &defaultPath, bool multiple) {
NFD::Init();
nfdchar_t *outPath = nullptr;
NFD::UniquePathU8 outPath;
NFD::UniquePathSet outPaths;
nfdresult_t result;
switch (mode) {
case DialogMode::Open:
result = NFD::OpenDialog(outPath, validExtensions.data(), validExtensions.size(), defaultPath.c_str());
if (multiple)
result = NFD::OpenDialogMultiple(outPaths, validExtensions.data(), validExtensions.size(), defaultPath.empty() ? nullptr : defaultPath.c_str());
else
result = NFD::OpenDialog(outPath, validExtensions.data(), validExtensions.size(), defaultPath.empty() ? nullptr : defaultPath.c_str());
break;
case DialogMode::Save:
result = NFD::SaveDialog(outPath, validExtensions.data(), validExtensions.size(), defaultPath.c_str());
result = NFD::SaveDialog(outPath, validExtensions.data(), validExtensions.size(), defaultPath.empty() ? nullptr : defaultPath.c_str());
break;
case DialogMode::Folder:
result = NFD::PickFolder(outPath, defaultPath.c_str());
result = NFD::PickFolder(outPath, defaultPath.empty() ? nullptr : defaultPath.c_str());
break;
default:
hex::unreachable();
@ -102,10 +106,19 @@ namespace hex::fs {
if (result == NFD_OKAY){
if(outPath != nullptr) {
callback(reinterpret_cast<char8_t*>(outPath));
NFD::FreePath(outPath);
callback(reinterpret_cast<char8_t*>(outPath.get()));
}
} else if (result==NFD_ERROR) {
if (outPaths != nullptr) {
nfdpathsetsize_t numPaths = 0;
if (NFD::PathSet::Count(outPaths, numPaths) == NFD_OKAY) {
for (size_t i = 0; i < numPaths; i++) {
NFD::UniquePathSetPath path;
if (NFD::PathSet::GetPath(outPaths, i, path) == NFD_OKAY)
callback(reinterpret_cast<char8_t*>(path.get()));
}
}
}
} else if (result == NFD_ERROR) {
if (s_fileBrowserErrorCallback != nullptr)
s_fileBrowserErrorCallback();
}

View File

@ -34,13 +34,13 @@ namespace hex {
}
void View::showFileChooserPopup(const std::vector<std::fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback) {
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);
EventManager::post<RequestShowFileChooserPopup>(paths, validExtensions, callback, multiple);
}
}

View File

@ -16,10 +16,11 @@ namespace hex::plugin::builtin {
static std::string s_popupMessage;
static std::function<void()> s_yesCallback, s_noCallback;
static u32 s_selectableFileIndex;
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() {
@ -128,8 +129,22 @@ namespace hex::plugin::builtin {
u32 index = 0;
for (auto &path : s_selectableFiles) {
ImGui::PushID(index);
if (ImGui::Selectable(hex::toUTF8String(path.filename()).c_str(), index == s_selectableFileIndex))
s_selectableFileIndex = index;
bool selected = s_selectableFileIndices.contains(index);
if (ImGui::Selectable(hex::toUTF8String(path.filename()).c_str(), selected)) {
if (!s_selectableFileMultiple) {
s_selectableFileIndices.clear();
s_selectableFileIndices.insert(index);
} else {
if (selected) {
s_selectableFileIndices.erase(index);
} else {
s_selectableFileIndices.insert(index);
}
}
}
ImGui::PopID();
index++;
@ -139,7 +154,8 @@ namespace hex::plugin::builtin {
}
if (ImGui::Button("hex.builtin.common.open"_lang)) {
s_selectableFileOpenCallback(s_selectableFiles[s_selectableFileIndex]);
for (auto &index : s_selectableFileIndices)
s_selectableFileOpenCallback(s_selectableFiles[index]);
ImGui::CloseCurrentPopup();
}
@ -149,7 +165,7 @@ namespace hex::plugin::builtin {
fs::openFileBrowser(fs::DialogMode::Open, s_selectableFilesValidExtensions, [](const auto &path) {
s_selectableFileOpenCallback(path);
ImGui::CloseCurrentPopup();
});
}, {}, s_selectableFileMultiple);
}
ImGui::EndPopup();
@ -195,11 +211,12 @@ namespace hex::plugin::builtin {
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) {
s_selectableFileIndex = 0;
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;
s_selectableFilesValidExtensions = validExtensions;
s_selectableFileOpenCallback = callback;
s_selectableFileMultiple = multiple;
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.choose_file"_lang); });
});

View File

@ -944,7 +944,7 @@ namespace hex::plugin::builtin {
}
}
View::showFileChooserPopup(paths, { {"Thingy Table File", "tbl"} },
View::showFileChooserPopup(paths, { {"Thingy Table File", "tbl"} }, false,
[this](const auto &path) {
this->m_hexEditor.setCustomEncoding(EncodingFile(EncodingFile::Type::Thingy, path));
});

View File

@ -867,10 +867,10 @@ namespace hex::plugin::builtin {
}
}
View::showFileChooserPopup(paths, { {"Pattern File", "hexpat"} },
[this, provider](const std::fs::path &path) {
this->loadPatternFile(path, provider);
});
View::showFileChooserPopup(paths, { { "Pattern File", "hexpat" } }, false,
[this, provider](const std::fs::path &path) {
this->loadPatternFile(path, provider);
});
}
if (ImGui::MenuItem("hex.builtin.view.pattern_editor.menu.file.save_pattern"_lang, nullptr, false, providerValid)) {

View File

@ -20,7 +20,7 @@ namespace hex::plugin::builtin {
ViewYara::ViewYara() : View("hex.builtin.view.yara.name") {
yr_initialize();
ContentRegistry::FileHandler::add({ ".yar" }, [](const auto &path) {
ContentRegistry::FileHandler::add({ ".yar", ".yara" }, [](const auto &path) {
for (const auto &destPath : fs::getDefaultPaths(fs::ImHexPath::Yara)) {
if (fs::copyFile(path, destPath / path.filename(), std::fs::copy_options::overwrite_existing)) {
View::showInfoPopup("hex.builtin.view.yara.rule_added"_lang);
@ -64,9 +64,10 @@ namespace hex::plugin::builtin {
}
}
View::showFileChooserPopup(paths, { { "Yara File", "yara" }, { "Yara File", "yar" } }, [this](const auto &path) {
this->m_rules.push_back({ path.filename(), path });
});
View::showFileChooserPopup(paths, { { "Yara File", "yara" }, { "Yara File", "yar" } }, true,
[this](const auto &path) {
this->m_rules.push_back({ path.filename(), path });
});
}
ImGui::SameLine();