Skip to content
This repository has been archived by the owner on Sep 30, 2020. It is now read-only.

Minimap for hexedit #266

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/ui/hexedit.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public slots:
signals:
void selectionChanged(qint64 start_addr, qint64 selection_size);
void editStateChanged(bool has_changes, bool has_undo);
void visibleRegionChanged(qint64 start_addr, qint64 region_size);

private:
FileBlobModel *dataModel_;
Expand Down Expand Up @@ -154,6 +155,9 @@ public slots:
QScopedPointer<util::encoders::TextEncoder> textEncoder_;
util::EditEngine edit_engine_;

qint64 visible_region_start_;
qint64 visible_region_size_;

void recalculateValues();
void initParseMenu();
void adjustBytesPerRowToWindowSize();
Expand Down
2 changes: 2 additions & 0 deletions include/ui/hexeditwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,12 @@ class HexEditWidget : public View {
signals:
void showNodeTree(bool show);
void showMinimap(bool show);
void updateMinimap(qint64 start_addr, qint64 region_size);

public slots:
void nodeTreeVisibilityChanged(bool visibility);
void minimapVisibilityChanged(bool visibility);
void minimapSelectionChanged(size_t start, size_t end);

private slots:
void parse(QAction *action);
Expand Down
11 changes: 11 additions & 0 deletions include/ui/nodewidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <QToolButton>
#include <QMainWindow>
#include <QSharedPointer>
#include <QTimer>

#include "util/sampling/uniform_sampler.h"

Expand Down Expand Up @@ -50,6 +51,10 @@ class NodeWidget : public View {
public slots:
void loadBinDataToMinimap();

private slots:
void updateMinimap();
void showMinimap(bool show);

private:
MainWindowWithDetachableDockWidgets *main_window_;

Expand All @@ -65,6 +70,12 @@ class NodeWidget : public View {

util::UniformSampler* sampler_;
QByteArray sampler_data_;

// don't change minimap too often when scrolling by "normal" hex edit scroll bar
QTimer update_minimap_timer_;
qint64 update_minimap_start_;
qint64 update_minimap_size_;
bool ignore_update_minimap_;
};

} // namespace ui
Expand Down
5 changes: 4 additions & 1 deletion include/visualization/minimap.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ class VisualizationMinimap : public QOpenGLWidget,
ENTROPY
};

explicit VisualizationMinimap(QWidget *parent = 0);
explicit VisualizationMinimap(bool size_control = true, QWidget *parent = 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parent should be the first argument (same as you did in MinimapPanel ctor)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so it is wrong in MinimapPanel , all qt things have it as last argmunet

~VisualizationMinimap();

void setSampler(util::ISampler * sampler);
QPair<size_t, size_t> getRange();
void setRange(size_t start, size_t end, bool reset_selection = true);
QPair<size_t, size_t> getSelectedRange();
void setSelectedRange(size_t start_address, size_t end_address);
Expand Down Expand Up @@ -153,6 +154,8 @@ class VisualizationMinimap : public QOpenGLWidget,

QOpenGLBuffer square_vertex_;
QOpenGLVertexArrayObject vao_;

bool size_control_;
};


