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

ui: Added global running tasks progress bar

This commit is contained in:
WerWolv 2021-12-16 23:48:52 +01:00
parent 677036fb9c
commit 891cc42f08
18 changed files with 193 additions and 29 deletions

View File

@ -86,4 +86,6 @@ namespace ImGui {
void StyleCustomColorsDark();
void StyleCustomColorsLight();
void StyleCustomColorsClassic();
void SmallProgressBar(float fraction, float yOffset = 0.0F);
}

View File

@ -492,4 +492,27 @@ namespace ImGui {
return pressed;
}
void SmallProgressBar(float fraction, float yOffset) {
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems)
return;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
ImVec2 pos = window->DC.CursorPos + ImVec2(0, yOffset);
ImVec2 size = CalcItemSize(ImVec2(100, 5), 100, g.FontSize + style.FramePadding.y * 2.0f);
ImRect bb(pos, pos + size);
ItemSize(size, 0);
if (!ItemAdd(bb, 0))
return;
// Render
fraction = ImSaturate(fraction);
RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
bb.Expand(ImVec2(-style.FrameBorderSize, -style.FrameBorderSize));
const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y);
RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding);
}
}

View File

@ -31,7 +31,6 @@ namespace hex::plugin::builtin {
std::array<ImU64, 256> m_valueCounts = { 0 };
bool m_analyzing = false;
std::atomic<u64> m_bytesAnalyzed;
std::pair<u64, u64> m_analyzedRegion = { 0, 0 };

View File

@ -741,9 +741,12 @@ namespace hex::plugin::builtin {
}
size_t fileSize = file.getSize();
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.shredder.shredding", fileSize);
for (const auto &pattern : overwritePattern) {
for (u64 offset = 0; offset < fileSize; offset += 3) {
file.write(pattern.data(), std::min<u64>(pattern.size(), fileSize - offset));
task.update(offset);
}
file.flush();
@ -851,8 +854,11 @@ namespace hex::plugin::builtin {
return;
}
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.splitter.splitting", file.getSize());
u32 index = 1;
for (u64 offset = 0; offset < file.getSize(); offset += splitSize) {
task.update(offset);
File partFile(baseOutputPath + hex::format(".{:05}", index), File::Mode::Create);
if (!partFile.isValid()) {
@ -978,9 +984,14 @@ namespace hex::plugin::builtin {
return;
}
for (const auto &file : files) {
File input(file, File::Mode::Read);
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.combiner.combining", files.size());
u64 fileIndex = 0;
for (const auto &file : files) {
task.update(fileIndex);
fileIndex++;
File input(file, File::Mode::Read);
if (!input.isValid()) {
View::showErrorPopup(hex::format("hex.builtin.tools.file_tools.combiner.open_input"_lang, std::filesystem::path(file).filename().string()));
return;

View File

@ -9,6 +9,8 @@
#include <imgui_internal.h>
#include <imgui_imhex_extensions.h>
#include <atomic>
namespace hex::plugin::builtin {
void addFooterItems() {
@ -20,12 +22,43 @@ namespace hex::plugin::builtin {
}
ContentRegistry::Interface::addFooterItem([] {
static float framerate = 0;
if (ImGui::HasSecondPassed()) {
framerate = 1.0F / ImGui::GetIO().DeltaTime;
}
ImGui::TextUnformatted(hex::format("FPS {0:2}.{1:02}", u32(framerate), u32(framerate * 100) % 100).c_str());
});
ContentRegistry::Interface::addFooterItem([] {
size_t taskCount = 0;
double taskProgress = 0.0;
std::string taskName;
{
std::scoped_lock lock(SharedData::tasksMutex);
taskCount = SharedData::runningTasks.size();
if (taskCount > 0) {
taskProgress = SharedData::runningTasks.front()->getProgress();
taskName = SharedData::runningTasks.front()->getName();
}
}
if (taskCount > 0) {
if (taskCount > 0)
ImGui::TextSpinner(hex::format("({})", taskCount).c_str());
else
ImGui::TextSpinner("");
ImGui::SameLine();
ImGui::SmallProgressBar(taskProgress, (ImGui::GetCurrentWindow()->MenuBarHeight() - 10 * SharedData::globalScale) / 2.0);
ImGui::InfoTooltip(taskName.c_str());
}
});
}

View File

@ -66,7 +66,12 @@ namespace hex::plugin::builtin {
auto provider = ImHexApi::Provider::get();
std::vector<u8> buffer(2048, 0x00);
for (u64 address = 0; address < (this->m_codeRegion[1] - this->m_codeRegion[0] + 1); address += 2048) {
size_t size = (this->m_codeRegion[1] - this->m_codeRegion[0] + 1);
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.disassembler.disassembling", size);
for (u64 address = 0; address < size; address += 2048) {
task.update(address);
size_t bufferSize = std::min(u64(2048), (this->m_codeRegion[1] - this->m_codeRegion[0] + 1) - address);
provider->read(this->m_codeRegion[0] + address, buffer.data(), bufferSize);

View File

@ -71,8 +71,19 @@ namespace hex::plugin::builtin {
std::thread([this]{
auto provider = ImHexApi::Provider::get();
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.information.analyzing", provider->getSize());
this->m_analyzedRegion = { provider->getBaseAddress(), provider->getBaseAddress() + provider->getSize() };
{
magic::compile();
this->m_fileDescription = magic::getDescription(provider);
this->m_mimeType = magic::getMIMEType(provider);
}
this->m_dataValid = true;
{
this->m_blockSize = std::max<u32>(std::ceil(provider->getSize() / 2048.0F), 256);
std::vector<u8> buffer(this->m_blockSize, 0x00);
@ -90,22 +101,13 @@ namespace hex::plugin::builtin {
}
this->m_blockEntropy.push_back(calculateEntropy(blockValueCounts, this->m_blockSize));
this->m_bytesAnalyzed = i;
task.update(i);
}
this->m_averageEntropy = calculateEntropy(this->m_valueCounts, provider->getSize());
this->m_highestBlockEntropy = *std::max_element(this->m_blockEntropy.begin(), this->m_blockEntropy.end());
}
{
magic::compile();
this->m_fileDescription = magic::getDescription(provider);
this->m_mimeType = magic::getMIMEType(provider);
this->m_dataValid = true;
}
this->m_analyzing = false;
}).detach();
}
@ -127,10 +129,8 @@ namespace hex::plugin::builtin {
if (this->m_analyzing) {
ImGui::TextSpinner("hex.builtin.view.information.analyzing"_lang);
ImGui::ProgressBar(this->m_bytesAnalyzed / static_cast<double>(provider->getSize()));
} else {
ImGui::NewLine();
ImGui::NewLine();
}
ImGui::NewLine();

View File

@ -384,6 +384,8 @@ namespace hex::plugin::builtin {
}
void ViewPatternEditor::drawAlwaysVisible() {
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
if (ImGui::BeginPopupModal("hex.builtin.view.pattern_editor.accept_pattern"_lang, &this->m_acceptPatternWindowOpen, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextWrapped("%s", static_cast<const char *>("hex.builtin.view.pattern_editor.accept_pattern.desc"_lang));
@ -423,6 +425,7 @@ namespace hex::plugin::builtin {
}
bool opened = true;
ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F));
if (ImGui::BeginPopupModal("hex.builtin.view.pattern_editor.menu.file.load_pattern"_lang, &opened, ImGuiWindowFlags_AlwaysAutoResize)) {
if (ImGui::BeginListBox("##patterns", ImVec2(-FLT_MIN, 0))) {

View File

@ -65,16 +65,19 @@ namespace hex::plugin::builtin {
std::thread([this] {
auto provider = ImHexApi::Provider::get();
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.strings.searching", provider->getActualSize());
std::vector<u8> buffer(1024, 0x00);
u32 foundCharacters = 0;
for (u64 offset = 0; offset < provider->getSize(); offset += buffer.size()) {
size_t readSize = std::min(u64(buffer.size()), provider->getSize() - offset);
for (u64 offset = 0; offset < provider->getActualSize(); offset += buffer.size()) {
task.update(offset);
size_t readSize = std::min(u64(buffer.size()), provider->getActualSize() - offset);
provider->read(offset + provider->getBaseAddress(), buffer.data(), readSize);
for (u32 i = 0; i < readSize; i++) {
if (buffer[i] >= ' ' && buffer[i] <= '~' && offset < provider->getSize() - 1)
if (buffer[i] >= ' ' && buffer[i] <= '~' && offset < provider->getActualSize() - 1)
foundCharacters++;
else {
if (foundCharacters >= this->m_minimumLength) {

View File

@ -144,6 +144,10 @@ namespace hex::plugin::builtin {
this->m_matching = true;
std::thread([this] {
if (!ImHexApi::Provider::isValid()) return;
auto provider = ImHexApi::Provider::get();
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.yara.matching", provider->getActualSize());
YR_COMPILER *compiler = nullptr;
yr_compiler_create(&compiler);
@ -192,11 +196,13 @@ namespace hex::plugin::builtin {
YR_MEMORY_BLOCK_ITERATOR iterator;
struct ScanContext {
Task *task;
std::vector<u8> buffer;
YR_MEMORY_BLOCK currBlock;
};
ScanContext context;
context.task = &task;
context.currBlock.base = 0;
context.currBlock.fetch_data = [](auto *block) -> const u8* {
auto &context = *static_cast<ScanContext*>(block->context);
@ -237,6 +243,7 @@ namespace hex::plugin::builtin {
context.currBlock.base = address;
context.currBlock.size = ImHexApi::Provider::get()->getActualSize() - address;
context.currBlock.context = &context;
context.task->update(address);
if (context.currBlock.size == 0) return nullptr;

View File

@ -92,6 +92,7 @@ set(LIBIMHEX_SOURCES
source/api/event.cpp
source/api/imhex_api.cpp
source/api/content_registry.cpp
source/api/task.cpp
source/data_processor/attribute.cpp
source/data_processor/link.cpp

View File

@ -7,6 +7,7 @@
#include <string>
#include <hex/helpers/concepts.hpp>
#include <hex/api/task.hpp>
namespace hex {
@ -15,7 +16,6 @@ namespace hex {
namespace ImHexApi {
namespace Common {
void sayHello();
void closeImHex(bool noQuestions = false);
void restartImHex();
@ -55,6 +55,12 @@ namespace hex {
};
namespace Tasks {
Task createTask(const std::string &unlocalizedName, u64 maxValue);
}
};
}

View File

@ -0,0 +1,28 @@
#pragma once
#include <hex.hpp>
#include <string>
namespace hex {
class Task {
public:
Task(const std::string& unlocalizedName, u64 maxValue);
~Task();
void update(u64 currValue);
void finish();
[[nodiscard]]
double getProgress() const;
[[nodiscard]]
const std::string& getName() const;
private:
std::string m_name;
u64 m_maxValue, m_currValue;
};
}

View File

@ -5,10 +5,12 @@
#include <list>
#include <map>
#include <memory>
#include <mutex>
#include <vector>
#include <hex/api/content_registry.hpp>
#include <hex/api/imhex_api.hpp>
#include <hex/api/task.hpp>
#include <hex/views/view.hpp>
#include <imgui.h>
@ -77,6 +79,9 @@ namespace hex {
static std::vector<ContentRegistry::Interface::DrawCallback> footerItems;
static std::vector<ContentRegistry::Interface::DrawCallback> toolbarItems;
static std::mutex tasksMutex;
static std::list<Task*> runningTasks;
static std::vector<std::string> providerNames;
static std::vector<ContentRegistry::DataProcessorNode::impl::Entry> dataProcessorNodes;

View File

@ -9,10 +9,6 @@
namespace hex {
void ImHexApi::Common::sayHello() {
log::warn("Hello!");
}
void ImHexApi::Common::closeImHex(bool noQuestions) {
EventManager::post<RequestCloseImHex>(noQuestions);
}
@ -85,4 +81,9 @@ namespace hex {
delete provider;
}
Task ImHexApi::Tasks::createTask(const std::string &unlocalizedName, u64 maxValue) {
return Task(unlocalizedName, maxValue);
}
}

View File

@ -0,0 +1,32 @@
#include <hex/api/task.hpp>
#include <hex/helpers/shared_data.hpp>
namespace hex {
Task::Task(const std::string& unlocalizedName, u64 maxValue) : m_name(LangEntry(unlocalizedName)), m_maxValue(maxValue), m_currValue(0) {
SharedData::runningTasks.push_back(this);
}
Task::~Task() {
this->finish();
}
void Task::finish() {
SharedData::runningTasks.remove(this);
}
void Task::update(u64 currValue) {
if (this->m_currValue < this->m_maxValue)
this->m_currValue = currValue;
}
double Task::getProgress() const {
return static_cast<double>(this->m_currValue) / static_cast<double>(this->m_maxValue);
}
const std::string& Task::getName() const {
return this->m_name;
}
}

View File

@ -29,6 +29,9 @@ namespace hex {
std::vector<ContentRegistry::Interface::DrawCallback> SharedData::footerItems;
std::vector<ContentRegistry::Interface::DrawCallback> SharedData::toolbarItems;
std::mutex SharedData::tasksMutex;
std::list<Task*> SharedData::runningTasks;
std::vector<std::string> SharedData::providerNames;
std::vector<ContentRegistry::DataProcessorNode::impl::Entry> SharedData::dataProcessorNodes;

View File

@ -279,15 +279,17 @@ namespace hex {
}
void Window::loop() {
double timeout;
this->m_lastFrameTime = glfwGetTime();
while (!glfwWindowShouldClose(this->m_window)) {
if (!glfwGetWindowAttrib(this->m_window, GLFW_VISIBLE) || glfwGetWindowAttrib(this->m_window, GLFW_ICONIFIED))
if (!glfwGetWindowAttrib(this->m_window, GLFW_VISIBLE) || glfwGetWindowAttrib(this->m_window, GLFW_ICONIFIED)) {
glfwWaitEvents();
else
timeout = (1.0 / 5.0) - (glfwGetTime() - this->m_lastFrameTime);
} else {
double timeout = (1.0 / 5.0) - (glfwGetTime() - this->m_lastFrameTime);
timeout = timeout > 0 ? timeout : 0;
glfwWaitEventsTimeout(ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId) ? 0 : timeout);
glfwWaitEventsTimeout(ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId) || !SharedData::runningTasks.empty() ? 0 : timeout);
}
this->frameBegin();
this->frame();