X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;ds=inline;f=pv%2Fviews%2Fdecoder_binary%2FQHexView.cpp;h=2c893e366d6d65cdafb8eaca9d3e021eb22f0a44;hb=2802b9ec97992323dc797c1b2cd5f9213e3d6932;hp=ed003949f242c67f482667a26b315554c1b90fd8;hpb=d5397ccbb61e1937757c95c2603156fdd18d1300;p=pulseview.git diff --git a/pv/views/decoder_binary/QHexView.cpp b/pv/views/decoder_binary/QHexView.cpp index ed003949..2c893e36 100644 --- a/pv/views/decoder_binary/QHexView.cpp +++ b/pv/views/decoder_binary/QHexView.cpp @@ -27,6 +27,8 @@ * SOFTWARE. */ +#include + #include #include #include @@ -40,6 +42,8 @@ #include "QHexView.hpp" +using std::make_pair; + const unsigned int BYTES_PER_LINE = 16; const unsigned int HEXCHARS_IN_LINE = BYTES_PER_LINE * 3 - 1; const unsigned int GAP_ADR_HEX = 10; @@ -53,7 +57,9 @@ QHexView::QHexView(QWidget *parent): data_(nullptr), selectBegin_(0), selectEnd_(0), - cursorPos_(0) + cursorPos_(0), + visible_range_(0, 0), + highlighted_sample_(std::numeric_limits::max()) { setFont(QFont("Courier", 10)); @@ -67,11 +73,13 @@ QHexView::QHexView(QWidget *parent): chunk_colors_.emplace_back(100, 149, 237); // QColorConstants::Svg::cornflowerblue chunk_colors_.emplace_back(60, 179, 113); // QColorConstants::Svg::mediumseagreen chunk_colors_.emplace_back(210, 180, 140); // QColorConstants::Svg::tan + visible_range_color_ = QColor("#fff5ee"); // QColorConstants::Svg::seashell } else { // Color is dark - chunk_colors_.emplace_back(0, 0, 139); // QColorConstants::Svg::darkblue - chunk_colors_.emplace_back(34, 139, 34); // QColorConstants::Svg::forestgreen - chunk_colors_.emplace_back(160, 82, 45); // QColorConstants::Svg::sienna + chunk_colors_.emplace_back(0, 0, 139); // QColorConstants::Svg::darkblue + chunk_colors_.emplace_back(34, 139, 34); // QColorConstants::Svg::forestgreen + chunk_colors_.emplace_back(160, 82, 45); // QColorConstants::Svg::sienna + visible_range_color_ = QColor("#fff5ee"); // QColorConstants::Svg::seashell } } @@ -105,6 +113,20 @@ void QHexView::set_data(const DecodeBinaryClass* data) viewport()->update(); } +void QHexView::set_visible_sample_range(uint64_t start, uint64_t end) +{ + visible_range_ = make_pair(start, end); + + viewport()->update(); +} + +void QHexView::set_highlighted_data_sample(uint64_t sample) +{ + highlighted_sample_ = sample; + + viewport()->update(); +} + unsigned int QHexView::get_bytes_per_line() const { return BYTES_PER_LINE; @@ -116,6 +138,8 @@ void QHexView::clear() data_ = nullptr; data_size_ = 0; + highlighted_sample_ = std::numeric_limits::max(); + viewport()->update(); } @@ -216,17 +240,35 @@ void QHexView::initialize_byte_iterator(size_t offset) if (current_chunk_id_ < data_->chunks.size()) current_chunk_ = data_->chunks[current_chunk_id_]; + + current_chunk_sample_ = current_chunk_.sample; + + // Obtain sample of next chunk if there is one + if ((current_chunk_id_ + 1) < data_->chunks.size()) + next_chunk_sample_ = data_->chunks[current_chunk_id_ + 1].sample; + else + next_chunk_sample_ = std::numeric_limits::max(); } -uint8_t QHexView::get_next_byte(bool* is_next_chunk) +uint8_t QHexView::get_next_byte(bool* is_new_chunk) { - if (is_next_chunk != nullptr) - *is_next_chunk = (current_chunk_offset_ == 0); + if (is_new_chunk != nullptr) + *is_new_chunk = (current_chunk_offset_ == 0); uint8_t v = 0; if (current_chunk_offset_ < current_chunk_.data.size()) v = current_chunk_.data[current_chunk_offset_]; + current_chunk_sample_ = current_chunk_.sample; + + if (is_new_chunk) { + // Obtain sample of next chunk if there is one + if ((current_chunk_id_ + 1) < data_->chunks.size()) + next_chunk_sample_ = data_->chunks[current_chunk_id_ + 1].sample; + else + next_chunk_sample_ = std::numeric_limits::max(); + } + current_offset_++; current_chunk_offset_++; @@ -269,6 +311,12 @@ void QHexView::paintEvent(QPaintEvent *event) { QPainter painter(viewport()); + QFont normal_font = painter.font(); + QFont bold_font = painter.font(); + bold_font.setWeight(QFont::Bold); + + bool bold_font_was_used = false; + // Calculate and update the widget and paint area sizes QSize widgetSize = getFullSize(); setMinimumWidth(widgetSize.width()); @@ -334,13 +382,15 @@ void QHexView::paintEvent(QPaintEvent *event) charHeight_ - 3, QString::number(offset, 16).toUpper()); // Paint hex values - QBrush regular = palette().buttonText(); - QBrush selected = palette().highlight(); + QBrush regular_brush = palette().buttonText(); + QBrush selected_brush = palette().highlight(); + QBrush visible_range_brush = QBrush(visible_range_color_); bool multiple_chunks = (data_->chunks.size() > 1); unsigned int chunk_color = 0; initialize_byte_iterator(firstLineIdx * BYTES_PER_LINE); + yStart = 2 * charHeight_; for (size_t lineIdx = firstLineIdx, y = yStart; lineIdx < lastLineIdx; lineIdx++) { @@ -349,26 +399,42 @@ void QHexView::paintEvent(QPaintEvent *event) size_t pos = (lineIdx * BYTES_PER_LINE + i) * 2; // Fetch byte - bool is_next_chunk; - uint8_t byte_value = get_next_byte(&is_next_chunk); + bool is_new_chunk; + uint8_t byte_value = get_next_byte(&is_new_chunk); - if (is_next_chunk) { + if (is_new_chunk) { chunk_color++; if (chunk_color == chunk_colors_.size()) chunk_color = 0; + + // New chunk means also new chunk sample, so check for required changes + if (bold_font_was_used) + painter.setFont(normal_font); + if ((highlighted_sample_ >= current_chunk_sample_) && (highlighted_sample_ < next_chunk_sample_)) { + painter.setFont(bold_font); + bold_font_was_used = true; + } + } + + // Restore default paint style + painter.setBackground(regular_brush); + painter.setBackgroundMode(Qt::TransparentMode); + if (!multiple_chunks) + painter.setPen(palette().color(QPalette::Text)); + else + painter.setPen(chunk_colors_[chunk_color]); + + // Highlight needed because it's the range visible in main view? + if ((current_chunk_sample_ >= visible_range_.first) && (current_chunk_sample_ < visible_range_.second)) { + painter.setBackgroundMode(Qt::OpaqueMode); + painter.setBackground(visible_range_brush); } + // Highlight for selection range needed? (takes priority over visible range highlight) if ((pos >= selectBegin_) && (pos < selectEnd_)) { painter.setBackgroundMode(Qt::OpaqueMode); - painter.setBackground(selected); + painter.setBackground(selected_brush); painter.setPen(palette().color(QPalette::HighlightedText)); - } else { - painter.setBackground(regular); - painter.setBackgroundMode(Qt::TransparentMode); - if (!multiple_chunks) - painter.setPen(palette().color(QPalette::Text)); - else - painter.setPen(chunk_colors_[chunk_color]); } // First nibble @@ -379,7 +445,7 @@ void QHexView::paintEvent(QPaintEvent *event) val = QString::number((byte_value & 0xF), 16).toUpper(); painter.drawText(x + charWidth_, y, val); - if ((pos >= selectBegin_) && (pos < selectEnd_ - 1) && (i < BYTES_PER_LINE - 1)) + if ((i < BYTES_PER_LINE - 1) && (current_offset_ < data_size_)) painter.drawText(x + 2 * charWidth_, y, QString(' ')); x += 3 * charWidth_; @@ -396,20 +462,39 @@ void QHexView::paintEvent(QPaintEvent *event) int x = posAscii_; for (size_t i = 0; (i < BYTES_PER_LINE) && (current_offset_ < data_size_); i++) { // Fetch byte - uint8_t ch = get_next_byte(); + bool is_new_chunk; + uint8_t ch = get_next_byte(&is_new_chunk); + + if (is_new_chunk) { + // New chunk means also new chunk sample, so check for required changes + if (bold_font_was_used) + painter.setFont(normal_font); + if ((highlighted_sample_ >= current_chunk_sample_) && (highlighted_sample_ < next_chunk_sample_)) { + painter.setFont(bold_font); + bold_font_was_used = true; + } + } if ((ch < 0x20) || (ch > 0x7E)) ch = '.'; + // Restore default paint style + painter.setBackgroundMode(Qt::TransparentMode); + painter.setBackground(regular_brush); + painter.setPen(palette().color(QPalette::Text)); + + // Highlight needed because it's the range visible in main view? + if ((current_chunk_sample_ >= visible_range_.first) && (current_chunk_sample_ < visible_range_.second)) { + painter.setBackgroundMode(Qt::OpaqueMode); + painter.setBackground(visible_range_brush); + } + + // Highlight for selection range needed? (takes priority over visible range highlight) size_t pos = (lineIdx * BYTES_PER_LINE + i) * 2; if ((pos >= selectBegin_) && (pos < selectEnd_)) { painter.setBackgroundMode(Qt::OpaqueMode); - painter.setBackground(selected); + painter.setBackground(selected_brush); painter.setPen(palette().color(QPalette::HighlightedText)); - } else { - painter.setBackgroundMode(Qt::TransparentMode); - painter.setBackground(regular); - painter.setPen(palette().color(QPalette::Text)); } painter.drawText(x, y, QString(ch)); @@ -419,6 +504,10 @@ void QHexView::paintEvent(QPaintEvent *event) y += charHeight_; } + // Restore painter defaults + painter.setBackgroundMode(Qt::TransparentMode); + painter.setBackground(regular_brush); + // Paint cursor if (hasFocus()) { int x = (cursorPos_ % (2 * BYTES_PER_LINE));