feat: Add setting to only show data inspector rows matching exact size

#2684
This commit is contained in:
WerWolv
2026-03-13 21:00:06 +01:00
parent 21a94d67c2
commit e668feb807
5 changed files with 45 additions and 25 deletions

View File

@@ -535,7 +535,7 @@ namespace hex::plugin::builtin {
constexpr static auto MaxStringLength = 64;
ContentRegistry::DataInspector::add("hex.builtin.inspector.string", 1,
ContentRegistry::DataInspector::add("hex.builtin.inspector.string", 1, 512,
[](auto buffer, auto endian, auto style) {
std::ignore = buffer;
std::ignore = endian;
@@ -566,7 +566,7 @@ namespace hex::plugin::builtin {
})
);
ContentRegistry::DataInspector::add("hex.builtin.inspector.wstring", sizeof(wchar_t),
ContentRegistry::DataInspector::add("hex.builtin.inspector.wstring", sizeof(wchar_t), 512,
[](auto buffer, auto endian, auto style) {
std::ignore = buffer;
std::ignore = endian;
@@ -612,7 +612,7 @@ namespace hex::plugin::builtin {
})
);
ContentRegistry::DataInspector::add("hex.builtin.inspector.string16", sizeof(char16_t),
ContentRegistry::DataInspector::add("hex.builtin.inspector.string16", sizeof(char16_t), 512,
[](auto buffer, auto endian, auto style) {
std::ignore = buffer;
std::ignore = endian;
@@ -658,7 +658,7 @@ namespace hex::plugin::builtin {
})
);
ContentRegistry::DataInspector::add("hex.builtin.inspector.string32", sizeof(char32_t),
ContentRegistry::DataInspector::add("hex.builtin.inspector.string32", sizeof(char32_t), 512,
[](auto buffer, auto endian, auto style) {
std::ignore = buffer;
std::ignore = endian;
@@ -704,7 +704,7 @@ namespace hex::plugin::builtin {
})
);
ContentRegistry::DataInspector::add("hex.builtin.inspector.custom_encoding", 1, [encodingFile = EncodingFile()](const std::vector<u8> &, std::endian, Style) mutable {
ContentRegistry::DataInspector::add("hex.builtin.inspector.custom_encoding", 1, 512, [encodingFile = EncodingFile()](const std::vector<u8> &, std::endian, Style) mutable {
std::string value, copyValue;
if (encodingFile.valid()) {

View File

@@ -754,6 +754,8 @@ for (const auto &path : m_paths) {
.setTooltip("hex.builtin.setting.general.max_mem_file_size.desc");
ContentRegistry::Settings::add<Widgets::SliderInteger>("hex.builtin.setting.general", "hex.builtin.setting.general.patterns", "hex.builtin.setting.general.pattern_data_max_filter_items", 128, 32, 1024);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "", "hex.builtin.setting.general.data_inspector_exact_size_only", false);
auto suggestPatterns = ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.patterns", "hex.builtin.setting.general.suggest_patterns", true);
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.patterns", "hex.builtin.setting.general.auto_apply_patterns", false).setEnabledCallback([=] {
return static_cast<Widgets::Checkbox&>(suggestPatterns.getWidget()).isChecked();

View File

@@ -26,6 +26,7 @@
namespace hex::plugin::builtin {
static ContentRegistry::Settings::SettingsVariable<bool, "hex.builtin.setting.general", "hex.builtin.setting.general.data_inspector_exact_size_only"> onlyShowExactSizeMatchEntries = false;
using NumberDisplayStyle = ContentRegistry::DataInspector::NumberDisplayStyle;
ViewDataInspector::ViewDataInspector() : View::Window("hex.builtin.view.data_inspector.name", ICON_VS_INSPECT) {
@@ -34,11 +35,10 @@ namespace hex::plugin::builtin {
// Save current selection
if (!ImHexApi::Provider::isValid() || region == Region::Invalid()) {
m_validBytes = 0;
m_selectedProvider = nullptr;
m_selectedRegion = { Region::Invalid(), nullptr };
} else {
m_validBytes = u64((region.getProvider()->getBaseAddress() + region.getProvider()->getActualSize()) - region.address);
m_startAddress = region.address;
m_selectedProvider = region.getProvider();
m_selectedRegion = region;
}
// Invalidate inspector rows
@@ -46,12 +46,12 @@ namespace hex::plugin::builtin {
});
EventDataChanged::subscribe(this, [this](const auto &provider) {
if (provider == m_selectedProvider)
if (provider == m_selectedRegion.getProvider())
m_shouldInvalidate = true;
});
EventProviderClosed::subscribe(this, [this](const auto*) {
m_selectedProvider = nullptr;
m_selectedRegion = { Region::Invalid(), nullptr };
});
ContentRegistry::Settings::onChange("hex.builtin.setting.data_inspector", "hex.builtin.setting.data_inspector.hidden_rows", [this](const ContentRegistry::Settings::SettingsValue &value) {
@@ -101,17 +101,30 @@ namespace hex::plugin::builtin {
void ViewDataInspector::updateInspectorRowsTask() {
m_workData.clear();
if (m_selectedProvider == nullptr)
if (m_selectedRegion.getProvider() == nullptr)
return;
// Decode bytes using registered inspectors
for (auto &entry : ContentRegistry::DataInspector::impl::getEntries()) {
for (const auto &entry : ContentRegistry::DataInspector::impl::getEntries()) {
if (m_validBytes < entry.requiredSize)
continue;
// If the setting is enabled, skip all entries that don't match the exact selection size
if (onlyShowExactSizeMatchEntries) {
const auto selectedBytes = m_selectedRegion.getSize();
if (entry.requiredSize != entry.maxSize) {
if (selectedBytes < entry.requiredSize || selectedBytes > entry.maxSize)
continue;
} else {
if (selectedBytes != entry.requiredSize)
continue;
}
}
// Try to read as many bytes as requested and possible
std::vector<u8> buffer(m_validBytes > entry.maxSize ? entry.maxSize : m_validBytes);
m_selectedProvider->read(m_startAddress, buffer.data(), buffer.size());
m_selectedRegion.getProvider()->read(m_selectedRegion.getStartAddress(), buffer.data(), buffer.size());
preprocessBytes(buffer);
@@ -133,7 +146,7 @@ namespace hex::plugin::builtin {
}
void ViewDataInspector::inspectorReadFunction(u64 offset, u8 *buffer, size_t size) {
m_selectedProvider->read(offset, buffer, size);
m_selectedRegion.getProvider()->read(offset, buffer, size);
preprocessBytes({ buffer, size });
}
@@ -144,11 +157,13 @@ namespace hex::plugin::builtin {
{ "numberDisplayStyle", u128(u64(m_numberDisplayStyle)) }
};
const auto provider = m_selectedRegion.getProvider();
// Setup a new pattern language runtime
ContentRegistry::PatternLanguage::configureRuntime(m_runtime, m_selectedProvider);
ContentRegistry::PatternLanguage::configureRuntime(m_runtime, provider);
// Setup the runtime to read from the selected provider
m_runtime.setDataSource(m_selectedProvider->getBaseAddress(), m_selectedProvider->getActualSize(), [this](u64 offset, u8 *buffer, size_t size) {
m_runtime.setDataSource(provider->getBaseAddress(), provider->getActualSize(), [this](u64 offset, u8 *buffer, size_t size) {
this->inspectorReadFunction(offset, buffer, size);
});
@@ -159,7 +174,7 @@ namespace hex::plugin::builtin {
m_runtime.setDefaultEndian(m_endian);
// Set start address to the selected address
m_runtime.setStartAddress(m_startAddress);
m_runtime.setStartAddress(m_selectedRegion.getStartAddress());
// Loop over all files in the inspectors folder and execute them
for (const auto &folderPath : paths::Inspectors.read()) {
@@ -289,14 +304,16 @@ namespace hex::plugin::builtin {
u64 requiredSize = selectedEntryIt == m_cachedData.end() ? 0x00 : selectedEntryIt->requiredSize;
bool noData = m_selectedProvider == nullptr || !m_selectedProvider->isReadable() || m_validBytes <= 0;
const auto provider = m_selectedRegion.getProvider();
bool noData = provider == nullptr || !provider->isReadable() || m_validBytes <= 0;
ImGui::BeginDisabled(noData || !selection.has_value() || !m_selectedEntryName.has_value());
{
const auto buttonSizeSmall = ImVec2(ImGui::GetTextLineHeightWithSpacing() * 1.5F, 0);
const auto buttonSize = ImVec2((ImGui::GetContentRegionAvail().x / 2) - buttonSizeSmall.x - ImGui::GetStyle().FramePadding.x * 3, 0);
const auto baseAddress = noData ? 0x00 : m_selectedProvider->getBaseAddress();
const auto providerSize = noData ? 0x00 : m_selectedProvider->getActualSize();
const auto baseAddress = noData ? 0x00 : provider->getBaseAddress();
const auto providerSize = noData ? 0x00 : provider->getActualSize();
const auto providerEndAddress = baseAddress + providerSize;
ImGui::BeginDisabled(!selection.has_value() || providerSize < requiredSize || selection->getStartAddress() < baseAddress + requiredSize);
@@ -338,7 +355,7 @@ namespace hex::plugin::builtin {
ImGuiTableColumnFlags_WidthStretch);
if (m_tableEditingModeEnabled)
ImGui::TableSetupColumn("##favorite", ImGuiTableColumnFlags_WidthFixed, ImGui::GetTextLineHeight());
ImGui::TableSetupColumn("##editing", ImGuiTableColumnFlags_WidthFixed, ImGui::GetTextLineHeight());
ImGui::TableHeadersRow();
@@ -476,7 +493,7 @@ namespace hex::plugin::builtin {
}
// Enter editing mode when double-clicking the row
const bool editable = entry.editingFunction.has_value() && m_selectedProvider->isWritable();
const bool editable = entry.editingFunction.has_value() && m_selectedRegion.getProvider()->isWritable();
if (ImGui::IsItemHovered()) {
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && editable) {
entry.editing = true;
@@ -515,7 +532,7 @@ namespace hex::plugin::builtin {
preprocessBytes(*bytes);
// Write those bytes to the selected provider at the current address
m_selectedProvider->write(m_startAddress, bytes->data(), bytes->size());
m_selectedRegion.getProvider()->write(m_selectedRegion.getStartAddress(), bytes->data(), bytes->size());
// Disable editing mode
m_editingValue.clear();