1
0
mirror of synced 2024-12-01 02:37:18 +01:00

impr: Make data information view have per-provider state

This commit is contained in:
WerWolv 2024-01-25 22:49:56 +01:00
parent 9c25a1609e
commit 919110b024
5 changed files with 166 additions and 127 deletions

View File

@ -210,7 +210,7 @@ namespace hex {
EVENT_DEF(EventImHexStartupFinished); EVENT_DEF(EventImHexStartupFinished);
EVENT_DEF(EventFileLoaded, std::fs::path); EVENT_DEF(EventFileLoaded, std::fs::path);
EVENT_DEF(EventDataChanged); EVENT_DEF(EventDataChanged, prv::Provider *);
EVENT_DEF(EventHighlightingChanged); EVENT_DEF(EventHighlightingChanged);
EVENT_DEF(EventWindowClosing, GLFWwindow *); EVENT_DEF(EventWindowClosing, GLFWwindow *);
EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion); EVENT_DEF(EventRegionSelected, ImHexApi::HexEditor::ProviderRegion);

View File

@ -2,12 +2,12 @@
#include <hex.hpp> #include <hex.hpp>
#include <hex/api/localization_manager.hpp> #include <hex/api/localization_manager.hpp>
#include <hex/api/event_manager.hpp>
#include <hex/providers/undo_redo/operations/operation.hpp> #include <hex/providers/undo_redo/operations/operation.hpp>
#include <map> #include <map>
#include <memory> #include <memory>
#include <mutex>
#include <vector> #include <vector>
namespace hex::prv { namespace hex::prv {
@ -33,6 +33,7 @@ namespace hex::prv::undo {
template<std::derived_from<Operation> T> template<std::derived_from<Operation> T>
bool add(auto && ... args) { bool add(auto && ... args) {
EventDataChanged::post(m_provider);
return this->add(std::make_unique<T>(std::forward<decltype(args)>(args)...)); return this->add(std::make_unique<T>(std::forward<decltype(args)>(args)...));
} }

View File

@ -18,38 +18,47 @@ namespace hex::plugin::builtin {
void drawContent() override; void drawContent() override;
private: private:
bool m_dataValid = false; struct AnalysisData {
u32 m_blockSize = 0; AnalysisData() = default;
double m_averageEntropy = -1.0; AnalysisData(const AnalysisData&) = default;
double m_highestBlockEntropy = -1.0; TaskHolder analyzerTask;
u64 m_highestBlockEntropyAddress = 0x00;
double m_lowestBlockEntropy = -1.0;
u64 m_lowestBlockEntropyAddress = 0x00;
double m_plainTextCharacterPercentage = -1.0; bool dataValid = false;
u32 blockSize = 0;
double averageEntropy = -1.0;
TaskHolder m_analyzerTask; double highestBlockEntropy = -1.0;
u64 highestBlockEntropyAddress = 0x00;
double lowestBlockEntropy = -1.0;
u64 lowestBlockEntropyAddress = 0x00;
Region m_analysisRegion = { 0, 0 }; double plainTextCharacterPercentage = -1.0;
Region m_analyzedRegion = { 0, 0 };
prv::Provider *m_analyzedProvider = nullptr;
std::string m_dataDescription; Region analysisRegion = { 0, 0 };
std::string m_dataMimeType; Region analyzedRegion = { 0, 0 };
std::string m_dataAppleCreatorType; prv::Provider *analyzedProvider = nullptr;
std::string m_dataExtensions;
std::string dataDescription;
std::string dataMimeType;
std::string dataAppleCreatorType;
std::string dataExtensions;
std::shared_ptr<DiagramDigram> digram;
std::shared_ptr<DiagramLayeredDistribution> layeredDistribution;
std::shared_ptr<DiagramByteDistribution> byteDistribution;
std::shared_ptr<DiagramByteTypesDistribution> byteTypesDistribution;
std::shared_ptr<DiagramChunkBasedEntropyAnalysis> chunkBasedEntropy;
u32 inputChunkSize = 0;
ui::RegionType selectionType = ui::RegionType::EntireData;
};
PerProvider<AnalysisData> m_analysis;
DiagramDigram m_digram;
DiagramLayeredDistribution m_layeredDistribution;
DiagramByteDistribution m_byteDistribution;
DiagramByteTypesDistribution m_byteTypesDistribution;
DiagramChunkBasedEntropyAnalysis m_chunkBasedEntropy;
void analyze(); void analyze();
u32 m_inputChunkSize = 0;
ui::RegionType m_selectionType = ui::RegionType::EntireData;
}; };
} }

