]> sigrok.org Git - pulseview.git/commitdiff
Implement segment display mode handling and update notifications
authorSoeren Apel <redacted>
Tue, 7 Nov 2017 09:56:25 +0000 (10:56 +0100)
committerSoeren Apel <redacted>
Wed, 27 Dec 2017 17:40:19 +0000 (18:40 +0100)
pv/views/trace/analogsignal.cpp
pv/views/trace/analogsignal.hpp
pv/views/trace/logicsignal.cpp
pv/views/trace/logicsignal.hpp
pv/views/trace/standardbar.cpp
pv/views/trace/standardbar.hpp
pv/views/trace/trace.cpp
pv/views/trace/trace.hpp
pv/views/trace/view.cpp
pv/views/trace/view.hpp

index cddf59c15059cdda26a209b4781032f73fdd9bce..90e441e09f125392c5ccd215e0b2441b55f3c026 100644 (file)
@@ -268,19 +268,10 @@ void AnalogSignal::paint_mid(QPainter &p, ViewItemPaintParams &pp)
        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();
@@ -539,19 +530,9 @@ void AnalogSignal::paint_logic_mid(QPainter &p, ViewItemPaintParams &pp)
        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();
 
@@ -666,6 +647,52 @@ void AnalogSignal::paint_logic_caps(QPainter &p, QLineF *const lines,
        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};
index af29c5e26b41230c533ec9bca6bae4b091d4416a..a66fb9e2fcefca99164644ac7ceb7dae75c209a4 100644 (file)
@@ -145,6 +145,9 @@ private:
                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.
         */
index e536171667307c8e43a2a81876de90c3ca9f815c..4a3a80a7255fa7b5cd6a6f1bdb263bfce4bcfd3f 100644 (file)
@@ -192,18 +192,9 @@ 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<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();
 
@@ -355,6 +346,30 @@ void LogicSignal::paint_caps(QPainter &p, QLineF *const lines,
        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"),
index 9899260a8cfc503f342802020a17e6db56d11a8e..4a52d379060523569e42628e94aa99d2aea6ee20 100644 (file)
@@ -120,6 +120,8 @@ private:
                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;
index d773a5c1367df44113d9392ef8e44a2e4a53a38a..6363e2ec6fcc9717e92dfc3a327713836d5b93eb 100644 (file)
@@ -91,6 +91,10 @@ StandardBar::StandardBar(Session &session, QWidget *parent,
                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)));
@@ -125,6 +129,8 @@ void StandardBar::show_multi_segment_ui(const bool state)
 {
        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
@@ -195,6 +201,18 @@ void StandardBar::on_new_segment(int new_segment_id)
                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
index 8640b4c9520ae01b0f41a2721a8cd4da8261a13a..e1394372dc4a0a5273b9b03501f99dba24c5d48e 100644 (file)
@@ -89,6 +89,8 @@ protected Q_SLOTS:
        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_;
index f9bd87e1dd906bafdc23e135b818bc7c47f4b6b1..b5fc0b1b5478333930ffbb150460c779a0a2ee40 100644 (file)
@@ -51,6 +51,7 @@ const QColor Trace::DarkGrayBGColour = QColor(0, 0, 0, 15 * 255 / 100);
 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)
 {
@@ -242,6 +243,14 @@ void Trace::set_colour(QColor colour)
        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 */
index 407592de63bc7bb2221aadc77388424789533dfe..75705226780e8c7a7aea029806fbf5ffdf78b4d4 100644 (file)
@@ -63,6 +63,19 @@ class Trace : public TraceTreeItem
 {
        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;
@@ -89,6 +102,11 @@ public:
         */
        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.
@@ -146,6 +164,8 @@ protected:
        shared_ptr<data::SignalBase> base_;
        QPen axis_pen_;
 
+       SegmentDisplayMode segment_display_mode_;
+
 private:
        pv::widgets::Popup *popup_;
        QFormLayout *popup_form_;
index 07919c28ac937d13b4767f5ccea297e2df5543df..e26e8fc2582a8a45b57f41d3abbf2d72940ed6f7 100644 (file)
@@ -125,6 +125,8 @@ bool CustomScrollArea::viewportEvent(QEvent *event)
 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),
@@ -255,6 +257,8 @@ void View::add_signal(const shared_ptr<Signal> signal)
        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()));
 }
@@ -271,6 +275,8 @@ void View::add_decode_signal(shared_ptr<data::DecodeSignal> signal)
                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()));
 }
@@ -477,6 +483,26 @@ void View::set_time_unit(pv::util::TimeUnit time_unit)
        }
 }
 
+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);
@@ -1386,16 +1412,25 @@ void View::capture_state_updated(int state)
 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()
index 8fd7e968552f6af0528e3697e16f8eca2a5fb11e..da05691f42f5274b8c8fd86d54ffeccd80230927 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "cursorpair.hpp"
 #include "flag.hpp"
+#include "trace.hpp"
 #include "tracetreeitemowner.hpp"
 
 using std::list;
@@ -190,6 +191,14 @@ public:
         */
        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);
 
@@ -295,6 +304,12 @@ Q_SIGNALS:
        /// 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);
 
@@ -424,6 +439,10 @@ private:
 
        /// 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_;