]> sigrok.org Git - pulseview.git/blame - pv/view/decodetrace.cpp
Fixed unit test CMakeLists.txt
[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) :
83c23cc9 114 Trace(QString::fromUtf8(
27e8df22 115 decoder_stack->stack().front()->decoder()->name)),
83c23cc9 116 _session(session),
613d097c 117 _decoder_stack(decoder_stack),
dd048a7e
JH
118 _delete_mapper(this),
119 _show_hide_mapper(this)
55d3603d 120{
6e89374a 121 assert(_decoder_stack);
e0fc5810 122
06bb4e6a 123 _colour = DecodeColours[index % countof(DecodeColours)];
9cef9567 124
6e89374a 125 connect(_decoder_stack.get(), SIGNAL(new_decode_data()),
9cef9567 126 this, SLOT(on_new_decode_data()));
613d097c
JH
127 connect(&_delete_mapper, SIGNAL(mapped(int)),
128 this, SLOT(on_delete_decoder(int)));
dd048a7e
JH
129 connect(&_show_hide_mapper, SIGNAL(mapped(int)),
130 this, SLOT(on_show_hide_decoder(int)));
55d3603d
JH
131}
132
b9329558 133bool DecodeTrace::enabled() const
55d3603d
JH
134{
135 return true;
136}
137
6e89374a 138const boost::shared_ptr<pv::data::DecoderStack>& DecodeTrace::decoder() const
b6b267bb 139{
6e89374a 140 return _decoder_stack;
b6b267bb
JH
141}
142
b9329558 143void DecodeTrace::set_view(pv::view::View *view)
e0fc5810
JH
144{
145 assert(view);
146 Trace::set_view(view);
147}
148
b9329558 149void DecodeTrace::paint_back(QPainter &p, int left, int right)
fe08b6e8 150{
5dfeb70f 151 Trace::paint_back(p, left, right);
fe08b6e8
JH
152 paint_axis(p, get_y(), left, right);
153}
154
b9329558 155void DecodeTrace::paint_mid(QPainter &p, int left, int right)
55d3603d 156{
f9101a91 157 using namespace pv::data::decode;
9472f447 158
9472f447
JH
159 const double scale = _view->scale();
160 assert(scale > 0);
161
9d28da5a 162 double samplerate = _decoder_stack->samplerate();
9472f447
JH
163
164 // Show sample rate as 1Hz when it is unknown
165 if (samplerate == 0.0)
166 samplerate = 1.0;
167
168 const double pixels_offset = (_view->offset() -
6e89374a 169 _decoder_stack->get_start_time()) / scale;
9472f447
JH
170 const double samples_per_pixel = samplerate * scale;
171
92421299
JH
172 const uint64_t start_sample = (uint64_t)max((left + pixels_offset) *
173 samples_per_pixel, 0.0);
174 const uint64_t end_sample = (uint64_t)max((right + pixels_offset) *
175 samples_per_pixel, 0.0);
176
d7c0ca4a 177 QFontMetrics m(QApplication::font());
f9101a91
JH
178 const int text_height = m.boundingRect(QRect(), 0, "Tg").height();
179 const int annotation_height = (text_height * 5) / 4;
180 const int row_height = (text_height * 6) / 4;
5dfeb70f
JH
181
182 assert(_decoder_stack);
183 const QString err = _decoder_stack->error_message();
184 if (!err.isEmpty())
185 {
f9101a91
JH
186 draw_unresolved_period(p, annotation_height, left, right,
187 samples_per_pixel, pixels_offset);
5b8b1e47 188 draw_error(p, err, left, right);
5dfeb70f
JH
189 return;
190 }
191
f9101a91 192 // Iterate through the rows
5dfeb70f 193 assert(_view);
f9101a91 194 int y = get_y();
5dfeb70f 195
6e89374a 196 assert(_decoder_stack);
7e674e43 197
dd048a7e 198 const vector<Row> rows(_decoder_stack->get_visible_rows());
bf51365c 199 for (size_t i = 0; i < rows.size(); i++)
92421299 200 {
bf51365c 201 const Row &row = rows[i];
287d607f
JH
202
203 size_t base_colour = 0x13579BDF;
204 boost::hash_combine(base_colour, this);
205 boost::hash_combine(base_colour, row.decoder());
206 boost::hash_combine(base_colour, row.row());
207 base_colour >>= 16;
208
f9101a91
JH
209 vector<Annotation> annotations;
210 _decoder_stack->get_annotation_subset(annotations, row,
211 start_sample, end_sample);
212 if (!annotations.empty()) {
213 BOOST_FOREACH(const Annotation &a, annotations)
214 draw_annotation(a, p, get_text_colour(),
215 annotation_height, left, right,
287d607f
JH
216 samples_per_pixel, pixels_offset, y,
217 base_colour);
f9101a91
JH
218 y += row_height;
219 }
7e674e43 220 }
5dfeb70f 221
f9101a91
JH
222 // Draw the hatching
223 draw_unresolved_period(p, annotation_height, left, right,
5dfeb70f 224 samples_per_pixel, pixels_offset);
55d3603d
JH
225}
226
b9329558 227void DecodeTrace::populate_popup_form(QWidget *parent, QFormLayout *form)
4e5a4405 228{
613d097c
JH
229 using pv::data::decode::Decoder;
230
4e5a4405
JH
231 assert(form);
232 assert(parent);
6e89374a 233 assert(_decoder_stack);
4e5a4405 234
7491a29f 235 // Add the standard options
4e5a4405
JH
236 Trace::populate_popup_form(parent, form);
237
7491a29f
JH
238 // Add the decoder options
239 _bindings.clear();
240 _probe_selectors.clear();
dd048a7e 241 _decoder_forms.clear();
4e5a4405 242
613d097c 243 const list< shared_ptr<Decoder> >& stack = _decoder_stack->stack();
4e5a4405 244
5069084a
JH
245 if (stack.empty())
246 {
247 QLabel *const l = new QLabel(
248 tr("<p><i>No decoders in the stack</i></p>"));
249 l->setAlignment(Qt::AlignCenter);
250 form->addRow(l);
251 }
252 else
253 {
254 list< shared_ptr<Decoder> >::const_iterator iter =
255 stack.begin();
256 for (int i = 0; i < (int)stack.size(); i++, iter++) {
257 shared_ptr<Decoder> dec(*iter);
258 create_decoder_form(i, dec, parent, form);
259 }
260
261 form->addRow(new QLabel(
262 tr("<i>* Required Probes</i>"), parent));
263 }
4e5a4405 264
ce94e4fd 265 // Add stacking button
ce94e4fd
JH
266 pv::widgets::DecoderMenu *const decoder_menu =
267 new pv::widgets::DecoderMenu(parent);
7491a29f
JH
268 connect(decoder_menu, SIGNAL(decoder_selected(srd_decoder*)),
269 this, SLOT(on_stack_decoder(srd_decoder*)));
270
271 QPushButton *const stack_button =
272 new QPushButton(tr("Stack Decoder"), parent);
ce94e4fd
JH
273 stack_button->setMenu(decoder_menu);
274
275 QHBoxLayout *stack_button_box = new QHBoxLayout;
276 stack_button_box->addWidget(stack_button, 0, Qt::AlignRight);
277 form->addRow(stack_button_box);
4e5a4405
JH
278}
279
b9329558 280QMenu* DecodeTrace::create_context_menu(QWidget *parent)
c51482b3
JH
281{
282 QMenu *const menu = Trace::create_context_menu(parent);
283
284 menu->addSeparator();
285
286 QAction *const del = new QAction(tr("Delete"), this);
a2d21018 287 del->setShortcuts(QKeySequence::Delete);
c51482b3
JH
288 connect(del, SIGNAL(triggered()), this, SLOT(on_delete()));
289 menu->addAction(del);
290
291 return menu;
292}
293
287d607f
JH
294void DecodeTrace::draw_annotation(const pv::data::decode::Annotation &a,
295 QPainter &p, QColor text_color, int h, int left, int right,
296 double samples_per_pixel, double pixels_offset, int y,
297 size_t base_colour) const
06e810f2
JH
298{
299 const double start = a.start_sample() / samples_per_pixel -
300 pixels_offset;
301 const double end = a.end_sample() / samples_per_pixel -
302 pixels_offset;
287d607f
JH
303
304 const size_t colour = (base_colour + a.format()) % countof(Colours);
305 const QColor &fill = Colours[colour];
306 const QColor &outline = OutlineColours[colour];
06e810f2
JH
307
308 if (start > right + DrawPadding || end < left - DrawPadding)
309 return;
310
311 if (a.start_sample() == a.end_sample())
312 draw_instant(a, p, fill, outline, text_color, h,
313 start, y);
314 else
315 draw_range(a, p, fill, outline, text_color, h,
316 start, end, y);
317}
318
319void DecodeTrace::draw_instant(const pv::data::decode::Annotation &a, QPainter &p,
320 QColor fill, QColor outline, QColor text_color, int h, double x, int y) const
321{
322 const QString text = a.annotations().empty() ?
323 QString() : a.annotations().back();
324 const double w = min(p.boundingRect(QRectF(), 0, text).width(),
325 0.0) + h;
326 const QRectF rect(x - w / 2, y - h / 2, w, h);
327
328 p.setPen(outline);
329 p.setBrush(fill);
330 p.drawRoundedRect(rect, h / 2, h / 2);
331
332 p.setPen(text_color);
333 p.drawText(rect, Qt::AlignCenter | Qt::AlignVCenter, text);
334}
335
336void DecodeTrace::draw_range(const pv::data::decode::Annotation &a, QPainter &p,
337 QColor fill, QColor outline, QColor text_color, int h, double start,
338 double end, int y) const
339{
340 const double top = y + .5 - h / 2;
341 const double bottom = y + .5 + h / 2;
342 const vector<QString> annotations = a.annotations();
343
344 p.setPen(outline);
345 p.setBrush(fill);
346
347 // If the two ends are within 1 pixel, draw a vertical line
348 if (start + 1.0 > end)
349 {
350 p.drawLine(QPointF(start, top), QPointF(start, bottom));
351 return;
352 }
353
354 const double cap_width = min((end - start) / 4, EndCapWidth);
355
356 QPointF pts[] = {
357 QPointF(start, y + .5f),
358 QPointF(start + cap_width, top),
359 QPointF(end - cap_width, top),
360 QPointF(end, y + .5f),
361 QPointF(end - cap_width, bottom),
362 QPointF(start + cap_width, bottom)
363 };
364
365 p.drawConvexPolygon(pts, countof(pts));
366
367 if (annotations.empty())
368 return;
369
370 QRectF rect(start + cap_width, y - h / 2,
371 end - start - cap_width * 2, h);
372 p.setPen(text_color);
373
374 // Try to find an annotation that will fit
375 QString best_annotation;
376 int best_width = 0;
377
378 BOOST_FOREACH(const QString &a, annotations) {
379 const int w = p.boundingRect(QRectF(), 0, a).width();
380 if (w <= rect.width() && w > best_width)
381 best_annotation = a, best_width = w;
382 }
383
384 if (best_annotation.isEmpty())
385 best_annotation = annotations.back();
386
387 // If not ellide the last in the list
388 p.drawText(rect, Qt::AlignCenter, p.fontMetrics().elidedText(
389 best_annotation, Qt::ElideRight, rect.width()));
390}
391
b9329558 392void DecodeTrace::draw_error(QPainter &p, const QString &message,
ad50ac1a
JH
393 int left, int right)
394{
395 const int y = get_y();
396
397 p.setPen(ErrorBgColour.darker());
398 p.setBrush(ErrorBgColour);
399
400 const QRectF bounding_rect =
401 QRectF(left, INT_MIN / 2 + y, right - left, INT_MAX);
402 const QRectF text_rect = p.boundingRect(bounding_rect,
403 Qt::AlignCenter, message);
404 const float r = text_rect.height() / 4;
405
406 p.drawRoundedRect(text_rect.adjusted(-r, -r, r, r), r, r,
407 Qt::AbsoluteSize);
408
409 p.setPen(get_text_colour());
410 p.drawText(text_rect, message);
411}
412
5dfeb70f
JH
413void DecodeTrace::draw_unresolved_period(QPainter &p, int h, int left,
414 int right, double samples_per_pixel, double pixels_offset)
415{
416 using namespace pv::data;
417 using pv::data::decode::Decoder;
418
419 assert(_decoder_stack);
420
421 shared_ptr<Logic> data;
422 shared_ptr<LogicSignal> logic_signal;
423
424 const list< shared_ptr<Decoder> > &stack = _decoder_stack->stack();
425
426 // We get the logic data of the first probe in the list.
427 // This works because we are currently assuming all
428 // LogicSignals have the same data/snapshot
429 BOOST_FOREACH (const shared_ptr<Decoder> &dec, stack)
430 if (dec && !dec->probes().empty() &&
431 ((logic_signal = (*dec->probes().begin()).second)) &&
7aa09b00 432 ((data = logic_signal->logic_data())))
5dfeb70f
JH
433 break;
434
435 if (!data || data->get_snapshots().empty())
436 return;
437
438 const shared_ptr<LogicSnapshot> snapshot =
439 data->get_snapshots().front();
440 assert(snapshot);
441 const int64_t sample_count = (int64_t)snapshot->get_sample_count();
442 if (sample_count == 0)
443 return;
444
445 const int64_t samples_decoded = _decoder_stack->samples_decoded();
446 if (sample_count == samples_decoded)
447 return;
448
449 const int y = get_y();
450 const double start = max(samples_decoded /
451 samples_per_pixel - pixels_offset, left - 1.0);
452 const double end = min(sample_count / samples_per_pixel -
453 pixels_offset, right + 1.0);
454 const QRectF no_decode_rect(start, y - h/2 + 0.5, end - start, h);
455
456 p.setPen(QPen(Qt::NoPen));
457 p.setBrush(Qt::white);
458 p.drawRect(no_decode_rect);
459
460 p.setPen(NoDecodeColour);
461 p.setBrush(QBrush(NoDecodeColour, Qt::Dense6Pattern));
462 p.drawRect(no_decode_rect);
463}
464
613d097c
JH
465void DecodeTrace::create_decoder_form(int index,
466 shared_ptr<data::decode::Decoder> &dec, QWidget *parent,
467 QFormLayout *form)
7491a29f
JH
468{
469 const GSList *probe;
470
471 assert(dec);
472 const srd_decoder *const decoder = dec->decoder();
473 assert(decoder);
474
204bae45 475 pv::widgets::DecoderGroupBox *const group =
27e8df22
JH
476 new pv::widgets::DecoderGroupBox(
477 QString::fromUtf8(decoder->name));
dd048a7e 478 group->set_decoder_visible(dec->shown());
613d097c
JH
479
480 _delete_mapper.setMapping(group, index);
481 connect(group, SIGNAL(delete_decoder()), &_delete_mapper, SLOT(map()));
482
dd048a7e
JH
483 _show_hide_mapper.setMapping(group, index);
484 connect(group, SIGNAL(show_hide_decoder()),
485 &_show_hide_mapper, SLOT(map()));
486
204bae45
JH
487 QFormLayout *const decoder_form = new QFormLayout;
488 group->add_layout(decoder_form);
7491a29f
JH
489
490 // Add the mandatory probes
491 for(probe = decoder->probes; probe; probe = probe->next) {
492 const struct srd_probe *const p =
493 (struct srd_probe *)probe->data;
494 QComboBox *const combo = create_probe_selector(parent, dec, p);
495 connect(combo, SIGNAL(currentIndexChanged(int)),
496 this, SLOT(on_probe_selected(int)));
204bae45 497 decoder_form->addRow(tr("<b>%1</b> (%2) *")
636782c1
JH
498 .arg(QString::fromUtf8(p->name))
499 .arg(QString::fromUtf8(p->desc)), combo);
7491a29f
JH
500
501 const ProbeSelector s = {combo, dec, p};
502 _probe_selectors.push_back(s);
503 }
504
505 // Add the optional probes
506 for(probe = decoder->opt_probes; probe; probe = probe->next) {
507 const struct srd_probe *const p =
508 (struct srd_probe *)probe->data;
509 QComboBox *const combo = create_probe_selector(parent, dec, p);
510 connect(combo, SIGNAL(currentIndexChanged(int)),
511 this, SLOT(on_probe_selected(int)));
204bae45 512 decoder_form->addRow(tr("<b>%1</b> (%2)")
636782c1
JH
513 .arg(QString::fromUtf8(p->name))
514 .arg(QString::fromUtf8(p->desc)), combo);
7491a29f
JH
515
516 const ProbeSelector s = {combo, dec, p};
517 _probe_selectors.push_back(s);
518 }
519
520 // Add the options
521 shared_ptr<prop::binding::DecoderOptions> binding(
522 new prop::binding::DecoderOptions(_decoder_stack, dec));
204bae45 523 binding->add_properties_to_form(decoder_form, true);
7491a29f
JH
524
525 _bindings.push_back(binding);
204bae45
JH
526
527 form->addRow(group);
dd048a7e 528 _decoder_forms.push_back(group);
7491a29f
JH
529}
530
b9329558 531QComboBox* DecodeTrace::create_probe_selector(
7491a29f
JH
532 QWidget *parent, const shared_ptr<data::decode::Decoder> &dec,
533 const srd_probe *const probe)
4e5a4405 534{
7491a29f
JH
535 assert(dec);
536
4e5a4405
JH
537 const vector< shared_ptr<Signal> > sigs = _session.get_signals();
538
6e89374a 539 assert(_decoder_stack);
4e5a4405
JH
540 const map<const srd_probe*,
541 shared_ptr<LogicSignal> >::const_iterator probe_iter =
7491a29f 542 dec->probes().find(probe);
4e5a4405
JH
543
544 QComboBox *selector = new QComboBox(parent);
545
546 selector->addItem("-", qVariantFromValue((void*)NULL));
547
7491a29f 548 if (probe_iter == dec->probes().end())
4e5a4405
JH
549 selector->setCurrentIndex(0);
550
551 for(size_t i = 0; i < sigs.size(); i++) {
552 const shared_ptr<view::Signal> s(sigs[i]);
553 assert(s);
554
555 if (dynamic_pointer_cast<LogicSignal>(s) && s->enabled())
556 {
557 selector->addItem(s->get_name(),
558 qVariantFromValue((void*)s.get()));
559 if ((*probe_iter).second == s)
560 selector->setCurrentIndex(i + 1);
561 }
562 }
563
564 return selector;
565}
566
7491a29f 567void DecodeTrace::commit_decoder_probes(shared_ptr<data::decode::Decoder> &dec)
4e5a4405 568{
7491a29f 569 assert(dec);
4e5a4405
JH
570
571 map<const srd_probe*, shared_ptr<LogicSignal> > probe_map;
572 const vector< shared_ptr<Signal> > sigs = _session.get_signals();
573
7491a29f 574 BOOST_FOREACH(const ProbeSelector &s, _probe_selectors)
4e5a4405 575 {
7491a29f
JH
576 if(s._decoder != dec)
577 break;
578
4e5a4405 579 const LogicSignal *const selection =
7491a29f
JH
580 (LogicSignal*)s._combo->itemData(
581 s._combo->currentIndex()).value<void*>();
4e5a4405 582
7491a29f
JH
583 BOOST_FOREACH(shared_ptr<Signal> sig, sigs)
584 if(sig.get() == selection) {
585 probe_map[s._probe] =
586 dynamic_pointer_cast<LogicSignal>(sig);
4e5a4405
JH
587 break;
588 }
589 }
590
7491a29f
JH
591 dec->set_probes(probe_map);
592}
593
594void DecodeTrace::commit_probes()
595{
596 assert(_decoder_stack);
597 BOOST_FOREACH(shared_ptr<data::decode::Decoder> dec,
598 _decoder_stack->stack())
599 commit_decoder_probes(dec);
600
601 _decoder_stack->begin_decode();
4e5a4405
JH
602}
603
b9329558 604void DecodeTrace::on_new_decode_data()
9cef9567
JH
605{
606 if (_view)
607 _view->update_viewport();
608}
609
b9329558 610void DecodeTrace::delete_pressed()
5ed1adf5
JH
611{
612 on_delete();
613}
614
b9329558 615void DecodeTrace::on_delete()
c51482b3
JH
616{
617 _session.remove_decode_signal(this);
618}
619
b9329558 620void DecodeTrace::on_probe_selected(int)
4e5a4405
JH
621{
622 commit_probes();
623}
624
7491a29f
JH
625void DecodeTrace::on_stack_decoder(srd_decoder *decoder)
626{
627 assert(decoder);
628 assert(_decoder_stack);
629 _decoder_stack->push(shared_ptr<data::decode::Decoder>(
630 new data::decode::Decoder(decoder)));
631 _decoder_stack->begin_decode();
37fd11b1
JH
632
633 create_popup_form();
7491a29f
JH
634}
635
613d097c
JH
636void DecodeTrace::on_delete_decoder(int index)
637{
638 _decoder_stack->remove(index);
639
640 // Update the popup
641 create_popup_form();
642
643 _decoder_stack->begin_decode();
644}
645
dd048a7e
JH
646void DecodeTrace::on_show_hide_decoder(int index)
647{
648 using pv::data::decode::Decoder;
649
650 const list< shared_ptr<Decoder> > stack(_decoder_stack->stack());
651
652 // Find the decoder in the stack
653 list< shared_ptr<Decoder> >::const_iterator iter = stack.begin();
654 for(int i = 0; i < index; i++, iter++)
655 assert(iter != stack.end());
656
657 shared_ptr<Decoder> dec = *iter;
658 assert(dec);
659
660 const bool show = !dec->shown();
661 dec->show(show);
662
663 assert(index < (int)_decoder_forms.size());
664 _decoder_forms[index]->set_decoder_visible(show);
665
666 _view->update_viewport();
667}
668
55d3603d
JH
669} // namespace view
670} // namespace pv