]> sigrok.org Git - pulseview.git/blame - pv/view/decodetrace.cpp
Improved decode annotation colouring
[pulseview.git] / pv / view / decodetrace.cpp
CommitLineData
55d3603d
JH
1/*
2 * This file is part of the PulseView project.
3 *
4 * Copyright (C) 2012 Joel Holdsworth <joel@airwebreathe.org.uk>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21extern "C" {
22#include <libsigrokdecode/libsigrokdecode.h>
23}
24
06bb4e6a
JH
25#include <extdef.h>
26
b213ef09
JH
27#include <boost/foreach.hpp>
28
c51482b3 29#include <QAction>
d7c0ca4a 30#include <QApplication>
4e5a4405
JH
31#include <QComboBox>
32#include <QFormLayout>
33#include <QLabel>
b213ef09 34#include <QMenu>
ce94e4fd 35#include <QPushButton>
c51482b3 36
b9329558 37#include "decodetrace.h"
55d3603d 38
06bb4e6a 39#include <pv/sigsession.h>
6e89374a 40#include <pv/data/decoderstack.h>
7491a29f 41#include <pv/data/decode/decoder.h>
5dfeb70f
JH
42#include <pv/data/logic.h>
43#include <pv/data/logicsnapshot.h>
06e810f2 44#include <pv/data/decode/annotation.h>
4e5a4405 45#include <pv/view/logicsignal.h>
e0fc5810 46#include <pv/view/view.h>
204bae45 47#include <pv/widgets/decodergroupbox.h>
ce94e4fd 48#include <pv/widgets/decodermenu.h>
119aff65 49
819f4c25
JH
50using boost::dynamic_pointer_cast;
51using boost::shared_ptr;
52using std::list;
53using std::max;
54using std::map;
55using std::min;
56using std::vector;
55d3603d
JH
57
58namespace pv {
59namespace view {
60
b9329558 61const QColor DecodeTrace::DecodeColours[4] = {
06bb4e6a
JH
62 QColor(0xEF, 0x29, 0x29), // Red
63 QColor(0xFC, 0xE9, 0x4F), // Yellow
64 QColor(0x8A, 0xE2, 0x34), // Green
65 QColor(0x72, 0x9F, 0xCF) // Blue
66};
67
b9329558 68const QColor DecodeTrace::ErrorBgColour = QColor(0xEF, 0x29, 0x29);
5dfeb70f 69const QColor DecodeTrace::NoDecodeColour = QColor(0x88, 0x8A, 0x85);
ad50ac1a 70
06e810f2
JH
71const double DecodeTrace::EndCapWidth = 5;
72const int DecodeTrace::DrawPadding = 100;
73
287d607f
JH
74const QColor DecodeTrace::Colours[16] = {
75 QColor(0xEF, 0x29, 0x29),
76 QColor(0xF6, 0x6A, 0x32),
77 QColor(0xFC, 0xAE, 0x3E),
78 QColor(0xFB, 0xCA, 0x47),
79 QColor(0xFC, 0xE9, 0x4F),
80 QColor(0xCD, 0xF0, 0x40),
81 QColor(0x8A, 0xE2, 0x34),
82 QColor(0x4E, 0xDC, 0x44),
83 QColor(0x55, 0xD7, 0x95),
84 QColor(0x64, 0xD1, 0xD2),
85 QColor(0x72, 0x9F, 0xCF),
86 QColor(0xD4, 0x76, 0xC4),
87 QColor(0x9D, 0x79, 0xB9),
88 QColor(0xAD, 0x7F, 0xA8),
89 QColor(0xC2, 0x62, 0x9B),
90 QColor(0xD7, 0x47, 0x6F)
91};
92
93const QColor DecodeTrace::OutlineColours[16] = {
94 QColor(0x77, 0x14, 0x14),
95 QColor(0x7B, 0x35, 0x19),
96 QColor(0x7E, 0x57, 0x1F),
97 QColor(0x7D, 0x65, 0x23),
98 QColor(0x7E, 0x74, 0x27),
99 QColor(0x66, 0x78, 0x20),
100 QColor(0x45, 0x71, 0x1A),
101 QColor(0x27, 0x6E, 0x22),
102 QColor(0x2A, 0x6B, 0x4A),
103 QColor(0x32, 0x68, 0x69),
104 QColor(0x39, 0x4F, 0x67),
105 QColor(0x6A, 0x3B, 0x62),
106 QColor(0x4E, 0x3C, 0x5C),
107 QColor(0x56, 0x3F, 0x54),
108 QColor(0x61, 0x31, 0x4D),
109 QColor(0x6B, 0x23, 0x37)
06e810f2
JH
110};
111
b9329558 112DecodeTrace::DecodeTrace(pv::SigSession &session,
6e89374a 113 boost::shared_ptr<pv::data::DecoderStack> decoder_stack, int index) :
27e8df22
JH
114 Trace(session, QString::fromUtf8(
115 decoder_stack->stack().front()->decoder()->name)),
613d097c 116 _decoder_stack(decoder_stack),
dd048a7e
JH
117 _delete_mapper(this),
118 _show_hide_mapper(this)
55d3603d 119{
6e89374a 120 assert(_decoder_stack);
e0fc5810 121
06bb4e6a 122 _colour = DecodeColours[index % countof(DecodeColours)];
9cef9567 123
6e89374a 124 connect(_decoder_stack.get(), SIGNAL(new_decode_data()),
9cef9567 125 this, SLOT(on_new_decode_data()));
613d097c
JH
126 connect(&_delete_mapper, SIGNAL(mapped(int)),
127 this, SLOT(on_delete_decoder(int)));
dd048a7e
JH
128 connect(&_show_hide_mapper, SIGNAL(mapped(int)),
129 this, SLOT(on_show_hide_decoder(int)));
55d3603d
JH
130}
131
b9329558 132bool DecodeTrace::enabled() const
55d3603d
JH
133{
134 return true;
135}
136
6e89374a 137const boost::shared_ptr<pv::data::DecoderStack>& DecodeTrace::decoder() const
b6b267bb 138{
6e89374a 139 return _decoder_stack;
b6b267bb
JH
140}
141
b9329558 142void DecodeTrace::set_view(pv::view::View *view)
e0fc5810
JH
143{
144 assert(view);
145 Trace::set_view(view);
146}
147
b9329558 148void DecodeTrace::paint_back(QPainter &p, int left, int right)
fe08b6e8 149{
5dfeb70f 150 Trace::paint_back(p, left, right);
fe08b6e8
JH
151 paint_axis(p, get_y(), left, right);
152}
153
b9329558 154void DecodeTrace::paint_mid(QPainter &p, int left, int right)
55d3603d 155{
f9101a91 156 using namespace pv::data::decode;
9472f447 157
9472f447
JH
158 const double scale = _view->scale();
159 assert(scale > 0);
160
9d28da5a 161 double samplerate = _decoder_stack->samplerate();
9472f447
JH
162
163 // Show sample rate as 1Hz when it is unknown
164 if (samplerate == 0.0)
165 samplerate = 1.0;
166
167 const double pixels_offset = (_view->offset() -
6e89374a 168 _decoder_stack->get_start_time()) / scale;
9472f447
JH
169 const double samples_per_pixel = samplerate * scale;
170
92421299
JH
171 const uint64_t start_sample = (uint64_t)max((left + pixels_offset) *
172 samples_per_pixel, 0.0);
173 const uint64_t end_sample = (uint64_t)max((right + pixels_offset) *
174 samples_per_pixel, 0.0);
175
d7c0ca4a 176 QFontMetrics m(QApplication::font());
f9101a91
JH
177 const int text_height = m.boundingRect(QRect(), 0, "Tg").height();
178 const int annotation_height = (text_height * 5) / 4;
179 const int row_height = (text_height * 6) / 4;
5dfeb70f
JH
180
181 assert(_decoder_stack);
182 const QString err = _decoder_stack->error_message();
183 if (!err.isEmpty())
184 {
185 draw_error(p, err, left, right);
f9101a91
JH
186 draw_unresolved_period(p, annotation_height, left, right,
187 samples_per_pixel, pixels_offset);
5dfeb70f
JH
188 return;
189 }
190
f9101a91 191 // Iterate through the rows
5dfeb70f 192 assert(_view);
f9101a91 193 int y = get_y();
5dfeb70f 194
6e89374a 195 assert(_decoder_stack);
7e674e43 196
dd048a7e 197 const vector<Row> rows(_decoder_stack->get_visible_rows());
bf51365c 198 for (size_t i = 0; i < rows.size(); i++)
92421299 199 {
bf51365c 200 const Row &row = rows[i];
287d607f
JH
201
202 size_t base_colour = 0x13579BDF;
203 boost::hash_combine(base_colour, this);
204 boost::hash_combine(base_colour, row.decoder());
205 boost::hash_combine(base_colour, row.row());
206 base_colour >>= 16;
207
f9101a91
JH
208 vector<Annotation> annotations;
209 _decoder_stack->get_annotation_subset(annotations, row,
210 start_sample, end_sample);
211 if (!annotations.empty()) {
212 BOOST_FOREACH(const Annotation &a, annotations)
213 draw_annotation(a, p, get_text_colour(),
214 annotation_height, left, right,
287d607f
JH
215 samples_per_pixel, pixels_offset, y,
216 base_colour);
f9101a91
JH
217 y += row_height;
218 }
7e674e43 219 }
5dfeb70f 220
f9101a91
JH
221 // Draw the hatching
222 draw_unresolved_period(p, annotation_height, left, right,
5dfeb70f 223 samples_per_pixel, pixels_offset);
55d3603d
JH
224}
225
b9329558 226void DecodeTrace::populate_popup_form(QWidget *parent, QFormLayout *form)
4e5a4405 227{
613d097c
JH
228 using pv::data::decode::Decoder;
229
4e5a4405
JH
230 assert(form);
231 assert(parent);
6e89374a 232 assert(_decoder_stack);
4e5a4405 233
7491a29f 234 // Add the standard options
4e5a4405
JH
235 Trace::populate_popup_form(parent, form);
236
7491a29f
JH
237 // Add the decoder options
238 _bindings.clear();
239 _probe_selectors.clear();
dd048a7e 240 _decoder_forms.clear();
4e5a4405 241
613d097c 242 const list< shared_ptr<Decoder> >& stack = _decoder_stack->stack();
4e5a4405 243
5069084a
JH
244 if (stack.empty())
245 {
246 QLabel *const l = new QLabel(
247 tr("<p><i>No decoders in the stack</i></p>"));
248 l->setAlignment(Qt::AlignCenter);
249 form->addRow(l);
250 }
251 else
252 {
253 list< shared_ptr<Decoder> >::const_iterator iter =
254 stack.begin();
255 for (int i = 0; i < (int)stack.size(); i++, iter++) {
256 shared_ptr<Decoder> dec(*iter);
257 create_decoder_form(i, dec, parent, form);
258 }
259
260 form->addRow(new QLabel(
261 tr("<i>* Required Probes</i>"), parent));
262 }
4e5a4405 263
ce94e4fd 264 // Add stacking button
ce94e4fd
JH
265 pv::widgets::DecoderMenu *const decoder_menu =
266 new pv::widgets::DecoderMenu(parent);
7491a29f
JH
267 connect(decoder_menu, SIGNAL(decoder_selected(srd_decoder*)),
268 this, SLOT(on_stack_decoder(srd_decoder*)));
269
270 QPushButton *const stack_button =
271 new QPushButton(tr("Stack Decoder"), parent);
ce94e4fd
JH
272 stack_button->setMenu(decoder_menu);
273
274 QHBoxLayout *stack_button_box = new QHBoxLayout;
275 stack_button_box->addWidget(stack_button, 0, Qt::AlignRight);
276 form->addRow(stack_button_box);
4e5a4405
JH
277}
278
b9329558 279QMenu* DecodeTrace::create_context_menu(QWidget *parent)
c51482b3
JH
280{
281 QMenu *const menu = Trace::create_context_menu(parent);
282
283 menu->addSeparator();
284
285 QAction *const del = new QAction(tr("Delete"), this);
a2d21018 286 del->setShortcuts(QKeySequence::Delete);
c51482b3
JH
287 connect(del, SIGNAL(triggered()), this, SLOT(on_delete()));
288 menu->addAction(del);
289
290 return menu;
291}
292
287d607f
JH
293void DecodeTrace::draw_annotation(const pv::data::decode::Annotation &a,
294 QPainter &p, QColor text_color, int h, int left, int right,
295 double samples_per_pixel, double pixels_offset, int y,
296 size_t base_colour) const
06e810f2
JH
297{
298 const double start = a.start_sample() / samples_per_pixel -
299 pixels_offset;
300 const double end = a.end_sample() / samples_per_pixel -
301 pixels_offset;
287d607f
JH
302
303 const size_t colour = (base_colour + a.format()) % countof(Colours);
304 const QColor &fill = Colours[colour];
305 const QColor &outline = OutlineColours[colour];
06e810f2
JH
306
307 if (start > right + DrawPadding || end < left - DrawPadding)
308 return;
309
310 if (a.start_sample() == a.end_sample())
311 draw_instant(a, p, fill, outline, text_color, h,
312 start, y);
313 else
314 draw_range(a, p, fill, outline, text_color, h,
315 start, end, y);
316}
317
318void DecodeTrace::draw_instant(const pv::data::decode::Annotation &a, QPainter &p,
319 QColor fill, QColor outline, QColor text_color, int h, double x, int y) const
320{
321 const QString text = a.annotations().empty() ?
322 QString() : a.annotations().back();
323 const double w = min(p.boundingRect(QRectF(), 0, text).width(),
324 0.0) + h;
325 const QRectF rect(x - w / 2, y - h / 2, w, h);
326
327 p.setPen(outline);
328 p.setBrush(fill);
329 p.drawRoundedRect(rect, h / 2, h / 2);
330
331 p.setPen(text_color);
332 p.drawText(rect, Qt::AlignCenter | Qt::AlignVCenter, text);
333}
334
335void DecodeTrace::draw_range(const pv::data::decode::Annotation &a, QPainter &p,
336 QColor fill, QColor outline, QColor text_color, int h, double start,
337 double end, int y) const
338{
339 const double top = y + .5 - h / 2;
340 const double bottom = y + .5 + h / 2;
341 const vector<QString> annotations = a.annotations();
342
343 p.setPen(outline);
344 p.setBrush(fill);
345
346 // If the two ends are within 1 pixel, draw a vertical line
347 if (start + 1.0 > end)
348 {
349 p.drawLine(QPointF(start, top), QPointF(start, bottom));
350 return;
351 }
352
353 const double cap_width = min((end - start) / 4, EndCapWidth);
354
355 QPointF pts[] = {
356 QPointF(start, y + .5f),
357 QPointF(start + cap_width, top),
358 QPointF(end - cap_width, top),
359 QPointF(end, y + .5f),
360 QPointF(end - cap_width, bottom),
361 QPointF(start + cap_width, bottom)
362 };
363
364 p.drawConvexPolygon(pts, countof(pts));
365
366 if (annotations.empty())
367 return;
368
369 QRectF rect(start + cap_width, y - h / 2,
370 end - start - cap_width * 2, h);
371 p.setPen(text_color);
372
373 // Try to find an annotation that will fit
374 QString best_annotation;
375 int best_width = 0;
376
377 BOOST_FOREACH(const QString &a, annotations) {
378 const int w = p.boundingRect(QRectF(), 0, a).width();
379 if (w <= rect.width() && w > best_width)
380 best_annotation = a, best_width = w;
381 }
382
383 if (best_annotation.isEmpty())
384 best_annotation = annotations.back();
385
386 // If not ellide the last in the list
387 p.drawText(rect, Qt::AlignCenter, p.fontMetrics().elidedText(
388 best_annotation, Qt::ElideRight, rect.width()));
389}
390
b9329558 391void DecodeTrace::draw_error(QPainter &p, const QString &message,
ad50ac1a
JH
392 int left, int right)
393{
394 const int y = get_y();
395
396 p.setPen(ErrorBgColour.darker());
397 p.setBrush(ErrorBgColour);
398
399 const QRectF bounding_rect =
400 QRectF(left, INT_MIN / 2 + y, right - left, INT_MAX);
401 const QRectF text_rect = p.boundingRect(bounding_rect,
402 Qt::AlignCenter, message);
403 const float r = text_rect.height() / 4;
404
405 p.drawRoundedRect(text_rect.adjusted(-r, -r, r, r), r, r,
406 Qt::AbsoluteSize);
407
408 p.setPen(get_text_colour());
409 p.drawText(text_rect, message);
410}
411
5dfeb70f
JH
412void DecodeTrace::draw_unresolved_period(QPainter &p, int h, int left,
413 int right, double samples_per_pixel, double pixels_offset)
414{
415 using namespace pv::data;
416 using pv::data::decode::Decoder;
417
418 assert(_decoder_stack);
419
420 shared_ptr<Logic> data;
421 shared_ptr<LogicSignal> logic_signal;
422
423 const list< shared_ptr<Decoder> > &stack = _decoder_stack->stack();
424
425 // We get the logic data of the first probe in the list.
426 // This works because we are currently assuming all
427 // LogicSignals have the same data/snapshot
428 BOOST_FOREACH (const shared_ptr<Decoder> &dec, stack)
429 if (dec && !dec->probes().empty() &&
430 ((logic_signal = (*dec->probes().begin()).second)) &&
7aa09b00 431 ((data = logic_signal->logic_data())))
5dfeb70f
JH
432 break;
433
434 if (!data || data->get_snapshots().empty())
435 return;
436
437 const shared_ptr<LogicSnapshot> snapshot =
438 data->get_snapshots().front();
439 assert(snapshot);
440 const int64_t sample_count = (int64_t)snapshot->get_sample_count();
441 if (sample_count == 0)
442 return;
443
444 const int64_t samples_decoded = _decoder_stack->samples_decoded();
445 if (sample_count == samples_decoded)
446 return;
447
448 const int y = get_y();
449 const double start = max(samples_decoded /
450 samples_per_pixel - pixels_offset, left - 1.0);
451 const double end = min(sample_count / samples_per_pixel -
452 pixels_offset, right + 1.0);
453 const QRectF no_decode_rect(start, y - h/2 + 0.5, end - start, h);
454
455 p.setPen(QPen(Qt::NoPen));
456 p.setBrush(Qt::white);
457 p.drawRect(no_decode_rect);
458
459 p.setPen(NoDecodeColour);
460 p.setBrush(QBrush(NoDecodeColour, Qt::Dense6Pattern));
461 p.drawRect(no_decode_rect);
462}
463
613d097c
JH
464void DecodeTrace::create_decoder_form(int index,
465 shared_ptr<data::decode::Decoder> &dec, QWidget *parent,
466 QFormLayout *form)
7491a29f
JH
467{
468 const GSList *probe;
469
470 assert(dec);
471 const srd_decoder *const decoder = dec->decoder();
472 assert(decoder);
473
204bae45 474 pv::widgets::DecoderGroupBox *const group =
27e8df22
JH
475 new pv::widgets::DecoderGroupBox(
476 QString::fromUtf8(decoder->name));
dd048a7e 477 group->set_decoder_visible(dec->shown());
613d097c
JH
478
479 _delete_mapper.setMapping(group, index);
480 connect(group, SIGNAL(delete_decoder()), &_delete_mapper, SLOT(map()));
481
dd048a7e
JH
482 _show_hide_mapper.setMapping(group, index);
483 connect(group, SIGNAL(show_hide_decoder()),
484 &_show_hide_mapper, SLOT(map()));
485
204bae45
JH
486 QFormLayout *const decoder_form = new QFormLayout;
487 group->add_layout(decoder_form);
7491a29f
JH
488
489 // Add the mandatory probes
490 for(probe = decoder->probes; probe; probe = probe->next) {
491 const struct srd_probe *const p =
492 (struct srd_probe *)probe->data;
493 QComboBox *const combo = create_probe_selector(parent, dec, p);
494 connect(combo, SIGNAL(currentIndexChanged(int)),
495 this, SLOT(on_probe_selected(int)));
204bae45 496 decoder_form->addRow(tr("<b>%1</b> (%2) *")
7491a29f
JH
497 .arg(p->name).arg(p->desc), combo);
498
499 const ProbeSelector s = {combo, dec, p};
500 _probe_selectors.push_back(s);
501 }
502
503 // Add the optional probes
504 for(probe = decoder->opt_probes; probe; probe = probe->next) {
505 const struct srd_probe *const p =
506 (struct srd_probe *)probe->data;
507 QComboBox *const combo = create_probe_selector(parent, dec, p);
508 connect(combo, SIGNAL(currentIndexChanged(int)),
509 this, SLOT(on_probe_selected(int)));
204bae45 510 decoder_form->addRow(tr("<b>%1</b> (%2)")
7491a29f
JH
511 .arg(p->name).arg(p->desc), combo);
512
513 const ProbeSelector s = {combo, dec, p};
514 _probe_selectors.push_back(s);
515 }
516
517 // Add the options
518 shared_ptr<prop::binding::DecoderOptions> binding(
519 new prop::binding::DecoderOptions(_decoder_stack, dec));
204bae45 520 binding->add_properties_to_form(decoder_form, true);
7491a29f
JH
521
522 _bindings.push_back(binding);
204bae45
JH
523
524 form->addRow(group);
dd048a7e 525 _decoder_forms.push_back(group);
7491a29f
JH
526}
527
b9329558 528QComboBox* DecodeTrace::create_probe_selector(
7491a29f
JH
529 QWidget *parent, const shared_ptr<data::decode::Decoder> &dec,
530 const srd_probe *const probe)
4e5a4405 531{
7491a29f
JH
532 assert(dec);
533
4e5a4405
JH
534 const vector< shared_ptr<Signal> > sigs = _session.get_signals();
535
6e89374a 536 assert(_decoder_stack);
4e5a4405
JH
537 const map<const srd_probe*,
538 shared_ptr<LogicSignal> >::const_iterator probe_iter =
7491a29f 539 dec->probes().find(probe);
4e5a4405
JH
540
541 QComboBox *selector = new QComboBox(parent);
542
543 selector->addItem("-", qVariantFromValue((void*)NULL));
544
7491a29f 545 if (probe_iter == dec->probes().end())
4e5a4405
JH
546 selector->setCurrentIndex(0);
547
548 for(size_t i = 0; i < sigs.size(); i++) {
549 const shared_ptr<view::Signal> s(sigs[i]);
550 assert(s);
551
552 if (dynamic_pointer_cast<LogicSignal>(s) && s->enabled())
553 {
554 selector->addItem(s->get_name(),
555 qVariantFromValue((void*)s.get()));
556 if ((*probe_iter).second == s)
557 selector->setCurrentIndex(i + 1);
558 }
559 }
560
561 return selector;
562}
563
7491a29f 564void DecodeTrace::commit_decoder_probes(shared_ptr<data::decode::Decoder> &dec)
4e5a4405 565{
7491a29f 566 assert(dec);
4e5a4405
JH
567
568 map<const srd_probe*, shared_ptr<LogicSignal> > probe_map;
569 const vector< shared_ptr<Signal> > sigs = _session.get_signals();
570
7491a29f 571 BOOST_FOREACH(const ProbeSelector &s, _probe_selectors)
4e5a4405 572 {
7491a29f
JH
573 if(s._decoder != dec)
574 break;
575
4e5a4405 576 const LogicSignal *const selection =
7491a29f
JH
577 (LogicSignal*)s._combo->itemData(
578 s._combo->currentIndex()).value<void*>();
4e5a4405 579
7491a29f
JH
580 BOOST_FOREACH(shared_ptr<Signal> sig, sigs)
581 if(sig.get() == selection) {
582 probe_map[s._probe] =
583 dynamic_pointer_cast<LogicSignal>(sig);
4e5a4405
JH
584 break;
585 }
586 }
587
7491a29f
JH
588 dec->set_probes(probe_map);
589}
590
591void DecodeTrace::commit_probes()
592{
593 assert(_decoder_stack);
594 BOOST_FOREACH(shared_ptr<data::decode::Decoder> dec,
595 _decoder_stack->stack())
596 commit_decoder_probes(dec);
597
598 _decoder_stack->begin_decode();
4e5a4405
JH
599}
600
b9329558 601void DecodeTrace::on_new_decode_data()
9cef9567
JH
602{
603 if (_view)
604 _view->update_viewport();
605}
606
b9329558 607void DecodeTrace::delete_pressed()
5ed1adf5
JH
608{
609 on_delete();
610}
611
b9329558 612void DecodeTrace::on_delete()
c51482b3
JH
613{
614 _session.remove_decode_signal(this);
615}
616
b9329558 617void DecodeTrace::on_probe_selected(int)
4e5a4405
JH
618{
619 commit_probes();
620}
621
7491a29f
JH
622void DecodeTrace::on_stack_decoder(srd_decoder *decoder)
623{
624 assert(decoder);
625 assert(_decoder_stack);
626 _decoder_stack->push(shared_ptr<data::decode::Decoder>(
627 new data::decode::Decoder(decoder)));
628 _decoder_stack->begin_decode();
37fd11b1
JH
629
630 create_popup_form();
7491a29f
JH
631}
632
613d097c
JH
633void DecodeTrace::on_delete_decoder(int index)
634{
635 _decoder_stack->remove(index);
636
637 // Update the popup
638 create_popup_form();
639
640 _decoder_stack->begin_decode();
641}
642
dd048a7e
JH
643void DecodeTrace::on_show_hide_decoder(int index)
644{
645 using pv::data::decode::Decoder;
646
647 const list< shared_ptr<Decoder> > stack(_decoder_stack->stack());
648
649 // Find the decoder in the stack
650 list< shared_ptr<Decoder> >::const_iterator iter = stack.begin();
651 for(int i = 0; i < index; i++, iter++)
652 assert(iter != stack.end());
653
654 shared_ptr<Decoder> dec = *iter;
655 assert(dec);
656
657 const bool show = !dec->shown();
658 dec->show(show);
659
660 assert(index < (int)_decoder_forms.size());
661 _decoder_forms[index]->set_decoder_visible(show);
662
663 _view->update_viewport();
664}
665
55d3603d
JH
666} // namespace view
667} // namespace pv