X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fview%2Fview.cpp;h=3f832474cebdf9415df879dc3592a7de27a25f7d;hp=9a46bab8c4c4d41ea9f91e36b05d84c96c05b9c7;hb=bb7dd726eb7159ddd80d94ede791f2e2a9eaef0f;hpb=d9ea96280ab1128427143660ae375c30b19aa0cb diff --git a/pv/view/view.cpp b/pv/view/view.cpp index 9a46bab8..3f832474 100644 --- a/pv/view/view.cpp +++ b/pv/view/view.cpp @@ -186,6 +186,45 @@ const Session& View::session() const return session_; } +std::unordered_set< std::shared_ptr > View::signals() const +{ + return signals_; +} + +void View::clear_signals() +{ + signals_.clear(); +} + +void View::add_signal(const shared_ptr signal) +{ + signals_.insert(signal); +} + +#ifdef ENABLE_DECODE +void View::clear_decode_traces() +{ + decode_traces_.clear(); +} + +void View::add_decode_trace(shared_ptr signalbase) +{ + shared_ptr d( + new view::DecodeTrace(session_, signalbase, decode_traces_.size())); + decode_traces_.push_back(d); +} + +void View::remove_decode_trace(shared_ptr signalbase) +{ + for (auto i = decode_traces_.begin(); i != decode_traces_.end(); i++) + if ((*i)->base() == signalbase) { + decode_traces_.erase(i); + signals_changed(); + return; + } +} +#endif + View* View::view() { return this; @@ -397,11 +436,9 @@ void View::set_scale_offset(double scale, const Timestamp& offset) set< shared_ptr > View::get_visible_data() const { - const unordered_set< shared_ptr > sigs(session().signals()); - // Make a set of all the visible data objects set< shared_ptr > visible_data; - for (const shared_ptr sig : sigs) + for (const shared_ptr sig : signals_) if (sig->enabled()) visible_data.insert(sig->data()); @@ -527,13 +564,6 @@ const QPoint& View::hover_point() const return hover_point_; } -void View::update_viewport() -{ - assert(viewport_); - viewport_->update(); - header_->update(); -} - void View::restack_all_trace_tree_items() { // Make a list of owners that is sorted from deepest first @@ -689,8 +719,47 @@ void View::update_scroll() verticalScrollBar()->setSingleStep(areaSize.height() / 8); const pair extents = v_extents(); - verticalScrollBar()->setRange(extents.first - (areaSize.height() / 2), - extents.second - (areaSize.height() / 2)); + + // Don't change the scrollbar range if there are no traces + if (extents.first != extents.second) + verticalScrollBar()->setRange(extents.first - areaSize.height(), + extents.second); + + if (scroll_needs_defaults) + set_scroll_default(); +} + +void View::reset_scroll() +{ + verticalScrollBar()->setRange(0, 0); +} + +void View::set_scroll_default() +{ + assert(viewport_); + + const QSize areaSize = viewport_->size(); + + // Special case: when starting up and the window isn't visible yet, + // areaSize is [0, 0]. In this case we want to be called again later + if (areaSize.height() == 0) { + scroll_needs_defaults = true; + return; + } else { + scroll_needs_defaults = false; + } + + const pair extents = v_extents(); + const int trace_height = extents.second - extents.first; + + // Do all traces fit in the view? + if (areaSize.height() >= trace_height) + // Center all traces vertically + set_v_offset(extents.first - + ((areaSize.height() - trace_height) / 2)); + else + // Put the first trace at the top, letting the bottom ones overflow + set_v_offset(extents.first); } void View::update_layout() @@ -705,22 +774,9 @@ void View::update_layout() update_scroll(); } -void View::paint_label(QPainter &p, const QRect &rect, bool hover) -{ - (void)p; - (void)rect; - (void)hover; -} - -QRectF View::label_rect(const QRectF &rect) -{ - (void)rect; - return QRectF(); -} - TraceTreeItemOwner* View::find_prevalent_trace_group( const shared_ptr &group, - const unordered_map, shared_ptr > + const unordered_map, shared_ptr > &signal_map) { assert(group); @@ -730,13 +786,13 @@ TraceTreeItemOwner* View::find_prevalent_trace_group( // Make a set and a list of all the owners for (const auto &channel : group->channels()) { - const auto iter = signal_map.find(channel); - if (iter == signal_map.end()) - continue; - - TraceTreeItemOwner *const o = (*iter).second->owner(); - owner_list.push_back(o); - owners.insert(o); + for (auto entry : signal_map) { + if (entry.first->channel() == channel) { + TraceTreeItemOwner *const o = (entry.second)->owner(); + owner_list.push_back(o); + owners.insert(o); + } + } } // Iterate through the list of owners, and find the most prevalent @@ -757,24 +813,24 @@ TraceTreeItemOwner* View::find_prevalent_trace_group( vector< shared_ptr > View::extract_new_traces_for_channels( const vector< shared_ptr > &channels, - const unordered_map, shared_ptr > + const unordered_map, shared_ptr > &signal_map, set< shared_ptr > &add_list) { vector< shared_ptr > filtered_traces; for (const auto &channel : channels) { - const auto map_iter = signal_map.find(channel); - if (map_iter == signal_map.end()) - continue; - - shared_ptr trace = (*map_iter).second; - const auto list_iter = add_list.find(trace); - if (list_iter == add_list.end()) - continue; - - filtered_traces.push_back(trace); - add_list.erase(list_iter); + for (auto entry : signal_map) { + if (entry.first->channel() == channel) { + shared_ptr trace = entry.second; + const auto list_iter = add_list.find(trace); + if (list_iter == add_list.end()) + continue; + + filtered_traces.push_back(trace); + add_list.erase(list_iter); + } + } } return filtered_traces; @@ -784,10 +840,8 @@ void View::determine_time_unit() { // Check whether we know the sample rate and hence can use time as the unit if (time_unit_ == util::TimeUnit::Samples) { - const unordered_set< shared_ptr > sigs(session().signals()); - // Check all signals but... - for (const shared_ptr signal : sigs) { + for (const shared_ptr signal : signals_) { const shared_ptr data = signal->data(); // ...only check first segment of each @@ -909,17 +963,24 @@ void View::signals_changed() { using sigrok::Channel; - vector< shared_ptr > new_top_level_items; + vector< shared_ptr > channels; + shared_ptr sr_dev; - const auto device = session_.device(); - if (!device) - return; + // Do we need to set the vertical scrollbar to its default position later? + // We do if there are no traces, i.e. the scroll bar has no range set + bool reset_scrollbar = + verticalScrollBar()->minimum() == verticalScrollBar()->maximum(); - shared_ptr sr_dev = device->device(); - assert(sr_dev); + if (!session_.device()) { + reset_scroll(); + signals_.clear(); + } else { + sr_dev = session_.device()->device(); + assert(sr_dev); + channels = sr_dev->channels(); + } - const vector< shared_ptr > channels( - sr_dev->channels()); + vector< shared_ptr > new_top_level_items; // Make a list of traces that are being added, and a list of traces // that are being removed @@ -927,14 +988,10 @@ void View::signals_changed() const set> prev_traces( prev_trace_list.begin(), prev_trace_list.end()); - const unordered_set< shared_ptr > sigs(session_.signals()); - - set< shared_ptr > traces(sigs.begin(), sigs.end()); + set< shared_ptr > traces(signals_.begin(), signals_.end()); #ifdef ENABLE_DECODE - const vector< shared_ptr > decode_traces( - session().get_decode_signals()); - traces.insert(decode_traces.begin(), decode_traces.end()); + traces.insert(decode_traces_.begin(), decode_traces_.end()); #endif set< shared_ptr > add_traces; @@ -948,74 +1005,84 @@ 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 > + unordered_map, shared_ptr > signal_map; - for (const shared_ptr &sig : sigs) - signal_map[sig->channel()] = sig; + for (const shared_ptr &sig : signals_) + signal_map[sig->base()] = sig; // Populate channel groups - for (auto entry : sr_dev->channel_groups()) { - const shared_ptr &group = entry.second; - - if (group->channels().size() <= 1) - continue; - - // Find best trace group to add to - TraceTreeItemOwner *owner = find_prevalent_trace_group( - group, signal_map); - - // If there is no trace group, create one - shared_ptr new_trace_group; - if (!owner) { - new_trace_group.reset(new TraceGroup()); - owner = new_trace_group.get(); - } - - // Extract traces for the trace group, removing them from - // the add list - const vector< shared_ptr > new_traces_in_group = - extract_new_traces_for_channels(group->channels(), - signal_map, add_traces); - - // Add the traces to the group - const pair prev_v_extents = owner->v_extents(); - int offset = prev_v_extents.second - prev_v_extents.first; - for (shared_ptr trace : new_traces_in_group) { - assert(trace); - owner->add_child_item(trace); - - const pair extents = trace->v_extents(); - if (trace->enabled()) - offset += -extents.first; - trace->force_to_v_offset(offset); - if (trace->enabled()) - offset += extents.second; + if (sr_dev) + for (auto entry : sr_dev->channel_groups()) { + const shared_ptr &group = entry.second; + + if (group->channels().size() <= 1) + continue; + + // Find best trace group to add to + TraceTreeItemOwner *owner = find_prevalent_trace_group( + group, signal_map); + + // If there is no trace group, create one + shared_ptr new_trace_group; + if (!owner) { + new_trace_group.reset(new TraceGroup()); + owner = new_trace_group.get(); + } + + // Extract traces for the trace group, removing them from + // the add list + const vector< shared_ptr > new_traces_in_group = + extract_new_traces_for_channels(group->channels(), + signal_map, add_traces); + + // Add the traces to the group + const pair prev_v_extents = owner->v_extents(); + int offset = prev_v_extents.second - prev_v_extents.first; + for (shared_ptr trace : new_traces_in_group) { + assert(trace); + owner->add_child_item(trace); + + const pair extents = trace->v_extents(); + if (trace->enabled()) + offset += -extents.first; + trace->force_to_v_offset(offset); + if (trace->enabled()) + offset += extents.second; + } + + if (new_trace_group) { + // Assign proper vertical offsets to each channel in the group + new_trace_group->restack_items(); + + // If this is a new group, enqueue it in the new top level + // items list + if (!new_traces_in_group.empty()) + new_top_level_items.push_back(new_trace_group); + } } - // If this is a new group, enqueue it in the new top level - // items list - if (!new_traces_in_group.empty() && new_trace_group) - new_top_level_items.push_back(new_trace_group); - } - // Enqueue the remaining logic channels in a group vector< shared_ptr > logic_channels; copy_if(channels.begin(), channels.end(), back_inserter(logic_channels), [](const shared_ptr& c) { return c->type() == sigrok::ChannelType::LOGIC; }); + const vector< shared_ptr > non_grouped_logic_signals = - extract_new_traces_for_channels(logic_channels, - signal_map, add_traces); - const shared_ptr non_grouped_trace_group( - make_shared()); - for (shared_ptr trace : non_grouped_logic_signals) - non_grouped_trace_group->add_child_item(trace); - new_top_level_items.push_back(non_grouped_trace_group); + extract_new_traces_for_channels(logic_channels, signal_map, add_traces); + + if (non_grouped_logic_signals.size() > 0) { + const shared_ptr non_grouped_trace_group( + make_shared()); + for (shared_ptr trace : non_grouped_logic_signals) + non_grouped_trace_group->add_child_item(trace); + + non_grouped_trace_group->restack_items(); + new_top_level_items.push_back(non_grouped_trace_group); + } // Enqueue the remaining channels as free ungrouped traces const vector< shared_ptr > new_top_level_signals = - extract_new_traces_for_channels(channels, - signal_map, add_traces); + extract_new_traces_for_channels(channels, signal_map, add_traces); new_top_level_items.insert(new_top_level_items.end(), new_top_level_signals.begin(), new_top_level_signals.end()); @@ -1030,16 +1097,26 @@ void View::signals_changed() owner->remove_child_item(trace); } + // Remove any empty trace groups + for (shared_ptr group : list_by_type()) + if (group->child_items().size() == 0) { + remove_child_item(group); + group.reset(); + } + // Add and position the pending top levels items for (auto item : new_top_level_items) { add_child_item(item); - // Position the item after the last present item + // Position the item after the last item or at the top if there is none int offset = v_extents().second; const pair extents = item->v_extents(); + if (item->enabled()) offset += -extents.first; + item->force_to_v_offset(offset); + if (item->enabled()) offset += extents.second; } @@ -1048,6 +1125,9 @@ void View::signals_changed() header_->update(); viewport_->update(); + + if (reset_scrollbar) + set_scroll_default(); } void View::capture_state_updated(int state)