comparison layer/TimeInstantLayer.cpp @ 1474:36ad3cdabf55 by-id

Further layer updates for ModelById
author Chris Cannam
date Tue, 02 Jul 2019 14:08:44 +0100
parents f2525e6cbdf1
children 37df1530519d
comparison
equal deleted inserted replaced
1473:886c1cd48f9d 1474:36ad3cdabf55
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 {
160 159
161 bool 160 bool
162 TimeInstantLayer::needsTextLabelHeight() const 161 TimeInstantLayer::needsTextLabelHeight() const
163 { 162 {
164 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model); 163 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
165 if (model) return m_model->hasTextLabels(); 164 if (model) return model->hasTextLabels();
166 else return false; 165 else return false;
167 } 166 }
168 167
169 bool 168 bool
170 TimeInstantLayer::isLayerScrollable(const LayerGeometryProvider *v) const 169 TimeInstantLayer::isLayerScrollable(const LayerGeometryProvider *v) const
174 } 173 }
175 174
176 EventVector 175 EventVector
177 TimeInstantLayer::getLocalPoints(LayerGeometryProvider *v, int x) const 176 TimeInstantLayer::getLocalPoints(LayerGeometryProvider *v, int x) const
178 { 177 {
179 if (!m_model) return {}; 178 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
179 if (!model) return {};
180 180
181 // 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
182 // nearest to the given x coordinate, and that are within a 182 // nearest to the given x coordinate, and that are within a
183 // certain fuzz distance of that x coordinate. 183 // certain fuzz distance of that x coordinate.
184 184
185 sv_frame_t frame = v->getFrameForX(x); 185 sv_frame_t frame = v->getFrameForX(x);
186 186
187 EventVector exact = m_model->getEventsStartingAt(frame); 187 EventVector exact = model->getEventsStartingAt(frame);
188 if (!exact.empty()) return exact; 188 if (!exact.empty()) return exact;
189 189
190 // overspill == 1, so one event either side of the given span 190 // overspill == 1, so one event either side of the given span
191 EventVector neighbouring = m_model->getEventsWithin 191 EventVector neighbouring = model->getEventsWithin
192 (frame, m_model->getResolution(), 1); 192 (frame, model->getResolution(), 1);
193 193
194 double fuzz = v->scaleSize(2); 194 double fuzz = v->scaleSize(2);
195 sv_frame_t suitable = 0; 195 sv_frame_t suitable = 0;
196 bool have = false; 196 bool have = false;
197 197
211 suitable = f; 211 suitable = f;
212 } 212 }
213 } 213 }
214 214
215 if (have) { 215 if (have) {
216 return m_model->getEventsStartingAt(suitable); 216 return model->getEventsStartingAt(suitable);
217 } else { 217 } else {
218 return {}; 218 return {};
219 } 219 }
220 } 220 }
221 221
222 QString 222 QString
223 TimeInstantLayer::getLabelPreceding(sv_frame_t frame) const 223 TimeInstantLayer::getLabelPreceding(sv_frame_t frame) const
224 { 224 {
225 if (!m_model || !m_model->hasTextLabels()) return ""; 225 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
226 if (!model || !model->hasTextLabels()) return "";
226 227
227 Event e; 228 Event e;
228 if (m_model->getNearestEventMatching 229 if (model->getNearestEventMatching
229 (frame, 230 (frame,
230 [](Event e) { return e.hasLabel() && e.getLabel() != ""; }, 231 [](Event e) { return e.hasLabel() && e.getLabel() != ""; },
231 EventSeries::Backward, 232 EventSeries::Backward,
232 e)) { 233 e)) {
233 return e.getLabel(); 234 return e.getLabel();
239 QString 240 QString
240 TimeInstantLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const 241 TimeInstantLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const
241 { 242 {
242 int x = pos.x(); 243 int x = pos.x();
243 244
244 if (!m_model || !m_model->getSampleRate()) return ""; 245 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
246 if (!model || !model->getSampleRate()) return "";
245 247
246 EventVector points = getLocalPoints(v, x); 248 EventVector points = getLocalPoints(v, x);
247 249
248 if (points.empty()) { 250 if (points.empty()) {
249 if (!m_model->isReady()) { 251 if (!model->isReady()) {
250 return tr("In progress"); 252 return tr("In progress");
251 } else { 253 } else {
252 return tr("No local points"); 254 return tr("No local points");
253 } 255 }
254 } 256 }
255 257
256 sv_frame_t useFrame = points.begin()->getFrame(); 258 sv_frame_t useFrame = points.begin()->getFrame();
257 259
258 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); 260 RealTime rt = RealTime::frame2RealTime(useFrame, model->getSampleRate());
259 261
260 QString text; 262 QString text;
261 263
262 if (points.begin()->getLabel() == "") { 264 if (points.begin()->getLabel() == "") {
263 text = QString(tr("Time:\t%1\nNo label")) 265 text = QString(tr("Time:\t%1\nNo label"))
275 bool 277 bool
276 TimeInstantLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, 278 TimeInstantLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
277 int &resolution, 279 int &resolution,
278 SnapType snap) const 280 SnapType snap) const
279 { 281 {
280 if (!m_model) { 282 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
283 if (!model) {
281 return Layer::snapToFeatureFrame(v, frame, resolution, snap); 284 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
282 } 285 }
283 286
284 // SnapLeft / SnapRight: return frame of nearest feature in that 287 // SnapLeft / SnapRight: return frame of nearest feature in that
285 // direction no matter how far away 288 // direction no matter how far away
286 // 289 //
287 // SnapNeighbouring: return frame of feature that would be used in 290 // SnapNeighbouring: return frame of feature that would be used in
288 // an editing operation, i.e. closest feature in either direction 291 // an editing operation, i.e. closest feature in either direction
289 // but only if it is "close enough" 292 // but only if it is "close enough"
290 293
291 resolution = m_model->getResolution(); 294 resolution = model->getResolution();
292 295
293 if (snap == SnapNeighbouring) { 296 if (snap == SnapNeighbouring) {
294 EventVector points = getLocalPoints(v, v->getXForFrame(frame)); 297 EventVector points = getLocalPoints(v, v->getXForFrame(frame));
295 if (points.empty()) return false; 298 if (points.empty()) return false;
296 frame = points.begin()->getFrame(); 299 frame = points.begin()->getFrame();
297 return true; 300 return true;
298 } 301 }
299 302
300 Event e; 303 Event e;
301 if (m_model->getNearestEventMatching 304 if (model->getNearestEventMatching
302 (frame, 305 (frame,
303 [](Event) { return true; }, 306 [](Event) { return true; },
304 snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, 307 snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward,
305 e)) { 308 e)) {
306 frame = e.getFrame(); 309 frame = e.getFrame();
311 } 314 }
312 315
313 void 316 void
314 TimeInstantLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const 317 TimeInstantLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
315 { 318 {
316 if (!m_model || !m_model->isOK()) return; 319 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
320 if (!model || !model->isOK()) return;
317 321
318 // Profiler profiler("TimeInstantLayer::paint", true); 322 // Profiler profiler("TimeInstantLayer::paint", true);
319 323
320 int x0 = rect.left(), x1 = rect.right(); 324 int x0 = rect.left(), x1 = rect.right();
321 325
327 // 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
328 // fill in the visible part of its segmentation area 332 // fill in the visible part of its segmentation area
329 overspill = 1; 333 overspill = 1;
330 } 334 }
331 335
332 EventVector points(m_model->getEventsWithin(frame0, frame1 - frame0, 336 EventVector points(model->getEventsWithin(frame0, frame1 - frame0,
333 overspill)); 337 overspill));
334 338
335 bool odd = false; 339 bool odd = false;
336 if (m_plotStyle == PlotSegmentation && !points.empty()) { 340 if (m_plotStyle == PlotSegmentation && !points.empty()) {
337 int index = m_model->getRowForFrame(points.begin()->getFrame()); 341 int index = model->getRowForFrame(points.begin()->getFrame());
338 odd = ((index % 2) == 1); 342 odd = ((index % 2) == 1);
339 } 343 }
340 344
341 paint.setPen(getBaseQColor()); 345 paint.setPen(getBaseQColor());
342 346
353 } else if (getBaseQColor() == Qt::darkBlue) { 357 } else if (getBaseQColor() == Qt::darkBlue) {
354 oddBrushColour = Qt::blue; 358 oddBrushColour = Qt::blue;
355 } else if (getBaseQColor() == Qt::darkGreen) { 359 } else if (getBaseQColor() == Qt::darkGreen) {
356 oddBrushColour = Qt::green; 360 oddBrushColour = Qt::green;
357 } else { 361 } else {
358 oddBrushColour = oddBrushColour.light(150); 362 oddBrushColour = oddBrushColour.lighter(150);
359 } 363 }
360 oddBrushColour.setAlpha(100); 364 oddBrushColour.setAlpha(100);
361 } 365 }
362 366
363 // SVDEBUG << "TimeInstantLayer::paint: resolution is " 367 // SVDEBUG << "TimeInstantLayer::paint: resolution is "
364 // << m_model->getResolution() << " frames" << endl; 368 // << model->getResolution() << " frames" << endl;
365 369
366 QPoint localPos; 370 QPoint localPos;
367 sv_frame_t illuminateFrame = -1; 371 sv_frame_t illuminateFrame = -1;
368 372
369 if (v->shouldIlluminateLocalFeatures(this, localPos)) { 373 if (v->shouldIlluminateLocalFeatures(this, localPos)) {
385 389
386 int x = v->getXForFrame(p.getFrame()); 390 int x = v->getXForFrame(p.getFrame());
387 if (x == prevX && m_plotStyle == PlotInstants && 391 if (x == prevX && m_plotStyle == PlotInstants &&
388 p.getFrame() != illuminateFrame) continue; 392 p.getFrame() != illuminateFrame) continue;
389 393
390 int iw = v->getXForFrame(p.getFrame() + m_model->getResolution()) - x; 394 int iw = v->getXForFrame(p.getFrame() + model->getResolution()) - x;
391 if (iw < 2) { 395 if (iw < 2) {
392 if (iw < 1) { 396 if (iw < 1) {
393 iw = 2; 397 iw = 2;
394 if (j != points.end()) { 398 if (j != points.end()) {
395 int nx = v->getXForFrame(j->getFrame()); 399 int nx = v->getXForFrame(j->getFrame());
421 425
422 if (j != points.end()) { 426 if (j != points.end()) {
423 Event q(*j); 427 Event q(*j);
424 nx = v->getXForFrame(q.getFrame()); 428 nx = v->getXForFrame(q.getFrame());
425 } else { 429 } else {
426 nx = v->getXForFrame(m_model->getEndFrame()); 430 nx = v->getXForFrame(model->getEndFrame());
427 } 431 }
428 432
429 if (nx >= x) { 433 if (nx >= x) {
430 434
431 if (illuminateFrame != p.getFrame() && 435 if (illuminateFrame != p.getFrame() &&
440 } 444 }
441 445
442 paint.setPen(getBaseQColor()); 446 paint.setPen(getBaseQColor());
443 447
444 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"
445 454
446 // 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
447 456
448 int lw = paint.fontMetrics().width(p.getLabel()); 457 int lw = paint.fontMetrics().width(p.getLabel());
449 bool good = true; 458 bool good = true;
470 { 479 {
471 #ifdef DEBUG_TIME_INSTANT_LAYER 480 #ifdef DEBUG_TIME_INSTANT_LAYER
472 cerr << "TimeInstantLayer::drawStart(" << e->x() << ")" << endl; 481 cerr << "TimeInstantLayer::drawStart(" << e->x() << ")" << endl;
473 #endif 482 #endif
474 483
475 if (!m_model) return; 484 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
485 if (!model) return;
476 486
477 sv_frame_t frame = v->getFrameForX(e->x()); 487 sv_frame_t frame = v->getFrameForX(e->x());
478 if (frame < 0) frame = 0; 488 if (frame < 0) frame = 0;
479 frame = frame / m_model->getResolution() * m_model->getResolution(); 489 frame = frame / model->getResolution() * model->getResolution();
480 490
481 m_editingPoint = Event(frame, tr("New Point")); 491 m_editingPoint = Event(frame, tr("New Point"));
482 492
483 if (m_editingCommand) finish(m_editingCommand); 493 if (m_editingCommand) finish(m_editingCommand);
484 m_editingCommand = new ChangeEventsCommand(m_model, tr("Draw Point")); 494 m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Draw Point"));
485 m_editingCommand->add(m_editingPoint); 495 m_editingCommand->add(m_editingPoint);
486 496
487 m_editing = true; 497 m_editing = true;
488 } 498 }
489 499
492 { 502 {
493 #ifdef DEBUG_TIME_INSTANT_LAYER 503 #ifdef DEBUG_TIME_INSTANT_LAYER
494 cerr << "TimeInstantLayer::drawDrag(" << e->x() << ")" << endl; 504 cerr << "TimeInstantLayer::drawDrag(" << e->x() << ")" << endl;
495 #endif 505 #endif
496 506
497 if (!m_model || !m_editing) return; 507 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
508 if (!model || !m_editing) return;
498 509
499 sv_frame_t frame = v->getFrameForX(e->x()); 510 sv_frame_t frame = v->getFrameForX(e->x());
500 if (frame < 0) frame = 0; 511 if (frame < 0) frame = 0;
501 frame = frame / m_model->getResolution() * m_model->getResolution(); 512 frame = frame / model->getResolution() * model->getResolution();
502 m_editingCommand->remove(m_editingPoint); 513 m_editingCommand->remove(m_editingPoint);
503 m_editingPoint = m_editingPoint.withFrame(frame); 514 m_editingPoint = m_editingPoint.withFrame(frame);
504 m_editingCommand->add(m_editingPoint); 515 m_editingCommand->add(m_editingPoint);
505 } 516 }
506 517
508 TimeInstantLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) 519 TimeInstantLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *)
509 { 520 {
510 #ifdef DEBUG_TIME_INSTANT_LAYER 521 #ifdef DEBUG_TIME_INSTANT_LAYER
511 cerr << "TimeInstantLayer::drawEnd(" << e->x() << ")" << endl; 522 cerr << "TimeInstantLayer::drawEnd(" << e->x() << ")" << endl;
512 #endif 523 #endif
513 if (!m_model || !m_editing) return; 524 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
525 if (!model || !m_editing) return;
514 QString newName = tr("Add Point at %1 s") 526 QString newName = tr("Add Point at %1 s")
515 .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(), 527 .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(),
516 m_model->getSampleRate()) 528 model->getSampleRate())
517 .toText(false).c_str()); 529 .toText(false).c_str());
518 m_editingCommand->setName(newName); 530 m_editingCommand->setName(newName);
519 finish(m_editingCommand); 531 finish(m_editingCommand);
520 m_editingCommand = nullptr; 532 m_editingCommand = nullptr;
521 m_editing = false; 533 m_editing = false;
522 } 534 }
523 535
524 void 536 void
525 TimeInstantLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) 537 TimeInstantLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e)
526 { 538 {
527 if (!m_model) return; 539 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
540 if (!model) return;
528 541
529 EventVector points = getLocalPoints(v, e->x()); 542 EventVector points = getLocalPoints(v, e->x());
530 if (points.empty()) return; 543 if (points.empty()) return;
531 544
532 m_editingPoint = *points.begin(); 545 m_editingPoint = *points.begin();
545 } 558 }
546 559
547 void 560 void
548 TimeInstantLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) 561 TimeInstantLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e)
549 { 562 {
550 if (!m_model || !m_editing) return; 563 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
564 if (!model || !m_editing) return;
551 565
552 m_editing = false; 566 m_editing = false;
553 567
554 EventVector points = getLocalPoints(v, e->x()); 568 EventVector points = getLocalPoints(v, e->x());
555 if (points.empty()) return; 569 if (points.empty()) return;
556 if (points.begin()->getFrame() != m_editingPoint.getFrame()) return; 570 if (points.begin()->getFrame() != m_editingPoint.getFrame()) return;
557 571
558 m_editingCommand = new ChangeEventsCommand(m_model, tr("Erase Point")); 572 m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Erase Point"));
559 m_editingCommand->remove(m_editingPoint); 573 m_editingCommand->remove(m_editingPoint);
560 finish(m_editingCommand); 574 finish(m_editingCommand);
561 m_editingCommand = nullptr; 575 m_editingCommand = nullptr;
562 m_editing = false; 576 m_editing = false;
563 } 577 }
567 { 581 {
568 #ifdef DEBUG_TIME_INSTANT_LAYER 582 #ifdef DEBUG_TIME_INSTANT_LAYER
569 cerr << "TimeInstantLayer::editStart(" << e->x() << ")" << endl; 583 cerr << "TimeInstantLayer::editStart(" << e->x() << ")" << endl;
570 #endif 584 #endif
571 585
572 if (!m_model) return; 586 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
587 if (!model) return;
573 588
574 EventVector points = getLocalPoints(v, e->x()); 589 EventVector points = getLocalPoints(v, e->x());
575 if (points.empty()) return; 590 if (points.empty()) return;
576 591
577 m_editingPoint = *points.begin(); 592 m_editingPoint = *points.begin();
589 { 604 {
590 #ifdef DEBUG_TIME_INSTANT_LAYER 605 #ifdef DEBUG_TIME_INSTANT_LAYER
591 cerr << "TimeInstantLayer::editDrag(" << e->x() << ")" << endl; 606 cerr << "TimeInstantLayer::editDrag(" << e->x() << ")" << endl;
592 #endif 607 #endif
593 608
594 if (!m_model || !m_editing) return; 609 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
610 if (!model || !m_editing) return;
595 611
596 sv_frame_t frame = v->getFrameForX(e->x()); 612 sv_frame_t frame = v->getFrameForX(e->x());
597 if (frame < 0) frame = 0; 613 if (frame < 0) frame = 0;
598 frame = frame / m_model->getResolution() * m_model->getResolution(); 614 frame = frame / model->getResolution() * model->getResolution();
599 615
600 if (!m_editingCommand) { 616 if (!m_editingCommand) {
601 m_editingCommand = new ChangeEventsCommand(m_model, tr("Drag Point")); 617 m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Drag Point"));
602 } 618 }
603 619
604 m_editingCommand->remove(m_editingPoint); 620 m_editingCommand->remove(m_editingPoint);
605 m_editingPoint = m_editingPoint.withFrame(frame); 621 m_editingPoint = m_editingPoint.withFrame(frame);
606 m_editingCommand->add(m_editingPoint); 622 m_editingCommand->add(m_editingPoint);
610 TimeInstantLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) 626 TimeInstantLayer::editEnd(LayerGeometryProvider *, QMouseEvent *)
611 { 627 {
612 #ifdef DEBUG_TIME_INSTANT_LAYER 628 #ifdef DEBUG_TIME_INSTANT_LAYER
613 cerr << "TimeInstantLayer::editEnd(" << e->x() << ")" << endl; 629 cerr << "TimeInstantLayer::editEnd(" << e->x() << ")" << endl;
614 #endif 630 #endif
615 if (!m_model || !m_editing) return; 631 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
632 if (!model || !m_editing) return;
616 if (m_editingCommand) { 633 if (m_editingCommand) {
617 QString newName = tr("Move Point to %1 s") 634 QString newName = tr("Move Point to %1 s")
618 .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(), 635 .arg(RealTime::frame2RealTime(m_editingPoint.getFrame(),
619 m_model->getSampleRate()) 636 model->getSampleRate())
620 .toText(false).c_str()); 637 .toText(false).c_str());
621 m_editingCommand->setName(newName); 638 m_editingCommand->setName(newName);
622 finish(m_editingCommand); 639 finish(m_editingCommand);
623 } 640 }
624 m_editingCommand = nullptr; 641 m_editingCommand = nullptr;
626 } 643 }
627 644
628 bool 645 bool
629 TimeInstantLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) 646 TimeInstantLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e)
630 { 647 {
631 if (!m_model) return false; 648 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
649 if (!model) return false;
632 650
633 EventVector points = getLocalPoints(v, e->x()); 651 EventVector points = getLocalPoints(v, e->x());
634 if (points.empty()) return false; 652 if (points.empty()) return false;
635 653
636 Event point = *points.begin(); 654 Event point = *points.begin();
637 655
638 ItemEditDialog *dialog = new ItemEditDialog 656 ItemEditDialog *dialog = new ItemEditDialog
639 (m_model->getSampleRate(), 657 (model->getSampleRate(),
640 ItemEditDialog::ShowTime | 658 ItemEditDialog::ShowTime |
641 ItemEditDialog::ShowText); 659 ItemEditDialog::ShowText);
642 660
643 dialog->setFrameTime(point.getFrame()); 661 dialog->setFrameTime(point.getFrame());
644 dialog->setText(point.getLabel()); 662 dialog->setText(point.getLabel());
648 Event newPoint = point 666 Event newPoint = point
649 .withFrame(dialog->getFrameTime()) 667 .withFrame(dialog->getFrameTime())
650 .withLabel(dialog->getText()); 668 .withLabel(dialog->getText());
651 669
652 ChangeEventsCommand *command = 670 ChangeEventsCommand *command =
653 new ChangeEventsCommand(m_model, tr("Edit Point")); 671 new ChangeEventsCommand(m_model.untyped, tr("Edit Point"));
654 command->remove(point); 672 command->remove(point);
655 command->add(newPoint); 673 command->add(newPoint);
656 finish(command); 674 finish(command);
657 } 675 }
658 676
661 } 679 }
662 680
663 void 681 void
664 TimeInstantLayer::moveSelection(Selection s, sv_frame_t newStartFrame) 682 TimeInstantLayer::moveSelection(Selection s, sv_frame_t newStartFrame)
665 { 683 {
666 if (!m_model) return; 684 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
685 if (!model) return;
667 686
668 ChangeEventsCommand *command = 687 ChangeEventsCommand *command =
669 new ChangeEventsCommand(m_model, tr("Drag Selection")); 688 new ChangeEventsCommand(m_model.untyped, tr("Drag Selection"));
670 689
671 EventVector points = 690 EventVector points =
672 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); 691 model->getEventsWithin(s.getStartFrame(), s.getDuration());
673 692
674 for (auto p: points) { 693 for (auto p: points) {
675 Event newPoint = p 694 Event newPoint = p
676 .withFrame(p.getFrame() + newStartFrame - s.getStartFrame()); 695 .withFrame(p.getFrame() + newStartFrame - s.getStartFrame());
677 command->remove(p); 696 command->remove(p);
682 } 701 }
683 702
684 void 703 void
685 TimeInstantLayer::resizeSelection(Selection s, Selection newSize) 704 TimeInstantLayer::resizeSelection(Selection s, Selection newSize)
686 { 705 {
687 if (!m_model) return; 706 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
707 if (!model) return;
688 708
689 ChangeEventsCommand *command = 709 ChangeEventsCommand *command =
690 new ChangeEventsCommand(m_model, tr("Resize Selection")); 710 new ChangeEventsCommand(m_model.untyped, tr("Resize Selection"));
691 711
692 EventVector points = 712 EventVector points =
693 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); 713 model->getEventsWithin(s.getStartFrame(), s.getDuration());
694 714
695 double ratio = double(newSize.getDuration()) / double(s.getDuration()); 715 double ratio = double(newSize.getDuration()) / double(s.getDuration());
696 double oldStart = double(s.getStartFrame()); 716 double oldStart = double(s.getStartFrame());
697 double newStart = double(newSize.getStartFrame()); 717 double newStart = double(newSize.getStartFrame());
698 718
710 } 730 }
711 731
712 void 732 void
713 TimeInstantLayer::deleteSelection(Selection s) 733 TimeInstantLayer::deleteSelection(Selection s)
714 { 734 {
715 if (!m_model) return; 735 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
736 if (!model) return;
716 737
717 ChangeEventsCommand *command = 738 ChangeEventsCommand *command =
718 new ChangeEventsCommand(m_model, tr("Delete Selection")); 739 new ChangeEventsCommand(m_model.untyped, tr("Delete Selection"));
719 740
720 EventVector points = 741 EventVector points =
721 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); 742 model->getEventsWithin(s.getStartFrame(), s.getDuration());
722 743
723 for (auto p: points) { 744 for (auto p: points) {
724 command->remove(p); 745 command->remove(p);
725 } 746 }
726 747
728 } 749 }
729 750
730 void 751 void
731 TimeInstantLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) 752 TimeInstantLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to)
732 { 753 {
733 if (!m_model) return; 754 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
755 if (!model) return;
734 756
735 EventVector points = 757 EventVector points =
736 m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); 758 model->getEventsWithin(s.getStartFrame(), s.getDuration());
737 759
738 for (auto p: points) { 760 for (auto p: points) {
739 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); 761 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame())));
740 } 762 }
741 } 763 }
742 764
743 bool 765 bool
744 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)
745 { 767 {
746 if (!m_model) return false; 768 auto model = ModelById::getAs<SparseOneDimensionalModel>(m_model);
769 if (!model) return false;
747 770
748 EventVector points = from.getPoints(); 771 EventVector points = from.getPoints();
749 772
750 bool realign = false; 773 bool realign = false;
751 774
765 realign = true; 788 realign = true;
766 } 789 }
767 } 790 }
768 791
769 ChangeEventsCommand *command = 792 ChangeEventsCommand *command =
770 new ChangeEventsCommand(m_model, tr("Paste")); 793 new ChangeEventsCommand(m_model.untyped, tr("Paste"));
771 794
772 for (EventVector::const_iterator i = points.begin(); 795 for (EventVector::const_iterator i = points.begin();
773 i != points.end(); ++i) { 796 i != points.end(); ++i) {
774 797
775 sv_frame_t frame = 0; 798 sv_frame_t frame = 0;