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;