|
|
@ -1,7 +1,5 @@ |
|
|
|
#include "tools/cabana/binaryview.h" |
|
|
|
#include "tools/cabana/binaryview.h" |
|
|
|
|
|
|
|
|
|
|
|
#include <cmath> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <QFontDatabase> |
|
|
|
#include <QFontDatabase> |
|
|
|
#include <QHeaderView> |
|
|
|
#include <QHeaderView> |
|
|
|
#include <QMouseEvent> |
|
|
|
#include <QMouseEvent> |
|
|
@ -11,16 +9,12 @@ |
|
|
|
#include <QToolTip> |
|
|
|
#include <QToolTip> |
|
|
|
|
|
|
|
|
|
|
|
#include "tools/cabana/commands.h" |
|
|
|
#include "tools/cabana/commands.h" |
|
|
|
#include "tools/cabana/signalview.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// BinaryView
|
|
|
|
// BinaryView
|
|
|
|
|
|
|
|
|
|
|
|
const int CELL_HEIGHT = 36; |
|
|
|
const int CELL_HEIGHT = 36; |
|
|
|
const int VERTICAL_HEADER_WIDTH = 30; |
|
|
|
const int VERTICAL_HEADER_WIDTH = 30; |
|
|
|
|
|
|
|
inline int get_bit_pos(const QModelIndex &index) { return flipBitPos(index.row() * 8 + index.column()); } |
|
|
|
inline int get_bit_index(const QModelIndex &index, bool little_endian) { |
|
|
|
|
|
|
|
return index.row() * 8 + (little_endian ? 7 - index.column() : index.column()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BinaryView::BinaryView(QWidget *parent) : QTableView(parent) { |
|
|
|
BinaryView::BinaryView(QWidget *parent) : QTableView(parent) { |
|
|
|
model = new BinaryViewModel(this); |
|
|
|
model = new BinaryViewModel(this); |
|
|
@ -66,7 +60,7 @@ void BinaryView::addShortcuts() { |
|
|
|
QObject::connect(shortcut_delete_backspace, &QShortcut::activated, shortcut_delete_x, &QShortcut::activated); |
|
|
|
QObject::connect(shortcut_delete_backspace, &QShortcut::activated, shortcut_delete_x, &QShortcut::activated); |
|
|
|
QObject::connect(shortcut_delete_x, &QShortcut::activated, [=]{ |
|
|
|
QObject::connect(shortcut_delete_x, &QShortcut::activated, [=]{ |
|
|
|
if (hovered_sig != nullptr) { |
|
|
|
if (hovered_sig != nullptr) { |
|
|
|
emit removeSignal(hovered_sig); |
|
|
|
UndoStack::push(new RemoveSigCommand(model->msg_id, hovered_sig)); |
|
|
|
hovered_sig = nullptr; |
|
|
|
hovered_sig = nullptr; |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
@ -75,13 +69,9 @@ void BinaryView::addShortcuts() { |
|
|
|
QShortcut *shortcut_endian = new QShortcut(QKeySequence(Qt::Key_E), this); |
|
|
|
QShortcut *shortcut_endian = new QShortcut(QKeySequence(Qt::Key_E), this); |
|
|
|
QObject::connect(shortcut_endian, &QShortcut::activated, [=]{ |
|
|
|
QObject::connect(shortcut_endian, &QShortcut::activated, [=]{ |
|
|
|
if (hovered_sig != nullptr) { |
|
|
|
if (hovered_sig != nullptr) { |
|
|
|
const cabana::Signal *hovered_sig_prev = hovered_sig; |
|
|
|
|
|
|
|
cabana::Signal s = *hovered_sig; |
|
|
|
cabana::Signal s = *hovered_sig; |
|
|
|
s.is_little_endian = !s.is_little_endian; |
|
|
|
s.is_little_endian = !s.is_little_endian; |
|
|
|
emit editSignal(hovered_sig, s); |
|
|
|
emit editSignal(hovered_sig, s); |
|
|
|
|
|
|
|
|
|
|
|
hovered_sig = nullptr; |
|
|
|
|
|
|
|
highlight(hovered_sig_prev); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
@ -89,13 +79,9 @@ void BinaryView::addShortcuts() { |
|
|
|
QShortcut *shortcut_sign = new QShortcut(QKeySequence(Qt::Key_S), this); |
|
|
|
QShortcut *shortcut_sign = new QShortcut(QKeySequence(Qt::Key_S), this); |
|
|
|
QObject::connect(shortcut_sign, &QShortcut::activated, [=]{ |
|
|
|
QObject::connect(shortcut_sign, &QShortcut::activated, [=]{ |
|
|
|
if (hovered_sig != nullptr) { |
|
|
|
if (hovered_sig != nullptr) { |
|
|
|
const cabana::Signal *hovered_sig_prev = hovered_sig; |
|
|
|
|
|
|
|
cabana::Signal s = *hovered_sig; |
|
|
|
cabana::Signal s = *hovered_sig; |
|
|
|
s.is_signed = !s.is_signed; |
|
|
|
s.is_signed = !s.is_signed; |
|
|
|
emit editSignal(hovered_sig, s); |
|
|
|
emit editSignal(hovered_sig, s); |
|
|
|
|
|
|
|
|
|
|
|
hovered_sig = nullptr; |
|
|
|
|
|
|
|
highlight(hovered_sig_prev); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
@ -139,24 +125,24 @@ void BinaryView::setSelection(const QRect &rect, QItemSelectionModel::SelectionF |
|
|
|
|
|
|
|
|
|
|
|
QItemSelection selection; |
|
|
|
QItemSelection selection; |
|
|
|
auto [start, size, is_lb] = getSelection(index); |
|
|
|
auto [start, size, is_lb] = getSelection(index); |
|
|
|
for (int i = start; i < start + size; ++i) { |
|
|
|
for (int i = 0; i < size; ++i) { |
|
|
|
auto idx = model->bitIndex(i, is_lb); |
|
|
|
int pos = is_lb ? flipBitPos(start + i) : flipBitPos(start) + i; |
|
|
|
selection.merge({idx, idx}, flags); |
|
|
|
selection << QItemSelectionRange{model->index(pos / 8, pos % 8)}; |
|
|
|
} |
|
|
|
} |
|
|
|
selectionModel()->select(selection, flags); |
|
|
|
selectionModel()->select(selection, flags); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BinaryView::mousePressEvent(QMouseEvent *event) { |
|
|
|
void BinaryView::mousePressEvent(QMouseEvent *event) { |
|
|
|
delegate->selection_color = (palette().color(QPalette::Active, QPalette::Highlight)); |
|
|
|
resize_sig = nullptr; |
|
|
|
if (auto index = indexAt(event->pos()); index.isValid() && index.column() != 8) { |
|
|
|
if (auto index = indexAt(event->pos()); index.isValid() && index.column() != 8) { |
|
|
|
anchor_index = index; |
|
|
|
anchor_index = index; |
|
|
|
auto item = (const BinaryViewModel::Item *)anchor_index.internalPointer(); |
|
|
|
auto item = (const BinaryViewModel::Item *)anchor_index.internalPointer(); |
|
|
|
int bit_idx = get_bit_index(anchor_index, true); |
|
|
|
int bit_pos = get_bit_pos(anchor_index); |
|
|
|
for (auto s : item->sigs) { |
|
|
|
for (auto s : item->sigs) { |
|
|
|
if (bit_idx == s->lsb || bit_idx == s->msb) { |
|
|
|
if (bit_pos == s->lsb || bit_pos == s->msb) { |
|
|
|
anchor_index = model->bitIndex(bit_idx == s->lsb ? s->msb : s->lsb, true); |
|
|
|
int idx = flipBitPos(bit_pos == s->lsb ? s->msb : s->lsb); |
|
|
|
|
|
|
|
anchor_index = model->index(idx / 8, idx % 8); |
|
|
|
resize_sig = s; |
|
|
|
resize_sig = s; |
|
|
|
delegate->selection_color = s->color; |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -183,9 +169,10 @@ void BinaryView::mouseReleaseEvent(QMouseEvent *event) { |
|
|
|
auto release_index = indexAt(event->pos()); |
|
|
|
auto release_index = indexAt(event->pos()); |
|
|
|
if (release_index.isValid() && anchor_index.isValid()) { |
|
|
|
if (release_index.isValid() && anchor_index.isValid()) { |
|
|
|
if (selectionModel()->hasSelection()) { |
|
|
|
if (selectionModel()->hasSelection()) { |
|
|
|
auto [start_bit, size, is_lb] = getSelection(release_index); |
|
|
|
auto sig = resize_sig ? *resize_sig : cabana::Signal{}; |
|
|
|
resize_sig ? emit resizeSignal(resize_sig, start_bit, size) |
|
|
|
std::tie(sig.start_bit, sig.size, sig.is_little_endian) = getSelection(release_index); |
|
|
|
: emit addSignal(start_bit, size, is_lb); |
|
|
|
resize_sig ? emit editSignal(resize_sig, sig) |
|
|
|
|
|
|
|
: UndoStack::push(new AddSigCommand(model->msg_id, sig)); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
auto item = (const BinaryViewModel::Item *)anchor_index.internalPointer(); |
|
|
|
auto item = (const BinaryViewModel::Item *)anchor_index.internalPointer(); |
|
|
|
if (item && item->sigs.size() > 0) |
|
|
|
if (item && item->sigs.size() > 0) |
|
|
@ -246,10 +233,11 @@ std::tuple<int, int, bool> BinaryView::getSelection(QModelIndex index) { |
|
|
|
is_lb = false; |
|
|
|
is_lb = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int cur_bit_idx = get_bit_index(index, is_lb); |
|
|
|
int cur_bit_pos = get_bit_pos(index); |
|
|
|
int anchor_bit_idx = get_bit_index(anchor_index, is_lb); |
|
|
|
int anchor_bit_pos = get_bit_pos(anchor_index); |
|
|
|
auto [start_bit, end_bit] = std::minmax(cur_bit_idx, anchor_bit_idx); |
|
|
|
int start_bit = is_lb ? std::min(cur_bit_pos, anchor_bit_pos) : get_bit_pos(std::min(index, anchor_index)); |
|
|
|
return {start_bit, end_bit - start_bit + 1, is_lb}; |
|
|
|
int size = is_lb ? std::abs(cur_bit_pos - anchor_bit_pos) + 1 : std::abs(flipBitPos(cur_bit_pos) - flipBitPos(anchor_bit_pos)) + 1; |
|
|
|
|
|
|
|
return {start_bit, size, is_lb}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// BinaryViewModel
|
|
|
|
// BinaryViewModel
|
|
|
@ -261,16 +249,15 @@ void BinaryViewModel::refresh() { |
|
|
|
row_count = dbc_msg->size; |
|
|
|
row_count = dbc_msg->size; |
|
|
|
items.resize(row_count * column_count); |
|
|
|
items.resize(row_count * column_count); |
|
|
|
for (auto sig : dbc_msg->getSignals()) { |
|
|
|
for (auto sig : dbc_msg->getSignals()) { |
|
|
|
auto [start, end] = getSignalRange(sig); |
|
|
|
for (int j = 0; j < sig->size; ++j) { |
|
|
|
for (int j = start; j <= end; ++j) { |
|
|
|
int pos = sig->is_little_endian ? flipBitPos(sig->start_bit + j) : flipBitPos(sig->start_bit) + j; |
|
|
|
int bit_index = sig->is_little_endian ? bigEndianBitIndex(j) : j; |
|
|
|
int idx = column_count * (pos / 8) + pos % 8; |
|
|
|
int idx = column_count * (bit_index / 8) + bit_index % 8; |
|
|
|
|
|
|
|
if (idx >= items.size()) { |
|
|
|
if (idx >= items.size()) { |
|
|
|
qWarning() << "signal " << sig->name << "out of bounds.start_bit:" << sig->start_bit << "size:" << sig->size; |
|
|
|
qWarning() << "signal " << sig->name << "out of bounds.start_bit:" << sig->start_bit << "size:" << sig->size; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (j == start) sig->is_little_endian ? items[idx].is_lsb = true : items[idx].is_msb = true; |
|
|
|
if (j == 0) sig->is_little_endian ? items[idx].is_lsb = true : items[idx].is_msb = true; |
|
|
|
if (j == end) sig->is_little_endian ? items[idx].is_msb = true : items[idx].is_lsb = true; |
|
|
|
if (j == sig->size - 1) sig->is_little_endian ? items[idx].is_msb = true : items[idx].is_lsb = true; |
|
|
|
|
|
|
|
|
|
|
|
auto &sigs = items[idx].sigs; |
|
|
|
auto &sigs = items[idx].sigs; |
|
|
|
sigs.push_back(sig); |
|
|
|
sigs.push_back(sig); |
|
|
@ -379,7 +366,8 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op |
|
|
|
painter->fillRect(option.rect, item->bg_color); |
|
|
|
painter->fillRect(option.rect, item->bg_color); |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (option.state & QStyle::State_Selected) { |
|
|
|
} else if (option.state & QStyle::State_Selected) { |
|
|
|
painter->fillRect(option.rect, selection_color); |
|
|
|
auto color = bin_view->resize_sig ? bin_view->resize_sig->color : option.palette.color(QPalette::Active, QPalette::Highlight); |
|
|
|
|
|
|
|
painter->fillRect(option.rect, color); |
|
|
|
painter->setPen(option.palette.color(QPalette::BrightText)); |
|
|
|
painter->setPen(option.palette.color(QPalette::BrightText)); |
|
|
|
} else if (!bin_view->selectionModel()->hasSelection() || !item->sigs.contains(bin_view->resize_sig)) { // not resizing
|
|
|
|
} else if (!bin_view->selectionModel()->hasSelection() || !item->sigs.contains(bin_view->resize_sig)) { // not resizing
|
|
|
|
if (item->sigs.size() > 0) { |
|
|
|
if (item->sigs.size() > 0) { |
|
|
@ -441,7 +429,7 @@ void BinaryItemDelegate::drawSignalCell(QPainter *painter, const QStyleOptionVie |
|
|
|
QColor color = sig->color; |
|
|
|
QColor color = sig->color; |
|
|
|
color.setAlpha(item->bg_color.alpha()); |
|
|
|
color.setAlpha(item->bg_color.alpha()); |
|
|
|
// Mixing the signal colour with the Base background color to fade it
|
|
|
|
// Mixing the signal colour with the Base background color to fade it
|
|
|
|
painter->fillRect(rc, QApplication::palette().color(QPalette::Base)); |
|
|
|
painter->fillRect(rc, option.palette.color(QPalette::Base)); |
|
|
|
painter->fillRect(rc, color); |
|
|
|
painter->fillRect(rc, color); |
|
|
|
|
|
|
|
|
|
|
|
// Draw edges
|
|
|
|
// Draw edges
|
|
|
|