X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=pv%2Fviews%2Ftrace%2Fdecodetrace.cpp;h=002e195439e9d3f3d32e60fab95fb91df0cef16c;hb=93dbad3ed4954c3e0c140c26e867bda219cd683f;hp=9c7196bfb04f24e1c3322172ce023d12f12f4b36;hpb=7a0d99e6d48870c51d00c25617eb309181dc2a60;p=pulseview.git diff --git a/pv/views/trace/decodetrace.cpp b/pv/views/trace/decodetrace.cpp index 9c7196bf..002e1954 100644 --- a/pv/views/trace/decodetrace.cpp +++ b/pv/views/trace/decodetrace.cpp @@ -31,6 +31,7 @@ extern "C" { #include #include +#include #include #include #include @@ -101,6 +102,11 @@ DecodeTrace::DecodeTrace(pv::Session &session, { decode_signal_ = dynamic_pointer_cast(base_); + GlobalSettings settings; + always_show_all_rows_ = settings.value(GlobalSettings::Key_Dec_AlwaysShowAllRows).toBool(); + + GlobalSettings::add_change_handler(this); + // Determine shortest string we want to see displayed in full QFontMetrics m(QApplication::font()); min_useful_label_width_ = m.width("XX"); // e.g. two hex characters @@ -136,6 +142,11 @@ DecodeTrace::DecodeTrace(pv::Session &session, delayed_trace_updater_.setInterval(1000 / MaxTraceUpdateRate); } +DecodeTrace::~DecodeTrace() +{ + GlobalSettings::remove_change_handler(this); +} + bool DecodeTrace::enabled() const { return true; @@ -181,7 +192,7 @@ void DecodeTrace::paint_mid(QPainter &p, ViewItemPaintParams &pp) sample_range.second = min((int64_t)sample_range.second, decode_signal_->get_decoded_sample_count(current_segment_, false)); - const vector rows = decode_signal_->visible_rows(); + const vector rows = decode_signal_->get_rows(!always_show_all_rows_); visible_rows_.clear(); for (const Row& row : rows) { @@ -199,7 +210,7 @@ void DecodeTrace::paint_mid(QPainter &p, ViewItemPaintParams &pp) vector annotations; decode_signal_->get_annotation_subset(annotations, row, current_segment_, sample_range.first, sample_range.second); - if (!annotations.empty()) { + if (always_show_all_rows_ || !annotations.empty()) { draw_annotations(annotations, p, annotation_height, pp, y, get_row_color(row.index()), row_title_width); y += row_height_; @@ -263,6 +274,33 @@ void DecodeTrace::paint_fore(QPainter &p, ViewItemPaintParams &pp) paint_hover_marker(p); } +void DecodeTrace::update_stack_button() +{ + const vector< shared_ptr > &stack = decode_signal_->decoder_stack(); + + // Only show decoders in the menu that can be stacked onto the last one in the stack + if (!stack.empty()) { + const srd_decoder* d = stack.back()->decoder(); + + if (d->outputs) { + pv::widgets::DecoderMenu *const decoder_menu = + new pv::widgets::DecoderMenu(stack_button_, (const char*)(d->outputs->data)); + connect(decoder_menu, SIGNAL(decoder_selected(srd_decoder*)), + this, SLOT(on_stack_decoder(srd_decoder*))); + + decoder_menu->setStyleSheet("QMenu { menu-scrollable: 1; }"); + + stack_button_->setMenu(decoder_menu); + stack_button_->show(); + return; + } + } + + // No decoders available for stacking + stack_button_->setMenu(nullptr); + stack_button_->hide(); +} + void DecodeTrace::populate_popup_form(QWidget *parent, QFormLayout *form) { using pv::data::decode::Decoder; @@ -297,18 +335,12 @@ void DecodeTrace::populate_popup_form(QWidget *parent, QFormLayout *form) } // Add stacking button - pv::widgets::DecoderMenu *const decoder_menu = - new pv::widgets::DecoderMenu(parent); - connect(decoder_menu, SIGNAL(decoder_selected(srd_decoder*)), - this, SLOT(on_stack_decoder(srd_decoder*))); - - QPushButton *const stack_button = - new QPushButton(tr("Stack Decoder"), parent); - stack_button->setMenu(decoder_menu); - stack_button->setToolTip(tr("Stack a higher-level decoder on top of this one")); + stack_button_ = new QPushButton(tr("Stack Decoder"), parent); + stack_button_->setToolTip(tr("Stack a higher-level decoder on top of this one")); + update_stack_button(); QHBoxLayout *stack_button_box = new QHBoxLayout; - stack_button_box->addWidget(stack_button, 0, Qt::AlignRight); + stack_button_box->addWidget(stack_button_, 0, Qt::AlignRight); form->addRow(stack_button_box); } @@ -351,9 +383,12 @@ QMenu* DecodeTrace::create_view_context_menu(QWidget *parent, QPoint &click_pos) selected_row_ = nullptr; } + const View *const view = owner_->view(); + assert(view); + QPoint pos = view->viewport()->mapFrom(parent, click_pos); + // Default sample range is "from here" - const pair sample_range = - get_view_sample_range(click_pos.x(), click_pos.x() + 1); + const pair sample_range = get_view_sample_range(pos.x(), pos.x() + 1); selected_sample_range_ = make_pair(sample_range.first, numeric_limits::max()); if (decode_signal_->is_paused()) { @@ -372,6 +407,13 @@ QMenu* DecodeTrace::create_view_context_menu(QWidget *parent, QPoint &click_pos) menu->addAction(pause); } + QAction *const copy_annotation_to_clipboard = + new QAction(tr("Copy annotation text to clipboard"), this); + copy_annotation_to_clipboard->setIcon(QIcon::fromTheme("edit-paste", + QIcon(":/icons/edit-paste.png"))); + connect(copy_annotation_to_clipboard, SIGNAL(triggered()), this, SLOT(on_copy_annotation_to_clipboard())); + menu->addAction(copy_annotation_to_clipboard); + menu->addSeparator(); QAction *const export_all_rows = @@ -420,9 +462,6 @@ QMenu* DecodeTrace::create_view_context_menu(QWidget *parent, QPoint &click_pos) connect(export_row_with_cursor, SIGNAL(triggered()), this, SLOT(on_export_row_with_cursor())); menu->addAction(export_row_with_cursor); - const View *view = owner_->view(); - assert(view); - if (!view->cursors()->enabled()) { export_all_rows_with_cursor->setEnabled(false); export_row_with_cursor->setEnabled(false); @@ -834,8 +873,6 @@ void DecodeTrace::hover_point_changed(const QPoint &hp) QString ann = get_annotation_at_point(hp); - assert(view); - if (!row_height_ || ann.isEmpty()) { QToolTip::hideText(); return; @@ -1036,13 +1073,21 @@ void DecodeTrace::export_annotations(vector *annotations) const } QMessageBox msg(owner_->view()); - msg.setText(tr("Error")); - msg.setInformativeText(tr("File %1 could not be written to.").arg(file_name)); + msg.setText(tr("Error") + "\n\n" + tr("File %1 could not be written to.").arg(file_name)); msg.setStandardButtons(QMessageBox::Ok); msg.setIcon(QMessageBox::Warning); msg.exec(); } +void DecodeTrace::on_setting_changed(const QString &key, const QVariant &value) +{ + if (key == GlobalSettings::Key_Dec_AlwaysShowAllRows) { + visible_rows_.clear(); + max_visible_rows_ = 0; + always_show_all_rows_ = value.toBool(); + } +} + void DecodeTrace::on_new_annotations() { if (!delayed_trace_updater_.isActive()) @@ -1157,6 +1202,30 @@ void DecodeTrace::on_show_hide_decoder(int index) owner_->row_item_appearance_changed(false, true); } +void DecodeTrace::on_copy_annotation_to_clipboard() +{ + using namespace pv::data::decode; + + if (!selected_row_) + return; + + vector *annotations = new vector(); + + decode_signal_->get_annotation_subset(*annotations, *selected_row_, + current_segment_, selected_sample_range_.first, selected_sample_range_.first); + + if (annotations->empty()) + return; + + QClipboard *clipboard = QGuiApplication::clipboard(); + clipboard->setText(annotations->front().annotations().front(), QClipboard::Clipboard); + + if (clipboard->supportsSelection()) + clipboard->setText(annotations->front().annotations().front(), QClipboard::Selection); + + delete annotations; +} + void DecodeTrace::on_export_row() { selected_sample_range_ = make_pair(0, numeric_limits::max());