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