]> sigrok.org Git - pulseview.git/blobdiff - pv/views/trace/decodetrace.cpp
Fix #1107 by implementing a copy-to-clipboard menu entry
[pulseview.git] / pv / views / trace / decodetrace.cpp
index 65a2bf6c6a72f3e773b837e1941565bd7378012a..638de4da5b84bd3686c8ff44afbdee5b562f9115 100644 (file)
@@ -31,6 +31,7 @@ extern "C" {
 
 #include <QAction>
 #include <QApplication>
+#include <QClipboard>
 #include <QComboBox>
 #include <QFileDialog>
 #include <QFormLayout>
@@ -263,6 +264,31 @@ void DecodeTrace::paint_fore(QPainter &p, ViewItemPaintParams &pp)
                paint_hover_marker(p);
 }
 
+void DecodeTrace::update_stack_button()
+{
+       const vector< shared_ptr<data::decode::Decoder> > &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*)));
+
+                       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 +323,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 +371,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<uint64_t, uint64_t> sample_range =
-               get_view_sample_range(click_pos.x(), click_pos.x() + 1);
+       const pair<uint64_t, uint64_t> sample_range = get_view_sample_range(pos.x(), pos.x() + 1);
        selected_sample_range_ = make_pair(sample_range.first, numeric_limits<uint64_t>::max());
 
        if (decode_signal_->is_paused()) {
@@ -372,6 +395,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 +450,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 +861,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;
@@ -1156,6 +1181,27 @@ 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<Annotation> *annotations = new vector<Annotation>();
+
+       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());
+
+       delete annotations;
+}
+
 void DecodeTrace::on_export_row()
 {
        selected_sample_range_ = make_pair(0, numeric_limits<uint64_t>::max());