View File

@ -388,8 +388,8 @@ namespace hex::plugin::builtin {
m_updateNodePositions = true; m_updateNodePositions = true;
}); });
EventDataChanged::subscribe(this, [this] { EventDataChanged::subscribe(this, [this](prv::Provider *provider) {
ViewDataProcessor::processNodes(*m_workspaceStack->back()); ViewDataProcessor::processNodes(*m_workspaceStack.get(provider).back());
}); });
/* Import Nodes */ /* Import Nodes */

View File

@ -21,32 +21,29 @@ namespace hex::plugin::builtin {
using namespace hex::literals; using namespace hex::literals;
ViewInformation::ViewInformation() : View::Window("hex.builtin.view.information.name", ICON_VS_GRAPH_LINE) { ViewInformation::ViewInformation() : View::Window("hex.builtin.view.information.name", ICON_VS_GRAPH_LINE) {
EventDataChanged::subscribe(this, [this] { EventDataChanged::subscribe(this, [this](prv::Provider *provider) {
m_dataValid = false; auto &analysis = m_analysis.get(provider);
m_plainTextCharacterPercentage = -1.0;
m_averageEntropy = -1.0; analysis.dataValid = false;
m_highestBlockEntropy = -1.0; analysis.plainTextCharacterPercentage = -1.0;
m_blockSize = 0; analysis.averageEntropy = -1.0;
m_dataMimeType.clear(); analysis.highestBlockEntropy = -1.0;
m_dataDescription.clear(); analysis.blockSize = 0;
m_dataAppleCreatorType.clear(); analysis.dataMimeType.clear();
m_dataExtensions.clear(); analysis.dataDescription.clear();
m_analyzedRegion = { 0, 0 }; analysis.dataAppleCreatorType.clear();
analysis.dataExtensions.clear();
analysis.analyzedRegion = { 0, 0 };
}); });
EventRegionSelected::subscribe(this, [this](Region region) { EventRegionSelected::subscribe(this, [this](ImHexApi::HexEditor::ProviderRegion region) {
auto &analysis = m_analysis.get(region.getProvider());
// Set the position of the diagram relative to the place where // Set the position of the diagram relative to the place where
// the user clicked inside the hex editor view // the user clicked inside the hex editor view
if (m_blockSize != 0) { if (analysis.blockSize != 0) {
m_byteTypesDistribution.setHandlePosition(region.getStartAddress()); analysis.byteTypesDistribution->setHandlePosition(region.getStartAddress());
m_chunkBasedEntropy.setHandlePosition(region.getStartAddress()); analysis.chunkBasedEntropy->setHandlePosition(region.getStartAddress());
}
});
EventProviderDeleted::subscribe(this, [this](const auto *provider) {
if (provider == m_analyzedProvider) {
m_dataValid = false;
m_analyzedProvider = nullptr;
} }
}); });
@ -59,88 +56,118 @@ namespace hex::plugin::builtin {
} }
return false; return false;
});
m_analysis.setOnCreateCallback([](prv::Provider *provider, AnalysisData &analysis) {
analysis.dataValid = false;
analysis.blockSize = 0;
analysis.averageEntropy = -1.0;
analysis.lowestBlockEntropy = -1.0;
analysis.highestBlockEntropy = -1.0;
analysis.lowestBlockEntropyAddress = 0x00;
analysis.highestBlockEntropyAddress = 0x00;
analysis.plainTextCharacterPercentage = -1.0;
analysis.analysisRegion = { 0, 0 };
analysis.analyzedRegion = { 0, 0 };
analysis.analyzedProvider = provider;
analysis.inputChunkSize = 0;
analysis.selectionType = ui::RegionType::EntireData;
analysis.digram = std::make_shared<DiagramDigram>();
analysis.layeredDistribution = std::make_shared<DiagramLayeredDistribution>();
analysis.byteDistribution = std::make_shared<DiagramByteDistribution>();
analysis.byteTypesDistribution = std::make_shared<DiagramByteTypesDistribution>();
analysis.chunkBasedEntropy = std::make_shared<DiagramChunkBasedEntropyAnalysis>();
}); });
} }
ViewInformation::~ViewInformation() { ViewInformation::~ViewInformation() {
EventDataChanged::unsubscribe(this); EventDataChanged::unsubscribe(this);
EventRegionSelected::unsubscribe(this); EventRegionSelected::unsubscribe(this);
EventProviderDeleted::unsubscribe(this); EventProviderOpened::unsubscribe(this);
} }
void ViewInformation::analyze() { void ViewInformation::analyze() {
AchievementManager::unlockAchievement("hex.builtin.achievement.misc", "hex.builtin.achievement.misc.analyze_file.name"); AchievementManager::unlockAchievement("hex.builtin.achievement.misc", "hex.builtin.achievement.misc.analyze_file.name");
m_analyzerTask = TaskManager::createTask("hex.builtin.view.information.analyzing", 0, [this](auto &task) { auto provider = ImHexApi::Provider::get();
auto provider = ImHexApi::Provider::get();
m_analyzedProvider = provider; m_analysis.get(provider).analyzerTask = TaskManager::createTask("hex.builtin.view.information.analyzing", 0, [this, provider](auto &task) {
auto &analysis = m_analysis.get(provider);
const auto &region = analysis.analysisRegion;
if ((m_analyzedRegion.getStartAddress() >= m_analyzedRegion.getEndAddress()) || (m_analyzedRegion.getEndAddress() > provider->getActualSize())) { analysis.analyzedProvider = provider;
m_analyzedRegion = { provider->getBaseAddress(), provider->getActualSize() };
if ((region.getStartAddress() >= region.getEndAddress()) || (region.getEndAddress() > provider->getActualSize())) {
analysis.analyzedRegion = { provider->getBaseAddress(), provider->getActualSize() };
} }
if (m_inputChunkSize == 0) { if (analysis.inputChunkSize == 0) {
m_inputChunkSize = 256; analysis.inputChunkSize = 256;
} }
task.setMaxValue(m_analyzedRegion.getSize()); task.setMaxValue(analysis.analyzedRegion.getSize());
{ {
magic::compile(); magic::compile();
m_dataDescription = magic::getDescription(provider); analysis.dataDescription = magic::getDescription(provider);
m_dataMimeType = magic::getMIMEType(provider); analysis.dataMimeType = magic::getMIMEType(provider);
m_dataAppleCreatorType = magic::getAppleCreatorType(provider); analysis.dataAppleCreatorType = magic::getAppleCreatorType(provider);
m_dataExtensions = magic::getExtensions(provider); analysis.dataExtensions = magic::getExtensions(provider);
} }
{ {
m_blockSize = std::max<u32>(std::ceil(provider->getActualSize() / 2048.0F), 256); analysis.blockSize = std::max<u32>(std::ceil(provider->getActualSize() / 2048.0F), 256);
m_averageEntropy = -1.0; analysis.averageEntropy = -1.0;
m_highestBlockEntropy = -1.0; analysis.highestBlockEntropy = -1.0;
m_plainTextCharacterPercentage = -1.0; analysis.plainTextCharacterPercentage = -1.0;
// Setup / start each analysis // Setup / start each analysis
m_byteDistribution.reset(); analysis.byteDistribution->reset();
m_digram.reset(m_analysisRegion.getSize()); analysis.digram->reset(region.getSize());
m_layeredDistribution.reset(m_analysisRegion.getSize()); analysis.layeredDistribution->reset(region.getSize());
m_byteTypesDistribution.reset(m_analysisRegion.getStartAddress(), m_analysisRegion.getEndAddress(), provider->getBaseAddress(), provider->getActualSize()); analysis.byteTypesDistribution->reset(region.getStartAddress(), region.getEndAddress(), provider->getBaseAddress(), provider->getActualSize());
m_chunkBasedEntropy.reset(m_inputChunkSize, m_analysisRegion.getStartAddress(), m_analysisRegion.getEndAddress(), analysis.chunkBasedEntropy->reset(analysis.inputChunkSize, region.getStartAddress(), region.getEndAddress(),
provider->getBaseAddress(), provider->getActualSize()); provider->getBaseAddress(), provider->getActualSize());
// Create a handle to the file // Create a handle to the file
auto reader = prv::ProviderReader(provider); auto reader = prv::ProviderReader(provider);
reader.seek(m_analysisRegion.getStartAddress()); reader.seek(region.getStartAddress());
reader.setEndAddress(m_analysisRegion.getEndAddress()); reader.setEndAddress(region.getEndAddress());
m_analyzedRegion = m_analysisRegion; analysis.analyzedRegion = region;
u64 count = 0; u64 count = 0;
// Loop over each byte of the selection and update each analysis // Loop over each byte of the selection and update each analysis
// one byte at a time to process the file only once // one byte at a time to process the file only once
for (u8 byte : reader) { for (u8 byte : reader) {
m_byteDistribution.update(byte); analysis.byteDistribution->update(byte);
m_byteTypesDistribution.update(byte); analysis.byteTypesDistribution->update(byte);
m_chunkBasedEntropy.update(byte); analysis.chunkBasedEntropy->update(byte);
m_layeredDistribution.update(byte); analysis.layeredDistribution->update(byte);
m_digram.update(byte); analysis.digram->update(byte);
++count; ++count;
task.update(count); task.update(count);
} }
m_averageEntropy = m_chunkBasedEntropy.calculateEntropy(m_byteDistribution.get(), m_analyzedRegion.getSize()); analysis.averageEntropy = analysis.chunkBasedEntropy->calculateEntropy(analysis.byteDistribution->get(), analysis.analyzedRegion.getSize());
m_highestBlockEntropy = m_chunkBasedEntropy.getHighestEntropyBlockValue(); analysis.highestBlockEntropy = analysis.chunkBasedEntropy->getHighestEntropyBlockValue();
m_highestBlockEntropyAddress = m_chunkBasedEntropy.getHighestEntropyBlockAddress(); analysis.highestBlockEntropyAddress = analysis.chunkBasedEntropy->getHighestEntropyBlockAddress();
m_lowestBlockEntropy = m_chunkBasedEntropy.getLowestEntropyBlockValue(); analysis.lowestBlockEntropy = analysis.chunkBasedEntropy->getLowestEntropyBlockValue();
m_lowestBlockEntropyAddress = m_chunkBasedEntropy.getLowestEntropyBlockAddress(); analysis.lowestBlockEntropyAddress = analysis.chunkBasedEntropy->getLowestEntropyBlockAddress();
m_plainTextCharacterPercentage = m_byteTypesDistribution.getPlainTextCharacterPercentage(); analysis.plainTextCharacterPercentage = analysis.byteTypesDistribution->getPlainTextCharacterPercentage();
} }
m_dataValid = true; analysis.dataValid = true;
}); });
} }
@ -149,7 +176,9 @@ namespace hex::plugin::builtin {
auto provider = ImHexApi::Provider::get(); auto provider = ImHexApi::Provider::get();
if (ImHexApi::Provider::isValid() && provider->isReadable()) { if (ImHexApi::Provider::isValid() && provider->isReadable()) {
ImGui::BeginDisabled(m_analyzerTask.isRunning()); auto &analysis = m_analysis.get(provider);
ImGui::BeginDisabled(analysis.analyzerTask.isRunning());
ImGuiExt::BeginSubWindow("hex.ui.common.settings"_lang); ImGuiExt::BeginSubWindow("hex.ui.common.settings"_lang);
{ {
if (ImGui::BeginTable("SettingsTable", 2, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingFixedSame, ImVec2(ImGui::GetContentRegionAvail().x, 0))) { if (ImGui::BeginTable("SettingsTable", 2, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingFixedSame, ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
@ -157,10 +186,10 @@ namespace hex::plugin::builtin {
ImGui::TableSetupColumn("Right", ImGuiTableColumnFlags_WidthStretch, 0.5F); ImGui::TableSetupColumn("Right", ImGuiTableColumnFlags_WidthStretch, 0.5F);
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ui::regionSelectionPicker(&m_analysisRegion, provider, &m_selectionType, false); ui::regionSelectionPicker(&analysis.analysisRegion, provider, &analysis.selectionType, false);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::InputHexadecimal("hex.builtin.view.information.block_size"_lang, &m_inputChunkSize); ImGuiExt::InputHexadecimal("hex.builtin.view.information.block_size"_lang, &analysis.inputChunkSize);
ImGui::EndTable(); ImGui::EndTable();
} }
@ -173,13 +202,13 @@ namespace hex::plugin::builtin {
ImGuiExt::EndSubWindow(); ImGuiExt::EndSubWindow();
ImGui::EndDisabled(); ImGui::EndDisabled();
if (m_analyzerTask.isRunning()) { if (analysis.analyzerTask.isRunning()) {
ImGuiExt::TextSpinner("hex.builtin.view.information.analyzing"_lang); ImGuiExt::TextSpinner("hex.builtin.view.information.analyzing"_lang);
} else { } else {
ImGui::NewLine(); ImGui::NewLine();
} }
if (!m_analyzerTask.isRunning() && m_dataValid && m_analyzedProvider != nullptr) { if (!analysis.analyzerTask.isRunning() && analysis.dataValid && analysis.analyzedProvider != nullptr) {
// Provider information // Provider information
ImGuiExt::Header("hex.builtin.view.information.provider_information"_lang, true); ImGuiExt::Header("hex.builtin.view.information.provider_information"_lang, true);
@ -190,7 +219,7 @@ namespace hex::plugin::builtin {
ImGui::TableNextRow(); ImGui::TableNextRow();
for (auto &[name, value] : m_analyzedProvider->getDataDescription()) { for (auto &[name, value] : analysis.analyzedProvider->getDataDescription()) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("{}", name); ImGuiExt::TextFormatted("{}", name);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
@ -200,13 +229,13 @@ namespace hex::plugin::builtin {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.region"_lang); ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.region"_lang);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("0x{:X} - 0x{:X}", m_analyzedRegion.getStartAddress(), m_analyzedRegion.getEndAddress()); ImGuiExt::TextFormatted("0x{:X} - 0x{:X}", analysis.analyzedRegion.getStartAddress(), analysis.analyzedRegion.getEndAddress());
ImGui::EndTable(); ImGui::EndTable();
} }
// Magic information // Magic information
if (!(m_dataDescription.empty() && m_dataMimeType.empty())) { if (!(analysis.dataDescription.empty() && analysis.dataMimeType.empty())) {
ImGuiExt::Header("hex.builtin.view.information.magic"_lang); ImGuiExt::Header("hex.builtin.view.information.magic"_lang);
if (ImGui::BeginTable("magic", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) { if (ImGui::BeginTable("magic", 2, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg)) {
@ -215,46 +244,46 @@ namespace hex::plugin::builtin {
ImGui::TableNextRow(); ImGui::TableNextRow();
if (!m_dataDescription.empty()) { if (!analysis.dataDescription.empty()) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextUnformatted("hex.builtin.view.information.description"_lang); ImGui::TextUnformatted("hex.builtin.view.information.description"_lang);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (m_dataDescription == "data") { if (analysis.dataDescription == "data") {
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{} ({})", "hex.builtin.view.information.octet_stream_text"_lang, m_dataDescription); ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{} ({})", "hex.builtin.view.information.octet_stream_text"_lang, analysis.dataDescription);
} else { } else {
ImGuiExt::TextFormattedWrapped("{}", m_dataDescription); ImGuiExt::TextFormattedWrapped("{}", analysis.dataDescription);
} }
} }
if (!m_dataMimeType.empty()) { if (!analysis.dataMimeType.empty()) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextUnformatted("hex.builtin.view.information.mime"_lang); ImGui::TextUnformatted("hex.builtin.view.information.mime"_lang);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (m_dataMimeType.contains("application/octet-stream")) { if (analysis.dataMimeType.contains("application/octet-stream")) {
ImGuiExt::TextFormatted("{}", m_dataMimeType); ImGuiExt::TextFormatted("{}", analysis.dataMimeType);
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGuiExt::HelpHover("hex.builtin.view.information.octet_stream_warning"_lang); ImGuiExt::HelpHover("hex.builtin.view.information.octet_stream_warning"_lang);
ImGui::PopStyleVar(); ImGui::PopStyleVar();
} else { } else {
ImGuiExt::TextFormatted("{}", m_dataMimeType); ImGuiExt::TextFormatted("{}", analysis.dataMimeType);
} }
} }
if (!m_dataAppleCreatorType.empty()) { if (!analysis.dataAppleCreatorType.empty()) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextUnformatted("hex.builtin.view.information.apple_type"_lang); ImGui::TextUnformatted("hex.builtin.view.information.apple_type"_lang);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("{}", m_dataAppleCreatorType); ImGuiExt::TextFormatted("{}", analysis.dataAppleCreatorType);
} }
if (!m_dataExtensions.empty()) { if (!analysis.dataExtensions.empty()) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TextUnformatted("hex.builtin.view.information.extension"_lang); ImGui::TextUnformatted("hex.builtin.view.information.extension"_lang);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("{}", m_dataExtensions); ImGuiExt::TextFormatted("{}", analysis.dataExtensions);
} }
ImGui::EndTable(); ImGui::EndTable();
@ -264,7 +293,7 @@ namespace hex::plugin::builtin {
} }
// Information analysis // Information analysis
if (m_analyzedRegion.getSize() > 0) { if (analysis.analyzedRegion.getSize() > 0) {
ImGuiExt::Header("hex.builtin.view.information.info_analysis"_lang); ImGuiExt::Header("hex.builtin.view.information.info_analysis"_lang);
@ -273,14 +302,14 @@ namespace hex::plugin::builtin {
// Display byte distribution analysis // Display byte distribution analysis
ImGui::TextUnformatted("hex.builtin.view.information.distribution"_lang); ImGui::TextUnformatted("hex.builtin.view.information.distribution"_lang);
m_byteDistribution.draw( analysis.byteDistribution->draw(
ImVec2(-1, 0), ImVec2(-1, 0),
ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect
); );
// Display byte types distribution analysis // Display byte types distribution analysis
ImGui::TextUnformatted("hex.builtin.view.information.byte_types"_lang); ImGui::TextUnformatted("hex.builtin.view.information.byte_types"_lang);
m_byteTypesDistribution.draw( analysis.byteTypesDistribution->draw(
ImVec2(-1, 0), ImVec2(-1, 0),
ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect, ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect,
true true
@ -288,7 +317,7 @@ namespace hex::plugin::builtin {
// Display chunk-based entropy analysis // Display chunk-based entropy analysis
ImGui::TextUnformatted("hex.builtin.view.information.entropy"_lang); ImGui::TextUnformatted("hex.builtin.view.information.entropy"_lang);
m_chunkBasedEntropy.draw( analysis.chunkBasedEntropy->draw(
ImVec2(-1, 0), ImVec2(-1, 0),
ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect, ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect,
true true
@ -310,15 +339,15 @@ namespace hex::plugin::builtin {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.block_size"_lang); ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.block_size"_lang);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("hex.builtin.view.information.block_size.desc"_lang, m_chunkBasedEntropy.getSize(), m_chunkBasedEntropy.getChunkSize()); ImGuiExt::TextFormatted("hex.builtin.view.information.block_size.desc"_lang, analysis.chunkBasedEntropy->getSize(), analysis.chunkBasedEntropy->getChunkSize());
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.file_entropy"_lang); ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.file_entropy"_lang);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (m_averageEntropy < 0) { if (analysis.averageEntropy < 0) {
ImGui::TextUnformatted("???"); ImGui::TextUnformatted("???");
} else { } else {
auto entropy = std::abs(m_averageEntropy); auto entropy = std::abs(analysis.averageEntropy);
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.1F); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.1F);
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_TableRowBgAlt)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_TableRowBgAlt));
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImColor::HSV(0.3F - (0.3F * entropy), 0.6F, 0.8F, 1.0F).Value); ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImColor::HSV(0.3F - (0.3F * entropy), 0.6F, 0.8F, 1.0F).Value);
@ -330,12 +359,12 @@ namespace hex::plugin::builtin {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.highest_entropy"_lang); ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.highest_entropy"_lang);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("{:.5f} @", m_highestBlockEntropy); ImGuiExt::TextFormatted("{:.5f} @", analysis.highestBlockEntropy);
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
if (ImGui::Button(hex::format("0x{:06X}", m_highestBlockEntropyAddress).c_str())) { if (ImGui::Button(hex::format("0x{:06X}", analysis.highestBlockEntropyAddress).c_str())) {
ImHexApi::HexEditor::setSelection(m_highestBlockEntropyAddress, m_inputChunkSize); ImHexApi::HexEditor::setSelection(analysis.highestBlockEntropyAddress, analysis.inputChunkSize);
} }
ImGui::PopStyleColor(); ImGui::PopStyleColor();
ImGui::PopStyleVar(); ImGui::PopStyleVar();
@ -343,12 +372,12 @@ namespace hex::plugin::builtin {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.lowest_entropy"_lang); ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.lowest_entropy"_lang);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("{:.5f} @", m_lowestBlockEntropy); ImGuiExt::TextFormatted("{:.5f} @", analysis.lowestBlockEntropy);
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
if (ImGui::Button(hex::format("0x{:06X}", m_lowestBlockEntropyAddress).c_str())) { if (ImGui::Button(hex::format("0x{:06X}", analysis.lowestBlockEntropyAddress).c_str())) {
ImHexApi::HexEditor::setSelection(m_lowestBlockEntropyAddress, m_inputChunkSize); ImHexApi::HexEditor::setSelection(analysis.lowestBlockEntropyAddress, analysis.inputChunkSize);
} }
ImGui::PopStyleColor(); ImGui::PopStyleColor();
ImGui::PopStyleVar(); ImGui::PopStyleVar();
@ -356,13 +385,13 @@ namespace hex::plugin::builtin {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.plain_text_percentage"_lang); ImGuiExt::TextFormatted("{}", "hex.builtin.view.information.plain_text_percentage"_lang);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (m_plainTextCharacterPercentage < 0) { if (analysis.plainTextCharacterPercentage < 0) {
ImGui::TextUnformatted("???"); ImGui::TextUnformatted("???");
} else { } else {
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.1F); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.1F);
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_TableRowBgAlt)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_TableRowBgAlt));
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImColor::HSV(0.3F * (m_plainTextCharacterPercentage / 100.0F), 0.8F, 0.6F, 1.0F).Value); ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImColor::HSV(0.3F * (analysis.plainTextCharacterPercentage / 100.0F), 0.8F, 0.6F, 1.0F).Value);
ImGui::ProgressBar(m_plainTextCharacterPercentage / 100.0F, ImVec2(200_scaled, ImGui::GetTextLineHeight())); ImGui::ProgressBar(analysis.plainTextCharacterPercentage / 100.0F, ImVec2(200_scaled, ImGui::GetTextLineHeight()));
ImGui::PopStyleColor(2); ImGui::PopStyleColor(2);
ImGui::PopStyleVar(); ImGui::PopStyleVar();
} }
@ -377,12 +406,12 @@ namespace hex::plugin::builtin {
ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("value", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow(); ImGui::TableNextRow();
if (m_averageEntropy > 0.83 && m_highestBlockEntropy > 0.9) { if (analysis.averageEntropy > 0.83 && analysis.highestBlockEntropy > 0.9) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{}", "hex.builtin.view.information.encrypted"_lang); ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{}", "hex.builtin.view.information.encrypted"_lang);
} }
if (m_plainTextCharacterPercentage > 95) { if (analysis.plainTextCharacterPercentage > 95) {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{}", "hex.builtin.view.information.plain_text"_lang); ImGuiExt::TextFormattedColored(ImVec4(0.92F, 0.25F, 0.2F, 1.0F), "{}", "hex.builtin.view.information.plain_text"_lang);
} }
@ -393,7 +422,7 @@ namespace hex::plugin::builtin {
ImGui::BeginGroup(); ImGui::BeginGroup();
{ {
ImGui::TextUnformatted("hex.builtin.view.information.digram"_lang); ImGui::TextUnformatted("hex.builtin.view.information.digram"_lang);
m_digram.draw(scaled(ImVec2(300, 300))); analysis.digram->draw(scaled(ImVec2(300, 300)));
} }
ImGui::EndGroup(); ImGui::EndGroup();
@ -402,7 +431,7 @@ namespace hex::plugin::builtin {
ImGui::BeginGroup(); ImGui::BeginGroup();
{ {
ImGui::TextUnformatted("hex.builtin.view.information.layered_distribution"_lang); ImGui::TextUnformatted("hex.builtin.view.information.layered_distribution"_lang);
m_layeredDistribution.draw(scaled(ImVec2(300, 300))); analysis.layeredDistribution->draw(scaled(ImVec2(300, 300)));
} }
ImGui::EndGroup(); ImGui::EndGroup();
} }