]> sigrok.org Git - pulseview.git/blame - pv/view/decodetrace.cpp
Don't allow disabled probes to be selected
[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 {
306 list< shared_ptr<Decoder> >::const_iterator iter =
307 stack.begin();
308 for (int i = 0; i < (int)stack.size(); i++, iter++) {
309 shared_ptr<Decoder> dec(*iter);
310 create_decoder_form(i, dec, parent, form);
311 }
312
313 form->addRow(new QLabel(
314 tr("<i>* Required Probes</i>"), parent));
315 }
4e5a4405 316
ce94e4fd 317 // Add stacking button
ce94e4fd
JH
318 pv::widgets::DecoderMenu *const decoder_menu =
319 new pv::widgets::DecoderMenu(parent);
7491a29f
JH
320 connect(decoder_menu, SIGNAL(decoder_selected(srd_decoder*)),
321 this, SLOT(on_stack_decoder(srd_decoder*)));
322
323 QPushButton *const stack_button =
324 new QPushButton(tr("Stack Decoder"), parent);
ce94e4fd
JH
325 stack_button->setMenu(decoder_menu);
326
327 QHBoxLayout *stack_button_box = new QHBoxLayout;
328 stack_button_box->addWidget(stack_button, 0, Qt::AlignRight);
329 form->addRow(stack_button_box);
4e5a4405
JH
330}
331
b9329558 332QMenu* DecodeTrace::create_context_menu(QWidget *parent)
c51482b3
JH
333{
334 QMenu *const menu = Trace::create_context_menu(parent);
335
336 menu->addSeparator();
337
338 QAction *const del = new QAction(tr("Delete"), this);
a2d21018 339 del->setShortcuts(QKeySequence::Delete);
c51482b3
JH
340 connect(del, SIGNAL(triggered()), this, SLOT(on_delete()));
341 menu->addAction(del);
342
343 return menu;
344}
345
287d607f
JH
346void DecodeTrace::draw_annotation(const pv::data::decode::Annotation &a,
347 QPainter &p, QColor text_color, int h, int left, int right,
348 double samples_per_pixel, double pixels_offset, int y,
349 size_t base_colour) const
06e810f2
JH
350{
351 const double start = a.start_sample() / samples_per_pixel -
352 pixels_offset;
353 const double end = a.end_sample() / samples_per_pixel -
354 pixels_offset;
287d607f
JH
355
356 const size_t colour = (base_colour + a.format()) % countof(Colours);
357 const QColor &fill = Colours[colour];
358 const QColor &outline = OutlineColours[colour];
06e810f2
JH
359
360 if (start > right + DrawPadding || end < left - DrawPadding)
361 return;
362
363 if (a.start_sample() == a.end_sample())
364 draw_instant(a, p, fill, outline, text_color, h,
365 start, y);
366 else
367 draw_range(a, p, fill, outline, text_color, h,
368 start, end, y);
369}
370
371void DecodeTrace::draw_instant(const pv::data::decode::Annotation &a, QPainter &p,
372 QColor fill, QColor outline, QColor text_color, int h, double x, int y) const
373{
374 const QString text = a.annotations().empty() ?
375 QString() : a.annotations().back();
376 const double w = min(p.boundingRect(QRectF(), 0, text).width(),
377 0.0) + h;
378 const QRectF rect(x - w / 2, y - h / 2, w, h);
379
380 p.setPen(outline);
381 p.setBrush(fill);
382 p.drawRoundedRect(rect, h / 2, h / 2);
383
384 p.setPen(text_color);
385 p.drawText(rect, Qt::AlignCenter | Qt::AlignVCenter, text);
386}
387
388void DecodeTrace::draw_range(const pv::data::decode::Annotation &a, QPainter &p,
389 QColor fill, QColor outline, QColor text_color, int h, double start,
390 double end, int y) const
391{
392 const double top = y + .5 - h / 2;
393 const double bottom = y + .5 + h / 2;
394 const vector<QString> annotations = a.annotations();
395
396 p.setPen(outline);
397 p.setBrush(fill);
398
399 // If the two ends are within 1 pixel, draw a vertical line
400 if (start + 1.0 > end)
401 {
402 p.drawLine(QPointF(start, top), QPointF(start, bottom));
403 return;
404 }
405
406 const double cap_width = min((end - start) / 4, EndCapWidth);
407
408 QPointF pts[] = {
409 QPointF(start, y + .5f),
410 QPointF(start + cap_width, top),
411 QPointF(end - cap_width, top),
412 QPointF(end, y + .5f),
413 QPointF(end - cap_width, bottom),
414 QPointF(start + cap_width, bottom)
415 };
416
417 p.drawConvexPolygon(pts, countof(pts));
418
419 if (annotations.empty())
420 return;
421
422 QRectF rect(start + cap_width, y - h / 2,
423 end - start - cap_width * 2, h);
0f290e9b
JH
424 if (rect.width() <= 4)
425 return;
426
06e810f2
JH
427 p.setPen(text_color);
428
429 // Try to find an annotation that will fit
430 QString best_annotation;
431 int best_width = 0;
432
433 BOOST_FOREACH(const QString &a, annotations) {
434 const int w = p.boundingRect(QRectF(), 0, a).width();
435 if (w <= rect.width() && w > best_width)
436 best_annotation = a, best_width = w;
437 }
438
439 if (best_annotation.isEmpty())
440 best_annotation = annotations.back();
441
442 // If not ellide the last in the list
443 p.drawText(rect, Qt::AlignCenter, p.fontMetrics().elidedText(
444 best_annotation, Qt::ElideRight, rect.width()));
445}
446
b9329558 447void DecodeTrace::draw_error(QPainter &p, const QString &message,
ad50ac1a
JH
448 int left, int right)
449{
450 const int y = get_y();
451
452 p.setPen(ErrorBgColour.darker());
453 p.setBrush(ErrorBgColour);
454
455 const QRectF bounding_rect =
456 QRectF(left, INT_MIN / 2 + y, right - left, INT_MAX);
457 const QRectF text_rect = p.boundingRect(bounding_rect,
458 Qt::AlignCenter, message);
459 const float r = text_rect.height() / 4;
460
461 p.drawRoundedRect(text_rect.adjusted(-r, -r, r, r), r, r,
462 Qt::AbsoluteSize);
463
464 p.setPen(get_text_colour());
465 p.drawText(text_rect, message);
466}
467
5dfeb70f
JH
468void DecodeTrace::draw_unresolved_period(QPainter &p, int h, int left,
469 int right, double samples_per_pixel, double pixels_offset)
470{
471 using namespace pv::data;
472 using pv::data::decode::Decoder;
473
474 assert(_decoder_stack);
475
476 shared_ptr<Logic> data;
477 shared_ptr<LogicSignal> logic_signal;
478
479 const list< shared_ptr<Decoder> > &stack = _decoder_stack->stack();
480
481 // We get the logic data of the first probe in the list.
482 // This works because we are currently assuming all
483 // LogicSignals have the same data/snapshot
484 BOOST_FOREACH (const shared_ptr<Decoder> &dec, stack)
485 if (dec && !dec->probes().empty() &&
486 ((logic_signal = (*dec->probes().begin()).second)) &&
7aa09b00 487 ((data = logic_signal->logic_data())))
5dfeb70f
JH
488 break;
489
490 if (!data || data->get_snapshots().empty())
491 return;
492
493 const shared_ptr<LogicSnapshot> snapshot =
494 data->get_snapshots().front();
495 assert(snapshot);
496 const int64_t sample_count = (int64_t)snapshot->get_sample_count();
497 if (sample_count == 0)
498 return;
499
500 const int64_t samples_decoded = _decoder_stack->samples_decoded();
501 if (sample_count == samples_decoded)
502 return;
503
504 const int y = get_y();
505 const double start = max(samples_decoded /
506 samples_per_pixel - pixels_offset, left - 1.0);
507 const double end = min(sample_count / samples_per_pixel -
508 pixels_offset, right + 1.0);
509 const QRectF no_decode_rect(start, y - h/2 + 0.5, end - start, h);
510
511 p.setPen(QPen(Qt::NoPen));
512 p.setBrush(Qt::white);
513 p.drawRect(no_decode_rect);
514
515 p.setPen(NoDecodeColour);
516 p.setBrush(QBrush(NoDecodeColour, Qt::Dense6Pattern));
517 p.drawRect(no_decode_rect);
518}
519
613d097c
JH
520void DecodeTrace::create_decoder_form(int index,
521 shared_ptr<data::decode::Decoder> &dec, QWidget *parent,
522 QFormLayout *form)
7491a29f
JH
523{
524 const GSList *probe;
525
526 assert(dec);
527 const srd_decoder *const decoder = dec->decoder();
528 assert(decoder);
529
204bae45 530 pv::widgets::DecoderGroupBox *const group =
27e8df22
JH
531 new pv::widgets::DecoderGroupBox(
532 QString::fromUtf8(decoder->name));
dd048a7e 533 group->set_decoder_visible(dec->shown());
613d097c
JH
534
535 _delete_mapper.setMapping(group, index);
536 connect(group, SIGNAL(delete_decoder()), &_delete_mapper, SLOT(map()));
537
dd048a7e
JH
538 _show_hide_mapper.setMapping(group, index);
539 connect(group, SIGNAL(show_hide_decoder()),
540 &_show_hide_mapper, SLOT(map()));
541
204bae45
JH
542 QFormLayout *const decoder_form = new QFormLayout;
543 group->add_layout(decoder_form);
7491a29f
JH
544
545 // Add the mandatory probes
546 for(probe = decoder->probes; probe; probe = probe->next) {
547 const struct srd_probe *const p =
548 (struct srd_probe *)probe->data;
549 QComboBox *const combo = create_probe_selector(parent, dec, p);
550 connect(combo, SIGNAL(currentIndexChanged(int)),
551 this, SLOT(on_probe_selected(int)));
204bae45 552 decoder_form->addRow(tr("<b>%1</b> (%2) *")
636782c1
JH
553 .arg(QString::fromUtf8(p->name))
554 .arg(QString::fromUtf8(p->desc)), combo);
7491a29f
JH
555
556 const ProbeSelector s = {combo, dec, p};
557 _probe_selectors.push_back(s);
558 }
559
560 // Add the optional probes
561 for(probe = decoder->opt_probes; probe; probe = probe->next) {
562 const struct srd_probe *const p =
563 (struct srd_probe *)probe->data;
564 QComboBox *const combo = create_probe_selector(parent, dec, p);
565 connect(combo, SIGNAL(currentIndexChanged(int)),
566 this, SLOT(on_probe_selected(int)));
204bae45 567 decoder_form->addRow(tr("<b>%1</b> (%2)")
636782c1
JH
568 .arg(QString::fromUtf8(p->name))
569 .arg(QString::fromUtf8(p->desc)), combo);
7491a29f
JH
570
571 const ProbeSelector s = {combo, dec, p};
572 _probe_selectors.push_back(s);
573 }
574
575 // Add the options
576 shared_ptr<prop::binding::DecoderOptions> binding(
577 new prop::binding::DecoderOptions(_decoder_stack, dec));
204bae45 578 binding->add_properties_to_form(decoder_form, true);
7491a29f
JH
579
580 _bindings.push_back(binding);
204bae45
JH
581
582 form->addRow(group);
dd048a7e 583 _decoder_forms.push_back(group);
7491a29f
JH
584}
585
b9329558 586QComboBox* DecodeTrace::create_probe_selector(
7491a29f
JH
587 QWidget *parent, const shared_ptr<data::decode::Decoder> &dec,
588 const srd_probe *const probe)
4e5a4405 589{
7491a29f
JH
590 assert(dec);
591
4e5a4405
JH
592 const vector< shared_ptr<Signal> > sigs = _session.get_signals();
593
6e89374a 594 assert(_decoder_stack);
4e5a4405
JH
595 const map<const srd_probe*,
596 shared_ptr<LogicSignal> >::const_iterator probe_iter =
7491a29f 597 dec->probes().find(probe);
4e5a4405
JH
598
599 QComboBox *selector = new QComboBox(parent);
600
601 selector->addItem("-", qVariantFromValue((void*)NULL));
602
7491a29f 603 if (probe_iter == dec->probes().end())
4e5a4405
JH
604 selector->setCurrentIndex(0);
605
606 for(size_t i = 0; i < sigs.size(); i++) {
607 const shared_ptr<view::Signal> s(sigs[i]);
608 assert(s);
609
610 if (dynamic_pointer_cast<LogicSignal>(s) && s->enabled())
611 {
612 selector->addItem(s->get_name(),
613 qVariantFromValue((void*)s.get()));
614 if ((*probe_iter).second == s)
615 selector->setCurrentIndex(i + 1);
616 }
617 }
618
619 return selector;
620}
621
7491a29f 622void DecodeTrace::commit_decoder_probes(shared_ptr<data::decode::Decoder> &dec)
4e5a4405 623{
7491a29f 624 assert(dec);
4e5a4405
JH
625
626 map<const srd_probe*, shared_ptr<LogicSignal> > probe_map;
627 const vector< shared_ptr<Signal> > sigs = _session.get_signals();
628
7491a29f 629 BOOST_FOREACH(const ProbeSelector &s, _probe_selectors)
4e5a4405 630 {
7491a29f
JH
631 if(s._decoder != dec)
632 break;
633
4e5a4405 634 const LogicSignal *const selection =
7491a29f
JH
635 (LogicSignal*)s._combo->itemData(
636 s._combo->currentIndex()).value<void*>();
4e5a4405 637
7491a29f
JH
638 BOOST_FOREACH(shared_ptr<Signal> sig, sigs)
639 if(sig.get() == selection) {
640 probe_map[s._probe] =
641 dynamic_pointer_cast<LogicSignal>(sig);
4e5a4405
JH
642 break;
643 }
644 }
645
7491a29f
JH
646 dec->set_probes(probe_map);
647}
648
649void DecodeTrace::commit_probes()
650{
651 assert(_decoder_stack);
652 BOOST_FOREACH(shared_ptr<data::decode::Decoder> dec,
653 _decoder_stack->stack())
654 commit_decoder_probes(dec);
655
656 _decoder_stack->begin_decode();
4e5a4405
JH
657}
658
b9329558 659void DecodeTrace::on_new_decode_data()
9cef9567
JH
660{
661 if (_view)
662 _view->update_viewport();
663}
664
b9329558 665void DecodeTrace::delete_pressed()
5ed1adf5
JH
666{
667 on_delete();
668}
669
b9329558 670void DecodeTrace::on_delete()
c51482b3
JH
671{
672 _session.remove_decode_signal(this);
673}
674
b9329558 675void DecodeTrace::on_probe_selected(int)
4e5a4405
JH
676{
677 commit_probes();
678}
679
7491a29f
JH
680void DecodeTrace::on_stack_decoder(srd_decoder *decoder)
681{
682 assert(decoder);
683 assert(_decoder_stack);
684 _decoder_stack->push(shared_ptr<data::decode::Decoder>(
685 new data::decode::Decoder(decoder)));
686 _decoder_stack->begin_decode();
37fd11b1
JH
687
688 create_popup_form();
7491a29f
JH
689}
690
613d097c
JH
691void DecodeTrace::on_delete_decoder(int index)
692{
693 _decoder_stack->remove(index);
694
695 // Update the popup
696 create_popup_form();
697
698 _decoder_stack->begin_decode();
699}
700
dd048a7e
JH
701void DecodeTrace::on_show_hide_decoder(int index)
702{
703 using pv::data::decode::Decoder;
704
705 const list< shared_ptr<Decoder> > stack(_decoder_stack->stack());
706
707 // Find the decoder in the stack
708 list< shared_ptr<Decoder> >::const_iterator iter = stack.begin();
709 for(int i = 0; i < index; i++, iter++)
710 assert(iter != stack.end());
711
712 shared_ptr<Decoder> dec = *iter;
713 assert(dec);
714
715 const bool show = !dec->shown();
716 dec->show(show);
717
718 assert(index < (int)_decoder_forms.size());
719 _decoder_forms[index]->set_decoder_visible(show);
720
721 _view->update_viewport();
722}
723
55d3603d
JH
724} // namespace view
725} // namespace pv