X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fview%2Flogicsignal.cpp;h=3acf1b5cb03ebf53c8a632075a07f32adfa0f7f3;hp=aa581d0a4955351c0738b00ba0fb396c9da3eb64;hb=4c8a6a6d03e2a12f67d910a83589072b478114cb;hpb=aa5e914074b759c82974d1096f22164481eec006 diff --git a/pv/view/logicsignal.cpp b/pv/view/logicsignal.cpp index aa581d0a..3acf1b5c 100644 --- a/pv/view/logicsignal.cpp +++ b/pv/view/logicsignal.cpp @@ -31,7 +31,7 @@ #include "logicsignal.hpp" #include "view.hpp" -#include +#include #include #include #include @@ -81,6 +81,22 @@ const QColor LogicSignal::SignalColours[10] = { QColor(0xEE, 0xEE, 0xEC), // White }; +QColor LogicSignal::TriggerMarkerBackgroundColour = QColor(0xED, 0xD4, 0x00); +const int LogicSignal::TriggerMarkerPadding = 2; +const char* LogicSignal::TriggerMarkerIcons[8] = { + nullptr, + ":/icons/trigger-marker-low.svg", + ":/icons/trigger-marker-high.svg", + ":/icons/trigger-marker-rising.svg", + ":/icons/trigger-marker-falling.svg", + ":/icons/trigger-marker-change.svg", + nullptr, + nullptr +}; + +QCache LogicSignal::icon_cache_; +QCache LogicSignal::pixmap_cache_; + LogicSignal::LogicSignal( pv::Session &session, shared_ptr device, @@ -129,35 +145,24 @@ std::pair LogicSignal::v_extents() const return make_pair(-SignalHeight - SignalMargin, SignalMargin); } -void LogicSignal::paint_back(QPainter &p, int left, int right) +void LogicSignal::paint_back(QPainter &p, const RowItemPaintParams &pp) { if (channel_->enabled()) - paint_axis(p, get_visual_y(), left, right); + paint_axis(p, pp, get_visual_y()); } -void LogicSignal::paint_mid(QPainter &p, int left, int right) +void LogicSignal::paint_mid(QPainter &p, const RowItemPaintParams &pp) { - using pv::view::View; - QLineF *line; vector< pair > edges; assert(channel_); assert(data_); - assert(right >= left); assert(owner_); const int y = get_visual_y(); - const View *const view = owner_->view(); - assert(view); - - const double scale = view->scale(); - assert(scale > 0); - - const double offset = view->offset(); - if (!channel_->enabled()) return; @@ -178,12 +183,12 @@ void LogicSignal::paint_mid(QPainter &p, int left, int right) if (samplerate == 0.0) samplerate = 1.0; - const double pixels_offset = offset / scale; + const double pixels_offset = pp.pixels_offset(); const double start_time = data_->get_start_time(); const int64_t last_sample = snapshot->get_sample_count() - 1; - const double samples_per_pixel = samplerate * scale; - const double start = samplerate * (offset - start_time); - const double end = start + samples_per_pixel * (right - left); + const double samples_per_pixel = samplerate * pp.scale(); + const double start = samplerate * (pp.offset() - start_time); + const double end = start + samples_per_pixel * pp.width(); snapshot->get_subsampled_edges(edges, min(max((int64_t)floor(start), (int64_t)0), last_sample), @@ -198,7 +203,7 @@ void LogicSignal::paint_mid(QPainter &p, int left, int right) for (auto i = edges.cbegin() + 1; i != edges.cend() - 1; i++) { const float x = ((*i).first / samples_per_pixel - - pixels_offset) + left; + pixels_offset) + pp.left(); *line++ = QLineF(x, high_offset, x, low_offset); } @@ -212,14 +217,51 @@ void LogicSignal::paint_mid(QPainter &p, int left, int right) p.setPen(HighColour); paint_caps(p, cap_lines, edges, true, samples_per_pixel, - pixels_offset, left, high_offset); + pixels_offset, pp.left(), high_offset); p.setPen(LowColour); paint_caps(p, cap_lines, edges, false, samples_per_pixel, - pixels_offset, left, low_offset); + pixels_offset, pp.left(), low_offset); delete[] cap_lines; } +void LogicSignal::paint_fore(QPainter &p, const RowItemPaintParams &pp) +{ + // Draw the trigger marker + if (!trigger_match_) + return; + + 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 int pad = TriggerMarkerPadding; + const QSize size = pixmap->size(); + const QPoint point( + pp.right() - size.width() - pad * 2, + y - (SignalHeight + size.height()) / 2); + + p.setPen(QPen(Qt::NoPen)); + p.setBrush(TriggerMarkerBackgroundColour); + p.drawRoundedRect(QRect(point, size).adjusted( + -pad, -pad, pad, pad), pad, pad); + p.drawPixmap(point, *pixmap); + + break; + } +} + void LogicSignal::paint_caps(QPainter &p, QLineF *const lines, vector< pair > &edges, bool level, double samples_per_pixel, double pixels_offset, float x_offset, @@ -241,37 +283,49 @@ void LogicSignal::paint_caps(QPainter &p, QLineF *const lines, void LogicSignal::init_trigger_actions(QWidget *parent) { - trigger_none_ = new QAction(QIcon(":/icons/trigger-none.svg"), + trigger_none_ = new QAction(*get_icon(":/icons/trigger-none.svg"), tr("No trigger"), parent); trigger_none_->setCheckable(true); connect(trigger_none_, SIGNAL(triggered()), this, SLOT(on_trigger())); - trigger_rising_ = new QAction(QIcon(":/icons/trigger-rising.svg"), + trigger_rising_ = new QAction(*get_icon(":/icons/trigger-rising.svg"), tr("Trigger on rising edge"), parent); trigger_rising_->setCheckable(true); connect(trigger_rising_, SIGNAL(triggered()), this, SLOT(on_trigger())); - trigger_high_ = new QAction(QIcon(":/icons/trigger-high.svg"), + trigger_high_ = new QAction(*get_icon(":/icons/trigger-high.svg"), tr("Trigger on high level"), parent); trigger_high_->setCheckable(true); connect(trigger_high_, SIGNAL(triggered()), this, SLOT(on_trigger())); - trigger_falling_ = new QAction(QIcon(":/icons/trigger-falling.svg"), + trigger_falling_ = new QAction(*get_icon(":/icons/trigger-falling.svg"), tr("Trigger on falling edge"), parent); trigger_falling_->setCheckable(true); connect(trigger_falling_, SIGNAL(triggered()), this, SLOT(on_trigger())); - trigger_low_ = new QAction(QIcon(":/icons/trigger-low.svg"), + trigger_low_ = new QAction(*get_icon(":/icons/trigger-low.svg"), tr("Trigger on low level"), parent); trigger_low_->setCheckable(true); connect(trigger_low_, SIGNAL(triggered()), this, SLOT(on_trigger())); - trigger_change_ = new QAction(QIcon(":/icons/trigger-change.svg"), + trigger_change_ = new QAction(*get_icon(":/icons/trigger-change.svg"), tr("Trigger on rising or falling edge"), parent); trigger_change_->setCheckable(true); connect(trigger_change_, SIGNAL(triggered()), this, SLOT(on_trigger())); } +const vector LogicSignal::get_trigger_types() const +{ + try { + const Glib::VariantContainerBase gvar = + device_->config_list(ConfigKey::TRIGGER_MATCH); + return Glib::VariantBase::cast_dynamic< + Glib::Variant>>(gvar).get(); + } catch (Error e) { + return vector(); + } +} + QAction* LogicSignal::action_from_trigger_type(const TriggerMatchType *type) { QAction *action; @@ -320,24 +374,14 @@ const TriggerMatchType *LogicSignal::trigger_type_from_action(QAction *action) void LogicSignal::populate_popup_form(QWidget *parent, QFormLayout *form) { - Glib::VariantContainerBase gvar; - vector trig_types; - Signal::populate_popup_form(parent, form); - try { - gvar = device_->config_list(ConfigKey::TRIGGER_MATCH); - } catch (Error e) { - return; - } - trigger_bar_ = new QToolBar(parent); init_trigger_actions(trigger_bar_); trigger_bar_->addAction(trigger_none_); trigger_none_->setChecked(!trigger_match_); - trig_types = - Glib::VariantBase::cast_dynamic>>( - gvar).get(); + + const vector trig_types = get_trigger_types(); for (auto type_id : trig_types) { const TriggerMatchType *const type = TriggerMatchType::get(type_id); @@ -376,6 +420,31 @@ void LogicSignal::modify_trigger() session_.session()->set_trigger( new_trigger->stages().empty() ? nullptr : new_trigger); + + if (owner_) + owner_->appearance_changed(false, true); +} + +const QIcon* LogicSignal::get_icon(const char *path) +{ + const QIcon *icon = icon_cache_.take(path); + if (!icon) { + icon = new QIcon(path); + icon_cache_.insert(path, icon); + } + + return icon; +} + +const QPixmap* LogicSignal::get_pixmap(const char *path) +{ + const QPixmap *pixmap = pixmap_cache_.take(path); + if (!pixmap) { + pixmap = new QPixmap(path); + pixmap_cache_.insert(path, pixmap); + } + + return pixmap; } void LogicSignal::on_trigger()