comparison view/AlignmentView.cpp @ 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 84c4ddb38415
children 8145a9c4c253
comparison
equal deleted inserted replaced
1492:a2fbcfeb2572 1493:c5589d94b731
19 19
20 #include "data/model/SparseOneDimensionalModel.h" 20 #include "data/model/SparseOneDimensionalModel.h"
21 21
22 #include "layer/TimeInstantLayer.h" 22 #include "layer/TimeInstantLayer.h"
23 23
24 //#define DEBUG_ALIGNMENT_VIEW 1
25
24 using std::vector; 26 using std::vector;
27 using std::set;
25 28
26 AlignmentView::AlignmentView(QWidget *w) : 29 AlignmentView::AlignmentView(QWidget *w) :
27 View(w, false), 30 View(w, false),
28 m_above(nullptr), 31 m_above(nullptr),
29 m_below(nullptr) 32 m_below(nullptr)
30 { 33 {
31 setObjectName(tr("AlignmentView")); 34 setObjectName(tr("AlignmentView"));
35 }
36
37 void
38 AlignmentView::keyFramesChanged()
39 {
40 #ifdef DEBUG_ALIGNMENT_VIEW
41 SVCERR << "AlignmentView " << getId() << "::keyFramesChanged" << endl;
42 #endif
43
44 // This is just a notification that we need to rebuild it - so all
45 // we do here is clear it, and it'll be rebuilt on demand later
46 QMutexLocker locker(&m_keyFrameMutex);
47 m_keyFrameMap.clear();
32 } 48 }
33 49
34 void 50 void
35 AlignmentView::globalCentreFrameChanged(sv_frame_t f) 51 AlignmentView::globalCentreFrameChanged(sv_frame_t f)
36 { 52 {
81 if (m_above) { 97 if (m_above) {
82 connect(m_above, 98 connect(m_above,
83 SIGNAL(zoomLevelChanged(ZoomLevel, bool)), 99 SIGNAL(zoomLevelChanged(ZoomLevel, bool)),
84 this, 100 this,
85 SLOT(viewAboveZoomLevelChanged(ZoomLevel, bool))); 101 SLOT(viewAboveZoomLevelChanged(ZoomLevel, bool)));
86 } 102 connect(m_above,
103 SIGNAL(propertyContainerAdded(PropertyContainer *)),
104 this,
105 SLOT(keyFramesChanged()));
106 connect(m_above,
107 SIGNAL(layerModelChanged()),
108 this,
109 SLOT(keyFramesChanged()));
110 }
111
112 keyFramesChanged();
87 } 113 }
88 114
89 void 115 void
90 AlignmentView::setViewBelow(View *v) 116 AlignmentView::setViewBelow(View *v)
91 { 117 {
98 if (m_below) { 124 if (m_below) {
99 connect(m_below, 125 connect(m_below,
100 SIGNAL(zoomLevelChanged(ZoomLevel, bool)), 126 SIGNAL(zoomLevelChanged(ZoomLevel, bool)),
101 this, 127 this,
102 SLOT(viewBelowZoomLevelChanged(ZoomLevel, bool))); 128 SLOT(viewBelowZoomLevelChanged(ZoomLevel, bool)));
103 } 129 connect(m_below,
130 SIGNAL(propertyContainerAdded(PropertyContainer *)),
131 this,
132 SLOT(keyFramesChanged()));
133 connect(m_below,
134 SIGNAL(layerModelChanged()),
135 this,
136 SLOT(keyFramesChanged()));
137 }
138
139 keyFramesChanged();
104 } 140 }
105 141
106 void 142 void
107 AlignmentView::paintEvent(QPaintEvent *) 143 AlignmentView::paintEvent(QPaintEvent *)
108 { 144 {
109 if (m_above == nullptr || m_below == nullptr || !m_manager) return; 145 if (m_above == nullptr || m_below == nullptr || !m_manager) return;
110 146
147 #ifdef DEBUG_ALIGNMENT_VIEW
148 SVCERR << "AlignmentView " << getId() << "::paintEvent" << endl;
149 #endif
150
111 bool darkPalette = false; 151 bool darkPalette = false;
112 if (m_manager) darkPalette = m_manager->getGlobalDarkBackground(); 152 if (m_manager) darkPalette = m_manager->getGlobalDarkBackground();
113 153
114 QColor fg, bg; 154 QColor fg, bg;
115 if (darkPalette) { 155 if (darkPalette) {
125 paint.setBrush(Qt::NoBrush); 165 paint.setBrush(Qt::NoBrush);
126 paint.setRenderHint(QPainter::Antialiasing, true); 166 paint.setRenderHint(QPainter::Antialiasing, true);
127 167
128 paint.fillRect(rect(), bg); 168 paint.fillRect(rect(), bg);
129 169
130 vector<sv_frame_t> keyFrames = getKeyFrames(); 170 QMutexLocker locker(&m_keyFrameMutex);
171
172 if (m_keyFrameMap.empty()) {
173 reconnectModels();
174 buildKeyFrameMap();
175 }
176
177 #ifdef DEBUG_ALIGNMENT_VIEW
178 SVCERR << "AlignmentView " << getId() << "::paintEvent: painting "
179 << m_keyFrameMap.size() << " mappings" << endl;
180 #endif
181
182 for (const auto &km: m_keyFrameMap) {
183
184 sv_frame_t af = km.first;
185 sv_frame_t bf = km.second;
186
187 int ax = m_above->getXForFrame(af);
188 int bx = m_below->getXForFrame(bf);
189
190 if (ax >= 0 || ax < width() || bx >= 0 || bx < width()) {
191 paint.drawLine(ax, 0, bx, height());
192 }
193 }
194
195 paint.end();
196 }
197
198 void
199 AlignmentView::reconnectModels()
200 {
201 vector<ModelId> toConnect {
202 getSalientModel(m_above),
203 getSalientModel(m_below)
204 };
205
206 for (auto modelId: toConnect) {
207 if (auto model = ModelById::get(modelId)) {
208 auto referenceId = model->getAlignmentReference();
209 if (!referenceId.isNone()) {
210 toConnect.push_back(referenceId);
211 }
212 }
213 }
214
215 for (auto modelId: toConnect) {
216 if (auto model = ModelById::get(modelId)) {
217 auto ptr = model.get();
218 disconnect(ptr, 0, this, 0);
219 connect(ptr, SIGNAL(modelChanged(ModelId)),
220 this, SLOT(keyFramesChanged()));
221 connect(ptr, SIGNAL(completionChanged(ModelId)),
222 this, SLOT(keyFramesChanged()));
223 connect(ptr, SIGNAL(alignmentCompletionChanged(ModelId)),
224 this, SLOT(keyFramesChanged()));
225 }
226 }
227 }
228
229 void
230 AlignmentView::buildKeyFrameMap()
231 {
232 #ifdef DEBUG_ALIGNMENT_VIEW
233 SVCERR << "AlignmentView " << getId() << "::buildKeyFrameMap" << endl;
234 #endif
235
236 sv_frame_t resolution = 1;
237
238 set<sv_frame_t> keyFramesBelow;
239 for (auto f: getKeyFrames(m_below, resolution)) {
240 keyFramesBelow.insert(f);
241 }
242
243 vector<sv_frame_t> keyFrames = getKeyFrames(m_above, resolution);
131 244
132 foreach (sv_frame_t f, keyFrames) { 245 foreach (sv_frame_t f, keyFrames) {
133 int ax = m_above->getXForFrame(f); 246
134 sv_frame_t rf = m_above->alignToReference(f); 247 sv_frame_t rf = m_above->alignToReference(f);
135 sv_frame_t bf = m_below->alignFromReference(rf); 248 sv_frame_t bf = m_below->alignFromReference(rf);
136 int bx = m_below->getXForFrame(bf); 249
137 paint.drawLine(ax, 0, bx, height()); 250 bool mappedSomething = false;
138 } 251
139 252 if (resolution > 1) {
140 paint.end(); 253 if (keyFramesBelow.find(bf) == keyFramesBelow.end()) {
254
255 sv_frame_t f1 = f + resolution;
256 sv_frame_t rf1 = m_above->alignToReference(f1);
257 sv_frame_t bf1 = m_below->alignFromReference(rf1);
258
259 for (sv_frame_t probe = bf + 1; probe <= bf1; ++probe) {
260 if (keyFramesBelow.find(probe) != keyFramesBelow.end()) {
261 m_keyFrameMap.insert({ f, probe });
262 mappedSomething = true;
263 }
264 }
265 }
266 }
267
268 if (!mappedSomething) {
269 m_keyFrameMap.insert({ f, bf });
270 }
271 }
272
273 #ifdef DEBUG_ALIGNMENT_VIEW
274 SVCERR << "AlignmentView " << getId() << "::buildKeyFrameMap: have "
275 << m_keyFrameMap.size() << " mappings" << endl;
276 #endif
141 } 277 }
142 278
143 vector<sv_frame_t> 279 vector<sv_frame_t>
144 AlignmentView::getKeyFrames() 280 AlignmentView::getKeyFrames(View *view, sv_frame_t &resolution)
145 { 281 {
146 if (!m_above) { 282 resolution = 1;
283
284 if (!view) {
147 return getDefaultKeyFrames(); 285 return getDefaultKeyFrames();
148 } 286 }
149 287
150 ModelId m; 288 ModelId m = getSalientModel(view);
151
152 // get the topmost such
153 for (int i = 0; i < m_above->getLayerCount(); ++i) {
154 if (qobject_cast<TimeInstantLayer *>(m_above->getLayer(i))) {
155 ModelId mm = m_above->getLayer(i)->getModel();
156 if (ModelById::isa<SparseOneDimensionalModel>(mm)) {
157 m = mm;
158 }
159 }
160 }
161
162 auto model = ModelById::getAs<SparseOneDimensionalModel>(m); 289 auto model = ModelById::getAs<SparseOneDimensionalModel>(m);
163 if (!model) { 290 if (!model) {
164 return getDefaultKeyFrames(); 291 return getDefaultKeyFrames();
165 } 292 }
166 293
294 resolution = model->getResolution();
295
167 vector<sv_frame_t> keyFrames; 296 vector<sv_frame_t> keyFrames;
168 297
169 EventVector pp = model->getAllEvents(); 298 EventVector pp = model->getAllEvents();
170 for (EventVector::const_iterator pi = pp.begin(); pi != pp.end(); ++pi) { 299 for (EventVector::const_iterator pi = pp.begin(); pi != pp.end(); ++pi) {
171 keyFrames.push_back(pi->getFrame()); 300 keyFrames.push_back(pi->getFrame());
191 } 320 }
192 321
193 return keyFrames; 322 return keyFrames;
194 } 323 }
195 324
325 ModelId
326 AlignmentView::getSalientModel(View *view)
327 {
328 ModelId m;
329
330 // get the topmost such
331 for (int i = 0; i < view->getLayerCount(); ++i) {
332 if (qobject_cast<TimeInstantLayer *>(view->getLayer(i))) {
333 ModelId mm = view->getLayer(i)->getModel();
334 if (ModelById::isa<SparseOneDimensionalModel>(mm)) {
335 m = mm;
336 }
337 }
338 }
339
340 return m;
341 }
342
343