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:
Zackary Newman
2025-09-21 04:39:37 -04:00
committed by GitHub
parent fedbce6f9e
commit 3c167c3306
5 changed files with 121 additions and 7 deletions

View File

@@ -1,12 +1,15 @@
#include "content/views/view_diff.hpp"
#include <toasts/toast_notification.hpp>
#include <hex/api/imhex_api/provider.hpp>
#include <hex/api/events/requests_gui.hpp>
#include <hex/api/content_registry/user_interface.hpp>
#include <hex/helpers/fmt.hpp>
#include <hex/providers/buffered_reader.hpp>
#include <fonts/vscode_icons.hpp>
#include <fonts/tabler_icons.hpp>
#include <wolv/utils/guards.hpp>
namespace hex::plugin::diffing {
@@ -22,14 +25,28 @@ namespace hex::plugin::diffing {
m_analysisInterrupted = m_analyzed = false;
});
// Handle region selection
EventRegionSelected::subscribe(this, [this](const auto &region) {
// 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
m_columns[0].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(1));
m_columns[1].hexEditor.setBackgroundHighlightCallback(this->createCompareFunction(0));
this->registerMenuItems();
}
ViewDiff::~ViewDiff() {
EventProviderClosed::unsubscribe(this);
EventDataChanged::unsubscribe(this);
EventRegionSelected::unsubscribe(this);
}
namespace {
@@ -133,6 +150,7 @@ namespace hex::plugin::diffing {
column.diffTree.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
);
}
}