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