X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=pv%2Fview%2Fview.cpp;h=3b8508329cac79f1ee13fffd1e3f01d92844c9d9;hb=448a72cf7f0225eace2335ec05b979c4e9a6b882;hp=80ade0d23f5bccd573bb5385d064a1d40d9aec04;hpb=4f82e4f613aced3594f07fa219a9d8c247eaed11;p=pulseview.git diff --git a/pv/view/view.cpp b/pv/view/view.cpp index 80ade0d2..3b850832 100644 --- a/pv/view/view.cpp +++ b/pv/view/view.cpp @@ -26,16 +26,21 @@ #include #include #include +#include #include #include #include +#include + #include "cursorheader.h" #include "decodetrace.h" #include "header.h" +#include "logicsignal.h" #include "ruler.h" #include "signal.h" +#include "tracegroup.h" #include "view.h" #include "viewport.h" @@ -48,6 +53,7 @@ using boost::shared_mutex; using pv::data::SignalData; using std::back_inserter; using std::deque; +using std::dynamic_pointer_cast; using std::list; using std::lock_guard; using std::max; @@ -56,6 +62,8 @@ using std::min; using std::pair; using std::set; using std::shared_ptr; +using std::unordered_map; +using std::unordered_set; using std::vector; using std::weak_ptr; @@ -105,8 +113,6 @@ View::View(SigSession &session, QWidget *parent) : connect(_cursors.second().get(), SIGNAL(time_changed()), this, SLOT(marker_time_changed())); - connect(_header, SIGNAL(geometry_updated()), - this, SLOT(on_geometry_updated())); connect(_header, SIGNAL(signals_moved()), this, SLOT(on_signals_moved())); @@ -123,6 +129,10 @@ View::View(SigSession &session, QWidget *parent) : connect(this, SIGNAL(hover_point_changed()), this, SLOT(on_hover_point_changed())); + connect(&_lazy_event_handler, SIGNAL(timeout()), + this, SLOT(process_sticky_events())); + _lazy_event_handler.setSingleShot(true); + setViewport(_viewport); _viewport->installEventFilter(this); @@ -179,11 +189,16 @@ double View::offset() const return _offset; } -int View::owner_v_offset() const +int View::owner_visual_v_offset() const { return -_v_offset; } +unsigned int View::depth() const +{ + return 0; +} + void View::zoom(double steps) { zoom(steps, _viewport->width() / 2); @@ -324,6 +339,29 @@ void View::update_viewport() { assert(_viewport); _viewport->update(); + _header->update(); +} + +void View::restack_all_row_items() +{ + // Make a set of owners + unordered_set< RowItemOwner* > owners; + for (const auto &r : *this) + owners.insert(r->owner()); + + // Make a list that is sorted from deepest first + vector< RowItemOwner* > sorted_owners(owners.begin(), owners.end()); + sort(sorted_owners.begin(), sorted_owners.end(), + [](const RowItemOwner* a, const RowItemOwner *b) { + return a->depth() > b->depth(); }); + + // Restack the items recursively + for (auto &o : sorted_owners) + o->restack_items(); + + // Animate the items to their destination + for (const auto &r : *this) + r->animate_to_layout_v_offset(); } void View::get_scroll_layout(double &length, double &offset) const @@ -405,6 +443,45 @@ QRectF View::label_rect(int right) return QRectF(); } +bool View::add_channels_to_owner( + const vector< shared_ptr > &channels, + RowItemOwner *owner, int &offset, + unordered_map, shared_ptr > + &signal_map, + std::function)> filter_func) +{ + bool any_added = false; + + assert(owner); + + for (const auto &channel : channels) + { + const auto iter = signal_map.find(channel); + if (iter == signal_map.end() || + (filter_func && !filter_func((*iter).second))) + continue; + + shared_ptr row_item = (*iter).second; + owner->add_child_item(row_item); + apply_offset(row_item, offset); + signal_map.erase(iter); + + any_added = true; + } + + return any_added; +} + +void View::apply_offset(shared_ptr row_item, int &offset) { + assert(row_item); + const pair extents = row_item->v_extents(); + if (row_item->enabled()) + offset += -extents.first; + row_item->force_to_v_offset(offset); + if (row_item->enabled()) + offset += extents.second; +} + bool View::eventFilter(QObject *object, QEvent *event) { const QEvent::Type type = event->type(); @@ -454,6 +531,22 @@ void View::resizeEvent(QResizeEvent*) update_layout(); } +void View::appearance_changed(bool label, bool content) +{ + if (label) + _header->update(); + if (content) + _viewport->update(); +} + +void View::extents_changed(bool horz, bool vert) +{ + _sticky_events |= + (horz ? SelectableItemHExtentsChanged : 0) | + (vert ? SelectableItemVExtentsChanged : 0); + _lazy_event_handler.start(); +} + void View::h_scroll_value_changed(int value) { if (_updating_scroll) @@ -482,37 +575,72 @@ void View::v_scroll_value_changed(int value) void View::signals_changed() { + int offset = 0; + // Populate the traces clear_child_items(); - shared_lock lock(session().signals_mutex()); - const vector< shared_ptr > &sigs(session().signals()); - for (auto s : sigs) - add_child_item(s); + shared_ptr device = _session.device(); + assert(device); + + // Collect a set of signals + unordered_map, shared_ptr > + signal_map; + + shared_lock lock(_session.signals_mutex()); + const vector< shared_ptr > &sigs(_session.signals()); + + for (const shared_ptr &sig : sigs) + signal_map[sig->channel()] = sig; + + // Populate channel groups + for (auto entry : device->channel_groups()) + { + const shared_ptr &group = entry.second; + + if (group->channels().size() <= 1) + continue; + + shared_ptr trace_group(new TraceGroup()); + int child_offset = 0; + if (add_channels_to_owner(group->channels(), + trace_group.get(), child_offset, signal_map)) + { + add_child_item(trace_group); + apply_offset(trace_group, offset); + } + } + // Add the remaining logic channels + shared_ptr logic_trace_group(new TraceGroup()); + int child_offset = 0; + + if (add_channels_to_owner(device->channels(), + logic_trace_group.get(), child_offset, signal_map, + [](shared_ptr r) -> bool { + return dynamic_pointer_cast(r) != nullptr; + })) + + { + add_child_item(logic_trace_group); + apply_offset(logic_trace_group, offset); + } + + // Add the remaining channels + add_channels_to_owner(device->channels(), this, offset, signal_map); + assert(signal_map.empty()); + + // Add decode signals #ifdef ENABLE_DECODE const vector< shared_ptr > decode_sigs( session().get_decode_signals()); - for (auto s : decode_sigs) + for (auto s : decode_sigs) { add_child_item(s); -#endif - - // Create the initial layout - int offset = 0; - for (shared_ptr r : *this) { - const pair extents = r->v_extents(); - if (r->enabled()) - offset += -extents.first; - r->set_v_offset(offset); - if (r->enabled()) - offset += extents.second; + apply_offset(s, offset); } +#endif update_layout(); - - // Update the child widgets - _header->signals_updated(); - _viewport->signals_updated(); } void View::data_updated() @@ -536,9 +664,15 @@ void View::on_signals_moved() signals_moved(); } -void View::on_geometry_updated() +void View::process_sticky_events() { - update_layout(); + if (_sticky_events & SelectableItemHExtentsChanged) + update_layout(); + if (_sticky_events & SelectableItemVExtentsChanged) + restack_all_row_items(); + + // Clear the sticky events + _sticky_events = 0; } void View::on_hover_point_changed()