Mercurial > hg > svgui
comparison layer/TextLayer.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 |
---|---|
32 #include <iostream> | 32 #include <iostream> |
33 #include <cmath> | 33 #include <cmath> |
34 | 34 |
35 TextLayer::TextLayer() : | 35 TextLayer::TextLayer() : |
36 SingleColourLayer(), | 36 SingleColourLayer(), |
37 m_model(nullptr), | |
38 m_editing(false), | 37 m_editing(false), |
39 m_originalPoint(0, 0.0, tr("Empty Label")), | 38 m_originalPoint(0, 0.0, tr("Empty Label")), |
40 m_editingPoint(0, 0.0, tr("Empty Label")), | 39 m_editingPoint(0, 0.0, tr("Empty Label")), |
41 m_editingCommand(nullptr) | 40 m_editingCommand(nullptr) |
42 { | 41 { |
43 | 42 |
44 } | 43 } |
45 | 44 |
46 void | 45 int |
47 TextLayer::setModel(TextModel *model) | 46 TextLayer::getCompletion(LayerGeometryProvider *) const |
48 { | 47 { |
49 if (m_model == model) return; | 48 auto model = ModelById::get(m_model); |
50 m_model = model; | 49 if (model) return model->getCompletion(); |
51 | 50 else return 0; |
52 connectSignals(m_model); | 51 } |
53 | 52 |
54 // SVDEBUG << "TextLayer::setModel(" << model << ")" << endl; | 53 void |
54 TextLayer::setModel(ModelId modelId) | |
55 { | |
56 auto newModel = ModelById::getAs<TextModel>(modelId); | |
57 | |
58 if (!modelId.isNone() && !newModel) { | |
59 throw std::logic_error("Not a TextModel"); | |
60 } | |
61 | |
62 if (m_model == modelId) return; | |
63 m_model = modelId; | |
64 | |
65 if (newModel) { | |
66 connectSignals(m_model); | |
67 } | |
55 | 68 |
56 emit modelReplaced(); | 69 emit modelReplaced(); |
57 } | 70 } |
58 | 71 |
59 Layer::PropertyList | 72 Layer::PropertyList |
109 } | 122 } |
110 | 123 |
111 EventVector | 124 EventVector |
112 TextLayer::getLocalPoints(LayerGeometryProvider *v, int x, int y) const | 125 TextLayer::getLocalPoints(LayerGeometryProvider *v, int x, int y) const |
113 { | 126 { |
114 if (!m_model) return {}; | 127 auto model = ModelById::getAs<TextModel>(m_model); |
128 if (!model) return {}; | |
115 | 129 |
116 int overlap = ViewManager::scalePixelSize(150); | 130 int overlap = ViewManager::scalePixelSize(150); |
117 | 131 |
118 sv_frame_t frame0 = v->getFrameForX(-overlap); | 132 sv_frame_t frame0 = v->getFrameForX(-overlap); |
119 sv_frame_t frame1 = v->getFrameForX(v->getPaintWidth() + overlap); | 133 sv_frame_t frame1 = v->getFrameForX(v->getPaintWidth() + overlap); |
120 | 134 |
121 EventVector points(m_model->getEventsSpanning(frame0, frame1 - frame0)); | 135 EventVector points(model->getEventsSpanning(frame0, frame1 - frame0)); |
122 | 136 |
123 EventVector rv; | 137 EventVector rv; |
124 QFontMetrics metrics = QFontMetrics(QFont()); | 138 QFontMetrics metrics = QFontMetrics(QFont()); |
125 | 139 |
126 for (EventVector::iterator i = points.begin(); i != points.end(); ++i) { | 140 for (EventVector::iterator i = points.begin(); i != points.end(); ++i) { |
154 } | 168 } |
155 | 169 |
156 bool | 170 bool |
157 TextLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &p) const | 171 TextLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &p) const |
158 { | 172 { |
159 if (!m_model) return false; | 173 auto model = ModelById::getAs<TextModel>(m_model); |
174 if (!model) return false; | |
160 | 175 |
161 sv_frame_t a = v->getFrameForX(x - ViewManager::scalePixelSize(120)); | 176 sv_frame_t a = v->getFrameForX(x - ViewManager::scalePixelSize(120)); |
162 sv_frame_t b = v->getFrameForX(x + ViewManager::scalePixelSize(10)); | 177 sv_frame_t b = v->getFrameForX(x + ViewManager::scalePixelSize(10)); |
163 EventVector onPoints = m_model->getEventsWithin(a, b); | 178 EventVector onPoints = model->getEventsWithin(a, b); |
164 if (onPoints.empty()) return false; | 179 if (onPoints.empty()) return false; |
165 | 180 |
166 double nearestDistance = -1; | 181 double nearestDistance = -1; |
167 | 182 |
168 for (EventVector::const_iterator i = onPoints.begin(); | 183 for (EventVector::const_iterator i = onPoints.begin(); |
184 QString | 199 QString |
185 TextLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const | 200 TextLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const |
186 { | 201 { |
187 int x = pos.x(); | 202 int x = pos.x(); |
188 | 203 |
189 if (!m_model || !m_model->getSampleRate()) return ""; | 204 auto model = ModelById::getAs<TextModel>(m_model); |
205 if (!model || !model->getSampleRate()) return ""; | |
190 | 206 |
191 EventVector points = getLocalPoints(v, x, pos.y()); | 207 EventVector points = getLocalPoints(v, x, pos.y()); |
192 | 208 |
193 if (points.empty()) { | 209 if (points.empty()) { |
194 if (!m_model->isReady()) { | 210 if (!model->isReady()) { |
195 return tr("In progress"); | 211 return tr("In progress"); |
196 } else { | 212 } else { |
197 return ""; | 213 return ""; |
198 } | 214 } |
199 } | 215 } |
200 | 216 |
201 sv_frame_t useFrame = points.begin()->getFrame(); | 217 sv_frame_t useFrame = points.begin()->getFrame(); |
202 | 218 |
203 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); | 219 RealTime rt = RealTime::frame2RealTime(useFrame, model->getSampleRate()); |
204 | 220 |
205 QString text; | 221 QString text; |
206 | 222 |
207 if (points.begin()->getLabel() == "") { | 223 if (points.begin()->getLabel() == "") { |
208 text = QString(tr("Time:\t%1\nHeight:\t%2\nLabel:\t%3")) | 224 text = QString(tr("Time:\t%1\nHeight:\t%2\nLabel:\t%3")) |
222 bool | 238 bool |
223 TextLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, | 239 TextLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, |
224 int &resolution, | 240 int &resolution, |
225 SnapType snap) const | 241 SnapType snap) const |
226 { | 242 { |
227 if (!m_model) { | 243 auto model = ModelById::getAs<TextModel>(m_model); |
244 if (!model) { | |
228 return Layer::snapToFeatureFrame(v, frame, resolution, snap); | 245 return Layer::snapToFeatureFrame(v, frame, resolution, snap); |
229 } | 246 } |
230 | 247 |
231 // SnapLeft / SnapRight: return frame of nearest feature in that | 248 // SnapLeft / SnapRight: return frame of nearest feature in that |
232 // direction no matter how far away | 249 // direction no matter how far away |
233 // | 250 // |
234 // SnapNeighbouring: return frame of feature that would be used in | 251 // SnapNeighbouring: return frame of feature that would be used in |
235 // an editing operation, i.e. closest feature in either direction | 252 // an editing operation, i.e. closest feature in either direction |
236 // but only if it is "close enough" | 253 // but only if it is "close enough" |
237 | 254 |
238 resolution = m_model->getResolution(); | 255 resolution = model->getResolution(); |
239 | 256 |
240 if (snap == SnapNeighbouring) { | 257 if (snap == SnapNeighbouring) { |
241 EventVector points = getLocalPoints(v, v->getXForFrame(frame), -1); | 258 EventVector points = getLocalPoints(v, v->getXForFrame(frame), -1); |
242 if (points.empty()) return false; | 259 if (points.empty()) return false; |
243 frame = points.begin()->getFrame(); | 260 frame = points.begin()->getFrame(); |
244 return true; | 261 return true; |
245 } | 262 } |
246 | 263 |
247 Event e; | 264 Event e; |
248 if (m_model->getNearestEventMatching | 265 if (model->getNearestEventMatching |
249 (frame, | 266 (frame, |
250 [](Event) { return true; }, | 267 [](Event) { return true; }, |
251 snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, | 268 snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward, |
252 e)) { | 269 e)) { |
253 frame = e.getFrame(); | 270 frame = e.getFrame(); |
272 } | 289 } |
273 | 290 |
274 void | 291 void |
275 TextLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const | 292 TextLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const |
276 { | 293 { |
277 if (!m_model || !m_model->isOK()) return; | 294 auto model = ModelById::getAs<TextModel>(m_model); |
278 | 295 if (!model || !model->isOK()) return; |
279 sv_samplerate_t sampleRate = m_model->getSampleRate(); | 296 |
297 sv_samplerate_t sampleRate = model->getSampleRate(); | |
280 if (!sampleRate) return; | 298 if (!sampleRate) return; |
281 | 299 |
282 // Profiler profiler("TextLayer::paint", true); | 300 // Profiler profiler("TextLayer::paint", true); |
283 | 301 |
284 int x0 = rect.left(), x1 = rect.right(); | 302 int x0 = rect.left(), x1 = rect.right(); |
285 int overlap = ViewManager::scalePixelSize(150); | 303 int overlap = ViewManager::scalePixelSize(150); |
286 sv_frame_t frame0 = v->getFrameForX(x0 - overlap); | 304 sv_frame_t frame0 = v->getFrameForX(x0 - overlap); |
287 sv_frame_t frame1 = v->getFrameForX(x1 + overlap); | 305 sv_frame_t frame1 = v->getFrameForX(x1 + overlap); |
288 | 306 |
289 EventVector points(m_model->getEventsWithin(frame0, frame1 - frame0, 2)); | 307 EventVector points(model->getEventsWithin(frame0, frame1 - frame0, 2)); |
290 if (points.empty()) return; | 308 if (points.empty()) return; |
291 | 309 |
292 QColor brushColour(getBaseQColor()); | 310 QColor brushColour(getBaseQColor()); |
293 | 311 |
294 int h, s, val; | 312 int h, s, val; |
297 | 315 |
298 QColor penColour; | 316 QColor penColour; |
299 penColour = v->getForeground(); | 317 penColour = v->getForeground(); |
300 | 318 |
301 // SVDEBUG << "TextLayer::paint: resolution is " | 319 // SVDEBUG << "TextLayer::paint: resolution is " |
302 // << m_model->getResolution() << " frames" << endl; | 320 // << model->getResolution() << " frames" << endl; |
303 | 321 |
304 QPoint localPos; | 322 QPoint localPos; |
305 Event illuminatePoint(0); | 323 Event illuminatePoint(0); |
306 bool shouldIlluminate = false; | 324 bool shouldIlluminate = false; |
307 | 325 |
377 void | 395 void |
378 TextLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e) | 396 TextLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e) |
379 { | 397 { |
380 // SVDEBUG << "TextLayer::drawStart(" << e->x() << "," << e->y() << ")" << endl; | 398 // SVDEBUG << "TextLayer::drawStart(" << e->x() << "," << e->y() << ")" << endl; |
381 | 399 |
382 if (!m_model) { | 400 auto model = ModelById::getAs<TextModel>(m_model); |
401 if (!model) { | |
383 SVDEBUG << "TextLayer::drawStart: no model" << endl; | 402 SVDEBUG << "TextLayer::drawStart: no model" << endl; |
384 return; | 403 return; |
385 } | 404 } |
386 | 405 |
387 sv_frame_t frame = v->getFrameForX(e->x()); | 406 sv_frame_t frame = v->getFrameForX(e->x()); |
388 if (frame < 0) frame = 0; | 407 if (frame < 0) frame = 0; |
389 frame = frame / m_model->getResolution() * m_model->getResolution(); | 408 frame = frame / model->getResolution() * model->getResolution(); |
390 | 409 |
391 double height = getHeightForY(v, e->y()); | 410 double height = getHeightForY(v, e->y()); |
392 | 411 |
393 m_editingPoint = Event(frame, float(height), ""); | 412 m_editingPoint = Event(frame, float(height), ""); |
394 m_originalPoint = m_editingPoint; | 413 m_originalPoint = m_editingPoint; |
395 | 414 |
396 if (m_editingCommand) finish(m_editingCommand); | 415 if (m_editingCommand) finish(m_editingCommand); |
397 m_editingCommand = new ChangeEventsCommand(m_model, "Add Label"); | 416 m_editingCommand = new ChangeEventsCommand(m_model.untyped, "Add Label"); |
398 m_editingCommand->add(m_editingPoint); | 417 m_editingCommand->add(m_editingPoint); |
399 | 418 |
400 m_editing = true; | 419 m_editing = true; |
401 } | 420 } |
402 | 421 |
403 void | 422 void |
404 TextLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e) | 423 TextLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e) |
405 { | 424 { |
406 // SVDEBUG << "TextLayer::drawDrag(" << e->x() << "," << e->y() << ")" << endl; | 425 // SVDEBUG << "TextLayer::drawDrag(" << e->x() << "," << e->y() << ")" << endl; |
407 | 426 |
408 if (!m_model || !m_editing) return; | 427 auto model = ModelById::getAs<TextModel>(m_model); |
428 if (!model || !m_editing) return; | |
409 | 429 |
410 sv_frame_t frame = v->getFrameForX(e->x()); | 430 sv_frame_t frame = v->getFrameForX(e->x()); |
411 if (frame < 0) frame = 0; | 431 if (frame < 0) frame = 0; |
412 frame = frame / m_model->getResolution() * m_model->getResolution(); | 432 frame = frame / model->getResolution() * model->getResolution(); |
413 | 433 |
414 double height = getHeightForY(v, e->y()); | 434 double height = getHeightForY(v, e->y()); |
415 | 435 |
416 m_editingCommand->remove(m_editingPoint); | 436 m_editingCommand->remove(m_editingPoint); |
417 m_editingPoint = m_editingPoint | 437 m_editingPoint = m_editingPoint |
422 | 442 |
423 void | 443 void |
424 TextLayer::drawEnd(LayerGeometryProvider *v, QMouseEvent *) | 444 TextLayer::drawEnd(LayerGeometryProvider *v, QMouseEvent *) |
425 { | 445 { |
426 // SVDEBUG << "TextLayer::drawEnd(" << e->x() << "," << e->y() << ")" << endl; | 446 // SVDEBUG << "TextLayer::drawEnd(" << e->x() << "," << e->y() << ")" << endl; |
427 if (!m_model || !m_editing) return; | 447 auto model = ModelById::getAs<TextModel>(m_model); |
448 if (!model || !m_editing) return; | |
428 | 449 |
429 bool ok = false; | 450 bool ok = false; |
430 QString label = QInputDialog::getText(v->getView(), tr("Enter label"), | 451 QString label = QInputDialog::getText(v->getView(), tr("Enter label"), |
431 tr("Please enter a new label:"), | 452 tr("Please enter a new label:"), |
432 QLineEdit::Normal, "", &ok); | 453 QLineEdit::Normal, "", &ok); |
445 } | 466 } |
446 | 467 |
447 void | 468 void |
448 TextLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) | 469 TextLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) |
449 { | 470 { |
450 if (!m_model) return; | 471 auto model = ModelById::getAs<TextModel>(m_model); |
472 if (!model) return; | |
451 | 473 |
452 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; | 474 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; |
453 | 475 |
454 if (m_editingCommand) { | 476 if (m_editingCommand) { |
455 finish(m_editingCommand); | 477 finish(m_editingCommand); |
465 } | 487 } |
466 | 488 |
467 void | 489 void |
468 TextLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) | 490 TextLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) |
469 { | 491 { |
470 if (!m_model || !m_editing) return; | 492 auto model = ModelById::getAs<TextModel>(m_model); |
493 if (!model || !m_editing) return; | |
471 | 494 |
472 m_editing = false; | 495 m_editing = false; |
473 | 496 |
474 Event p; | 497 Event p; |
475 if (!getPointToDrag(v, e->x(), e->y(), p)) return; | 498 if (!getPointToDrag(v, e->x(), e->y(), p)) return; |
476 if (p.getFrame() != m_editingPoint.getFrame() || | 499 if (p.getFrame() != m_editingPoint.getFrame() || |
477 p.getValue() != m_editingPoint.getValue()) return; | 500 p.getValue() != m_editingPoint.getValue()) return; |
478 | 501 |
479 m_editingCommand = new ChangeEventsCommand(m_model, tr("Erase Point")); | 502 m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Erase Point")); |
480 m_editingCommand->remove(m_editingPoint); | 503 m_editingCommand->remove(m_editingPoint); |
481 finish(m_editingCommand); | 504 finish(m_editingCommand); |
482 m_editingCommand = nullptr; | 505 m_editingCommand = nullptr; |
483 m_editing = false; | 506 m_editing = false; |
484 } | 507 } |
486 void | 509 void |
487 TextLayer::editStart(LayerGeometryProvider *v, QMouseEvent *e) | 510 TextLayer::editStart(LayerGeometryProvider *v, QMouseEvent *e) |
488 { | 511 { |
489 // SVDEBUG << "TextLayer::editStart(" << e->x() << "," << e->y() << ")" << endl; | 512 // SVDEBUG << "TextLayer::editStart(" << e->x() << "," << e->y() << ")" << endl; |
490 | 513 |
491 if (!m_model) return; | 514 auto model = ModelById::getAs<TextModel>(m_model); |
515 if (!model) return; | |
492 | 516 |
493 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) { | 517 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) { |
494 return; | 518 return; |
495 } | 519 } |
496 | 520 |
506 } | 530 } |
507 | 531 |
508 void | 532 void |
509 TextLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e) | 533 TextLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e) |
510 { | 534 { |
511 if (!m_model || !m_editing) return; | 535 auto model = ModelById::getAs<TextModel>(m_model); |
536 if (!model || !m_editing) return; | |
512 | 537 |
513 sv_frame_t frameDiff = | 538 sv_frame_t frameDiff = |
514 v->getFrameForX(e->x()) - v->getFrameForX(m_editOrigin.x()); | 539 v->getFrameForX(e->x()) - v->getFrameForX(m_editOrigin.x()); |
515 double heightDiff = | 540 double heightDiff = |
516 getHeightForY(v, e->y()) - getHeightForY(v, m_editOrigin.y()); | 541 getHeightForY(v, e->y()) - getHeightForY(v, m_editOrigin.y()); |
517 | 542 |
518 sv_frame_t frame = m_originalPoint.getFrame() + frameDiff; | 543 sv_frame_t frame = m_originalPoint.getFrame() + frameDiff; |
519 double height = m_originalPoint.getValue() + heightDiff; | 544 double height = m_originalPoint.getValue() + heightDiff; |
520 | 545 |
521 if (frame < 0) frame = 0; | 546 if (frame < 0) frame = 0; |
522 frame = (frame / m_model->getResolution()) * m_model->getResolution(); | 547 frame = (frame / model->getResolution()) * model->getResolution(); |
523 | 548 |
524 if (!m_editingCommand) { | 549 if (!m_editingCommand) { |
525 m_editingCommand = new ChangeEventsCommand(m_model, tr("Drag Label")); | 550 m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Drag Label")); |
526 } | 551 } |
527 | 552 |
528 m_editingCommand->remove(m_editingPoint); | 553 m_editingCommand->remove(m_editingPoint); |
529 m_editingPoint = m_editingPoint | 554 m_editingPoint = m_editingPoint |
530 .withFrame(frame) | 555 .withFrame(frame) |
534 | 559 |
535 void | 560 void |
536 TextLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) | 561 TextLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) |
537 { | 562 { |
538 // SVDEBUG << "TextLayer::editEnd(" << e->x() << "," << e->y() << ")" << endl; | 563 // SVDEBUG << "TextLayer::editEnd(" << e->x() << "," << e->y() << ")" << endl; |
539 if (!m_model || !m_editing) return; | 564 auto model = ModelById::getAs<TextModel>(m_model); |
565 if (!model || !m_editing) return; | |
540 | 566 |
541 if (m_editingCommand) { | 567 if (m_editingCommand) { |
542 | 568 |
543 QString newName = m_editingCommand->getName(); | 569 QString newName = m_editingCommand->getName(); |
544 | 570 |
561 } | 587 } |
562 | 588 |
563 bool | 589 bool |
564 TextLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) | 590 TextLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) |
565 { | 591 { |
566 if (!m_model) return false; | 592 auto model = ModelById::getAs<TextModel>(m_model); |
593 if (!model) return false; | |
567 | 594 |
568 Event text; | 595 Event text; |
569 if (!getPointToDrag(v, e->x(), e->y(), text)) return false; | 596 if (!getPointToDrag(v, e->x(), e->y(), text)) return false; |
570 | 597 |
571 QString label = text.getLabel(); | 598 QString label = text.getLabel(); |
574 label = QInputDialog::getText(v->getView(), tr("Enter label"), | 601 label = QInputDialog::getText(v->getView(), tr("Enter label"), |
575 tr("Please enter a new label:"), | 602 tr("Please enter a new label:"), |
576 QLineEdit::Normal, label, &ok); | 603 QLineEdit::Normal, label, &ok); |
577 if (ok && label != text.getLabel()) { | 604 if (ok && label != text.getLabel()) { |
578 ChangeEventsCommand *command = | 605 ChangeEventsCommand *command = |
579 new ChangeEventsCommand(m_model, tr("Re-Label Point")); | 606 new ChangeEventsCommand(m_model.untyped, tr("Re-Label Point")); |
580 command->remove(text); | 607 command->remove(text); |
581 command->add(text.withLabel(label)); | 608 command->add(text.withLabel(label)); |
582 finish(command); | 609 finish(command); |
583 } | 610 } |
584 | 611 |
586 } | 613 } |
587 | 614 |
588 void | 615 void |
589 TextLayer::moveSelection(Selection s, sv_frame_t newStartFrame) | 616 TextLayer::moveSelection(Selection s, sv_frame_t newStartFrame) |
590 { | 617 { |
591 if (!m_model) return; | 618 auto model = ModelById::getAs<TextModel>(m_model); |
619 if (!model) return; | |
592 | 620 |
593 ChangeEventsCommand *command = | 621 ChangeEventsCommand *command = |
594 new ChangeEventsCommand(m_model, tr("Drag Selection")); | 622 new ChangeEventsCommand(m_model.untyped, tr("Drag Selection")); |
595 | 623 |
596 EventVector points = | 624 EventVector points = |
597 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); | 625 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); |
598 | 626 |
599 for (Event p: points) { | 627 for (Event p: points) { |
600 command->remove(p); | 628 command->remove(p); |
601 Event moved = p.withFrame(p.getFrame() + | 629 Event moved = p.withFrame(p.getFrame() + |
602 newStartFrame - s.getStartFrame()); | 630 newStartFrame - s.getStartFrame()); |
607 } | 635 } |
608 | 636 |
609 void | 637 void |
610 TextLayer::resizeSelection(Selection s, Selection newSize) | 638 TextLayer::resizeSelection(Selection s, Selection newSize) |
611 { | 639 { |
612 if (!m_model) return; | 640 auto model = ModelById::getAs<TextModel>(m_model); |
641 if (!model) return; | |
613 | 642 |
614 ChangeEventsCommand *command = | 643 ChangeEventsCommand *command = |
615 new ChangeEventsCommand(m_model, tr("Resize Selection")); | 644 new ChangeEventsCommand(m_model.untyped, tr("Resize Selection")); |
616 | 645 |
617 EventVector points = | 646 EventVector points = |
618 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); | 647 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); |
619 | 648 |
620 double ratio = double(newSize.getDuration()) / double(s.getDuration()); | 649 double ratio = double(newSize.getDuration()) / double(s.getDuration()); |
621 double oldStart = double(s.getStartFrame()); | 650 double oldStart = double(s.getStartFrame()); |
622 double newStart = double(newSize.getStartFrame()); | 651 double newStart = double(newSize.getStartFrame()); |
623 | 652 |
635 } | 664 } |
636 | 665 |
637 void | 666 void |
638 TextLayer::deleteSelection(Selection s) | 667 TextLayer::deleteSelection(Selection s) |
639 { | 668 { |
640 if (!m_model) return; | 669 auto model = ModelById::getAs<TextModel>(m_model); |
670 if (!model) return; | |
641 | 671 |
642 ChangeEventsCommand *command = | 672 ChangeEventsCommand *command = |
643 new ChangeEventsCommand(m_model, tr("Delete Selection")); | 673 new ChangeEventsCommand(m_model.untyped, tr("Delete Selection")); |
644 | 674 |
645 EventVector points = | 675 EventVector points = |
646 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); | 676 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); |
647 | 677 |
648 for (Event p: points) { | 678 for (Event p: points) { |
649 command->remove(p); | 679 command->remove(p); |
650 } | 680 } |
651 | 681 |
653 } | 683 } |
654 | 684 |
655 void | 685 void |
656 TextLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) | 686 TextLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) |
657 { | 687 { |
658 if (!m_model) return; | 688 auto model = ModelById::getAs<TextModel>(m_model); |
689 if (!model) return; | |
659 | 690 |
660 EventVector points = | 691 EventVector points = |
661 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); | 692 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); |
662 | 693 |
663 for (Event p: points) { | 694 for (Event p: points) { |
664 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); | 695 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); |
665 } | 696 } |
666 } | 697 } |
667 | 698 |
668 bool | 699 bool |
669 TextLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */, bool /* interactive */) | 700 TextLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */, bool /* interactive */) |
670 { | 701 { |
671 if (!m_model) return false; | 702 auto model = ModelById::getAs<TextModel>(m_model); |
703 if (!model) return false; | |
672 | 704 |
673 const EventVector &points = from.getPoints(); | 705 const EventVector &points = from.getPoints(); |
674 | 706 |
675 bool realign = false; | 707 bool realign = false; |
676 | 708 |
690 realign = true; | 722 realign = true; |
691 } | 723 } |
692 } | 724 } |
693 | 725 |
694 ChangeEventsCommand *command = | 726 ChangeEventsCommand *command = |
695 new ChangeEventsCommand(m_model, tr("Paste")); | 727 new ChangeEventsCommand(m_model.untyped, tr("Paste")); |
696 | 728 |
697 double valueMin = 0.0, valueMax = 1.0; | 729 double valueMin = 0.0, valueMax = 1.0; |
698 for (EventVector::const_iterator i = points.begin(); | 730 for (EventVector::const_iterator i = points.begin(); |
699 i != points.end(); ++i) { | 731 i != points.end(); ++i) { |
700 if (i->hasValue()) { | 732 if (i->hasValue()) { |