]> sigrok.org Git - pulseview.git/blobdiff - pv/views/trace/view.cpp
Fix a compiler warning
[pulseview.git] / pv / views / trace / view.cpp
index 69599b1bb1bd28a8ad767e474e56be3b7a9640a6..ee4a4042fdc072a5de65a089ad0b29c874745167 100644 (file)
@@ -29,7 +29,6 @@
 #include <cmath>
 #include <iostream>
 #include <iterator>
-#include <unordered_set>
 
 #include <QApplication>
 #include <QDebug>
@@ -55,6 +54,7 @@
 #include "pv/metadata_obj.hpp"
 #include "pv/data/logic.hpp"
 #include "pv/data/logicsegment.hpp"
+#include "pv/data/signalbase.hpp"
 #include "pv/devices/device.hpp"
 #include "pv/globalsettings.hpp"
 #include "pv/session.hpp"
@@ -64,6 +64,7 @@
 #include "decodetrace.hpp"
 #endif
 
+using pv::data::SignalBase;
 using pv::data::SignalData;
 using pv::data::Segment;
 using pv::util::TimeUnit;
@@ -73,6 +74,7 @@ using std::back_inserter;
 using std::copy_if;
 using std::count_if;
 using std::inserter;
+using std::lock_guard;
 using std::max;
 using std::make_pair;
 using std::make_shared;
@@ -82,8 +84,6 @@ using std::pair;
 using std::set;
 using std::set_difference;
 using std::shared_ptr;
