X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fviews%2Ftrace%2Flogicsignal.cpp;h=6a9bf432a07157c2a2e7713e60dbd7972c8abd8f;hp=9913d6873ddfd28639c36d1348203c1a921f9ddd;hb=f6b6c9bf50999dc99f9517318ffd3114cae4960f;hpb=1573bf16ba50d1c023ad3a9ce596f0ab6eaeacff diff --git a/pv/views/trace/logicsignal.cpp b/pv/views/trace/logicsignal.cpp index 9913d687..6a9bf432 100644 --- a/pv/views/trace/logicsignal.cpp +++ b/pv/views/trace/logicsignal.cpp @@ -46,6 +46,7 @@ using std::max; using std::make_pair; using std::min; using std::none_of; +using std::out_of_range; using std::pair; using std::shared_ptr; using std::vector; @@ -56,18 +57,20 @@ using sigrok::Trigger; using sigrok::TriggerMatch; using sigrok::TriggerMatchType; +using pv::data::LogicSegment; + namespace pv { namespace views { namespace trace { const float LogicSignal::Oversampling = 2.0f; -const QColor LogicSignal::EdgeColour(0x80, 0x80, 0x80); -const QColor LogicSignal::HighColour(0x00, 0xC0, 0x00); -const QColor LogicSignal::LowColour(0xC0, 0x00, 0x00); -const QColor LogicSignal::SamplingPointColour(0x77, 0x77, 0x77); +const QColor LogicSignal::EdgeColor(0x80, 0x80, 0x80); +const QColor LogicSignal::HighColor(0x00, 0xC0, 0x00); +const QColor LogicSignal::LowColor(0xC0, 0x00, 0x00); +const QColor LogicSignal::SamplingPointColor(0x77, 0x77, 0x77); -const QColor LogicSignal::SignalColours[10] = { +const QColor LogicSignal::SignalColors[10] = { QColor(0x16, 0x19, 0x1A), // Black QColor(0x8F, 0x52, 0x02), // Brown QColor(0xCC, 0x00, 0x00), // Red @@ -80,7 +83,7 @@ const QColor LogicSignal::SignalColours[10] = { QColor(0xEE, 0xEE, 0xEC), // White }; -QColor LogicSignal::TriggerMarkerBackgroundColour = QColor(0xED, 0xD4, 0x00); +QColor LogicSignal::TriggerMarkerBackgroundColor = QColor(0xED, 0xD4, 0x00); const int LogicSignal::TriggerMarkerPadding = 2; const char* LogicSignal::TriggerMarkerIcons[8] = { nullptr, @@ -101,8 +104,8 @@ LogicSignal::LogicSignal( shared_ptr device, shared_ptr base) : Signal(session, base), - signal_height_(QFontMetrics(QApplication::font()).height() * 2), device_(device), + trigger_types_(get_trigger_types()), trigger_none_(nullptr), trigger_rising_(nullptr), trigger_high_(nullptr), @@ -112,7 +115,10 @@ LogicSignal::LogicSignal( { shared_ptr trigger; - base_->set_colour(SignalColours[base->index() % countof(SignalColours)]); + base_->set_color(SignalColors[base->index() % countof(SignalColors)]); + + GlobalSettings gs; + signal_height_ = gs.value(GlobalSettings::Key_View_DefaultLogicHeight).toInt(); /* Populate this channel's trigger setting with whatever we * find in the current session trigger, if anything. */ @@ -134,23 +140,30 @@ shared_ptr LogicSignal::logic_data() const return base_->logic_data(); } -pair LogicSignal::v_extents() const +void LogicSignal::save_settings(QSettings &settings) const { - const int signal_margin = - QFontMetrics(QApplication::font()).height() / 2; - return make_pair(-signal_height_ - signal_margin, signal_margin); + settings.setValue("trace_height", signal_height_); } -int LogicSignal::scale_handle_offset() const +void LogicSignal::restore_settings(QSettings &settings) { - return -signal_height_; + if (settings.contains("trace_height")) { + const int old_height = signal_height_; + signal_height_ = settings.value("trace_height").toInt(); + + if ((signal_height_ != old_height) && owner_) { + // Call order is important, otherwise the lazy event handler won't work + owner_->extents_changed(false, true); + owner_->row_item_appearance_changed(false, true); + } + } } -void LogicSignal::scale_handle_dragged(int offset) +pair LogicSignal::v_extents() const { - const int font_height = QFontMetrics(QApplication::font()).height(); - const int units = (-offset / font_height); - signal_height_ = ((units < 1) ? 1 : units) * font_height; + const int signal_margin = + QFontMetrics(QApplication::font()).height() / 2; + return make_pair(-signal_height_ - signal_margin, signal_margin); } void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp) @@ -170,13 +183,10 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp) const float high_offset = y - signal_height_ + 0.5f; const float low_offset = y + 0.5f; - const deque< shared_ptr > &segments = - base_->logic_data()->logic_segments(); - if (segments.empty()) + shared_ptr segment = get_logic_segment_to_paint(); + if (!segment || (segment->get_sample_count() == 0)) return; - const shared_ptr &segment = segments.front(); - double samplerate = segment->samplerate(); // Show sample rate as 1Hz when it is unknown @@ -185,7 +195,7 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp) const double pixels_offset = pp.pixels_offset(); const pv::util::Timestamp& start_time = segment->start_time(); - const int64_t last_sample = segment->get_sample_count() - 1; + const int64_t last_sample = (int64_t)segment->get_sample_count() - 1; const double samples_per_pixel = samplerate * pp.scale(); const double pixels_per_sample = 1 / samples_per_pixel; const pv::util::Timestamp start = samplerate * (pp.offset() - start_time); @@ -247,7 +257,7 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp) sampling_point_x += pixels_per_sample; }; - p.setPen(EdgeColour); + p.setPen(EdgeColor); p.drawLines(edge_lines, edge_count); delete[] edge_lines; @@ -255,10 +265,10 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp) const unsigned int max_cap_line_count = edges.size(); QLineF *const cap_lines = new QLineF[max_cap_line_count]; - p.setPen(HighColour); + p.setPen(HighColor); paint_caps(p, cap_lines, edges, true, samples_per_pixel, pixels_offset, pp.left(), high_offset); - p.setPen(LowColour); + p.setPen(LowColor); paint_caps(p, cap_lines, edges, false, samples_per_pixel, pixels_offset, pp.left(), low_offset); @@ -266,48 +276,79 @@ void LogicSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp) // Paint the sampling points if (show_sampling_points) { - p.setPen(SamplingPointColour); + p.setPen(SamplingPointColor); p.drawRects(sampling_points.data(), sampling_points.size()); } } void LogicSignal::paint_fore(QPainter &p, ViewItemPaintParams &pp) { - // Draw the trigger marker - if (!trigger_match_ || !base_->enabled()) - return; + if (base_->enabled()) { + if (trigger_match_) { + // Draw the trigger marker + const int y = get_visual_y(); + + for (int32_t type_id : trigger_types_) { + const TriggerMatchType *const type = + TriggerMatchType::get(type_id); + if (trigger_match_ != type || type_id < 0 || + (size_t)type_id >= countof(TriggerMarkerIcons) || + !TriggerMarkerIcons[type_id]) + continue; - const int y = get_visual_y(); - const vector trig_types = get_trigger_types(); - for (int32_t type_id : trig_types) { - const TriggerMatchType *const type = - TriggerMatchType::get(type_id); - if (trigger_match_ != type || type_id < 0 || - (size_t)type_id >= countof(TriggerMarkerIcons) || - !TriggerMarkerIcons[type_id]) - continue; - - const QPixmap *const pixmap = get_pixmap( - TriggerMarkerIcons[type_id]); - if (!pixmap) - continue; - - const float pad = TriggerMarkerPadding - 0.5f; - const QSize size = pixmap->size(); - const QPoint point( - pp.right() - size.width() - pad * 2, - y - (signal_height_ + size.height()) / 2); - - p.setPen(QPen(TriggerMarkerBackgroundColour.darker())); - p.setBrush(TriggerMarkerBackgroundColour); - p.drawRoundedRect(QRectF(point, size).adjusted( - -pad, -pad, pad, pad), pad, pad); - p.drawPixmap(point, *pixmap); - - break; + const QPixmap *const pixmap = get_pixmap( + TriggerMarkerIcons[type_id]); + if (!pixmap) + continue; + + const float pad = TriggerMarkerPadding - 0.5f; + const QSize size = pixmap->size(); + const QPoint point( + pp.right() - size.width() - pad * 2, + y - (signal_height_ + size.height()) / 2); + + p.setPen(QPen(TriggerMarkerBackgroundColor.darker())); + p.setBrush(TriggerMarkerBackgroundColor); + p.drawRoundedRect(QRectF(point, size).adjusted( + -pad, -pad, pad, pad), pad, pad); + p.drawPixmap(point, *pixmap); + + break; + } + } + + if (show_hover_marker_) + paint_hover_marker(p); } } +vector LogicSignal::get_nearest_level_changes(uint64_t sample_pos) +{ + assert(base_); + assert(owner_); + + if (sample_pos == 0) + return vector(); + + shared_ptr segment = get_logic_segment_to_paint(); + if (!segment || (segment->get_sample_count() == 0)) + return vector(); + + const View *view = owner_->view(); + assert(view); + const double samples_per_pixel = base_->get_samplerate() * view->scale(); + + vector edges; + + segment->get_surrounding_edges(edges, sample_pos, + samples_per_pixel / Oversampling, base_->index()); + + if (edges.empty()) + return vector(); + + return edges; +} + void LogicSignal::paint_caps(QPainter &p, QLineF *const lines, vector< pair > &edges, bool level, double samples_per_pixel, double pixels_offset, float x_offset, @@ -327,6 +368,31 @@ void LogicSignal::paint_caps(QPainter &p, QLineF *const lines, p.drawLines(lines, line - lines); } +shared_ptr LogicSignal::get_logic_segment_to_paint() const +{ + shared_ptr segment; + + const deque< shared_ptr > &segments = + base_->logic_data()->logic_segments(); + + if (!segments.empty()) { + if (segment_display_mode_ == ShowLastSegmentOnly) { + segment = segments.back(); + } + + if ((segment_display_mode_ == ShowSingleSegmentOnly) || + (segment_display_mode_ == ShowLastCompleteSegmentOnly)) { + try { + segment = segments.at(current_segment_); + } catch (out_of_range&) { + qDebug() << "Current logic segment out of range for signal" << base_->name() << ":" << current_segment_; + } + } + } + + return segment; +} + void LogicSignal::init_trigger_actions(QWidget *parent) { trigger_none_ = new QAction(*get_icon(":/icons/trigger-none.svg"), @@ -439,6 +505,16 @@ void LogicSignal::populate_popup_form(QWidget *parent, QFormLayout *form) { Signal::populate_popup_form(parent, form); + signal_height_sb_ = new QSpinBox(parent); + signal_height_sb_->setRange(5, 1000); + signal_height_sb_->setSingleStep(5); + signal_height_sb_->setSuffix(tr(" pixels")); + signal_height_sb_->setValue(signal_height_); + connect(signal_height_sb_, SIGNAL(valueChanged(int)), + this, SLOT(on_signal_height_changed(int))); + form->addRow(tr("Trace height"), signal_height_sb_); + + // Trigger settings const vector trig_types = get_trigger_types(); if (!trig_types.empty()) { @@ -454,6 +530,12 @@ void LogicSignal::populate_popup_form(QWidget *parent, QFormLayout *form) trigger_bar_->addAction(action); action->setChecked(trigger_match_ == type); } + + // Only allow triggers to be changed when we're stopped + if (session_.get_capture_state() != Session::Stopped) + for (QAction* action : trigger_bar_->findChildren()) + action->setEnabled(false); + form->addRow(tr("Trigger"), trigger_bar_); } } @@ -531,6 +613,17 @@ void LogicSignal::on_trigger() modify_trigger(); } +void LogicSignal::on_signal_height_changed(int height) +{ + signal_height_ = height; + + if (owner_) { + // Call order is important, otherwise the lazy event handler won't work + owner_->extents_changed(false, true); + owner_->row_item_appearance_changed(false, true); + } +} + } // namespace trace } // namespace views } // namespace pv