# HG changeset patch # User Chris Cannam # Date 1595336532 -3600 # Node ID cbbb411da9770b8d46af288c1e21eef55f31e5ce # Parent 199dbb3547d4c76f2faee8a1a16c875e13ac51c2# Parent 911330a28a7c7d939a0fe8b2c35cbb75cdf1033c Merge diff -r 199dbb3547d4 -r cbbb411da977 view/AlignmentView.cpp --- a/view/AlignmentView.cpp Tue Jul 21 14:01:58 2020 +0100 +++ b/view/AlignmentView.cpp Tue Jul 21 14:02:12 2020 +0100 @@ -29,7 +29,10 @@ AlignmentView::AlignmentView(QWidget *w) : View(w, false), m_above(nullptr), - m_below(nullptr) + m_below(nullptr), + m_reference(nullptr), + m_leftmostAbove(-1), + m_rightmostAbove(-1) { setObjectName(tr("AlignmentView")); } @@ -41,10 +44,11 @@ SVCERR << "AlignmentView " << getId() << "::keyFramesChanged" << endl; #endif - // This is just a notification that we need to rebuild it - so all - // we do here is clear it, and it'll be rebuilt on demand later - QMutexLocker locker(&m_keyFrameMutex); - m_keyFrameMap.clear(); + // This is just a notification that we need to rebuild - so all we + // do here is clear, and rebuild on demand later + QMutexLocker locker(&m_mapsMutex); + m_fromAboveMap.clear(); + m_fromReferenceMap.clear(); } void @@ -86,7 +90,7 @@ } void -AlignmentView::setViewAbove(View *v) +AlignmentView::setAboveView(View *v) { if (m_above) { disconnect(m_above, nullptr, this, nullptr); @@ -113,7 +117,7 @@ } void -AlignmentView::setViewBelow(View *v) +AlignmentView::setBelowView(View *v) { if (m_below) { disconnect(m_below, nullptr, this, nullptr); @@ -140,6 +144,12 @@ } void +AlignmentView::setReferenceView(View *view) +{ + m_reference = view; +} + +void AlignmentView::paintEvent(QPaintEvent *) { if (m_above == nullptr || m_below == nullptr || !m_manager) return; @@ -167,28 +177,54 @@ paint.fillRect(rect(), bg); - QMutexLocker locker(&m_keyFrameMutex); + QMutexLocker locker(&m_mapsMutex); - if (m_keyFrameMap.empty()) { + if (m_fromAboveMap.empty()) { reconnectModels(); - buildKeyFrameMap(); + buildMaps(); } #ifdef DEBUG_ALIGNMENT_VIEW SVCERR << "AlignmentView " << getId() << "::paintEvent: painting " - << m_keyFrameMap.size() << " mappings" << endl; + << m_fromAboveMap.size() << " mappings" << endl; #endif - for (const auto &km: m_keyFrameMap) { + int w = width(); + int h = height(); - sv_frame_t af = km.first; - sv_frame_t bf = km.second; + if (m_leftmostAbove > 0) { + + for (const auto &km: m_fromAboveMap) { - int ax = m_above->getXForFrame(af); - int bx = m_below->getXForFrame(bf); + sv_frame_t af = km.first; + sv_frame_t bf = km.second; + + if (af < m_leftmostAbove || af > m_rightmostAbove) { + continue; + } - if (ax >= 0 || ax < width() || bx >= 0 || bx < width()) { - paint.drawLine(ax, 0, bx, height()); + int ax = m_above->getXForFrame(af); + int bx = m_below->getXForFrame(bf); + + if (ax >= 0 || ax < w || bx >= 0 || bx < w) { + paint.drawLine(ax, 0, bx, h); + } + } + } else if (m_reference != nullptr) { + // the below has nothing in common with the above: show things + // in common with the reference instead + + for (const auto &km: m_fromReferenceMap) { + + sv_frame_t af = km.first; + sv_frame_t bf = km.second; + + int ax = m_reference->getXForFrame(af); + int bx = m_below->getXForFrame(bf); + + if (ax >= 0 || ax < w || bx >= 0 || bx < w) { + paint.drawLine(ax, 0, bx, h); + } } } @@ -227,10 +263,10 @@ } void -AlignmentView::buildKeyFrameMap() +AlignmentView::buildMaps() { #ifdef DEBUG_ALIGNMENT_VIEW - SVCERR << "AlignmentView " << getId() << "::buildKeyFrameMap" << endl; + SVCERR << "AlignmentView " << getId() << "::buildMaps" << endl; #endif sv_frame_t resolution = 1; @@ -240,13 +276,40 @@ keyFramesBelow.insert(f); } + foreach(sv_frame_t f, keyFramesBelow) { + sv_frame_t rf = m_below->alignToReference(f); + m_fromReferenceMap.insert({ rf, f }); + } + vector keyFrames = getKeyFrames(m_above, resolution); + // These are the most extreme leftward and rightward frames in + // "above" that have distinct corresponding frames in + // "below". Anything left of m_leftmostAbove or right of + // m_rightmostAbove maps effectively off one end or the other of + // the below view. (They don't actually map off the ends, they + // just all map to the same first/last destination frame. But we + // don't want to display their mappings, as they're just noise.) + m_leftmostAbove = -1; + m_rightmostAbove = -1; + + sv_frame_t prevRf = -1; + sv_frame_t prevBf = -1; + foreach (sv_frame_t f, keyFrames) { sv_frame_t rf = m_above->alignToReference(f); sv_frame_t bf = m_below->alignFromReference(rf); + if (prevBf > 0 && bf > prevBf) { + if (m_leftmostAbove < 0 && prevBf > 0 && bf > prevBf) { + m_leftmostAbove = prevRf; + } + m_rightmostAbove = rf; + } + prevRf = rf; + prevBf = bf; + bool mappedSomething = false; if (resolution > 1) { @@ -258,7 +321,7 @@ for (sv_frame_t probe = bf + 1; probe <= bf1; ++probe) { if (keyFramesBelow.find(probe) != keyFramesBelow.end()) { - m_keyFrameMap.insert({ f, probe }); + m_fromAboveMap.insert({ f, probe }); mappedSomething = true; } } @@ -266,13 +329,13 @@ } if (!mappedSomething) { - m_keyFrameMap.insert({ f, bf }); + m_fromAboveMap.insert({ f, bf }); } } #ifdef DEBUG_ALIGNMENT_VIEW - SVCERR << "AlignmentView " << getId() << "::buildKeyFrameMap: have " - << m_keyFrameMap.size() << " mappings" << endl; + SVCERR << "AlignmentView " << getId() << "::buildMaps: have " + << m_fromAboveMap.size() << " mappings" << endl; #endif } diff -r 199dbb3547d4 -r cbbb411da977 view/AlignmentView.h --- a/view/AlignmentView.h Tue Jul 21 14:01:58 2020 +0100 +++ b/view/AlignmentView.h Tue Jul 21 14:02:12 2020 +0100 @@ -26,8 +26,9 @@ AlignmentView(QWidget *parent = 0); QString getPropertyContainerIconName() const override { return "alignment"; } - void setViewAbove(View *view); - void setViewBelow(View *view); + void setAboveView(View *view); + void setBelowView(View *view); + void setReferenceView(View *view); public slots: void globalCentreFrameChanged(sv_frame_t) override; @@ -44,7 +45,7 @@ void paintEvent(QPaintEvent *e) override; bool shouldLabelSelections() const override { return false; } - void buildKeyFrameMap(); + void buildMaps(); std::vector getKeyFrames(View *, sv_frame_t &resolution); std::vector getDefaultKeyFrames(); @@ -55,9 +56,13 @@ View *m_above; View *m_below; + View *m_reference; - QMutex m_keyFrameMutex; - std::multimap m_keyFrameMap; + QMutex m_mapsMutex; + std::multimap m_fromAboveMap; + std::multimap m_fromReferenceMap; + sv_frame_t m_leftmostAbove; + sv_frame_t m_rightmostAbove; }; #endif diff -r 199dbb3547d4 -r cbbb411da977 view/PaneStack.cpp --- a/view/PaneStack.cpp Tue Jul 21 14:01:58 2020 +0100 +++ b/view/PaneStack.cpp Tue Jul 21 14:02:12 2020 +0100 @@ -221,8 +221,9 @@ if (!(m_options & int(Option::ShowAlignmentViews))) { av->hide(); } else { - av->setViewAbove(m_panes[i-1].pane); - av->setViewBelow(m_panes[i].pane); + av->setAboveView(m_panes[i-1].pane); + av->setBelowView(m_panes[i].pane); + av->setReferenceView(m_panes[0].pane); av->show(); } } @@ -236,8 +237,9 @@ for (int i = 0; in_range_for(m_panes, i); ++i) { auto av = m_panes[i].alignmentView; if (!av) continue; - av->setViewAbove(nullptr); - av->setViewBelow(nullptr); + av->setAboveView(nullptr); + av->setBelowView(nullptr); + av->setReferenceView(nullptr); } } @@ -253,6 +255,7 @@ if (!(m_options & int(Option::ShowAlignmentViews))) return; if (!(m_options & int(Option::NoUserResize))) return; if (!isVisible()) return; + if (m_panes.empty()) return; int heightPerPane = forMyHeight / int(m_panes.size());