Mercurial > hg > svgui
comparison layer/TimeInstantLayer.cpp @ 1486:ac0a8addabcf
Merge from branch by-id
author | Chris Cannam |
---|---|
date | Wed, 17 Jul 2019 14:25:16 +0100 |
parents | 36ad3cdabf55 |
children | 37df1530519d |
comparison
equal
deleted
inserted
replaced
1468:de41a11cabc2 | 1486:ac0a8addabcf |
---|---|
39 | 39 |
40 //#define DEBUG_TIME_INSTANT_LAYER 1 | 40 //#define DEBUG_TIME_INSTANT_LAYER 1 |
41 | 41 |
42 TimeInstantLayer::TimeInstantLayer() : | 42 TimeInstantLayer::TimeInstantLayer() : |
43 SingleColourLayer(), | 43 SingleColourLayer(), |
44 m_model(nullptr), | |
45 m_editing(false), | 44 m_editing(false), |
46 m_editingPoint(0, tr("New Point")), | 45 m_editingPoint(0, tr("New Point")), |
47 m_editingCommand(nullptr), | 46 m_editingCommand(nullptr), |
48 m_plotStyle(PlotInstants) | 47 m_plotStyle(PlotInstants) |
49 { | 48 { |
51 | 50 |
52 TimeInstantLayer::~TimeInstantLayer() | 51 TimeInstantLayer::~TimeInstantLayer() |
53 { | 52 { |
54 } | 53 } |
55 | 54 |
56 void | 55 int |
57 TimeInstantLayer::setModel(SparseOneDimensionalModel *model) | 56 TimeInstantLayer::getCompletion(LayerGeometryProvider *) const |
58 { | 57 { |
59 if (m_model == model) return; | 58 auto model = ModelById::get(m_model); |
60 m_model = model; | 59 if (model) return model->getCompletion(); |
61 | 60 else return 0; |
62 connectSignals(m_model); | 61 } |
63 | 62 |
64 #ifdef DEBUG_TIME_INSTANT_LAYER | 63 void |
65 cerr << "TimeInstantLayer::setModel(" << model << ")" << endl; | 64 TimeInstantLayer::setModel(ModelId modelId) |
66 #endif | 65 { |
67 | 66 auto newModel = ModelById::getAs<SparseOneDimensionalModel>(modelId); |
68 if (m_model && m_model->getRDFTypeURI().endsWith("Segment")) { | 67 if (!modelId.isNone() && !newModel) { |
69 setPlotStyle(PlotSegmentation); | 68 throw std::logic_error("Not a SparseOneDimensionalModel"); |
69 } | |
70 | |
71 if (m_model == modelId) return; | |
72 m_model = modelId; | |
73 | |
74 if (newModel) { | |
75 connectSignals(m_model); | |
76 if (newModel->getRDFTypeURI().endsWith("Segment")) { | |
77 setPlotStyle(PlotSegmentation); | |
78 } | |
70 } | 79 } |
71 | 80 |
72 emit modelReplaced(); | 81 emit modelReplaced(); |
73 } | 82 } |
74 | 83 |
147 m_plotStyle = style; | 156 m_plotStyle = style; |
148 emit layerParametersChanged(); | 157 emit layerParametersChanged(); |
149 } | 158 } |
150 | 159 |
151 bool | 160 bool |
161 TimeInstantLayer::needsTextLabelHeight() const | |
162 { | |
163 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); | |
164 if (model) return model->hasTextLabels(); | |
165 else return false; | |
166 } | |
167 | |
168 bool | |
152 TimeInstantLayer::isLayerScrollable(const LayerGeometryProvider *v) const | 169 TimeInstantLayer::isLayerScrollable(const LayerGeometryProvider *v) const |
153 { | 170 { |
154 QPoint discard; | 171 QPoint discard; |
155 return !v->shouldIlluminateLocalFeatures(this, discard); | 172 return !v->shouldIlluminateLocalFeatures(this, discard); |
156 } | 173 } |
157 | 174 |
158 EventVector | 175 EventVector |
159 TimeInstantLayer::getLocalPoints(LayerGeometryProvider *v, int x) const | 176 TimeInstantLayer::getLocalPoints(LayerGeometryProvider *v, int x) const |
160 { | 177 { |
161 if (!m_model) return {}; | 178 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
179 if (!model) return {}; | |
162 | 180 |
163 // Return a set of points that all have the same frame number, the | 181 // Return a set of points that all have the same frame number, the |
164 // nearest to the given x coordinate, and that are within a | 182 // nearest to the given x coordinate, and that are within a |
165 // certain fuzz distance of that x coordinate. | 183 // certain fuzz distance of that x coordinate. |
166 | 184 |
167 sv_frame_t frame = v->getFrameForX(x); | 185 sv_frame_t frame = v->getFrameForX(x); |
168 | 186 |
169 EventVector exact = m_model->getEventsStartingAt(frame); | 187 EventVector exact = model->getEventsStartingAt(frame); |
170 if (!exact.empty()) return exact; | 188 if (!exact.empty()) return exact; |
171 | 189 |
172 // overspill == 1, so one event either side of the given span | 190 // overspill == 1, so one event either side of the given span |
173 EventVector neighbouring = m_model->getEventsWithin | 191 EventVector neighbouring = model->getEventsWithin |
174 (frame, m_model->getResolution(), 1); | 192 (frame, model->getResolution(), 1); |
175 | 193 |
176 double fuzz = v->scaleSize(2); | 194 double fuzz = v->scaleSize(2); |
177 sv_frame_t suitable = 0; | 195 sv_frame_t suitable = 0; |
178 bool have = false; | 196 bool have = false; |
179 | 197 |
193 suitable = f; | 211 suitable = f; |
194 } | 212 } |
195 } | 213 } |
196 | 214 |
197 if (have) { | 215 if (have) { |
198 return m_model->getEventsStartingAt(suitable); | 216 return model->getEventsStartingAt(suitable); |
199 } else { | 217 } else { |
200 return {}; | 218 return {}; |
201 } | 219 } |
202 } | 220 } |
203 | 221 |
204 QString | 222 QString |
205 TimeInstantLayer::getLabelPreceding(sv_frame_t frame) const | 223 TimeInstantLayer::getLabelPreceding(sv_frame_t frame) const |
206 { | 224 { |
207 if (!m_model || !m_model->hasTextLabels()) return ""; | 225 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
226 if (!model || !model->hasTextLabels()) return ""; | |
208 | 227 |
209 Event e; | 228 Event e; |
210 if (m_model->getNearestEventMatching | 229 if (model->getNearestEventMatching |
211 (frame, | 230 (frame, |
212 [](Event e) { return e.hasLabel() && e.getLabel() != ""; }, | 231 [](Event e) { return e.hasLabel() && e.getLabel() != ""; }, |
213 EventSeries::Backward, | 232 EventSeries::Backward, |
214 e)) { | 233 e)) { |
215 return e.getLabel(); | 234 return e.getLabel(); |
221 QString | 240 QString |
222 TimeInstantLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const | 241 TimeInstantLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const |
223 { | 242 { |
224 int x = pos.x(); | 243 int x = pos.x(); |
225 | 244 |
226 if (!m_model || !m_model->getSampleRate()) return ""; | 245 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
246 if (!model || !model->getSampleRate()) return ""; | |
227 | 247 |
228 EventVector points = getLocalPoints(v, x); | 248 EventVector points = getLocalPoints(v, x); |
229 | 249 |
230 if (points.empty()) { | 250 if (points.empty()) { |
231 if (!m_model->isReady()) { | 251 if (!model->isReady()) { |
232 return tr("In progress"); | 252 return tr("In progress"); |
233 } else { | 253 } else { |
234 return tr("No local points"); | 254 return tr("No local points"); |
235 } | 255 } |
236 } | 256 } |
237 | 257 |
238 sv_frame_t useFrame = points.begin()->getFrame(); | 258 sv_frame_t useFrame = points.begin()->getFrame(); |
239 | 259 |
240 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); | 260 RealTime rt = RealTime::frame2RealTime(useFrame, model->getSampleRate()); |
241 | 261 |
242 QString text; | 262 QString text; |
243 | 263 |
244 if (points.begin()->getLabel() == "") { | 264 if (points.begin()->getLabel() == "") { |
245 text = QString(tr("Time:\t%1\nNo label")) | 265 text = QString(tr("Time:\t%1\nNo label")) |
257 bool | 277 bool |
258 TimeInstantLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, | 278 TimeInstantLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, |
259 int &resolution, | 279 int &resolution, |
260 SnapType snap) const | 280 SnapType snap) const |
261 { | 281 { |
262 if (!m_model) { | 282 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
283 if (!model) { | |
263 return Layer::snapToFeatureFrame(v, frame, resolution, snap); | 284 return Layer::snapToFeatureFrame(v, frame, resolution, snap); |
264 } | 285 } |
265 | 286 |
266 // SnapLeft / SnapRight: return frame of nearest feature in that | 287 // SnapLeft / SnapRight: return frame of nearest feature in that |
267 // direction no matter how far away | 288 // direction no matter how far away |
268 // | 289 // |
269 // SnapNeighbouring: return frame of feature that would be used in | 290 // SnapNeighbouring: return frame of feature that would be used in |
270 // an editing operation, i.e. closest feature in either direction | 291 // an editing operation, i.e. closest feature in either direction |
271 // but only if it is "close enough" | 292 // but only if it is "close enough" |
272 | 293 |
273 resolution = m_model->getResolution(); | 294 resolution = model->getResolution(); |
274 | 295 |
275 if (snap == SnapNeighbouring) { | 296 if (snap == SnapNeighbouring) { |
276 EventVector points = getLocalPoints(v, v->getXForFrame(frame)); | 297 EventVector points = getLocalPoints(v, v->getXForFrame(frame)); |
277 if (points.empty()) return false; | 298 if (points.empty()) return false; |
278 frame = points.begin()->getFrame(); | 299 frame = points.begin()->getFrame(); |
279 return true; | 300 return true; |
280 } | 301 } |
281 | 302 |
282 Event e; | 303 Event e; |
283 if (m_model->getNearestEventMatching | 304 if (model->getNearestEventMatching |
284 (frame, | 305 (frame, |
285 [](Event) { return true; }, | 306 [](Event) { return true; }, |
286 snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, | 307 snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, |
287 e)) { | 308 e)) { |
288 frame = e.getFrame(); | 309 frame = e.getFrame(); |
293 } | 314 } |
294 | 315 |
295 void | 316 void |
296 TimeInstantLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | 317 TimeInstantLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const |
297 { | 318 { |
298 if (!m_model || !m_model->isOK()) return; | 319 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
320 if (!model || !model->isOK()) return; | |
299 | 321 |
300 // Profiler profiler("TimeInstantLayer::paint", true); | 322 // Profiler profiler("TimeInstantLayer::paint", true); |
301 | 323 |
302 int x0 = rect.left(), x1 = rect.right(); | 324 int x0 = rect.left(), x1 = rect.right(); |
303 | 325 |
309 // We need to start painting at the prior point, so we can | 331 // We need to start painting at the prior point, so we can |
310 // fill in the visible part of its segmentation area | 332 // fill in the visible part of its segmentation area |
311 overspill = 1; | 333 overspill = 1; |
312 } | 334 } |
313 | 335 |
314 EventVector points(m_model->getEventsWithin(frame0, frame1 - frame0, | 336 EventVector points(model->getEventsWithin(frame0, frame1 - frame0, |
315 overspill)); | 337 overspill)); |
316 | 338 |
317 bool odd = false; | 339 bool odd = false; |
318 if (m_plotStyle == PlotSegmentation && !points.empty()) { | 340 if (m_plotStyle == PlotSegmentation && !points.empty()) { |
319 int index = m_model->getRowForFrame(points.begin()->getFrame()); | 341 int index = model->getRowForFrame(points.begin()->getFrame()); |
320 odd = ((index % 2) == 1); | 342 odd = ((index % 2) == 1); |
321 } | 343 } |
322 | 344 |
323 paint.setPen(getBaseQColor()); | 345 paint.setPen(getBaseQColor()); |
324 | 346 |
335 } else if (getBaseQColor() == Qt::darkBlue) { | 357 } else if (getBaseQColor() == Qt::darkBlue) { |
336 oddBrushColour = Qt::blue; | 358 oddBrushColour = Qt::blue; |
337 } else if (getBaseQColor() == Qt::darkGreen) { | 359 } else if (getBaseQColor() == Qt::darkGreen) { |
338 oddBrushColour = Qt::green; | 360 oddBrushColour = Qt::green; |
339 } else { | 361 } else { |
340 oddBrushColour = oddBrushColour.light(150); | 362 oddBrushColour = oddBrushColour.lighter(150); |
341 } | 363 } |
342 oddBrushColour.setAlpha(100); | 364 oddBrushColour.setAlpha(100); |
343 } | 365 } |
344 | 366 |
345 // SVDEBUG << "TimeInstantLayer::paint: resolution is " | 367 // SVDEBUG << "TimeInstantLayer::paint: resolution is " |
346 // << m_model->getResolution() << " frames" << endl; | 368 // << model->getResolution() << " frames" << endl; |
347 | 369 |
348 QPoint localPos; | 370 QPoint localPos; |
349 sv_frame_t illuminateFrame = -1; | 371 sv_frame_t illuminateFrame = -1; |
350 | 372 |
351 if (v->shouldIlluminateLocalFeatures(this, localPos)) { | 373 if (v->shouldIlluminateLocalFeatures(this, localPos)) { |
367 | 389 |
368 int x = v->getXForFrame(p.getFrame()); | 390 int x = v->getXForFrame(p.getFrame()); |
369 if (x == prevX && m_plotStyle == PlotInstants && | 391 if (x == prevX && m_plotStyle == PlotInstants && |
370 p.getFrame() != illuminateFrame) continue; | 392 p.getFrame() != illuminateFrame) continue; |
371 | 393 |
372 int iw = v->getXForFrame(p.getFrame() + m_model->getResolution()) - x; | 394 int iw = v->getXForFrame(p.getFrame() + model->getResolution()) - x; |
373 if (iw < 2) { | 395 if (iw < 2) { |
374 if (iw < 1) { | 396 if (iw < 1) { |
375 iw = 2; | 397 iw = 2; |
376 if (j != points.end()) { | 398 if (j != points.end()) { |
377 int nx = v->getXForFrame(j->getFrame()); | 399 int nx = v->getXForFrame(j->getFrame()); |
403 | 425 |
404 if (j != points.end()) { | 426 if (j != points.end()) { |
405 Event q(*j); | 427 Event q(*j); |
406 nx = v->getXForFrame(q.getFrame()); | 428 nx = v->getXForFrame(q.getFrame()); |
407 } else { | 429 } else { |
408 nx = v->getXForFrame(m_model->getEndFrame()); | 430 nx = v->getXForFrame(model->getEndFrame()); |
409 } | 431 } |
410 | 432 |
411 if (nx >= x) { | 433 if (nx >= x) { |
412 | 434 |
413 if (illuminateFrame != p.getFrame() && | 435 if (illuminateFrame != p.getFrame() && |
422 } | 444 } |
423 | 445 |
424 paint.setPen(getBaseQColor()); | 446 paint.setPen(getBaseQColor()); |
425 | 447 |
426 if (p.getLabel() != "") { | 448 if (p.getLabel() != "") { |
449 | |
450 // Qt 5.13 deprecates QFontMetrics::width(), but its suggested | |
451 // replacement (horizontalAdvance) was only added in Qt 5.11 | |
452 // which is too new for us | |
453 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |
427 | 454 |
428 // only draw if there's enough room from here to the next point | 455 // only draw if there's enough room from here to the next point |
429 | 456 |
430 int lw = paint.fontMetrics().width(p.getLabel()); | 457 int lw = paint.fontMetrics().width(p.getLabel()); |
431 bool good = true; | 458 bool good = true; |
452 { | 479 { |
453 #ifdef DEBUG_TIME_INSTANT_LAYER | 480 #ifdef DEBUG_TIME_INSTANT_LAYER |
454 cerr << "TimeInstantLayer::drawStart(" << e->x() << ")" << endl; | 481 cerr << "TimeInstantLayer::drawStart(" << e->x() << ")" << endl; |
455 #endif | 482 #endif |
456 | 483 |
457 if (!m_model) return; | 484 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
485 if (!model) return; | |
458 | 486 |
459 sv_frame_t frame = v->getFrameForX(e->x()); | 487 sv_frame_t frame = v->getFrameForX(e->x()); |
460 if (frame < 0) frame = 0; | 488 if (frame < 0) frame = 0; |
461 frame = frame / m_model->getResolution() * m_model->getResolution(); | 489 frame = frame / model->getResolution() * model->getResolution(); |
462 | 490 |
463 m_editingPoint = Event(frame, tr("New Point")); | 491 m_editingPoint = Event(frame, tr("New Point")); |
464 | 492 |
465 if (m_editingCommand) finish(m_editingCommand); | 493 if (m_editingCommand) finish(m_editingCommand); |
466 m_editingCommand = new ChangeEventsCommand(m_model, tr("Draw Point")); | 494 m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Draw Point")); |
467 m_editingCommand->add(m_editingPoint); | 495 m_editingCommand->add(m_editingPoint); |
468 | 496 |
469 m_editing = true; | 497 m_editing = true; |
470 } | 498 } |
471 | 499 |
474 { | 502 { |
475 #ifdef DEBUG_TIME_INSTANT_LAYER | 503 #ifdef DEBUG_TIME_INSTANT_LAYER |
476 cerr << "TimeInstantLayer::drawDrag(" << e->x() << ")" << endl; | 504 cerr << "TimeInstantLayer::drawDrag(" << e->x() << ")" << endl; |
477 #endif | 505 #endif |
478 | 506 |
479 if (!m_model || !m_editing) return; | 507 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
508 if (!model || !m_editing) return; | |
480 | 509 |
481 sv_frame_t frame = v->getFrameForX(e->x()); | 510 sv_frame_t frame = v->getFrameForX(e->x()); |
482 if (frame < 0) frame = 0; | 511 if (frame < 0) frame = 0; |
483 frame = frame / m_model->getResolution() * m_model->getResolution(); | 512 frame = frame / model->getResolution() * model->getResolution(); |
484 m_editingCommand->remove(m_editingPoint); | 513 m_editingCommand->remove(m_editingPoint); |
485 m_editingPoint = m_editingPoint.withFrame(frame); | 514 m_editingPoint = m_editingPoint.withFrame(frame); |
486 m_editingCommand->add(m_editingPoint); | 515 m_editingCommand->add(m_editingPoint); |
487 } | 516 } |
488 | 517 |
490 TimeInstantLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) | 519 TimeInstantLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) |
491 { | 520 { |
492 #ifdef DEBUG_TIME_INSTANT_LAYER | 521 #ifdef DEBUG_TIME_INSTANT_LAYER |
493 cerr << "TimeInstantLayer::drawEnd(" << e->x() << ")" << endl; | 522 cerr << "TimeInstantLayer::drawEnd(" << e->x() << ")" << endl; |
494 #endif | 523 #endif |
495 if (!m_model || !m_editing) return; | 524 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
525 if (!model || !m_editing) return; | |
496 QString newName = tr("Add Point at %1 s") | 526 QString newName = tr("Add Point at %1 s") |
497 .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(), | 527 .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(), |
498 m_model->getSampleRate()) | 528 model->getSampleRate()) |
499 .toText(false).c_str()); | 529 .toText(false).c_str()); |
500 m_editingCommand->setName(newName); | 530 m_editingCommand->setName(newName); |
501 finish(m_editingCommand); | 531 finish(m_editingCommand); |
502 m_editingCommand = nullptr; | 532 m_editingCommand = nullptr; |
503 m_editing = false; | 533 m_editing = false; |
504 } | 534 } |
505 | 535 |
506 void | 536 void |
507 TimeInstantLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) | 537 TimeInstantLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) |
508 { | 538 { |
509 if (!m_model) return; | 539 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
540 if (!model) return; | |
510 | 541 |
511 EventVector points = getLocalPoints(v, e->x()); | 542 EventVector points = getLocalPoints(v, e->x()); |
512 if (points.empty()) return; | 543 if (points.empty()) return; |
513 | 544 |
514 m_editingPoint = *points.begin(); | 545 m_editingPoint = *points.begin(); |
527 } | 558 } |
528 | 559 |
529 void | 560 void |
530 TimeInstantLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) | 561 TimeInstantLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) |
531 { | 562 { |
532 if (!m_model || !m_editing) return; | 563 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
564 if (!model || !m_editing) return; | |
533 | 565 |
534 m_editing = false; | 566 m_editing = false; |
535 | 567 |
536 EventVector points = getLocalPoints(v, e->x()); | 568 EventVector points = getLocalPoints(v, e->x()); |
537 if (points.empty()) return; | 569 if (points.empty()) return; |
538 if (points.begin()->getFrame() != m_editingPoint.getFrame()) return; | 570 if (points.begin()->getFrame() != m_editingPoint.getFrame()) return; |
539 | 571 |
540 m_editingCommand = new ChangeEventsCommand(m_model, tr("Erase Point")); | 572 m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Erase Point")); |
541 m_editingCommand->remove(m_editingPoint); | 573 m_editingCommand->remove(m_editingPoint); |
542 finish(m_editingCommand); | 574 finish(m_editingCommand); |
543 m_editingCommand = nullptr; | 575 m_editingCommand = nullptr; |
544 m_editing = false; | 576 m_editing = false; |
545 } | 577 } |
549 { | 581 { |
550 #ifdef DEBUG_TIME_INSTANT_LAYER | 582 #ifdef DEBUG_TIME_INSTANT_LAYER |
551 cerr << "TimeInstantLayer::editStart(" << e->x() << ")" << endl; | 583 cerr << "TimeInstantLayer::editStart(" << e->x() << ")" << endl; |
552 #endif | 584 #endif |
553 | 585 |
554 if (!m_model) return; | 586 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
587 if (!model) return; | |
555 | 588 |
556 EventVector points = getLocalPoints(v, e->x()); | 589 EventVector points = getLocalPoints(v, e->x()); |
557 if (points.empty()) return; | 590 if (points.empty()) return; |
558 | 591 |
559 m_editingPoint = *points.begin(); | 592 m_editingPoint = *points.begin(); |
571 { | 604 { |
572 #ifdef DEBUG_TIME_INSTANT_LAYER | 605 #ifdef DEBUG_TIME_INSTANT_LAYER |
573 cerr << "TimeInstantLayer::editDrag(" << e->x() << ")" << endl; | 606 cerr << "TimeInstantLayer::editDrag(" << e->x() << ")" << endl; |
574 #endif | 607 #endif |
575 | 608 |
576 if (!m_model || !m_editing) return; | 609 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
610 if (!model || !m_editing) return; | |
577 | 611 |
578 sv_frame_t frame = v->getFrameForX(e->x()); | 612 sv_frame_t frame = v->getFrameForX(e->x()); |
579 if (frame < 0) frame = 0; | 613 if (frame < 0) frame = 0; |
580 frame = frame / m_model->getResolution() * m_model->getResolution(); | 614 frame = frame / model->getResolution() * model->getResolution(); |
581 | 615 |
582 if (!m_editingCommand) { | 616 if (!m_editingCommand) { |
583 m_editingCommand = new ChangeEventsCommand(m_model, tr("Drag Point")); | 617 m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Drag Point")); |
584 } | 618 } |
585 | 619 |
586 m_editingCommand->remove(m_editingPoint); | 620 m_editingCommand->remove(m_editingPoint); |
587 m_editingPoint = m_editingPoint.withFrame(frame); | 621 m_editingPoint = m_editingPoint.withFrame(frame); |
588 m_editingCommand->add(m_editingPoint); | 622 m_editingCommand->add(m_editingPoint); |
592 TimeInstantLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) | 626 TimeInstantLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) |
593 { | 627 { |
594 #ifdef DEBUG_TIME_INSTANT_LAYER | 628 #ifdef DEBUG_TIME_INSTANT_LAYER |
595 cerr << "TimeInstantLayer::editEnd(" << e->x() << ")" << endl; | 629 cerr << "TimeInstantLayer::editEnd(" << e->x() << ")" << endl; |
596 #endif | 630 #endif |
597 if (!m_model || !m_editing) return; | 631 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
632 if (!model || !m_editing) return; | |
598 if (m_editingCommand) { | 633 if (m_editingCommand) { |
599 QString newName = tr("Move Point to %1 s") | 634 QString newName = tr("Move Point to %1 s") |
600 .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(), | 635 .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(), |
601 m_model->getSampleRate()) | 636 model->getSampleRate()) |
602 .toText(false).c_str()); | 637 .toText(false).c_str()); |
603 m_editingCommand->setName(newName); | 638 m_editingCommand->setName(newName); |
604 finish(m_editingCommand); | 639 finish(m_editingCommand); |
605 } | 640 } |
606 m_editingCommand = nullptr; | 641 m_editingCommand = nullptr; |
608 } | 643 } |
609 | 644 |
610 bool | 645 bool |
611 TimeInstantLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) | 646 TimeInstantLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) |
612 { | 647 { |
613 if (!m_model) return false; | 648 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
649 if (!model) return false; | |
614 | 650 |
615 EventVector points = getLocalPoints(v, e->x()); | 651 EventVector points = getLocalPoints(v, e->x()); |
616 if (points.empty()) return false; | 652 if (points.empty()) return false; |
617 | 653 |
618 Event point = *points.begin(); | 654 Event point = *points.begin(); |
619 | 655 |
620 ItemEditDialog *dialog = new ItemEditDialog | 656 ItemEditDialog *dialog = new ItemEditDialog |
621 (m_model->getSampleRate(), | 657 (model->getSampleRate(), |
622 ItemEditDialog::ShowTime | | 658 ItemEditDialog::ShowTime | |
623 ItemEditDialog::ShowText); | 659 ItemEditDialog::ShowText); |
624 | 660 |
625 dialog->setFrameTime(point.getFrame()); | 661 dialog->setFrameTime(point.getFrame()); |
626 dialog->setText(point.getLabel()); | 662 dialog->setText(point.getLabel()); |
630 Event newPoint = point | 666 Event newPoint = point |
631 .withFrame(dialog->getFrameTime()) | 667 .withFrame(dialog->getFrameTime()) |
632 .withLabel(dialog->getText()); | 668 .withLabel(dialog->getText()); |
633 | 669 |
634 ChangeEventsCommand *command = | 670 ChangeEventsCommand *command = |
635 new ChangeEventsCommand(m_model, tr("Edit Point")); | 671 new ChangeEventsCommand(m_model.untyped, tr("Edit Point")); |
636 command->remove(point); | 672 command->remove(point); |
637 command->add(newPoint); | 673 command->add(newPoint); |
638 finish(command); | 674 finish(command); |
639 } | 675 } |
640 | 676 |
643 } | 679 } |
644 | 680 |
645 void | 681 void |
646 TimeInstantLayer::moveSelection(Selection s, sv_frame_t newStartFrame) | 682 TimeInstantLayer::moveSelection(Selection s, sv_frame_t newStartFrame) |
647 { | 683 { |
648 if (!m_model) return; | 684 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
685 if (!model) return; | |
649 | 686 |
650 ChangeEventsCommand *command = | 687 ChangeEventsCommand *command = |
651 new ChangeEventsCommand(m_model, tr("Drag Selection")); | 688 new ChangeEventsCommand(m_model.untyped, tr("Drag Selection")); |
652 | 689 |
653 EventVector points = | 690 EventVector points = |
654 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); | 691 model->getEventsWithin(s.getStartFrame(), s.getDuration()); |
655 | 692 |
656 for (auto p: points) { | 693 for (auto p: points) { |
657 Event newPoint = p | 694 Event newPoint = p |
658 .withFrame(p.getFrame() + newStartFrame - s.getStartFrame()); | 695 .withFrame(p.getFrame() + newStartFrame - s.getStartFrame()); |
659 command->remove(p); | 696 command->remove(p); |
664 } | 701 } |
665 | 702 |
666 void | 703 void |
667 TimeInstantLayer::resizeSelection(Selection s, Selection newSize) | 704 TimeInstantLayer::resizeSelection(Selection s, Selection newSize) |
668 { | 705 { |
669 if (!m_model) return; | 706 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
707 if (!model) return; | |
670 | 708 |
671 ChangeEventsCommand *command = | 709 ChangeEventsCommand *command = |
672 new ChangeEventsCommand(m_model, tr("Resize Selection")); | 710 new ChangeEventsCommand(m_model.untyped, tr("Resize Selection")); |
673 | 711 |
674 EventVector points = | 712 EventVector points = |
675 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); | 713 model->getEventsWithin(s.getStartFrame(), s.getDuration()); |
676 | 714 |
677 double ratio = double(newSize.getDuration()) / double(s.getDuration()); | 715 double ratio = double(newSize.getDuration()) / double(s.getDuration()); |
678 double oldStart = double(s.getStartFrame()); | 716 double oldStart = double(s.getStartFrame()); |
679 double newStart = double(newSize.getStartFrame()); | 717 double newStart = double(newSize.getStartFrame()); |
680 | 718 |
692 } | 730 } |
693 | 731 |
694 void | 732 void |
695 TimeInstantLayer::deleteSelection(Selection s) | 733 TimeInstantLayer::deleteSelection(Selection s) |
696 { | 734 { |
697 if (!m_model) return; | 735 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
736 if (!model) return; | |
698 | 737 |
699 ChangeEventsCommand *command = | 738 ChangeEventsCommand *command = |
700 new ChangeEventsCommand(m_model, tr("Delete Selection")); | 739 new ChangeEventsCommand(m_model.untyped, tr("Delete Selection")); |
701 | 740 |
702 EventVector points = | 741 EventVector points = |
703 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); | 742 model->getEventsWithin(s.getStartFrame(), s.getDuration()); |
704 | 743 |
705 for (auto p: points) { | 744 for (auto p: points) { |
706 command->remove(p); | 745 command->remove(p); |
707 } | 746 } |
708 | 747 |
710 } | 749 } |
711 | 750 |
712 void | 751 void |
713 TimeInstantLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) | 752 TimeInstantLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) |
714 { | 753 { |
715 if (!m_model) return; | 754 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
755 if (!model) return; | |
716 | 756 |
717 EventVector points = | 757 EventVector points = |
718 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); | 758 model->getEventsWithin(s.getStartFrame(), s.getDuration()); |
719 | 759 |
720 for (auto p: points) { | 760 for (auto p: points) { |
721 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); | 761 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); |
722 } | 762 } |
723 } | 763 } |
724 | 764 |
725 bool | 765 bool |
726 TimeInstantLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t frameOffset, bool) | 766 TimeInstantLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t frameOffset, bool) |
727 { | 767 { |
728 if (!m_model) return false; | 768 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); |
769 if (!model) return false; | |
729 | 770 |
730 EventVector points = from.getPoints(); | 771 EventVector points = from.getPoints(); |
731 | 772 |
732 bool realign = false; | 773 bool realign = false; |
733 | 774 |
747 realign = true; | 788 realign = true; |
748 } | 789 } |
749 } | 790 } |
750 | 791 |
751 ChangeEventsCommand *command = | 792 ChangeEventsCommand *command = |
752 new ChangeEventsCommand(m_model, tr("Paste")); | 793 new ChangeEventsCommand(m_model.untyped, tr("Paste")); |
753 | 794 |
754 for (EventVector::const_iterator i = points.begin(); | 795 for (EventVector::const_iterator i = points.begin(); |
755 i != points.end(); ++i) { | 796 i != points.end(); ++i) { |
756 | 797 |
757 sv_frame_t frame = 0; | 798 sv_frame_t frame = 0; |