Cabana: drag to adjust signal size (#26172)

* drag to adjust signal size

* rename

* override setSelection

* use signal color as selection color while resing

* helper funtion

* hide tooltip if not in signal

* cleanup

* cabana: remove unused metatype (#26175)

remove unused metatype

* cabana: improve signal highlight on hover (#26161)

* just change font color

* merge master

* cleanup
old-commit-hash: d6a0f1c25a44ad5629f491bb0066999eb0a9d357
This commit is contained in:
Dean Lee
2022-10-21 04:09:49 +08:00
committed by GitHub
parent e31ca17926
commit 8e68208690
4 changed files with 101 additions and 43 deletions
+70 -30
View File
@@ -13,21 +13,23 @@
const int CELL_HEIGHT = 30;
static std::pair<int, int> getSignalRange(const Signal *s) {
int from = s->is_little_endian ? s->start_bit : bigEndianBitIndex(s->start_bit);
int to = from + s->size - 1;
return {from, to};
}
BinaryView::BinaryView(QWidget *parent) : QTableView(parent) {
model = new BinaryViewModel(this);
setModel(model);
setItemDelegate(new BinaryItemDelegate(this));
delegate = new BinaryItemDelegate(this);
setItemDelegate(delegate);
horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
horizontalHeader()->hide();
verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setMouseTracking(true);
// replace selection model
auto old_model = selectionModel();
setSelectionModel(new BinarySelectionModel(model));
delete old_model;
QObject::connect(model, &QAbstractItemModel::modelReset, [this]() {
setFixedHeight((CELL_HEIGHT + 1) * std::min(model->rowCount(), 8) + 2);
});
@@ -41,12 +43,42 @@ void BinaryView::highlight(const Signal *sig) {
}
}
void BinaryView::setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags) {
QModelIndex tl = indexAt({qMin(rect.left(), rect.right()), qMin(rect.top(), rect.bottom())});
QModelIndex br = indexAt({qMax(rect.left(), rect.right()), qMax(rect.top(), rect.bottom())});
if (!tl.isValid() || !br.isValid())
return;
if (tl < anchor_index) {
br = anchor_index;
} else if (anchor_index < br) {
tl = anchor_index;
}
QItemSelection selection;
for (int row = tl.row(); row <= br.row(); ++row) {
int left_col = (row == tl.row()) ? tl.column() : 0;
int right_col = (row == br.row()) ? br.column() : 7;
selection.merge({model->index(row, left_col), model->index(row, right_col)}, flags);
}
selectionModel()->select(selection, flags);
}
void BinaryView::mousePressEvent(QMouseEvent *event) {
delegate->setSelectionColor(style()->standardPalette().color(QPalette::Active, QPalette::Highlight));
anchor_index = indexAt(event->pos());
if (getResizingSignal() != nullptr) {
auto item = (const BinaryViewModel::Item *)anchor_index.internalPointer();
delegate->setSelectionColor(item->bg_color);
}
QTableView::mousePressEvent(event);
}
void BinaryView::mouseMoveEvent(QMouseEvent *event) {
if (auto index = indexAt(event->pos()); index.isValid()) {
auto item = (BinaryViewModel::Item *)index.internalPointer();
highlight(item->sig);
if (item->sig)
QToolTip::showText(event->globalPos(), item->sig->name.c_str(), this, rect());
item->sig ? QToolTip::showText(event->globalPos(), item->sig->name.c_str(), this, rect())
: QToolTip::hideText();
}
QTableView::mouseMoveEvent(event);
}
@@ -55,10 +87,21 @@ void BinaryView::mouseReleaseEvent(QMouseEvent *event) {
QTableView::mouseReleaseEvent(event);
if (auto indexes = selectedIndexes(); !indexes.isEmpty()) {
int start_bit = indexes.first().row() * 8 + indexes.first().column();
int size = indexes.back().row() * 8 + indexes.back().column() - start_bit + 1;
emit cellsSelected(start_bit, size);
int from = indexes.first().row() * 8 + indexes.first().column();
int to = indexes.back().row() * 8 + indexes.back().column();
if (auto sig = getResizingSignal()) {
auto [sig_from, sig_to] = getSignalRange(sig);
if (from >= sig_from && to <= sig_to) { // reduce size
emit(from == sig_from ? resizeSignal(sig, to, sig_to) : resizeSignal(sig, sig_from, from));
} else { // increase size
emit resizeSignal(sig, std::min(from, sig_from), std::max(to, sig_to));
}
} else {
emit addSignal(from, to);
}
clearSelection();
}
anchor_index = QModelIndex();
}
void BinaryView::leaveEvent(QEvent *event) {
@@ -78,6 +121,19 @@ void BinaryView::updateState() {
model->updateState();
}
const Signal *BinaryView::getResizingSignal() const {
if (anchor_index.isValid()) {
auto item = (const BinaryViewModel::Item *)anchor_index.internalPointer();
if (item && item->sig) {
int archor_pos = anchor_index.row() * 8 + anchor_index.column();
auto [sig_from, sig_to] = getSignalRange(item->sig);
if (archor_pos == sig_from || archor_pos == sig_to)
return item->sig;
}
}
return nullptr;
}
// BinaryViewModel
void BinaryViewModel::setMessage(const QString &message_id) {
@@ -93,8 +149,7 @@ void BinaryViewModel::setMessage(const QString &message_id) {
items.resize(row_count * column_count);
for (int i = 0; i < dbc_msg->sigs.size(); ++i) {
const auto &sig = dbc_msg->sigs[i];
const int start = sig.is_little_endian ? sig.start_bit : bigEndianBitIndex(sig.start_bit);
const int end = start + sig.size - 1;
auto [start, end] = getSignalRange(&sig);
for (int j = start; j <= end; ++j) {
int idx = column_count * (j / 8) + j % 8;
if (idx >= items.size()) {
@@ -165,21 +220,6 @@ QVariant BinaryViewModel::headerData(int section, Qt::Orientation orientation, i
return {};
}
// BinarySelectionModel
void BinarySelectionModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) {
QItemSelection new_selection = selection;
if (auto indexes = selection.indexes(); !indexes.isEmpty()) {
auto [begin_idx, end_idx] = (QModelIndex[]){indexes.first(), indexes.back()};
for (int row = begin_idx.row(); row <= end_idx.row(); ++row) {
int left_col = (row == begin_idx.row()) ? begin_idx.column() : 0;
int right_col = (row == end_idx.row()) ? end_idx.column() : 7;
new_selection.merge({model()->index(row, left_col), model()->index(row, right_col)}, command);
}
}
QItemSelectionModel::select(new_selection, command);
}
// BinaryItemDelegate
BinaryItemDelegate::BinaryItemDelegate(QObject *parent) : QStyledItemDelegate(parent) {
@@ -187,7 +227,7 @@ BinaryItemDelegate::BinaryItemDelegate(QObject *parent) : QStyledItemDelegate(pa
small_font.setPointSize(6);
hex_font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
hex_font.setBold(true);
highlight_color = QApplication::style()->standardPalette().color(QPalette::Active, QPalette::Highlight);
selection_color = QApplication::style()->standardPalette().color(QPalette::Active, QPalette::Highlight);
}
QSize BinaryItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const {
@@ -204,7 +244,7 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op
// background
QColor bg_color = hover ? hoverColor(item->bg_color) : item->bg_color;
if (option.state & QStyle::State_Selected) {
bg_color = highlight_color;
bg_color = selection_color;
}
painter->fillRect(option.rect, bg_color);