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