]> sigrok.org Git - pulseview.git/blame - pv/view/decodetrace.cpp
DecodeTrace: Draw the error over the unresolved period
[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 {
f9101a91
JH
185 draw_unresolved_period(p, annotation_height, left, right,
186 samples_per_pixel, pixels_offset);
5b8b1e47 187 draw_error(p, err, left, right);
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) *")
636782c1
JH
497 .arg(QString::fromUtf8(p->name))
498 .arg(QString::fromUtf8(p->desc)), combo);
7491a29f
JH
499
500 const ProbeSelector s = {combo, dec, p};
501 _probe_selectors.push_back(s);
502 }
503
504 // Add the optional probes
505 for(probe = decoder->opt_probes; probe; probe = probe->next) {
506 const struct srd_probe *const p =
507 (struct srd_probe *)probe->data;
508 QComboBox *const combo = create_probe_selector(parent, dec, p);
509 connect(combo, SIGNAL(currentIndexChanged(int)),
510 this, SLOT(on_probe_selected(int)));
204bae45 511 decoder_form->addRow(tr("<b>%1</b> (%2)")
636782c1
JH
512 .arg(QString::fromUtf8(p->name))
513 .arg(QString::fromUtf8(p->desc)), combo);
7491a29f
JH
514
515 const ProbeSelector s = {combo, dec, p};
516 _probe_selectors.push_back(s);
517 }
518
519 // Add the options
520 shared_ptr<prop::binding::DecoderOptions> binding(
521 new prop::binding::DecoderOptions(_decoder_stack, dec));
204bae45 522 binding->add_properties_to_form(decoder_form, true);
7491a29f
JH
523
524 _bindings.push_back(binding);
204bae45
JH
525
526 form->addRow(group);
dd048a7e 527 _decoder_forms.push_back(group);
7491a29f
JH
528}
529
b9329558 530QComboBox* DecodeTrace::create_probe_selector(
7491a29f
JH
531 QWidget *parent, const shared_ptr<data::decode::Decoder> &dec,
532 const srd_probe *const probe)
4e5a4405 533{
7491a29f
JH
534 assert(dec);
535
4e5a4405
JH
536 const vector< shared_ptr<Signal> > sigs = _session.get_signals();
537
6e89374a 538 assert(_decoder_stack);
4e5a4405
JH
539 const map<const srd_probe*,
540 shared_ptr<LogicSignal> >::const_iterator probe_iter =
7491a29f 541 dec->probes().find(probe);
4e5a4405
JH
542
543 QComboBox *selector = new QComboBox(parent);
544
545 selector->addItem("-", qVariantFromValue((void*)NULL));
546
7491a29f 547 if (probe_iter == dec->probes().end())
4e5a4405
JH
548 selector->setCurrentIndex(0);
549
550 for(size_t i = 0; i < sigs.size(); i++) {
551 const shared_ptr<view::Signal> s(sigs[i]);
552 assert(s);
553
554 if (dynamic_pointer_cast<LogicSignal>(s) && s->enabled())
555 {
556 selector->addItem(s->get_name(),
557 qVariantFromValue((void*)s.get()));
558 if ((*probe_iter).second == s)
559 selector->setCurrentIndex(i + 1);
560 }
561 }
562
563 return selector;
564}
565
7491a29f 566void DecodeTrace::commit_decoder_probes(shared_ptr<data::decode::Decoder> &dec)
4e5a4405 567{
7491a29f 568 assert(dec);
4e5a4405
JH
569
570 map<const srd_probe*, shared_ptr<LogicSignal> > probe_map;
571 const vector< shared_ptr<Signal> > sigs = _session.get_signals();
572
7491a29f 573 BOOST_FOREACH(const ProbeSelector &s, _probe_selectors)
4e5a4405 574 {
7491a29f
JH
575 if(s._decoder != dec)
576 break;
577
4e5a4405 578 const LogicSignal *const selection =
7491a29f
JH
579 (LogicSignal*)s._combo->itemData(
580 s._combo->currentIndex()).value<void*>();
4e5a4405 581
7491a29f
JH
582 BOOST_FOREACH(shared_ptr<Signal> sig, sigs)
583 if(sig.get() == selection) {
584 probe_map[s._probe] =
585 dynamic_pointer_cast<LogicSignal>(sig);
4e5a4405
JH
586 break;
587 }
588 }
589
7491a29f
JH
590 dec->set_probes(probe_map);
591}
592
593void DecodeTrace::commit_probes()
594{
595 assert(_decoder_stack);
596 BOOST_FOREACH(shared_ptr<data::decode::Decoder> dec,
597 _decoder_stack->stack())
598 commit_decoder_probes(dec);
599
600 _decoder_stack->begin_decode();
4e5a4405
JH
601}
602
b9329558 603void DecodeTrace::on_new_decode_data()
9cef9567
JH
604{
605 if (_view)
606 _view->update_viewport();
607}
608
b9329558 609void DecodeTrace::delete_pressed()
5ed1adf5
JH
610{
611 on_delete();
612}
613
b9329558 614void DecodeTrace::on_delete()
c51482b3
JH
615{
616 _session.remove_decode_signal(this);
617}
618
b9329558 619void DecodeTrace::on_probe_selected(int)
4e5a4405
JH
620{
621 commit_probes();
622}
623
7491a29f
JH
624void DecodeTrace::on_stack_decoder(srd_decoder *decoder)
625{
626 assert(decoder);
627 assert(_decoder_stack);
628 _decoder_stack->push(shared_ptr<data::decode::Decoder>(
629 new data::decode::Decoder(decoder)));
630 _decoder_stack->begin_decode();
37fd11b1
JH
631
632 create_popup_form();
7491a29f
JH
633}
634
613d097c
JH
635void DecodeTrace::on_delete_decoder(int index)
636{
637 _decoder_stack->remove(index);
638
639 // Update the popup
640 create_popup_form();
641
642 _decoder_stack->begin_decode();
643}
644
dd048a7e
JH
645void DecodeTrace::on_show_hide_decoder(int index)
646{
647 using pv::data::decode::Decoder;
648
649 const list< shared_ptr<Decoder> > stack(_decoder_stack->stack());
650
651 // Find the decoder in the stack
652 list< shared_ptr<Decoder> >::const_iterator iter = stack.begin();
653 for(int i = 0; i < index; i++, iter++)
654 assert(iter != stack.end());
655
656 shared_ptr<Decoder> dec = *iter;
657 assert(dec);
658
659 const bool show = !dec->shown();
660 dec->show(show);
661
662 assert(index < (int)_decoder_forms.size());
663 _decoder_forms[index]->set_decoder_visible(show);
664
665 _view->update_viewport();
666}
667
55d3603d
JH
668} // namespace view
669} // namespace pv