-using std::unordered_map;
-using std::unordered_set;
 using std::vector;
 
 namespace pv {
@@ -344,24 +344,60 @@ shared_ptr<Signal> View::get_signal_by_signalbase(shared_ptr<data::SignalBase> b
        return ret_val;
 }
 
-void View::clear_signals()
+void View::clear_signalbases()
 {
-       ViewBase::clear_signals();
+       ViewBase::clear_signalbases();
        signals_.clear();
 }
 
-void View::add_signal(const shared_ptr<Signal> signal)
+void View::add_signalbase(const shared_ptr<data::SignalBase> signalbase)
 {
-       ViewBase::add_signalbase(signal->base());
+       ViewBase::add_signalbase(signalbase);
+
+       shared_ptr<Signal> signal;
+
+       switch (signalbase->type()) {
+       case SignalBase::LogicChannel:
+               signal = shared_ptr<Signal>(new LogicSignal(session_, session_.device(), signalbase));
+               break;
+
+       case SignalBase::AnalogChannel:
+               signal = shared_ptr<Signal>(new AnalogSignal(session_, signalbase));
+               break;
+
+       default:
+               qDebug() << "Unknown signalbase type:" << signalbase->type();
+               assert(false);
+               break;
+       }
+
        signals_.push_back(signal);
 
        signal->set_segment_display_mode(segment_display_mode_);
        signal->set_current_segment(current_segment_);
 
+       // Secondary views use the signal's settings in the main view
+       if (!is_main_view()) {
+               shared_ptr<View> main_tv = dynamic_pointer_cast<View>(session_.main_view());
+               shared_ptr<Signal> main_signal = main_tv->get_signal_by_signalbase(signalbase);
+               if (main_signal)
+                       signal->restore_settings(main_signal->save_settings());
+       }
+
        connect(signal->base().get(), SIGNAL(name_changed(const QString&)),
                this, SLOT(on_signal_name_changed()));
 }
 
+void View::remove_signalbase(const shared_ptr<data::SignalBase> signalbase)
+{
+       ViewBase::remove_signalbase(signalbase);
+
+       shared_ptr<Signal> signal = get_signal_by_signalbase(signalbase);
+
+       if (signal)
+               remove_trace(signal);
+}
+
 #ifdef ENABLE_DECODE
 void View::clear_decode_signals()
 {
@@ -389,14 +425,34 @@ void View::remove_decode_signal(shared_ptr<data::DecodeSignal> signal)
        for (auto i = decode_traces_.begin(); i != decode_traces_.end(); i++)
                if ((*i)->base() == signal) {
                        decode_traces_.erase(i);
-                       signals_changed();
-                       return;
+                       break;
                }
 
        ViewBase::remove_decode_signal(signal);
 }
 #endif
 
+void View::remove_trace(shared_ptr<Trace> trace)
+{
+       TraceTreeItemOwner *const owner = trace->owner();
+       assert(owner);
+       owner->remove_child_item(trace);
+
+       for (auto i = signals_.begin(); i != signals_.end(); i++)
+               if ((*i) == trace) {
+                       signals_.erase(i);
+                       break;
+               }
+
+       if (!header_was_shrunk_)
+               resize_header_to_fit();
+
+       update_layout();
+
+       header_->update();
+       viewport_->update();
+}
+
 shared_ptr<Signal> View::get_signal_under_mouse_cursor() const
 {
        return signal_under_mouse_cursor_;
@@ -895,7 +951,7 @@ pair<Timestamp, Timestamp> View::get_time_extents() const
        if (!left_time || !right_time)
                return make_pair(0, 0);
 
-       assert(*left_time < *right_time);
+       assert(*left_time <= *right_time);
        return make_pair(*left_time, *right_time);
 }
 
@@ -1375,12 +1431,11 @@ void View::update_layout()
 
 TraceTreeItemOwner* View::find_prevalent_trace_group(
        const shared_ptr<sigrok::ChannelGroup> &group,
-       const unordered_map<shared_ptr<data::SignalBase>, shared_ptr<Signal> >
-               &signal_map)
+       const map<shared_ptr<data::SignalBase>, shared_ptr<Signal> > &signal_map)
 {
        assert(group);
 
-       unordered_set<TraceTreeItemOwner*> owners;
+       set<TraceTreeItemOwner*> owners;
        vector<TraceTreeItemOwner*> owner_list;
 
        // Make a set and a list of all the owners
@@ -1412,8 +1467,7 @@ TraceTreeItemOwner* View::find_prevalent_trace_group(
 
 vector< shared_ptr<Trace> > View::extract_new_traces_for_channels(
        const vector< shared_ptr<sigrok::Channel> > &channels,
-       const unordered_map<shared_ptr<data::SignalBase>, shared_ptr<Signal> >
-               &signal_map,
+       const map<shared_ptr<data::SignalBase>, shared_ptr<Signal> > &signal_map,
        set< shared_ptr<Trace> > &add_list)
 {
        vector< shared_ptr<Trace> > filtered_traces;
@@ -1710,6 +1764,8 @@ void View::signals_changed()
 {
        using sigrok::Channel;
 
+       lock_guard<mutex> lock(signal_mutex_);
+
        vector< shared_ptr<Channel> > channels;
        shared_ptr<sigrok::Device> sr_dev;
        bool signals_added_or_removed = false;
@@ -1732,7 +1788,9 @@ void View::signals_changed()
        vector< shared_ptr<TraceTreeItem> > new_top_level_items;
 
        // Make a list of traces that are being added, and a list of traces
-       // that are being removed
+       // that are being removed. The set_difference() algorithms require
+       // both sets to be in the exact same order, which means that PD signals
+       // must always be last as they interrupt the sort order otherwise
        const vector<shared_ptr<Trace>> prev_trace_list = list_by_type<Trace>();
        const set<shared_ptr<Trace>> prev_traces(
                prev_trace_list.begin(), prev_trace_list.end());
@@ -1742,7 +1800,6 @@ void View::signals_changed()
 #ifdef ENABLE_DECODE
        traces.insert(decode_traces_.begin(), decode_traces_.end());
 #endif
-
        set< shared_ptr<Trace> > add_traces;
        set_difference(traces.begin(), traces.end(),
                prev_traces.begin(), prev_traces.end(),
@@ -1754,8 +1811,7 @@ void View::signals_changed()
                inserter(remove_traces, remove_traces.begin()));
 
        // Make a look-up table of sigrok Channels to pulseview Signals
-       unordered_map<shared_ptr<data::SignalBase>, shared_ptr<Signal> >
-               signal_map;
+       map<shared_ptr<data::SignalBase>, shared_ptr<Signal> > signal_map;
        for (const shared_ptr<Signal>& sig : signals_)
                signal_map[sig->base()] = sig;
 
@@ -1856,7 +1912,11 @@ void View::signals_changed()
 
        // Add and position the pending top levels items
        int offset = v_extents().second;
-       for (auto item : new_top_level_items) {
+       for (shared_ptr<TraceTreeItem> item : new_top_level_items) {
+               // items may already have gained an owner when they were added to a group above
+               if (item->owner())
+                       continue;
+
                add_child_item(item);
 
                // Position the item after the last item or at the top if there is none