mirror of https://github.com/WerWolv/ImHex
feat: Add keyboard shortcuts to jump to the prev/next differences in diff view (#2445)
Adds keyboard shortcuts (currently `n` and `N`) in the diffing plugin view to jump to the next/prev difference in the list. IMPORTANT NOTE: Depends on changes made in a library submodule. [This PR](https://github.com/WerWolv/libwolv/pull/34) must be accepted first. --------- Co-authored-by: Nik <werwolv98@gmail.com>
This commit is contained in:
parent
fedbce6f9e
commit
3c167c3306
|
|
@ -1 +1 @@
|
||||||
Subproject commit 56f77945fe292a4d00afdb1961f2b7e87a88be4c
|
Subproject commit 52cb24b1842cfc3e9cc681ba67090b0327efb2a3
|
||||||
|
|
@ -1345,7 +1345,8 @@ namespace hex::plugin::builtin {
|
||||||
/* Skip until */
|
/* Skip until */
|
||||||
ContentRegistry::UserInterface::addMenuItemSubMenu({ "hex.builtin.menu.file", "hex.builtin.view.hex_editor.menu.file.skip_until" }, ICON_VS_DEBUG_STEP_OVER, 1610,
|
ContentRegistry::UserInterface::addMenuItemSubMenu({ "hex.builtin.menu.file", "hex.builtin.view.hex_editor.menu.file.skip_until" }, ICON_VS_DEBUG_STEP_OVER, 1610,
|
||||||
[]{},
|
[]{},
|
||||||
canSearchForDifferingByte);
|
canSearchForDifferingByte,
|
||||||
|
this);
|
||||||
|
|
||||||
/* Skip until previous differing byte */
|
/* Skip until previous differing byte */
|
||||||
ContentRegistry::UserInterface::addMenuItem({
|
ContentRegistry::UserInterface::addMenuItem({
|
||||||
|
|
@ -1384,7 +1385,8 @@ namespace hex::plugin::builtin {
|
||||||
ui::ToastInfo::open("hex.builtin.view.hex_editor.menu.file.skip_until.beginning_reached"_lang);
|
ui::ToastInfo::open("hex.builtin.view.hex_editor.menu.file.skip_until.beginning_reached"_lang);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
canSearchForDifferingByte);
|
canSearchForDifferingByte,
|
||||||
|
this);
|
||||||
|
|
||||||
/* Skip until next differing byte */
|
/* Skip until next differing byte */
|
||||||
ContentRegistry::UserInterface::addMenuItem({
|
ContentRegistry::UserInterface::addMenuItem({
|
||||||
|
|
@ -1423,7 +1425,8 @@ namespace hex::plugin::builtin {
|
||||||
ui::ToastInfo::open("hex.builtin.view.hex_editor.menu.file.skip_until.end_reached"_lang);
|
ui::ToastInfo::open("hex.builtin.view.hex_editor.menu.file.skip_until.end_reached"_lang);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
canSearchForDifferingByte);
|
canSearchForDifferingByte,
|
||||||
|
this);
|
||||||
|
|
||||||
|
|
||||||
ContentRegistry::UserInterface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1100, this);
|
ContentRegistry::UserInterface::addMenuItemSeparator({ "hex.builtin.menu.edit" }, 1100, this);
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ namespace hex::plugin::diffing {
|
||||||
std::function<std::optional<color_t>(u64, const u8*, size_t)> createCompareFunction(size_t otherIndex) const;
|
std::function<std::optional<color_t>(u64, const u8*, size_t)> createCompareFunction(size_t otherIndex) const;
|
||||||
void analyze(prv::Provider *providerA, prv::Provider *providerB);
|
void analyze(prv::Provider *providerA, prv::Provider *providerB);
|
||||||
|
|
||||||
|
void registerMenuItems();
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -45,6 +47,9 @@ namespace hex::plugin::diffing {
|
||||||
std::atomic<bool> m_analyzed = false;
|
std::atomic<bool> m_analyzed = false;
|
||||||
std::atomic<bool> m_analysisInterrupted = false;
|
std::atomic<bool> m_analysisInterrupted = false;
|
||||||
ContentRegistry::Diffing::Algorithm *m_algorithm = nullptr;
|
ContentRegistry::Diffing::Algorithm *m_algorithm = nullptr;
|
||||||
|
|
||||||
|
u64 m_selectedAddress = 0;
|
||||||
|
prv::Provider *m_selectedProvider = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,5 +14,10 @@
|
||||||
"hex.diffing.view.diff.algorithm": "Diffing Algorithm",
|
"hex.diffing.view.diff.algorithm": "Diffing Algorithm",
|
||||||
"hex.diffing.view.diff.settings": "No settings available",
|
"hex.diffing.view.diff.settings": "No settings available",
|
||||||
"hex.diffing.view.diff.settings.no_settings": "No settings available",
|
"hex.diffing.view.diff.settings.no_settings": "No settings available",
|
||||||
"hex.diffing.view.diff.task.diffing": "Diffing data..."
|
"hex.diffing.view.diff.task.diffing": "Diffing data...",
|
||||||
}
|
"hex.diffing.view.diff.menu.file.jumping": "Jump Between Differences",
|
||||||
|
"hex.diffing.view.diff.menu.file.jumping.prev_diff": "Jump to Previous Difference",
|
||||||
|
"hex.diffing.view.diff.menu.file.jumping.next_diff": "Jump to Next Difference",
|
||||||
|
"hex.diffing.view.diff.jumping.beginning_reached": "No more differences till the beginning of the file",
|
||||||
|
"hex.diffing.view.diff.jumping.end_reached": "No more differences till the end of the file"
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
#include "content/views/view_diff.hpp"
|
#include "content/views/view_diff.hpp"
|
||||||
|
#include <toasts/toast_notification.hpp>
|
||||||
|
|
||||||
#include <hex/api/imhex_api/provider.hpp>
|
#include <hex/api/imhex_api/provider.hpp>
|
||||||
#include <hex/api/events/requests_gui.hpp>
|
#include <hex/api/events/requests_gui.hpp>
|
||||||
|
#include <hex/api/content_registry/user_interface.hpp>
|
||||||
|
|
||||||
#include <hex/helpers/fmt.hpp>
|
#include <hex/helpers/fmt.hpp>
|
||||||
#include <hex/providers/buffered_reader.hpp>
|
#include <hex/providers/buffered_reader.hpp>
|
||||||
|
|
||||||
#include <fonts/vscode_icons.hpp>
|
#include <fonts/vscode_icons.hpp>
|
||||||
|
#include <fonts/tabler_icons.hpp>
|
||||||
#include <wolv/utils/guards.hpp>
|
#include <wolv/utils/guards.hpp>
|
||||||
|
|
||||||
namespace hex::plugin::diffing {
|
namespace hex::plugin::diffing {
|
||||||
|
|
@ -22,14 +25,28 @@ namespace hex::plugin::diffing {
|
||||||
m_analysisInterrupted = m_analyzed = false;
|
m_analysisInterrupted = m_analyzed = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle region selection
|
||||||
|
EventRegionSelected::subscribe(this, [this](const auto ®ion) {
|
||||||
|
// Save current selection
|
||||||
|
if (!ImHexApi::Provider::isValid() || region == Region::Invalid()) {
|
||||||
|
m_selectedProvider = nullptr;
|
||||||
|
} else {
|
||||||
|
m_selectedAddress = region.address;
|
||||||
|
m_selectedProvider = region.getProvider();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Set the background highlight callbacks for the two hex editor columns
|
// Set the background highlight callbacks for the two hex editor columns
|
||||||
m_columns[0].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(1));
|
m_columns[0].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(1));
|
||||||
m_columns[1].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(0));
|
m_columns[1].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(0));
|
||||||
|
|
||||||
|
this->registerMenuItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewDiff::~ViewDiff() {
|
ViewDiff::~ViewDiff() {
|
||||||
EventProviderClosed::unsubscribe(this);
|
EventProviderClosed::unsubscribe(this);
|
||||||
EventDataChanged::unsubscribe(this);
|
EventDataChanged::unsubscribe(this);
|
||||||
|
EventRegionSelected::unsubscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
@ -133,6 +150,7 @@ namespace hex::plugin::diffing {
|
||||||
column.diffTree.clear();
|
column.diffTree.clear();
|
||||||
column.differences.clear();
|
column.differences.clear();
|
||||||
}
|
}
|
||||||
|
m_analysisInterrupted = m_analyzed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -441,5 +459,88 @@ namespace hex::plugin::diffing {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewDiff::registerMenuItems() {
|
||||||
|
ContentRegistry::UserInterface::addMenuItemSeparator({ "hex.builtin.menu.file" }, 1700, this);
|
||||||
|
|
||||||
|
ContentRegistry::UserInterface::addMenuItemSubMenu({ "hex.builtin.menu.file", "hex.diffing.view.diff.menu.file.jumping" }, ICON_TA_ARROWS_MOVE_HORIZONTAL, 1710,
|
||||||
|
[]{},
|
||||||
|
[this]{ return (bool) m_analyzed; },
|
||||||
|
this);
|
||||||
|
|
||||||
|
ContentRegistry::UserInterface::addMenuItem({
|
||||||
|
"hex.builtin.menu.file",
|
||||||
|
"hex.diffing.view.diff.menu.file.jumping",
|
||||||
|
"hex.diffing.view.diff.menu.file.jumping.prev_diff"
|
||||||
|
},
|
||||||
|
ICON_TA_ARROW_BAR_TO_LEFT_DASHED,
|
||||||
|
1720,
|
||||||
|
CTRLCMD + Keys::Left,
|
||||||
|
[this] {
|
||||||
|
if (m_selectedProvider == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get the column of the currently selected region
|
||||||
|
auto providers = ImHexApi::Provider::getProviders();
|
||||||
|
Column *selectedColumn = nullptr;
|
||||||
|
for (auto &column : m_columns) {
|
||||||
|
if (providers[column.provider] == m_selectedProvider) {
|
||||||
|
selectedColumn = &column;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedColumn == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Jump to previous difference
|
||||||
|
auto prevRange = selectedColumn->diffTree.prevInterval(m_selectedAddress);
|
||||||
|
if (prevRange.has_value()) {
|
||||||
|
selectedColumn->hexEditor.setSelection(prevRange->interval.start, prevRange->interval.end);
|
||||||
|
selectedColumn->hexEditor.jumpToSelection();
|
||||||
|
} else {
|
||||||
|
ui::ToastInfo::open("hex.diffing.view.diff.jumping.beginning_reached"_lang);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[this]{ return (bool) m_analyzed; },
|
||||||
|
this
|
||||||
|
);
|
||||||
|
|
||||||
|
ContentRegistry::UserInterface::addMenuItem({
|
||||||
|
"hex.builtin.menu.file",
|
||||||
|
"hex.diffing.view.diff.menu.file.jumping",
|
||||||
|
"hex.diffing.view.diff.menu.file.jumping.next_diff"
|
||||||
|
},
|
||||||
|
ICON_TA_ARROW_BAR_TO_RIGHT_DASHED,
|
||||||
|
1730,
|
||||||
|
CTRLCMD + Keys::Right,
|
||||||
|
[this] {
|
||||||
|
if (m_selectedProvider == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get the column of the currently selected region
|
||||||
|
auto providers = ImHexApi::Provider::getProviders();
|
||||||
|
Column *selectedColumn = nullptr;
|
||||||
|
for (auto &column : m_columns) {
|
||||||
|
if (providers[column.provider] == m_selectedProvider) {
|
||||||
|
selectedColumn = &column;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedColumn == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Jump to next difference
|
||||||
|
auto nextRange = selectedColumn->diffTree.nextInterval(m_selectedAddress);
|
||||||
|
if (nextRange.has_value()) {
|
||||||
|
selectedColumn->hexEditor.setSelection(nextRange->interval.start, nextRange->interval.end);
|
||||||
|
selectedColumn->hexEditor.jumpToSelection();
|
||||||
|
} else {
|
||||||
|
ui::ToastInfo::open("hex.diffing.view.diff.jumping.end_reached"_lang);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[this]{ return (bool) m_analyzed; },
|
||||||
|
this
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue