Mercurial > hg > svgui
changeset 1493:c5589d94b731
Improve drawn alignment of lines in AlignmentView against the view below; also cache the mapping locations
author | Chris Cannam |
---|---|
date | Fri, 09 Aug 2019 19:02:51 +0100 |
parents | a2fbcfeb2572 |
children | 78d9282519b0 |
files | view/AlignmentView.cpp view/AlignmentView.h view/View.cpp |
diffstat | 3 files changed, 187 insertions(+), 22 deletions(-) [+] |
line wrap: on
line diff
--- a/view/AlignmentView.cpp Thu Aug 08 13:33:38 2019 +0100 +++ b/view/AlignmentView.cpp Fri Aug 09 19:02:51 2019 +0100 @@ -21,7 +21,10 @@ #include "layer/TimeInstantLayer.h" +//#define DEBUG_ALIGNMENT_VIEW 1 + using std::vector; +using std::set; AlignmentView::AlignmentView(QWidget *w) : View(w, false), @@ -32,6 +35,19 @@ } void +AlignmentView::keyFramesChanged() +{ +#ifdef DEBUG_ALIGNMENT_VIEW + 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(); +} + +void AlignmentView::globalCentreFrameChanged(sv_frame_t f) { View::globalCentreFrameChanged(f); @@ -83,7 +99,17 @@ SIGNAL(zoomLevelChanged(ZoomLevel, bool)), this, SLOT(viewAboveZoomLevelChanged(ZoomLevel, bool))); + connect(m_above, + SIGNAL(propertyContainerAdded(PropertyContainer *)), + this, + SLOT(keyFramesChanged())); + connect(m_above, + SIGNAL(layerModelChanged()), + this, + SLOT(keyFramesChanged())); } + + keyFramesChanged(); } void @@ -100,14 +126,28 @@ SIGNAL(zoomLevelChanged(ZoomLevel, bool)), this, SLOT(viewBelowZoomLevelChanged(ZoomLevel, bool))); + connect(m_below, + SIGNAL(propertyContainerAdded(PropertyContainer *)), + this, + SLOT(keyFramesChanged())); + connect(m_below, + SIGNAL(layerModelChanged()), + this, + SLOT(keyFramesChanged())); } + + keyFramesChanged(); } void AlignmentView::paintEvent(QPaintEvent *) { if (m_above == nullptr || m_below == nullptr || !m_manager) return; - + +#ifdef DEBUG_ALIGNMENT_VIEW + SVCERR << "AlignmentView " << getId() << "::paintEvent" << endl; +#endif + bool darkPalette = false; if (m_manager) darkPalette = m_manager->getGlobalDarkBackground(); @@ -127,43 +167,132 @@ paint.fillRect(rect(), bg); - vector<sv_frame_t> keyFrames = getKeyFrames(); + QMutexLocker locker(&m_keyFrameMutex); - foreach (sv_frame_t f, keyFrames) { - int ax = m_above->getXForFrame(f); - sv_frame_t rf = m_above->alignToReference(f); - sv_frame_t bf = m_below->alignFromReference(rf); + if (m_keyFrameMap.empty()) { + reconnectModels(); + buildKeyFrameMap(); + } + +#ifdef DEBUG_ALIGNMENT_VIEW + SVCERR << "AlignmentView " << getId() << "::paintEvent: painting " + << m_keyFrameMap.size() << " mappings" << endl; +#endif + + for (const auto &km: m_keyFrameMap) { + + sv_frame_t af = km.first; + sv_frame_t bf = km.second; + + int ax = m_above->getXForFrame(af); int bx = m_below->getXForFrame(bf); - paint.drawLine(ax, 0, bx, height()); + + if (ax >= 0 || ax < width() || bx >= 0 || bx < width()) { + paint.drawLine(ax, 0, bx, height()); + } } paint.end(); -} +} -vector<sv_frame_t> -AlignmentView::getKeyFrames() +void +AlignmentView::reconnectModels() { - if (!m_above) { - return getDefaultKeyFrames(); - } + vector<ModelId> toConnect { + getSalientModel(m_above), + getSalientModel(m_below) + }; - ModelId m; - - // get the topmost such - for (int i = 0; i < m_above->getLayerCount(); ++i) { - if (qobject_cast<TimeInstantLayer *>(m_above->getLayer(i))) { - ModelId mm = m_above->getLayer(i)->getModel(); - if (ModelById::isa<SparseOneDimensionalModel>(mm)) { - m = mm; + for (auto modelId: toConnect) { + if (auto model = ModelById::get(modelId)) { + auto referenceId = model->getAlignmentReference(); + if (!referenceId.isNone()) { + toConnect.push_back(referenceId); } } } + for (auto modelId: toConnect) { + if (auto model = ModelById::get(modelId)) { + auto ptr = model.get(); + disconnect(ptr, 0, this, 0); + connect(ptr, SIGNAL(modelChanged(ModelId)), + this, SLOT(keyFramesChanged())); + connect(ptr, SIGNAL(completionChanged(ModelId)), + this, SLOT(keyFramesChanged())); + connect(ptr, SIGNAL(alignmentCompletionChanged(ModelId)), + this, SLOT(keyFramesChanged())); + } + } +} + +void +AlignmentView::buildKeyFrameMap() +{ +#ifdef DEBUG_ALIGNMENT_VIEW + SVCERR << "AlignmentView " << getId() << "::buildKeyFrameMap" << endl; +#endif + + sv_frame_t resolution = 1; + + set<sv_frame_t> keyFramesBelow; + for (auto f: getKeyFrames(m_below, resolution)) { + keyFramesBelow.insert(f); + } + + vector<sv_frame_t> keyFrames = getKeyFrames(m_above, resolution); + + foreach (sv_frame_t f, keyFrames) { + + sv_frame_t rf = m_above->alignToReference(f); + sv_frame_t bf = m_below->alignFromReference(rf); + + bool mappedSomething = false; + + if (resolution > 1) { + if (keyFramesBelow.find(bf) == keyFramesBelow.end()) { + + sv_frame_t f1 = f + resolution; + sv_frame_t rf1 = m_above->alignToReference(f1); + sv_frame_t bf1 = m_below->alignFromReference(rf1); + + for (sv_frame_t probe = bf + 1; probe <= bf1; ++probe) { + if (keyFramesBelow.find(probe) != keyFramesBelow.end()) { + m_keyFrameMap.insert({ f, probe }); + mappedSomething = true; + } + } + } + } + + if (!mappedSomething) { + m_keyFrameMap.insert({ f, bf }); + } + } + +#ifdef DEBUG_ALIGNMENT_VIEW + SVCERR << "AlignmentView " << getId() << "::buildKeyFrameMap: have " + << m_keyFrameMap.size() << " mappings" << endl; +#endif +} + +vector<sv_frame_t> +AlignmentView::getKeyFrames(View *view, sv_frame_t &resolution) +{ + resolution = 1; + + if (!view) { + return getDefaultKeyFrames(); + } + + ModelId m = getSalientModel(view); auto model = ModelById::getAs<SparseOneDimensionalModel>(m); if (!model) { return getDefaultKeyFrames(); } + resolution = model->getResolution(); + vector<sv_frame_t> keyFrames; EventVector pp = model->getAllEvents(); @@ -193,3 +322,22 @@ return keyFrames; } +ModelId +AlignmentView::getSalientModel(View *view) +{ + ModelId m; + + // get the topmost such + for (int i = 0; i < view->getLayerCount(); ++i) { + if (qobject_cast<TimeInstantLayer *>(view->getLayer(i))) { + ModelId mm = view->getLayer(i)->getModel(); + if (ModelById::isa<SparseOneDimensionalModel>(mm)) { + m = mm; + } + } + } + + return m; +} + +
--- a/view/AlignmentView.h Thu Aug 08 13:33:38 2019 +0100 +++ b/view/AlignmentView.h Fri Aug 09 19:02:51 2019 +0100 @@ -32,19 +32,32 @@ public slots: void globalCentreFrameChanged(sv_frame_t) override; void viewCentreFrameChanged(View *, sv_frame_t) override; + virtual void viewAboveZoomLevelChanged(ZoomLevel, bool); virtual void viewBelowZoomLevelChanged(ZoomLevel, bool); + void viewManagerPlaybackFrameChanged(sv_frame_t) override; + void keyFramesChanged(); + protected: void paintEvent(QPaintEvent *e) override; bool shouldLabelSelections() const override { return false; } - std::vector<sv_frame_t> getKeyFrames(); + void buildKeyFrameMap(); + + std::vector<sv_frame_t> getKeyFrames(View *, sv_frame_t &resolution); std::vector<sv_frame_t> getDefaultKeyFrames(); + ModelId getSalientModel(View *); + + void reconnectModels(); + View *m_above; View *m_below; + + QMutex m_keyFrameMutex; + std::multimap<sv_frame_t, sv_frame_t> m_keyFrameMap; }; #endif
--- a/view/View.cpp Thu Aug 08 13:33:38 2019 +0100 +++ b/view/View.cpp Fri Aug 09 19:02:51 2019 +0100 @@ -2166,9 +2166,13 @@ if (aligningModel) { alignmentModelId = aligningModel->getAlignment(); alignmentReferenceId = aligningModel->getAlignmentReference(); +#ifdef DEBUG_VIEW_WIDGET_PAINT SVCERR << "alignmentModelId = " << alignmentModelId << " (reference = " << alignmentReferenceId << ")" << endl; +#endif } else { +#ifdef DEBUG_VIEW_WIDGET_PAINT SVCERR << "no aligningModel" << endl; +#endif } ViewProxy aligningProxy(this, dpratio, alignmentModelId);