feat: Added filtering to Process Memory Provider
This commit is contained in:
parent
ff9048fcf0
commit
763196f0cc
@ -48,7 +48,7 @@ namespace ImGui {
|
||||
return this->m_textureId != nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr operator ImTextureID() {
|
||||
[[nodiscard]] constexpr operator ImTextureID() const noexcept {
|
||||
return this->m_textureId;
|
||||
}
|
||||
|
||||
|
62
lib/libimhex/include/hex/ui/widgets.hpp
Normal file
62
lib/libimhex/include/hex/ui/widgets.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <atomic>
|
||||
|
||||
#include <hex/api/task.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
|
||||
namespace hex::ui {
|
||||
|
||||
template<typename T>
|
||||
class SearchableWidget {
|
||||
public:
|
||||
SearchableWidget(const std::function<bool(const std::string&, const T&)> &comparator) : m_comparator(comparator) {
|
||||
|
||||
}
|
||||
|
||||
const std::vector<const T*> &draw(const auto &entries) {
|
||||
if (this->m_filteredEntries.empty() && this->m_searchBuffer.empty()) {
|
||||
for (auto &entry : entries)
|
||||
this->m_filteredEntries.push_back(&entry);
|
||||
}
|
||||
|
||||
if (ImGui::InputText("##search", this->m_searchBuffer)) {
|
||||
this->m_pendingUpdate = true;
|
||||
}
|
||||
|
||||
if (this->m_pendingUpdate && !this->m_updateTask.isRunning()) {
|
||||
this->m_pendingUpdate = false;
|
||||
this->m_filteredEntries.clear();
|
||||
this->m_filteredEntries.reserve(entries.size());
|
||||
|
||||
this->m_updateTask = TaskManager::createBackgroundTask("Searching", [this, &entries, searchBuffer = this->m_searchBuffer](Task&) {
|
||||
for (auto &entry : entries) {
|
||||
if (searchBuffer.empty() || this->m_comparator(searchBuffer, entry))
|
||||
this->m_filteredEntries.push_back(&entry);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return this->m_filteredEntries;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
this->m_filteredEntries.clear();
|
||||
}
|
||||
private:
|
||||
std::atomic<bool> m_pendingUpdate = false;
|
||||
TaskHolder m_updateTask;
|
||||
|
||||
std::string m_searchBuffer;
|
||||
std::vector<const T*> m_filteredEntries;
|
||||
std::function<bool(const std::string&, const T&)> m_comparator;
|
||||
};
|
||||
|
||||
}
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <imgui.h>
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
#include <hex/ui/widgets.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <mutex>
|
||||
@ -81,9 +82,15 @@ namespace hex::plugin::windows {
|
||||
};
|
||||
|
||||
std::vector<Process> m_processes;
|
||||
Process *m_selectedProcess = nullptr;
|
||||
const Process *m_selectedProcess = nullptr;
|
||||
|
||||
std::set<MemoryRegion> m_memoryRegions;
|
||||
ui::SearchableWidget<Process> m_processSearchWidget = ui::SearchableWidget<Process>([](const std::string &search, const Process &process) {
|
||||
return process.name.contains(search);
|
||||
});
|
||||
ui::SearchableWidget<MemoryRegion> m_regionSearchWidget = ui::SearchableWidget<MemoryRegion>([](const std::string &search, const MemoryRegion &memoryRegion) {
|
||||
return memoryRegion.name.contains(search);
|
||||
});
|
||||
|
||||
HANDLE m_processHandle = nullptr;
|
||||
|
||||
|
@ -127,7 +127,10 @@ namespace hex::plugin::windows {
|
||||
if (this->m_enumerationFailed) {
|
||||
ImGui::TextUnformatted("hex.windows.provider.process_memory.enumeration_failed"_lang);
|
||||
} else {
|
||||
if (ImGui::BeginTable("##process_table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY, ImVec2(0, 500_scaled))) {
|
||||
ImGui::PushItemWidth(350_scaled);
|
||||
const auto &filtered = this->m_processSearchWidget.draw(this->m_processes);
|
||||
ImGui::PopItemWidth();
|
||||
if (ImGui::BeginTable("##process_table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY, ImVec2(350_scaled, 500_scaled))) {
|
||||
ImGui::TableSetupColumn("##icon");
|
||||
ImGui::TableSetupColumn("hex.windows.provider.process_memory.process_id"_lang);
|
||||
ImGui::TableSetupColumn("hex.windows.provider.process_memory.process_name"_lang);
|
||||
@ -135,19 +138,19 @@ namespace hex::plugin::windows {
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (auto &process : this->m_processes) {
|
||||
ImGui::PushID(process.id);
|
||||
for (auto &process : filtered) {
|
||||
ImGui::PushID(process);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Image(process.icon, process.icon.getSize());
|
||||
ImGui::Image(process->icon, process->icon.getSize());
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d", process.id);
|
||||
ImGui::Text("%d", process->id);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Selectable(process.name.c_str(), this->m_selectedProcess != nullptr && process.id == this->m_selectedProcess->id, ImGuiSelectableFlags_SpanAllColumns, ImVec2(0, process.icon.getSize().y)))
|
||||
this->m_selectedProcess = &process;
|
||||
if (ImGui::Selectable(process->name.c_str(), this->m_selectedProcess != nullptr && process->id == this->m_selectedProcess->id, ImGuiSelectableFlags_SpanAllColumns, ImVec2(0, process->icon.getSize().y)))
|
||||
this->m_selectedProcess = process;
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
@ -160,7 +163,12 @@ namespace hex::plugin::windows {
|
||||
|
||||
void ProcessMemoryProvider::drawInterface() {
|
||||
ImGui::Header("hex.windows.provider.process_memory.memory_regions"_lang, true);
|
||||
if (ImGui::BeginTable("##module_table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY, ImVec2(0, 400_scaled))) {
|
||||
|
||||
auto availableX = ImGui::GetContentRegionAvail().x;
|
||||
ImGui::PushItemWidth(availableX);
|
||||
const auto &filtered = this->m_regionSearchWidget.draw(this->m_memoryRegions);
|
||||
ImGui::PopItemWidth();
|
||||
if (ImGui::BeginTable("##module_table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY, ImVec2(availableX, 400_scaled))) {
|
||||
ImGui::TableSetupColumn("hex.builtin.common.region"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.common.size"_lang);
|
||||
ImGui::TableSetupColumn("hex.builtin.common.name"_lang);
|
||||
@ -168,20 +176,20 @@ namespace hex::plugin::windows {
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (auto &memoryRegion : this->m_memoryRegions) {
|
||||
ImGui::PushID(memoryRegion.region.getStartAddress());
|
||||
for (auto &memoryRegion : filtered) {
|
||||
ImGui::PushID(memoryRegion->region.getStartAddress());
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("0x%016llX - 0x%016llX", memoryRegion.region.getStartAddress(), memoryRegion.region.getEndAddress());
|
||||
ImGui::Text("0x%016llX - 0x%016llX", memoryRegion->region.getStartAddress(), memoryRegion->region.getEndAddress());
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(hex::toByteString(memoryRegion.region.getSize()).c_str());
|
||||
ImGui::TextUnformatted(hex::toByteString(memoryRegion->region.getSize()).c_str());
|
||||
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Selectable(memoryRegion.name.c_str(), false, ImGuiSelectableFlags_SpanAllColumns))
|
||||
ImHexApi::HexEditor::setSelection(memoryRegion.region);
|
||||
if (ImGui::Selectable(memoryRegion->name.c_str(), false, ImGuiSelectableFlags_SpanAllColumns))
|
||||
ImHexApi::HexEditor::setSelection(memoryRegion->region);
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user