if ((display_type_ == DisplayAnalog) || (display_type_ == DisplayBoth)) {
paint_grid(p, y, pp.left(), pp.right());
- const deque< shared_ptr<pv::data::AnalogSegment> > &segments =
- base_->analog_data()->analog_segments();
- if (segments.empty())
+ shared_ptr<pv::data::AnalogSegment> segment = get_analog_segment_to_paint();
+ if (!segment)
return;
- shared_ptr<pv::data::AnalogSegment> segment;
- try {
- segment = segments.at(current_segment_);
- } catch (out_of_range) {
- qDebug() << "Current analog segment out of range for signal" << base_->name();
- return;
- }
-
const double pixels_offset = pp.pixels_offset();
const double samplerate = max(1.0, segment->samplerate());
const pv::util::Timestamp& start_time = segment->start_time();
const float high_offset = y - ph + signal_margin + 0.5f;
const float low_offset = y + nh - signal_margin - 0.5f;
- const deque< shared_ptr<pv::data::LogicSegment> > &segments =
- base_->logic_data()->logic_segments();
-
- if (segments.empty())
- return;
-
- shared_ptr<pv::data::LogicSegment> segment;
- try {
- segment = segments.at(current_segment_);
- } catch (out_of_range) {
- qDebug() << "Current logic segment out of range for signal" << base_->name();
+ shared_ptr<pv::data::LogicSegment> segment = get_logic_segment_to_paint();
+ if (!segment)
return;
- }
double samplerate = segment->samplerate();
p.drawLines(lines, line - lines);
}
+shared_ptr<pv::data::AnalogSegment> AnalogSignal::get_analog_segment_to_paint() const
+{
+ shared_ptr<pv::data::AnalogSegment> segment;
+
+ const deque< shared_ptr<pv::data::AnalogSegment> > &segments =
+ base_->analog_data()->analog_segments();
+
+ if (!segments.empty()) {
+ if (segment_display_mode_ == ShowLastSegmentOnly)
+ segment = segments.back();
+
+ if (segment_display_mode_ == ShowSingleSegmentOnly) {
+ try {
+ segment = segments.at(current_segment_);
+ } catch (out_of_range) {
+ qDebug() << "Current analog segment out of range for signal" << base_->name();
+ }
+ }
+ }
+
+ return segment;
+}
+
+shared_ptr<pv::data::LogicSegment> AnalogSignal::get_logic_segment_to_paint() const
+{
+ shared_ptr<pv::data::LogicSegment> segment;
+
+ const deque< shared_ptr<pv::data::LogicSegment> > &segments =
+ base_->logic_data()->logic_segments();
+
+ if (!segments.empty()) {
+ if (segment_display_mode_ == ShowLastSegmentOnly)
+ segment = segments.back();
+
+ if (segment_display_mode_ == ShowSingleSegmentOnly) {
+ try {
+ segment = segments.at(current_segment_);
+ } catch (out_of_range) {
+ qDebug() << "Current logic segment out of range for signal" << base_->name();
+ }
+ }
+ }
+
+ return segment;
+}
+
float AnalogSignal::get_resolution(int scale_index)
{
const float seq[] = {1.0f, 2.0f, 5.0f};
bool level, double samples_per_pixel, double pixels_offset,
float x_offset, float y_offset);
+ shared_ptr<pv::data::AnalogSegment> get_analog_segment_to_paint() const;
+ shared_ptr<pv::data::LogicSegment> get_logic_segment_to_paint() const;
+
/**
* Computes the scale factor from the scale index and vdiv settings.
*/
const float high_offset = y - signal_height_ + 0.5f;
const float low_offset = y + 0.5f;
- const deque< shared_ptr<pv::data::LogicSegment> > &segments =
- base_->logic_data()->logic_segments();
- if (segments.empty())
- return;
-
- shared_ptr<pv::data::LogicSegment> segment;
- try {
- segment = segments.at(current_segment_);
- } catch (out_of_range) {
- qDebug() << "Current logic segment out of range for signal" << base_->name();
+ shared_ptr<pv::data::LogicSegment> segment = get_logic_segment_to_paint();
+ if (!segment)
return;
- }
double samplerate = segment->samplerate();
p.drawLines(lines, line - lines);
}
+shared_ptr<pv::data::LogicSegment> LogicSignal::get_logic_segment_to_paint() const
+{
+ shared_ptr<pv::data::LogicSegment> segment;
+
+ const deque< shared_ptr<pv::data::LogicSegment> > &segments =
+ base_->logic_data()->logic_segments();
+
+ if (!segments.empty()) {
+ if (segment_display_mode_ == ShowLastSegmentOnly) {
+ segment = segments.back();
+ }
+
+ if (segment_display_mode_ == ShowSingleSegmentOnly) {
+ try {
+ segment = segments.at(current_segment_);
+ } catch (out_of_range) {
+ qDebug() << "Current logic segment out of range for signal" << base_->name();
+ }
+ }
+ }
+
+ return segment;
+}
+
void LogicSignal::init_trigger_actions(QWidget *parent)
{
trigger_none_ = new QAction(*get_icon(":/icons/trigger-none.svg"),
bool level, double samples_per_pixel, double pixels_offset,
float x_offset, float y_offset);
+ shared_ptr<pv::data::LogicSegment> get_logic_segment_to_paint() const;
+
void init_trigger_actions(QWidget *parent);
const vector<int32_t> get_trigger_types() const;
this, SLOT(on_new_segment(int)));
connect(segment_selector_, SIGNAL(valueChanged(int)),
view_, SLOT(on_segment_changed(int)));
+ connect(view_, SIGNAL(segment_changed(int)),
+ this, SLOT(on_segment_changed(int)));
+ connect(view_, SIGNAL(segment_display_mode_changed(bool)),
+ this, SLOT(on_segment_display_mode_changed(bool)));
connect(view_, SIGNAL(always_zoom_to_fit_changed(bool)),
this, SLOT(on_always_zoom_to_fit_changed(bool)));
{
for (QAction* action : multi_segment_actions_)
action->setVisible(state);
+
+ on_segment_display_mode_changed(view_->segment_is_selectable());
}
QAction* StandardBar::action_view_zoom_in() const
show_multi_segment_ui(false);
}
+void StandardBar::on_segment_changed(int segment_id)
+{
+ // This is called when the current segment was changed
+ // by other parts of the UI, e.g. the view itself
+ segment_selector_->setValue(segment_id);
+}
+
+void StandardBar::on_segment_display_mode_changed(bool segment_selectable)
+{
+ segment_selector_->setReadOnly(!segment_selectable);
+}
+
} // namespace trace
} // namespace views
} // namespace pv
void on_always_zoom_to_fit_changed(bool state);
void on_new_segment(int new_segment_id);
+ void on_segment_changed(int segment_id);
+ void on_segment_display_mode_changed(bool segment_selectable);
private:
vector<QAction*> multi_segment_actions_;
Trace::Trace(shared_ptr<data::SignalBase> channel) :
base_(channel),
axis_pen_(AxisPen),
+ segment_display_mode_(ShowLastSegmentOnly), // Will be overwritten by View
popup_(nullptr),
popup_form_(nullptr)
{
base_->set_colour(colour);
}
+void Trace::set_segment_display_mode(SegmentDisplayMode mode)
+{
+ segment_display_mode_ = mode;
+
+ if (owner_)
+ owner_->row_item_appearance_changed(true, true);
+}
+
void Trace::on_name_changed(const QString &text)
{
/* This event handler is called by SignalBase when the name was changed there */
{
Q_OBJECT
+public:
+ /**
+ * Allowed values for the multi-segment display mode.
+ *
+ * Note: Consider @ref View::set_segment_display_mode when updating the list.
+ */
+ enum SegmentDisplayMode {
+ ShowLastSegmentOnly = 1,
+ ShowSingleSegmentOnly,
+ ShowAllSegments,
+ ShowAccumulatedIntensity
+ };
+
private:
static const QPen AxisPen;
static const int LabelHitPadding;
*/
virtual void set_colour(QColor colour);
+ /**
+ * Configures the segment display mode to use.
+ */
+ virtual void set_segment_display_mode(SegmentDisplayMode mode);
+
/**
* Paints the signal label.
* @param p the QPainter to paint into.
shared_ptr<data::SignalBase> base_;
QPen axis_pen_;
+ SegmentDisplayMode segment_display_mode_;
+
private:
pv::widgets::Popup *popup_;
QFormLayout *popup_form_;
View::View(Session &session, bool is_main_view, QWidget *parent) :
ViewBase(session, is_main_view, parent),
splitter_(new QSplitter()),
+ segment_display_mode_(Trace::ShowLastSegmentOnly),
+ segment_selectable_(false),
scale_(1e-3),
offset_(0),
updating_scroll_(false),
ViewBase::add_signalbase(signal->base());
signals_.insert(signal);
+ signal->set_segment_display_mode(segment_display_mode_);
+
connect(signal->base().get(), SIGNAL(name_changed(const QString&)),
this, SLOT(on_signal_name_changed()));
}
new DecodeTrace(session_, signal, decode_traces_.size()));
decode_traces_.push_back(d);
+ d->set_segment_display_mode(segment_display_mode_);
+
connect(signal.get(), SIGNAL(name_changed(const QString&)),
this, SLOT(on_signal_name_changed()));
}
}
}
+bool View::segment_is_selectable() const
+{
+ return segment_selectable_;
+}
+
+void View::set_segment_display_mode(Trace::SegmentDisplayMode mode)
+{
+ for (shared_ptr<Signal> signal : signals_)
+ signal->set_segment_display_mode(mode);
+
+ viewport_->update();
+
+ segment_selectable_ = true;
+
+ if (mode == Trace::ShowSingleSegmentOnly)
+ segment_selectable_ = false;
+
+ segment_display_mode_changed(segment_selectable_);
+}
+
void View::zoom(double steps)
{
zoom(steps, viewport_->width() / 2);
void View::on_new_segment(int new_segment_id)
{
on_segment_changed(new_segment_id);
+ segment_changed(new_segment_id);
}
void View::on_segment_changed(int segment)
{
- current_segment_ = segment - 1;
-
- for (shared_ptr<Signal> signal : signals_)
- signal->set_current_segment(current_segment_);
+ switch (segment_display_mode_) {
+ case Trace::ShowLastSegmentOnly:
+ case Trace::ShowSingleSegmentOnly:
+ current_segment_ = segment - 1;
+ for (shared_ptr<Signal> signal : signals_)
+ signal->set_current_segment(current_segment_);
+ viewport_->update();
+ break;
- viewport_->update();
+ case Trace::ShowAllSegments:
+ case Trace::ShowAccumulatedIntensity:
+ default:
+ break;
+ }
}
void View::perform_delayed_view_update()
#include "cursorpair.hpp"
#include "flag.hpp"
+#include "trace.hpp"
#include "tracetreeitemowner.hpp"
using std::list;
*/
unsigned int depth() const;
+ /**
+ * Returns whether the currently shown segment can be influenced
+ * (selected) or not.
+ */
+ bool segment_is_selectable() const;
+
+ void set_segment_display_mode(Trace::SegmentDisplayMode mode);
+
void zoom(double steps);
void zoom(double steps, int offset);
/// Emitted when the time_unit changed.
void time_unit_changed();
+ /// Emitted when the currently selected segment changed
+ void segment_changed(int segment_id);
+
+ /// Emitted when the multi-segment display mode changed
+ void segment_display_mode_changed(bool segment_selectable);
+
public Q_SLOTS:
void trigger_event(util::Timestamp location);
/// The ID of the currently displayed segment
int current_segment_;
+ Trace::SegmentDisplayMode segment_display_mode_;
+
+ /// Signals whether the user can change the currently shown segment.
+ bool segment_selectable_;
/// The view time scale in seconds per pixel.
double scale_;