Expand Down
10 changes: 8 additions & 2 deletions include/visualization/minimap_panel.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,32 @@ class MinimapPanel : public QWidget {
Q_OBJECT

public:
explicit MinimapPanel(QWidget *parent = 0);
explicit MinimapPanel(bool size_control = true, QWidget *parent = 0);
~MinimapPanel();

void setSampler(util::ISampler *sampler);
QPair<size_t, size_t> getSelection();
void adjustMinimaps(size_t selection_size, int grow_factor, size_t start_position = 0);

signals:
void selectionChanged(size_t start, size_t end);

public slots:
void selectRange(size_t start, size_t end);

private slots:
void addMinimap();
void removeMinimap();
void changeMinimapMode();
void updateSelection(int minimap_index, size_t start, size_t end);
void showSelectRangeDialog();
void selectRange();

private:
void initLayout();
VisualizationMinimap::MinimapColor getMinimapColor();

bool size_control_;

util::ISampler *sampler_;
QVector<util::ISampler*> minimap_samplers_;
QVector<VisualizationMinimap*> minimaps_;
Expand All @@ -63,6 +68,7 @@ class MinimapPanel : public QWidget {

VisualizationMinimap::MinimapMode mode_;

QHBoxLayout *button_layout_;
QBoxLayout *layout_, *minimaps_layout_;
QPushButton *add_minimap_button_, *remove_minimap_button_;
QPushButton *change_mode_button_, *select_range_button_;
Expand Down
17 changes: 16 additions & 1 deletion src/ui/hexedit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ void HexEdit::recalculateValues() {

horizontalScrollBar()->setRange(0, lineWidth_ - viewport()->width());
startPosX_ = horizontalScrollBar()->value();

bool visible_region_start_changed = visible_region_start_ != startRow_ * bytesPerRow_;
bool visible_region_size_changed = visible_region_size_ != rowsOnScreen_ * bytesPerRow_;

visible_region_start_ = startRow_ * bytesPerRow_;
visible_region_size_ = rowsOnScreen_ * bytesPerRow_;

if (visible_region_start_changed || visible_region_size_changed) {
emit visibleRegionChanged(visible_region_start_, visible_region_size_);
}
}

void HexEdit::resizeEvent(QResizeEvent *event) {
Expand Down Expand Up @@ -110,7 +120,9 @@ HexEdit::HexEdit(FileBlobModel *dataModel, QItemSelectionModel *selectionModel,
current_area_(WindowArea::HEX),
cursor_pos_in_byte_(0),
cursor_visible_(false),
edit_engine_(bindata_width_) {
edit_engine_(bindata_width_),
visible_region_start_(0),
visible_region_size_(0) {
setFont(util::settings::theme::font());

connect(dataModel_, &FileBlobModel::newBinData,
Expand Down Expand Up @@ -1070,6 +1082,9 @@ void HexEdit::scrollToByte(qint64 bytePos, bool minimal_change) {
if (isByteVisible(bytePos) && minimal_change) {
return;
}
if (bytePos >= dataBytesCount_) {
return;
}

auto byte_row = bytePos / bytesPerRow_;
auto current_top_row = verticalScrollBar()->value();
Expand Down
32 changes: 20 additions & 12 deletions src/ui/hexeditwidget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ HexEditWidget::HexEditWidget(MainWindowWithDetachableDockWidgets *main_window,
connect(hex_edit_, &HexEdit::selectionChanged,
this, &HexEditWidget::selectionChanged);

connect(hex_edit_, &HexEdit::visibleRegionChanged, [this](qint64 start_addr, qint64 region_size) {
emit updateMinimap(start_addr, region_size);
});

search_dialog_ = new SearchDialog(hex_edit_, this);

createActions();
Expand Down Expand Up @@ -176,16 +180,16 @@ void HexEditWidget::createActions() {
connect(show_node_tree_act_, SIGNAL(toggled(bool)),
this, SIGNAL(showNodeTree(bool)));

// Currently not implemented
// show_minimap_act_ = ShortcutsModel::ShortcutsModel::getShortcutsModel()->createQAction(
// util::settings::shortcuts::SHOW_MINIMAP,
// this, QIcon(":/images/show_minimap.png"), Qt::WidgetWithChildrenShortcut);
// show_minimap_act_->setToolTip(tr("Minimap"));
// show_minimap_act_->setEnabled(true);
// show_minimap_act_->setCheckable(true);
// show_minimap_act_->setChecked(false);
// connect(show_minimap_act_, SIGNAL(toggled(bool)), this,
// SIGNAL(showMinimap(bool)));
// Currently not implemented
show_minimap_act_ = ShortcutsModel::ShortcutsModel::getShortcutsModel()->createQAction(
util::settings::shortcuts::SHOW_MINIMAP,
this, QIcon(":/images/show_minimap.png"), Qt::WidgetWithChildrenShortcut);
show_minimap_act_->setToolTip(tr("Minimap"));
show_minimap_act_->setEnabled(true);
show_minimap_act_->setCheckable(true);
show_minimap_act_->setChecked(false);
connect(show_minimap_act_, SIGNAL(toggled(bool)), this,
SIGNAL(showMinimap(bool)));

show_hex_edit_act_ = ShortcutsModel::getShortcutsModel()->createQAction(
util::settings::shortcuts::OPEN_HEX,
Expand All @@ -201,8 +205,8 @@ void HexEditWidget::createToolBars() {
addAction(show_node_tree_act_);
tools_tool_bar_->addAction(show_node_tree_act_);
//Disabled until minimap does anything of value in hex-view
//addAction(show_minimap_act_);
//tools_tool_bar_->addAction(show_minimap_act_);
addAction(show_minimap_act_);
tools_tool_bar_->addAction(show_minimap_act_);

auto parser_tool_button = new QToolButton();
parser_tool_button->setMenu(&parsers_menu_);
Expand Down Expand Up @@ -372,5 +376,9 @@ void HexEditWidget::minimapVisibilityChanged(bool visibility) {
show_minimap_act_->setChecked(visibility);
}

void HexEditWidget::minimapSelectionChanged(size_t start, size_t end) {
hex_edit_->scrollToByte(start);
}

} // namespace ui
} // namespace veles
102 changes: 69 additions & 33 deletions src/ui/nodewidget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
namespace veles {
namespace ui {

const float k_minimap_selection_factor = 10;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consts should be in uppercase

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

convention from this component, see trigram.cc

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll refactor this old convention in few days (after fixing Jenkins), so insert new code in Google C++ Style


/*****************************************************************************/
/* Public methods */
/*****************************************************************************/
Expand All @@ -54,7 +56,9 @@ NodeWidget::NodeWidget(MainWindowWithDetachableDockWidgets *main_window,
: View("Hex editor", ":/images/show_hex_edit.png"),
main_window_(main_window), minimap_(nullptr),
minimap_dock_(nullptr), data_model_(data_model),
selection_model_(selection_model), sampler_(nullptr) {
selection_model_(selection_model), sampler_(nullptr),
update_minimap_start_(0), update_minimap_size_(0),
ignore_update_minimap_(false) {
hex_edit_widget_ = new HexEditWidget(
main_window, data_model, selection_model);
addAction(hex_edit_widget_->uploadAction());
Expand All @@ -79,49 +83,80 @@ NodeWidget::NodeWidget(MainWindowWithDetachableDockWidgets *main_window,
setDockNestingEnabled(true);
addDockWidget(Qt::LeftDockWidgetArea, node_tree_dock_);

#if 0 // We do not use minimap for NodeWidget yet,
minimap_dock_ = new QDockWidget;
new DockWidgetVisibilityGuard(minimap_dock_);
minimap_dock_->setWindowTitle("Minimap");
minimap_ = new visualization::MinimapPanel(this);

if(data_model_->binData().size() > 0) {
loadBinDataToMinimap();
} else {
sampler_data_ = QByteArray("");
sampler_ = new util::UniformSampler(sampler_data_);
sampler_->setSampleSize(4096 * 1024);
minimap_->setSampler(sampler_);
}

minimap_dock_->setWidget(minimap_);
minimap_dock_->setContextMenuPolicy(Qt::PreventContextMenu);
minimap_dock_->setAllowedAreas(
Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
addDockWidget(Qt::LeftDockWidgetArea, minimap_dock_);
MainWindowWithDetachableDockWidgets::splitDockWidget2(this, node_tree_dock_,
minimap_dock_, Qt::Horizontal);
#endif

connect(hex_edit_widget_, &HexEditWidget::showNodeTree,
node_tree_dock_, &QDockWidget::setVisible);
connect(node_tree_dock_, &QDockWidget::visibilityChanged,
hex_edit_widget_, &HexEditWidget::nodeTreeVisibilityChanged);

#if 0 // We do not use minimap for NodeWidget yet,
connect(hex_edit_widget_, &HexEditWidget::showMinimap,
minimap_dock_, &QDockWidget::setVisible);
connect(data_model_.data(), &FileBlobModel::newBinData,
this, &NodeWidget::loadBinDataToMinimap);
connect(minimap_dock_, &QDockWidget::visibilityChanged,
hex_edit_widget_, &HexEditWidget::minimapVisibilityChanged);
#endif
connect(hex_edit_widget_, &HexEditWidget::showMinimap, this, &NodeWidget::showMinimap);
connect(hex_edit_widget_, &HexEditWidget::updateMinimap, [this](qint64 start, qint64 size) {
if (!ignore_update_minimap_) {
update_minimap_start_ = start;
update_minimap_size_ = size;
update_minimap_timer_.start(400);
}
});

update_minimap_timer_.setSingleShot(true);
connect(&update_minimap_timer_, &QTimer::timeout, this, &NodeWidget::updateMinimap);
}

NodeWidget::~NodeWidget() {
delete sampler_;
}

void NodeWidget::showMinimap(bool show) {
if (minimap_dock_ == nullptr) {
if (!show) {
return;
}
minimap_dock_ = new QDockWidget;
new DockWidgetVisibilityGuard(minimap_dock_);
minimap_dock_->setWindowTitle("Minimap");
minimap_ = new visualization::MinimapPanel(/*size_control=*/false, this);

if (data_model_->binData().size() > 0) {
loadBinDataToMinimap();
} else {
sampler_data_ = QByteArray("");
sampler_ = new util::UniformSampler(sampler_data_);
sampler_->setSampleSize(4096 * 1024);
minimap_->setSampler(sampler_);
}

minimap_dock_->setWidget(minimap_);
minimap_dock_->setContextMenuPolicy(Qt::PreventContextMenu);
minimap_dock_->setAllowedAreas(
Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
addDockWidget(Qt::LeftDockWidgetArea, minimap_dock_);
MainWindowWithDetachableDockWidgets::splitDockWidget2(this, node_tree_dock_,
minimap_dock_, Qt::Horizontal);

connect(data_model_.data(), &FileBlobModel::newBinData,
this, &NodeWidget::loadBinDataToMinimap);
connect(minimap_dock_, &QDockWidget::visibilityChanged,
hex_edit_widget_, &HexEditWidget::minimapVisibilityChanged);
connect(minimap_, &visualization::MinimapPanel::selectionChanged, [this](size_t start, size_t end) {
if (!ignore_update_minimap_) {
ignore_update_minimap_ = true;
hex_edit_widget_->minimapSelectionChanged(start, end);
ignore_update_minimap_ = false;
}
});
}
minimap_dock_->setVisible(show);

}

void NodeWidget::updateMinimap() {
if (minimap_dock_ == nullptr || sampler_->empty()) {
return;
}
ignore_update_minimap_ = true;
minimap_->adjustMinimaps(update_minimap_size_, k_minimap_selection_factor, update_minimap_start_);
ignore_update_minimap_ = false;
}

void NodeWidget::loadBinDataToMinimap() {
delete sampler_;

Expand All @@ -130,6 +165,7 @@ void NodeWidget::loadBinDataToMinimap() {
sampler_ = new util::UniformSampler(sampler_data_);
sampler_->setSampleSize(4096 * 1024);
minimap_->setSampler(sampler_);
updateMinimap();
}

} // namespace ui
Expand Down
Loading