changeset 1617:cbbb411da977

Merge
author Chris Cannam
date Tue, 21 Jul 2020 14:02:12 +0100
parents 199dbb3547d4 (current diff) 911330a28a7c (diff)
children f67e9e12e101
files
diffstat 3 files changed, 104 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- 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<sv_frame_t> 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
 }
 
--- 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<sv_frame_t> getKeyFrames(View *, sv_frame_t &resolution);
     std::vector<sv_frame_t> getDefaultKeyFrames();
@@ -55,9 +56,13 @@
 
     View *m_above;
     View *m_below;
+    View *m_reference;
 
-    QMutex m_keyFrameMutex;
-    std::multimap<sv_frame_t, sv_frame_t> m_keyFrameMap;
+    QMutex m_mapsMutex;
+    std::multimap<sv_frame_t, sv_frame_t> m_fromAboveMap;
+    std::multimap<sv_frame_t, sv_frame_t> m_fromReferenceMap;
+    sv_frame_t m_leftmostAbove;
+    sv_frame_t m_rightmostAbove;
 };
 
 #endif
--- 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());