Mercurial > hg > svgui
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 |