comparison layer/FlexiNoteLayer.cpp @ 1469:11a150e65ee1 by-id

Some work on updating layers for ModelId bits
author Chris Cannam
date Thu, 27 Jun 2019 13:16:25 +0100
parents 8a7c82282fbc
children 696e569ff21b
comparison
equal deleted inserted replaced
1468:de41a11cabc2 1469:11a150e65ee1
51 51
52 #define NOTE_HEIGHT 16 52 #define NOTE_HEIGHT 16
53 53
54 FlexiNoteLayer::FlexiNoteLayer() : 54 FlexiNoteLayer::FlexiNoteLayer() :
55 SingleColourLayer(), 55 SingleColourLayer(),
56 m_model(nullptr),
57 m_editing(false), 56 m_editing(false),
58 m_intelligentActions(true), 57 m_intelligentActions(true),
59 m_dragPointX(0), 58 m_dragPointX(0),
60 m_dragPointY(0), 59 m_dragPointY(0),
61 m_dragStartX(0), 60 m_dragStartX(0),
71 m_scaleMaximum(77) 70 m_scaleMaximum(77)
72 { 71 {
73 } 72 }
74 73
75 void 74 void
76 FlexiNoteLayer::setModel(NoteModel *model) 75 FlexiNoteLayer::setModel(ModelId modelId)
77 { 76 {
78 if (m_model == model) return; 77 if (m_model == modelId) return;
79 m_model = model; 78
79 auto model = ModelById::getAs<NoteModel>(modelId);
80 if (!model) throw std::logic_error("Not a NoteModel");
81
82 m_model = modelId;
80 83
81 connectSignals(m_model); 84 connectSignals(m_model);
82
83 // m_scaleMinimum = 0;
84 // m_scaleMaximum = 0;
85 85
86 emit modelReplaced(); 86 emit modelReplaced();
87 } 87 }
88 88
89 Layer::PropertyList 89 Layer::PropertyList
121 } 121 }
122 122
123 QString 123 QString
124 FlexiNoteLayer::getScaleUnits() const 124 FlexiNoteLayer::getScaleUnits() const
125 { 125 {
126 if (m_model) return m_model->getScaleUnits(); 126 auto model = ModelById::getAs<NoteModel>(m_model);
127 if (model) return model->getScaleUnits();
127 else return ""; 128 else return "";
128 } 129 }
129 130
130 int 131 int
131 FlexiNoteLayer::getPropertyRangeAndValue(const PropertyName &name, 132 FlexiNoteLayer::getPropertyRangeAndValue(const PropertyName &name,
142 val = int(m_verticalScale); 143 val = int(m_verticalScale);
143 144
144 } else if (name == "Scale Units") { 145 } else if (name == "Scale Units") {
145 146
146 if (deflt) *deflt = 0; 147 if (deflt) *deflt = 0;
147 if (m_model) { 148 auto model = ModelById::getAs<NoteModel>(m_model);
149 if (model) {
148 val = UnitDatabase::getInstance()->getUnitId 150 val = UnitDatabase::getInstance()->getUnitId
149 (getScaleUnits()); 151 (getScaleUnits());
150 } 152 }
151 153
152 } else { 154 } else {
177 FlexiNoteLayer::setProperty(const PropertyName &name, int value) 179 FlexiNoteLayer::setProperty(const PropertyName &name, int value)
178 { 180 {
179 if (name == "Vertical Scale") { 181 if (name == "Vertical Scale") {
180 setVerticalScale(VerticalScale(value)); 182 setVerticalScale(VerticalScale(value));
181 } else if (name == "Scale Units") { 183 } else if (name == "Scale Units") {
182 if (m_model) { 184 auto model = ModelById::getAs<NoteModel>(m_model);
183 m_model->setScaleUnits 185 if (model) {
186 model->setScaleUnits
184 (UnitDatabase::getInstance()->getUnitById(value)); 187 (UnitDatabase::getInstance()->getUnitById(value));
185 emit modelChanged(); 188 emit modelChanged();
186 } 189 }
187 } else { 190 } else {
188 return SingleColourLayer::setProperty(name, value); 191 return SingleColourLayer::setProperty(name, value);
213 // unit.startsWith("MIDI") || 216 // unit.startsWith("MIDI") ||
214 // unit.startsWith("midi")) return true; 217 // unit.startsWith("midi")) return true;
215 // return false; 218 // return false;
216 } 219 }
217 220
221 int
222 FlexiNoteLayer::getCompletion(LayerGeometryProvider *) const
223 {
224 auto model = ModelById::get(m_model);
225 if (model) return model->getCompletion();
226 else return 0;
227 }
228
218 bool 229 bool
219 FlexiNoteLayer::getValueExtents(double &min, double &max, 230 FlexiNoteLayer::getValueExtents(double &min, double &max,
220 bool &logarithmic, QString &unit) const 231 bool &logarithmic, QString &unit) const
221 { 232 {
222 if (!m_model) return false; 233 auto model = ModelById::getAs<NoteModel>(m_model);
223 min = m_model->getValueMinimum(); 234 if (!model) return false;
224 max = m_model->getValueMaximum(); 235 min = model->getValueMinimum();
236 max = model->getValueMaximum();
225 237
226 if (shouldConvertMIDIToHz()) { 238 if (shouldConvertMIDIToHz()) {
227 unit = "Hz"; 239 unit = "Hz";
228 min = Pitch::getFrequencyForPitch(int(lrint(min))); 240 min = Pitch::getFrequencyForPitch(int(lrint(min)));
229 max = Pitch::getFrequencyForPitch(int(lrint(max + 1))); 241 max = Pitch::getFrequencyForPitch(int(lrint(max + 1)));
236 } 248 }
237 249
238 bool 250 bool
239 FlexiNoteLayer::getDisplayExtents(double &min, double &max) const 251 FlexiNoteLayer::getDisplayExtents(double &min, double &max) const
240 { 252 {
241 if (!m_model || shouldAutoAlign()) { 253 auto model = ModelById::getAs<NoteModel>(m_model);
254 if (!model || shouldAutoAlign()) {
242 // std::cerr << "No model or shouldAutoAlign()" << std::endl; 255 // std::cerr << "No model or shouldAutoAlign()" << std::endl;
243 return false; 256 return false;
244 } 257 }
245 258
246 if (m_verticalScale == MIDIRangeScale) { 259 if (m_verticalScale == MIDIRangeScale) {
248 max = Pitch::getFrequencyForPitch(127); 261 max = Pitch::getFrequencyForPitch(127);
249 return true; 262 return true;
250 } 263 }
251 264
252 if (m_scaleMinimum == m_scaleMaximum) { 265 if (m_scaleMinimum == m_scaleMaximum) {
253 min = m_model->getValueMinimum(); 266 min = model->getValueMinimum();
254 max = m_model->getValueMaximum(); 267 max = model->getValueMaximum();
255 } else { 268 } else {
256 min = m_scaleMinimum; 269 min = m_scaleMinimum;
257 max = m_scaleMaximum; 270 max = m_scaleMaximum;
258 } 271 }
259 272
270 } 283 }
271 284
272 bool 285 bool
273 FlexiNoteLayer::setDisplayExtents(double min, double max) 286 FlexiNoteLayer::setDisplayExtents(double min, double max)
274 { 287 {
275 if (!m_model) return false; 288 auto model = ModelById::getAs<NoteModel>(m_model);
289 if (!model) return false;
276 290
277 if (min == max) { 291 if (min == max) {
278 if (min == 0.f) { 292 if (min == 0.f) {
279 max = 1.f; 293 max = 1.f;
280 } else { 294 } else {
295 309
296 int 310 int
297 FlexiNoteLayer::getVerticalZoomSteps(int &defaultStep) const 311 FlexiNoteLayer::getVerticalZoomSteps(int &defaultStep) const
298 { 312 {
299 if (shouldAutoAlign()) return 0; 313 if (shouldAutoAlign()) return 0;
300 if (!m_model) return 0; 314 auto model = ModelById::getAs<NoteModel>(m_model);
315 if (!model) return 0;
301 316
302 defaultStep = 0; 317 defaultStep = 0;
303 return 100; 318 return 100;
304 } 319 }
305 320
306 int 321 int
307 FlexiNoteLayer::getCurrentVerticalZoomStep() const 322 FlexiNoteLayer::getCurrentVerticalZoomStep() const
308 { 323 {
309 if (shouldAutoAlign()) return 0; 324 if (shouldAutoAlign()) return 0;
310 if (!m_model) return 0; 325 auto model = ModelById::getAs<NoteModel>(m_model);
326 if (!model) return 0;
311 327
312 RangeMapper *mapper = getNewVerticalZoomRangeMapper(); 328 RangeMapper *mapper = getNewVerticalZoomRangeMapper();
313 if (!mapper) return 0; 329 if (!mapper) return 0;
314 330
315 double dmin, dmax; 331 double dmin, dmax;
326 342
327 void 343 void
328 FlexiNoteLayer::setVerticalZoomStep(int step) 344 FlexiNoteLayer::setVerticalZoomStep(int step)
329 { 345 {
330 if (shouldAutoAlign()) return; 346 if (shouldAutoAlign()) return;
331 if (!m_model) return; 347 auto model = ModelById::getAs<NoteModel>(m_model);
348 if (!model) return;
332 349
333 RangeMapper *mapper = getNewVerticalZoomRangeMapper(); 350 RangeMapper *mapper = getNewVerticalZoomRangeMapper();
334 if (!mapper) return; 351 if (!mapper) return;
335 352
336 double min, max; 353 double min, max;
376 } 393 }
377 394
378 RangeMapper * 395 RangeMapper *
379 FlexiNoteLayer::getNewVerticalZoomRangeMapper() const 396 FlexiNoteLayer::getNewVerticalZoomRangeMapper() const
380 { 397 {
381 if (!m_model) return nullptr; 398 auto model = ModelById::getAs<NoteModel>(m_model);
399 if (!model) return nullptr;
382 400
383 RangeMapper *mapper; 401 RangeMapper *mapper;
384 402
385 double min, max; 403 double min, max;
386 bool logarithmic; 404 bool logarithmic;
399 } 417 }
400 418
401 EventVector 419 EventVector
402 FlexiNoteLayer::getLocalPoints(LayerGeometryProvider *v, int x) const 420 FlexiNoteLayer::getLocalPoints(LayerGeometryProvider *v, int x) const
403 { 421 {
404 if (!m_model) return {}; 422 auto model = ModelById::getAs<NoteModel>(m_model);
423 if (!model) return {};
405 424
406 sv_frame_t frame = v->getFrameForX(x); 425 sv_frame_t frame = v->getFrameForX(x);
407 426
408 EventVector local = m_model->getEventsCovering(frame); 427 EventVector local = model->getEventsCovering(frame);
409 if (!local.empty()) return local; 428 if (!local.empty()) return local;
410 429
411 int fuzz = ViewManager::scalePixelSize(2); 430 int fuzz = ViewManager::scalePixelSize(2);
412 sv_frame_t start = v->getFrameForX(x - fuzz); 431 sv_frame_t start = v->getFrameForX(x - fuzz);
413 sv_frame_t end = v->getFrameForX(x + fuzz); 432 sv_frame_t end = v->getFrameForX(x + fuzz);
414 433
415 local = m_model->getEventsStartingWithin(frame, end - frame); 434 local = model->getEventsStartingWithin(frame, end - frame);
416 if (!local.empty()) return local; 435 if (!local.empty()) return local;
417 436
418 local = m_model->getEventsSpanning(start, frame - start); 437 local = model->getEventsSpanning(start, frame - start);
419 if (!local.empty()) return local; 438 if (!local.empty()) return local;
420 439
421 return {}; 440 return {};
422 } 441 }
423 442
424 bool 443 bool
425 FlexiNoteLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &point) const 444 FlexiNoteLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &point) const
426 { 445 {
427 if (!m_model) return false; 446 auto model = ModelById::getAs<NoteModel>(m_model);
447 if (!model) return false;
428 448
429 sv_frame_t frame = v->getFrameForX(x); 449 sv_frame_t frame = v->getFrameForX(x);
430 450
431 EventVector onPoints = m_model->getEventsCovering(frame); 451 EventVector onPoints = model->getEventsCovering(frame);
432 if (onPoints.empty()) return false; 452 if (onPoints.empty()) return false;
433 453
434 int nearestDistance = -1; 454 int nearestDistance = -1;
435 for (const auto &p: onPoints) { 455 for (const auto &p: onPoints) {
436 int distance = getYForValue(v, p.getValue()) - y; 456 int distance = getYForValue(v, p.getValue()) - y;
446 466
447 bool 467 bool
448 FlexiNoteLayer::getNoteToEdit(LayerGeometryProvider *v, int x, int y, Event &point) const 468 FlexiNoteLayer::getNoteToEdit(LayerGeometryProvider *v, int x, int y, Event &point) const
449 { 469 {
450 // GF: find the note that is closest to the cursor 470 // GF: find the note that is closest to the cursor
451 if (!m_model) return false; 471 auto model = ModelById::getAs<NoteModel>(m_model);
472 if (!model) return false;
452 473
453 sv_frame_t frame = v->getFrameForX(x); 474 sv_frame_t frame = v->getFrameForX(x);
454 475
455 EventVector onPoints = m_model->getEventsCovering(frame); 476 EventVector onPoints = model->getEventsCovering(frame);
456 if (onPoints.empty()) return false; 477 if (onPoints.empty()) return false;
457 478
458 int nearestDistance = -1; 479 int nearestDistance = -1;
459 for (const auto &p: onPoints) { 480 for (const auto &p: onPoints) {
460 int distance = getYForValue(v, p.getValue()) - y; 481 int distance = getYForValue(v, p.getValue()) - y;
471 QString 492 QString
472 FlexiNoteLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const 493 FlexiNoteLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const
473 { 494 {
474 int x = pos.x(); 495 int x = pos.x();
475 496
476 if (!m_model || !m_model->getSampleRate()) return ""; 497 auto model = ModelById::getAs<NoteModel>(m_model);
498 if (!model || !model->getSampleRate()) return "";
477 499
478 EventVector points = getLocalPoints(v, x); 500 EventVector points = getLocalPoints(v, x);
479 501
480 if (points.empty()) { 502 if (points.empty()) {
481 if (!m_model->isReady()) { 503 if (!model->isReady()) {
482 return tr("In progress"); 504 return tr("In progress");
483 } else { 505 } else {
484 return tr("No local points"); 506 return tr("No local points");
485 } 507 }
486 } 508 }
491 for (i = points.begin(); i != points.end(); ++i) { 513 for (i = points.begin(); i != points.end(); ++i) {
492 514
493 int y = getYForValue(v, i->getValue()); 515 int y = getYForValue(v, i->getValue());
494 int h = NOTE_HEIGHT; // GF: larger notes 516 int h = NOTE_HEIGHT; // GF: larger notes
495 517
496 if (m_model->getValueQuantization() != 0.0) { 518 if (model->getValueQuantization() != 0.0) {
497 h = y - getYForValue 519 h = y - getYForValue
498 (v, i->getValue() + m_model->getValueQuantization()); 520 (v, i->getValue() + model->getValueQuantization());
499 if (h < NOTE_HEIGHT) h = NOTE_HEIGHT; 521 if (h < NOTE_HEIGHT) h = NOTE_HEIGHT;
500 } 522 }
501 523
502 // GF: this is not quite correct 524 // GF: this is not quite correct
503 if (pos.y() >= y - 4 && pos.y() <= y + h) { 525 if (pos.y() >= y - 4 && pos.y() <= y + h) {
507 } 529 }
508 530
509 if (i == points.end()) return tr("No local points"); 531 if (i == points.end()) return tr("No local points");
510 532
511 RealTime rt = RealTime::frame2RealTime(note.getFrame(), 533 RealTime rt = RealTime::frame2RealTime(note.getFrame(),
512 m_model->getSampleRate()); 534 model->getSampleRate());
513 RealTime rd = RealTime::frame2RealTime(note.getDuration(), 535 RealTime rd = RealTime::frame2RealTime(note.getDuration(),
514 m_model->getSampleRate()); 536 model->getSampleRate());
515 537
516 QString pitchText; 538 QString pitchText;
517 539
518 if (shouldConvertMIDIToHz()) { 540 if (shouldConvertMIDIToHz()) {
519 541
560 bool 582 bool
561 FlexiNoteLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, 583 FlexiNoteLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
562 int &resolution, 584 int &resolution,
563 SnapType snap) const 585 SnapType snap) const
564 { 586 {
565 if (!m_model) { 587 auto model = ModelById::getAs<NoteModel>(m_model);
588 if (!model) {
566 return Layer::snapToFeatureFrame(v, frame, resolution, snap); 589 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
567 } 590 }
568 591
569 resolution = m_model->getResolution(); 592 resolution = model->getResolution();
570 EventVector points; 593 EventVector points;
571 594
572 if (snap == SnapNeighbouring) { 595 if (snap == SnapNeighbouring) {
573 596
574 points = getLocalPoints(v, v->getXForFrame(frame)); 597 points = getLocalPoints(v, v->getXForFrame(frame));
575 if (points.empty()) return false; 598 if (points.empty()) return false;
576 frame = points.begin()->getFrame(); 599 frame = points.begin()->getFrame();
577 return true; 600 return true;
578 } 601 }
579 602
580 points = m_model->getEventsCovering(frame); 603 points = model->getEventsCovering(frame);
581 sv_frame_t snapped = frame; 604 sv_frame_t snapped = frame;
582 bool found = false; 605 bool found = false;
583 606
584 for (EventVector::const_iterator i = points.begin(); 607 for (EventVector::const_iterator i = points.begin();
585 i != points.end(); ++i) { 608 i != points.end(); ++i) {
648 671
649 if (shouldAutoAlign()) { 672 if (shouldAutoAlign()) {
650 673
651 if (!v->getValueExtents(queryUnits, min, max, log)) { 674 if (!v->getValueExtents(queryUnits, min, max, log)) {
652 675
653 min = m_model->getValueMinimum(); 676 auto model = ModelById::getAs<NoteModel>(m_model);
654 max = m_model->getValueMaximum(); 677 min = model->getValueMinimum();
678 max = model->getValueMaximum();
655 679
656 if (shouldConvertMIDIToHz()) { 680 if (shouldConvertMIDIToHz()) {
657 min = Pitch::getFrequencyForPitch(int(lrint(min))); 681 min = Pitch::getFrequencyForPitch(int(lrint(min)));
658 max = Pitch::getFrequencyForPitch(int(lrint(max + 1))); 682 max = Pitch::getFrequencyForPitch(int(lrint(max + 1)));
659 } 683 }
750 } 774 }
751 775
752 bool 776 bool
753 FlexiNoteLayer::shouldAutoAlign() const 777 FlexiNoteLayer::shouldAutoAlign() const
754 { 778 {
755 if (!m_model) return false;
756 return (m_verticalScale == AutoAlignScale); 779 return (m_verticalScale == AutoAlignScale);
757 } 780 }
758 781
759 void 782 void
760 FlexiNoteLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const 783 FlexiNoteLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
761 { 784 {
762 if (!m_model || !m_model->isOK()) return; 785 auto model = ModelById::getAs<NoteModel>(m_model);
763 786 if (!model || !model->isOK()) return;
764 sv_samplerate_t sampleRate = m_model->getSampleRate(); 787
788 sv_samplerate_t sampleRate = model->getSampleRate();
765 if (!sampleRate) return; 789 if (!sampleRate) return;
766 790
767 // Profiler profiler("FlexiNoteLayer::paint", true); 791 // Profiler profiler("FlexiNoteLayer::paint", true);
768 792
769 int x0 = rect.left(), x1 = rect.right(); 793 int x0 = rect.left(), x1 = rect.right();
770 sv_frame_t frame0 = v->getFrameForX(x0); 794 sv_frame_t frame0 = v->getFrameForX(x0);
771 sv_frame_t frame1 = v->getFrameForX(x1); 795 sv_frame_t frame1 = v->getFrameForX(x1);
772 796
773 EventVector points(m_model->getEventsSpanning(frame0, frame1 - frame0)); 797 EventVector points(model->getEventsSpanning(frame0, frame1 - frame0));
774 if (points.empty()) return; 798 if (points.empty()) return;
775 799
776 paint.setPen(getBaseQColor()); 800 paint.setPen(getBaseQColor());
777 801
778 QColor brushColour(getBaseQColor()); 802 QColor brushColour(getBaseQColor());
779 brushColour.setAlpha(80); 803 brushColour.setAlpha(80);
780 804
781 // SVDEBUG << "FlexiNoteLayer::paint: resolution is " 805 // SVDEBUG << "FlexiNoteLayer::paint: resolution is "
782 // << m_model->getResolution() << " frames" << endl; 806 // << model->getResolution() << " frames" << endl;
783 807
784 double min = m_model->getValueMinimum(); 808 double min = model->getValueMinimum();
785 double max = m_model->getValueMaximum(); 809 double max = model->getValueMaximum();
786 if (max == min) max = min + 1.0; 810 if (max == min) max = min + 1.0;
787 811
788 QPoint localPos; 812 QPoint localPos;
789 Event illuminatePoint(0); 813 Event illuminatePoint(0);
790 bool shouldIlluminate = false; 814 bool shouldIlluminate = false;
808 int x = v->getXForFrame(p.getFrame()); 832 int x = v->getXForFrame(p.getFrame());
809 int y = getYForValue(v, p.getValue()); 833 int y = getYForValue(v, p.getValue());
810 int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x; 834 int w = v->getXForFrame(p.getFrame() + p.getDuration()) - x;
811 int h = NOTE_HEIGHT; //GF: larger notes 835 int h = NOTE_HEIGHT; //GF: larger notes
812 836
813 if (m_model->getValueQuantization() != 0.0) { 837 if (model->getValueQuantization() != 0.0) {
814 h = y - getYForValue(v, p.getValue() + m_model->getValueQuantization()); 838 h = y - getYForValue(v, p.getValue() + model->getValueQuantization());
815 if (h < NOTE_HEIGHT) h = NOTE_HEIGHT; //GF: larger notes 839 if (h < NOTE_HEIGHT) h = NOTE_HEIGHT; //GF: larger notes
816 } 840 }
817 841
818 if (w < 1) w = 1; 842 if (w < 1) w = 1;
819 paint.setPen(getBaseQColor()); 843 paint.setPen(getBaseQColor());
825 paint.drawLine(x+w, -1, x+w, v->getPaintHeight() + 1); 849 paint.drawLine(x+w, -1, x+w, v->getPaintHeight() + 1);
826 850
827 paint.setPen(v->getForeground()); 851 paint.setPen(v->getForeground());
828 852
829 QString vlabel = tr("freq: %1%2") 853 QString vlabel = tr("freq: %1%2")
830 .arg(p.getValue()).arg(m_model->getScaleUnits()); 854 .arg(p.getValue()).arg(model->getScaleUnits());
831 PaintAssistant::drawVisibleText 855 PaintAssistant::drawVisibleText
832 (v, paint, 856 (v, paint,
833 x, 857 x,
834 y - h/2 - 2 - paint.fontMetrics().height() 858 y - h/2 - 2 - paint.fontMetrics().height()
835 - paint.fontMetrics().descent(), 859 - paint.fontMetrics().descent(),
836 vlabel, PaintAssistant::OutlinedText); 860 vlabel, PaintAssistant::OutlinedText);
837 861
838 QString hlabel = tr("dur: %1") 862 QString hlabel = tr("dur: %1")
839 .arg(RealTime::frame2RealTime 863 .arg(RealTime::frame2RealTime
840 (p.getDuration(), m_model->getSampleRate()).toText(true) 864 (p.getDuration(), model->getSampleRate()).toText(true)
841 .c_str()); 865 .c_str());
842 PaintAssistant::drawVisibleText 866 PaintAssistant::drawVisibleText
843 (v, paint, 867 (v, paint,
844 x, 868 x,
845 y - h/2 - paint.fontMetrics().descent() - 2, 869 y - h/2 - paint.fontMetrics().descent() - 2,
867 } 891 }
868 892
869 int 893 int
870 FlexiNoteLayer::getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &paint) const 894 FlexiNoteLayer::getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &paint) const
871 { 895 {
872 if (!m_model || shouldAutoAlign()) { 896 if (shouldAutoAlign()) {
873 return 0; 897 return 0;
874 } else { 898 } else {
875 if (m_verticalScale == LogScale || m_verticalScale == MIDIRangeScale) { 899 if (m_verticalScale == LogScale || m_verticalScale == MIDIRangeScale) {
876 return LogNumericalScale().getWidth(v, paint) + 10; // for piano 900 return LogNumericalScale().getWidth(v, paint) + 10; // for piano
877 } else { 901 } else {
881 } 905 }
882 906
883 void 907 void
884 FlexiNoteLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const 908 FlexiNoteLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const
885 { 909 {
886 if (!m_model || m_model->isEmpty()) return; 910 auto model = ModelById::getAs<NoteModel>(m_model);
911 if (!model || model->isEmpty()) return;
887 912
888 QString unit; 913 QString unit;
889 double min, max; 914 double min, max;
890 bool logarithmic; 915 bool logarithmic;
891 916
921 void 946 void
922 FlexiNoteLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e) 947 FlexiNoteLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e)
923 { 948 {
924 // SVDEBUG << "FlexiNoteLayer::drawStart(" << e->x() << "," << e->y() << ")" << endl; 949 // SVDEBUG << "FlexiNoteLayer::drawStart(" << e->x() << "," << e->y() << ")" << endl;
925 950
926 if (!m_model) return; 951 auto model = ModelById::getAs<NoteModel>(m_model);
952 if (!model) return;
927 953
928 sv_frame_t frame = v->getFrameForX(e->x()); 954 sv_frame_t frame = v->getFrameForX(e->x());
929 if (frame < 0) frame = 0; 955 if (frame < 0) frame = 0;
930 frame = frame / m_model->getResolution() * m_model->getResolution(); 956 frame = frame / model->getResolution() * model->getResolution();
931 957
932 double value = getValueForY(v, e->y()); 958 double value = getValueForY(v, e->y());
933 959
934 m_editingPoint = Event(frame, float(value), 0, 0.8f, tr("New Point")); 960 m_editingPoint = Event(frame, float(value), 0, 0.8f, tr("New Point"));
935 m_originalPoint = m_editingPoint; 961 m_originalPoint = m_editingPoint;
936 962
937 if (m_editingCommand) finish(m_editingCommand); 963 if (m_editingCommand) finish(m_editingCommand);
938 m_editingCommand = new ChangeEventsCommand(m_model, tr("Draw Point")); 964 m_editingCommand = new ChangeEventsCommand<Model>(m_model, tr("Draw Point"));
939 m_editingCommand->add(m_editingPoint); 965 m_editingCommand->add(m_editingPoint);
940 966
941 m_editing = true; 967 m_editing = true;
942 } 968 }
943 969
944 void 970 void
945 FlexiNoteLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e) 971 FlexiNoteLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e)
946 { 972 {
947 // SVDEBUG << "FlexiNoteLayer::drawDrag(" << e->x() << "," << e->y() << ")" << endl; 973 // SVDEBUG << "FlexiNoteLayer::drawDrag(" << e->x() << "," << e->y() << ")" << endl;
948 974
949 if (!m_model || !m_editing) return; 975 auto model = ModelById::getAs<NoteModel>(m_model);
976 if (!model || !m_editing) return;
950 977
951 sv_frame_t frame = v->getFrameForX(e->x()); 978 sv_frame_t frame = v->getFrameForX(e->x());
952 if (frame < 0) frame = 0; 979 if (frame < 0) frame = 0;
953 frame = frame / m_model->getResolution() * m_model->getResolution(); 980 frame = frame / model->getResolution() * model->getResolution();
954 981
955 double newValue = getValueForY(v, e->y()); 982 double newValue = getValueForY(v, e->y());
956 983
957 sv_frame_t newFrame = m_editingPoint.getFrame(); 984 sv_frame_t newFrame = m_editingPoint.getFrame();
958 sv_frame_t newDuration = frame - newFrame; 985 sv_frame_t newDuration = frame - newFrame;
973 1000
974 void 1001 void
975 FlexiNoteLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) 1002 FlexiNoteLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *)
976 { 1003 {
977 // SVDEBUG << "FlexiNoteLayer::drawEnd(" << e->x() << "," << e->y() << ")" << endl; 1004 // SVDEBUG << "FlexiNoteLayer::drawEnd(" << e->x() << "," << e->y() << ")" << endl;
978 if (!m_model || !m_editing) return; 1005 auto model = ModelById::getAs<NoteModel>(m_model);
1006 if (!model || !m_editing) return;
979 finish(m_editingCommand); 1007 finish(m_editingCommand);
980 m_editingCommand = nullptr; 1008 m_editingCommand = nullptr;
981 m_editing = false; 1009 m_editing = false;
982 } 1010 }
983 1011
984 void 1012 void
985 FlexiNoteLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) 1013 FlexiNoteLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e)
986 { 1014 {
987 if (!m_model) return; 1015 auto model = ModelById::getAs<NoteModel>(m_model);
1016 if (!model) return;
988 1017
989 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; 1018 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
990 1019
991 if (m_editingCommand) { 1020 if (m_editingCommand) {
992 finish(m_editingCommand); 1021 finish(m_editingCommand);
1002 } 1031 }
1003 1032
1004 void 1033 void
1005 FlexiNoteLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) 1034 FlexiNoteLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e)
1006 { 1035 {
1007 if (!m_model || !m_editing) return; 1036 if (!m_editing) return;
1008
1009 m_editing = false; 1037 m_editing = false;
1010 1038
1011 Event p(0); 1039 Event p(0);
1012 if (!getPointToDrag(v, e->x(), e->y(), p)) return; 1040 if (!getPointToDrag(v, e->x(), e->y(), p)) return;
1013 if (p.getFrame() != m_editingPoint.getFrame() || p.getValue() != m_editingPoint.getValue()) return; 1041 if (p.getFrame() != m_editingPoint.getFrame() ||
1014 1042 p.getValue() != m_editingPoint.getValue()) return;
1015 m_editingCommand = new ChangeEventsCommand(m_model, tr("Erase Point")); 1043
1044 m_editingCommand = new ChangeEventsCommand<Model>(m_model, tr("Erase Point"));
1016 m_editingCommand->remove(m_editingPoint); 1045 m_editingCommand->remove(m_editingPoint);
1017 finish(m_editingCommand); 1046 finish(m_editingCommand);
1018 m_editingCommand = nullptr; 1047 m_editingCommand = nullptr;
1019 m_editing = false; 1048 m_editing = false;
1020 } 1049 }
1023 FlexiNoteLayer::editStart(LayerGeometryProvider *v, QMouseEvent *e) 1052 FlexiNoteLayer::editStart(LayerGeometryProvider *v, QMouseEvent *e)
1024 { 1053 {
1025 // SVDEBUG << "FlexiNoteLayer::editStart(" << e->x() << "," << e->y() << ")" << endl; 1054 // SVDEBUG << "FlexiNoteLayer::editStart(" << e->x() << "," << e->y() << ")" << endl;
1026 std::cerr << "FlexiNoteLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl; 1055 std::cerr << "FlexiNoteLayer::editStart(" << e->x() << "," << e->y() << ")" << std::endl;
1027 1056
1028 if (!m_model) return; 1057 auto model = ModelById::getAs<NoteModel>(m_model);
1058 if (!model) return;
1029 1059
1030 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; 1060 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
1031 m_originalPoint = m_editingPoint; 1061 m_originalPoint = m_editingPoint;
1032 1062
1033 if (m_editMode == RightBoundary) { 1063 if (m_editMode == RightBoundary) {
1054 m_originalPoint.getDuration() - 1; 1084 m_originalPoint.getDuration() - 1;
1055 1085
1056 m_greatestLeftNeighbourFrame = -1; 1086 m_greatestLeftNeighbourFrame = -1;
1057 m_smallestRightNeighbourFrame = std::numeric_limits<int>::max(); 1087 m_smallestRightNeighbourFrame = std::numeric_limits<int>::max();
1058 1088
1059 EventVector allEvents = m_model->getAllEvents(); 1089 EventVector allEvents = model->getAllEvents();
1060 1090
1061 for (auto currentNote: allEvents) { 1091 for (auto currentNote: allEvents) {
1062 1092
1063 // left boundary 1093 // left boundary
1064 if (currentNote.getFrame() + currentNote.getDuration() - 1 < onset) { 1094 if (currentNote.getFrame() + currentNote.getDuration() - 1 < onset) {
1080 FlexiNoteLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e) 1110 FlexiNoteLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e)
1081 { 1111 {
1082 // SVDEBUG << "FlexiNoteLayer::editDrag(" << e->x() << "," << e->y() << ")" << endl; 1112 // SVDEBUG << "FlexiNoteLayer::editDrag(" << e->x() << "," << e->y() << ")" << endl;
1083 std::cerr << "FlexiNoteLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl; 1113 std::cerr << "FlexiNoteLayer::editDrag(" << e->x() << "," << e->y() << ")" << std::endl;
1084 1114
1085 if (!m_model || !m_editing) return; 1115 auto model = ModelById::getAs<NoteModel>(m_model);
1116 if (!model || !m_editing) return;
1086 1117
1087 int xdist = e->x() - m_dragStartX; 1118 int xdist = e->x() - m_dragStartX;
1088 int ydist = e->y() - m_dragStartY; 1119 int ydist = e->y() - m_dragStartY;
1089 int newx = m_dragPointX + xdist; 1120 int newx = m_dragPointX + xdist;
1090 int newy = m_dragPointY + ydist; 1121 int newy = m_dragPointY + ydist;
1091 1122
1092 sv_frame_t dragFrame = v->getFrameForX(newx); 1123 sv_frame_t dragFrame = v->getFrameForX(newx);
1093 if (dragFrame < 0) dragFrame = 0; 1124 if (dragFrame < 0) dragFrame = 0;
1094 dragFrame = dragFrame / m_model->getResolution() * m_model->getResolution(); 1125 dragFrame = dragFrame / model->getResolution() * model->getResolution();
1095 1126
1096 double value = getValueForY(v, newy); 1127 double value = getValueForY(v, newy);
1097 1128
1098 if (!m_editingCommand) { 1129 if (!m_editingCommand) {
1099 m_editingCommand = new ChangeEventsCommand(m_model, tr("Drag Point")); 1130 m_editingCommand =
1131 new ChangeEventsCommand<Model>(m_model, tr("Drag Point"));
1100 } 1132 }
1101 m_editingCommand->remove(m_editingPoint); 1133 m_editingCommand->remove(m_editingPoint);
1102 1134
1103 std::cerr << "edit mode: " << m_editMode << " intelligent actions = " 1135 std::cerr << "edit mode: " << m_editMode << " intelligent actions = "
1104 << m_intelligentActions << std::endl; 1136 << m_intelligentActions << std::endl;
1180 FlexiNoteLayer::editEnd(LayerGeometryProvider *v, QMouseEvent *e) 1212 FlexiNoteLayer::editEnd(LayerGeometryProvider *v, QMouseEvent *e)
1181 { 1213 {
1182 std::cerr << "FlexiNoteLayer::editEnd(" 1214 std::cerr << "FlexiNoteLayer::editEnd("
1183 << e->x() << "," << e->y() << ")" << std::endl; 1215 << e->x() << "," << e->y() << ")" << std::endl;
1184 1216
1185 if (!m_model || !m_editing) return; 1217 auto model = ModelById::getAs<NoteModel>(m_model);
1218 if (!model || !m_editing) return;
1186 1219
1187 if (m_editingCommand) { 1220 if (m_editingCommand) {
1188 1221
1189 QString newName = m_editingCommand->getName(); 1222 QString newName = m_editingCommand->getName();
1190 1223
1216 } 1249 }
1217 1250
1218 void 1251 void
1219 FlexiNoteLayer::splitStart(LayerGeometryProvider *v, QMouseEvent *e) 1252 FlexiNoteLayer::splitStart(LayerGeometryProvider *v, QMouseEvent *e)
1220 { 1253 {
1254 auto model = ModelById::getAs<NoteModel>(m_model);
1255 if (!model) return;
1256
1221 // GF: note splitting starts (!! remove printing soon) 1257 // GF: note splitting starts (!! remove printing soon)
1222 std::cerr << "splitStart (n.b. editStart will be called later, if the user drags the mouse)" << std::endl; 1258 std::cerr << "splitStart (n.b. editStart will be called later, if the user drags the mouse)" << std::endl;
1223 if (!m_model) return;
1224 1259
1225 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; 1260 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
1226 // m_originalPoint = m_editingPoint; 1261 // m_originalPoint = m_editingPoint;
1227 // 1262 //
1228 // m_dragPointX = v->getXForFrame(m_editingPoint.getFrame()); 1263 // m_dragPointX = v->getXForFrame(m_editingPoint.getFrame());
1239 } 1274 }
1240 1275
1241 void 1276 void
1242 FlexiNoteLayer::splitEnd(LayerGeometryProvider *v, QMouseEvent *e) 1277 FlexiNoteLayer::splitEnd(LayerGeometryProvider *v, QMouseEvent *e)
1243 { 1278 {
1279 auto model = ModelById::getAs<NoteModel>(m_model);
1244 // GF: note splitting ends. (!! remove printing soon) 1280 // GF: note splitting ends. (!! remove printing soon)
1245 std::cerr << "splitEnd" << std::endl; 1281 std::cerr << "splitEnd" << std::endl;
1246 if (!m_model || !m_editing || m_editMode != SplitNote) return; 1282 if (!model || !m_editing || m_editMode != SplitNote) return;
1247 1283
1248 int xdist = e->x() - m_dragStartX; 1284 int xdist = e->x() - m_dragStartX;
1249 int ydist = e->y() - m_dragStartY; 1285 int ydist = e->y() - m_dragStartY;
1250 if (xdist != 0 || ydist != 0) { 1286 if (xdist != 0 || ydist != 0) {
1251 std::cerr << "mouse moved" << std::endl; 1287 std::cerr << "mouse moved" << std::endl;
1264 } 1300 }
1265 1301
1266 void 1302 void
1267 FlexiNoteLayer::splitNotesAt(LayerGeometryProvider *v, sv_frame_t frame, QMouseEvent *e) 1303 FlexiNoteLayer::splitNotesAt(LayerGeometryProvider *v, sv_frame_t frame, QMouseEvent *e)
1268 { 1304 {
1269 EventVector onPoints = m_model->getEventsCovering(frame); 1305 auto model = ModelById::getAs<NoteModel>(m_model);
1306 if (!model) return;
1307
1308 EventVector onPoints = model->getEventsCovering(frame);
1270 if (onPoints.empty()) return; 1309 if (onPoints.empty()) return;
1271 1310
1272 Event note(*onPoints.begin()); 1311 Event note(*onPoints.begin());
1273 1312
1274 ChangeEventsCommand *command = new ChangeEventsCommand 1313 auto command = new ChangeEventsCommand<Model>(m_model, tr("Edit Point"));
1275 (m_model, tr("Edit Point"));
1276 command->remove(note); 1314 command->remove(note);
1277 1315
1278 if (!e || !(e->modifiers() & Qt::ShiftModifier)) { 1316 if (!e || !(e->modifiers() & Qt::ShiftModifier)) {
1279 1317
1280 int gap = 0; // MM: I prefer a gap of 0, but we can decide later 1318 int gap = 0; // MM: I prefer a gap of 0, but we can decide later
1304 } 1342 }
1305 1343
1306 void 1344 void
1307 FlexiNoteLayer::addNote(LayerGeometryProvider *v, QMouseEvent *e) 1345 FlexiNoteLayer::addNote(LayerGeometryProvider *v, QMouseEvent *e)
1308 { 1346 {
1347 auto model = ModelById::getAs<NoteModel>(m_model);
1309 std::cerr << "addNote" << std::endl; 1348 std::cerr << "addNote" << std::endl;
1310 if (!m_model) return; 1349 if (!model) return;
1311 1350
1312 sv_frame_t duration = 10000; 1351 sv_frame_t duration = 10000;
1313 1352
1314 sv_frame_t frame = v->getFrameForX(e->x()); 1353 sv_frame_t frame = v->getFrameForX(e->x());
1315 double value = getValueForY(v, e->y()); 1354 double value = getValueForY(v, e->y());
1316 1355
1317 EventVector noteList = m_model->getAllEvents(); 1356 EventVector noteList = model->getAllEvents();
1318 1357
1319 if (m_intelligentActions) { 1358 if (m_intelligentActions) {
1320 sv_frame_t smallestRightNeighbourFrame = 0; 1359 sv_frame_t smallestRightNeighbourFrame = 0;
1321 for (EventVector::const_iterator i = noteList.begin(); 1360 for (EventVector::const_iterator i = noteList.begin();
1322 i != noteList.end(); ++i) { 1361 i != noteList.end(); ++i) {
1331 duration = (duration > 0) ? duration : 0; 1370 duration = (duration > 0) ? duration : 0;
1332 } 1371 }
1333 } 1372 }
1334 1373
1335 if (!m_intelligentActions || 1374 if (!m_intelligentActions ||
1336 (m_model->getEventsCovering(frame).empty() && duration > 0)) { 1375 (model->getEventsCovering(frame).empty() && duration > 0)) {
1337 Event newNote(frame, float(value), duration, 100.f, tr("new note")); 1376 Event newNote(frame, float(value), duration, 100.f, tr("new note"));
1338 ChangeEventsCommand *command = new ChangeEventsCommand 1377 auto command = new ChangeEventsCommand<Model>(m_model, tr("Add Point"));
1339 (m_model, tr("Add Point"));
1340 command->add(newNote); 1378 command->add(newNote);
1341 finish(command); 1379 finish(command);
1342 } 1380 }
1343 } 1381 }
1344 1382
1345 SparseTimeValueModel * 1383 ModelId
1346 FlexiNoteLayer::getAssociatedPitchModel(LayerGeometryProvider *v) const 1384 FlexiNoteLayer::getAssociatedPitchModel(LayerGeometryProvider *v) const
1347 { 1385 {
1348 // Better than we used to do, but still not very satisfactory 1386 // Better than we used to do, but still not very satisfactory
1349 1387
1350 // cerr << "FlexiNoteLayer::getAssociatedPitchModel()" << endl; 1388 // cerr << "FlexiNoteLayer::getAssociatedPitchModel()" << endl;
1352 for (int i = 0; i < v->getView()->getLayerCount(); ++i) { 1390 for (int i = 0; i < v->getView()->getLayerCount(); ++i) {
1353 Layer *layer = v->getView()->getLayer(i); 1391 Layer *layer = v->getView()->getLayer(i);
1354 if (layer && 1392 if (layer &&
1355 layer->getLayerPresentationName() != "candidate") { 1393 layer->getLayerPresentationName() != "candidate") {
1356 // cerr << "FlexiNoteLayer::getAssociatedPitchModel: looks like our layer is " << layer << endl; 1394 // cerr << "FlexiNoteLayer::getAssociatedPitchModel: looks like our layer is " << layer << endl;
1357 SparseTimeValueModel *model = qobject_cast<SparseTimeValueModel *> 1395 auto modelId = layer->getModel();
1358 (layer->getModel()); 1396 auto model = ModelById::getAs<SparseTimeValueModel>(modelId);
1359 // cerr << "FlexiNoteLayer::getAssociatedPitchModel: and its model is " << model << endl;
1360 if (model && model->getScaleUnits() == "Hz") { 1397 if (model && model->getScaleUnits() == "Hz") {
1361 cerr << "FlexiNoteLayer::getAssociatedPitchModel: it's good, returning " << model << endl; 1398 // cerr << "FlexiNoteLayer::getAssociatedPitchModel: it's good, returning " << model << endl;
1362 return model; 1399 return modelId;
1363 } 1400 }
1364 } 1401 }
1365 } 1402 }
1366 cerr << "FlexiNoteLayer::getAssociatedPitchModel: failed to find a model" << endl; 1403 // cerr << "FlexiNoteLayer::getAssociatedPitchModel: failed to find a model" << endl;
1367 return nullptr; 1404 return {};
1368 } 1405 }
1369 1406
1370 void 1407 void
1371 FlexiNoteLayer::snapSelectedNotesToPitchTrack(LayerGeometryProvider *v, Selection s) 1408 FlexiNoteLayer::snapSelectedNotesToPitchTrack(LayerGeometryProvider *v, Selection s)
1372 { 1409 {
1373 if (!m_model) return; 1410 auto model = ModelById::getAs<NoteModel>(m_model);
1411 if (!model) return;
1374 1412
1375 EventVector points = 1413 EventVector points =
1376 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1414 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1377 1415
1378 ChangeEventsCommand *command = new ChangeEventsCommand 1416 auto command = new ChangeEventsCommand<Model>(m_model, tr("Snap Notes"));
1379 (m_model, tr("Snap Notes"));
1380 1417
1381 cerr << "snapSelectedNotesToPitchTrack: selection is from " << s.getStartFrame() << " to " << s.getEndFrame() << endl; 1418 cerr << "snapSelectedNotesToPitchTrack: selection is from " << s.getStartFrame() << " to " << s.getEndFrame() << endl;
1382 1419
1383 for (EventVector::iterator i = points.begin(); 1420 for (EventVector::iterator i = points.begin();
1384 i != points.end(); ++i) { 1421 i != points.end(); ++i) {
1406 } 1443 }
1407 1444
1408 void 1445 void
1409 FlexiNoteLayer::mergeNotes(LayerGeometryProvider *v, Selection s, bool inclusive) 1446 FlexiNoteLayer::mergeNotes(LayerGeometryProvider *v, Selection s, bool inclusive)
1410 { 1447 {
1448 auto model = ModelById::getAs<NoteModel>(m_model);
1449 if (!model) return;
1450
1411 EventVector points; 1451 EventVector points;
1412 if (inclusive) { 1452 if (inclusive) {
1413 points = m_model->getEventsSpanning(s.getStartFrame(), s.getDuration()); 1453 points = model->getEventsSpanning(s.getStartFrame(), s.getDuration());
1414 } else { 1454 } else {
1415 points = m_model->getEventsWithin(s.getStartFrame(), s.getDuration()); 1455 points = model->getEventsWithin(s.getStartFrame(), s.getDuration());
1416 } 1456 }
1417 1457
1418 EventVector::iterator i = points.begin(); 1458 EventVector::iterator i = points.begin();
1419 if (i == points.end()) return; 1459 if (i == points.end()) return;
1420 1460
1421 ChangeEventsCommand *command = 1461 auto command = new ChangeEventsCommand<Model>(m_model, tr("Merge Notes"));
1422 new ChangeEventsCommand(m_model, tr("Merge Notes"));
1423 1462
1424 Event newNote(*i); 1463 Event newNote(*i);
1425 1464
1426 while (i != points.end()) { 1465 while (i != points.end()) {
1427 1466
1444 } 1483 }
1445 1484
1446 bool 1485 bool
1447 FlexiNoteLayer::updateNoteValueFromPitchCurve(LayerGeometryProvider *v, Event &note) const 1486 FlexiNoteLayer::updateNoteValueFromPitchCurve(LayerGeometryProvider *v, Event &note) const
1448 { 1487 {
1449 SparseTimeValueModel *model = getAssociatedPitchModel(v); 1488 ModelId modelId = getAssociatedPitchModel(v);
1489 auto model = ModelById::getAs<SparseTimeValueModel>(modelId);
1450 if (!model) return false; 1490 if (!model) return false;
1451 1491
1452 std::cerr << model->getTypeName() << std::endl; 1492 std::cerr << model->getTypeName() << std::endl;
1453 1493
1454 EventVector dataPoints = 1494 EventVector dataPoints =
1523 } 1563 }
1524 1564
1525 void 1565 void
1526 FlexiNoteLayer::getRelativeMousePosition(LayerGeometryProvider *v, Event &note, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const 1566 FlexiNoteLayer::getRelativeMousePosition(LayerGeometryProvider *v, Event &note, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const
1527 { 1567 {
1528 // GF: TODO: consoloidate the tolerance values 1568 // GF: TODO: consolidate the tolerance values
1529 if (!m_model) return;
1530 1569
1531 int ctol = 0; 1570 int ctol = 0;
1532 int noteStartX = v->getXForFrame(note.getFrame()); 1571 int noteStartX = v->getXForFrame(note.getFrame());
1533 int noteEndX = v->getXForFrame(note.getFrame() + note.getDuration()); 1572 int noteEndX = v->getXForFrame(note.getFrame() + note.getDuration());
1534 int noteValueY = getYForValue(v,note.getValue()); 1573 int noteValueY = getYForValue(v,note.getValue());
1553 1592
1554 bool 1593 bool
1555 FlexiNoteLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) 1594 FlexiNoteLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e)
1556 { 1595 {
1557 std::cerr << "Opening note editor dialog" << std::endl; 1596 std::cerr << "Opening note editor dialog" << std::endl;
1558 if (!m_model) return false; 1597 auto model = ModelById::getAs<NoteModel>(m_model);
1598 if (!model) return false;
1559 1599
1560 Event note(0); 1600 Event note(0);
1561 if (!getPointToDrag(v, e->x(), e->y(), note)) return false; 1601 if (!getPointToDrag(v, e->x(), e->y(), note)) return false;
1562 1602
1563 // Event note = *points.begin(); 1603 // Event note = *points.begin();
1564 1604
1565 ItemEditDialog *dialog = new ItemEditDialog 1605 ItemEditDialog *dialog = new ItemEditDialog
1566 (m_model->getSampleRate(), 1606 (model->getSampleRate(),
1567 ItemEditDialog::ShowTime | 1607 ItemEditDialog::ShowTime |
1568 ItemEditDialog::ShowDuration | 1608 ItemEditDialog::ShowDuration |
1569 ItemEditDialog::ShowValue | 1609 ItemEditDialog::ShowValue |
1570 ItemEditDialog::ShowText, 1610 ItemEditDialog::ShowText,
1571 getScaleUnits()); 1611 getScaleUnits());
1581 .withFrame(dialog->getFrameTime()) 1621 .withFrame(dialog->getFrameTime())
1582 .withValue(dialog->getValue()) 1622 .withValue(dialog->getValue())
1583 .withDuration(dialog->getFrameDuration()) 1623 .withDuration(dialog->getFrameDuration())
1584 .withLabel(dialog->getText()); 1624 .withLabel(dialog->getText());
1585 1625
1586 ChangeEventsCommand *command = new ChangeEventsCommand 1626 auto command = new ChangeEventsCommand<Model>(m_model, tr("Edit Point"));
1587 (m_model, tr("Edit Point"));
1588 command->remove(note); 1627 command->remove(note);
1589 command->add(newNote); 1628 command->add(newNote);
1590 finish(command); 1629 finish(command);
1591 } 1630 }
1592 1631
1595 } 1634 }
1596 1635
1597 void 1636 void
1598 FlexiNoteLayer::moveSelection(Selection s, sv_frame_t newStartFrame) 1637 FlexiNoteLayer::moveSelection(Selection s, sv_frame_t newStartFrame)
1599 { 1638 {
1600 if (!m_model) return; 1639 auto model = ModelById::getAs<NoteModel>(m_model);
1601 1640 if (!model) return;
1602 ChangeEventsCommand *command = 1641
1603 new ChangeEventsCommand(m_model, tr("Drag Selection")); 1642 auto command = new ChangeEventsCommand<Model>(m_model, tr("Drag Selection"));
1604 1643
1605 EventVector points = 1644 EventVector points =
1606 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1645 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1607 1646
1608 for (Event p: points) { 1647 for (Event p: points) {
1609 command->remove(p); 1648 command->remove(p);
1610 Event moved = p.withFrame(p.getFrame() + 1649 Event moved = p.withFrame(p.getFrame() +
1611 newStartFrame - s.getStartFrame()); 1650 newStartFrame - s.getStartFrame());
1616 } 1655 }
1617 1656
1618 void 1657 void
1619 FlexiNoteLayer::resizeSelection(Selection s, Selection newSize) 1658 FlexiNoteLayer::resizeSelection(Selection s, Selection newSize)
1620 { 1659 {
1621 if (!m_model || !s.getDuration()) return; 1660 auto model = ModelById::getAs<NoteModel>(m_model);
1622 1661 if (!model || !s.getDuration()) return;
1623 ChangeEventsCommand *command = 1662
1624 new ChangeEventsCommand(m_model, tr("Resize Selection")); 1663 auto command = new ChangeEventsCommand<Model>(m_model, tr("Resize Selection"));
1625 1664
1626 EventVector points = 1665 EventVector points =
1627 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1666 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1628 1667
1629 double ratio = double(newSize.getDuration()) / double(s.getDuration()); 1668 double ratio = double(newSize.getDuration()) / double(s.getDuration());
1630 double oldStart = double(s.getStartFrame()); 1669 double oldStart = double(s.getStartFrame());
1631 double newStart = double(newSize.getStartFrame()); 1670 double newStart = double(newSize.getStartFrame());
1632 1671
1646 } 1685 }
1647 1686
1648 void 1687 void
1649 FlexiNoteLayer::deleteSelection(Selection s) 1688 FlexiNoteLayer::deleteSelection(Selection s)
1650 { 1689 {
1651 if (!m_model) return; 1690 auto model = ModelById::getAs<NoteModel>(m_model);
1652 1691 if (!model) return;
1653 ChangeEventsCommand *command = 1692
1654 new ChangeEventsCommand(m_model, tr("Delete Selected Points")); 1693 auto command =
1694 new ChangeEventsCommand<Model>(m_model, tr("Delete Selected Points"));
1655 1695
1656 EventVector points = 1696 EventVector points =
1657 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1697 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1658 1698
1659 for (Event p: points) { 1699 for (Event p: points) {
1660 command->remove(p); 1700 command->remove(p);
1661 } 1701 }
1662 1702
1664 } 1704 }
1665 1705
1666 void 1706 void
1667 FlexiNoteLayer::deleteSelectionInclusive(Selection s) 1707 FlexiNoteLayer::deleteSelectionInclusive(Selection s)
1668 { 1708 {
1669 if (!m_model) return; 1709 auto model = ModelById::getAs<NoteModel>(m_model);
1670 1710 if (!model) return;
1671 ChangeEventsCommand *command = 1711
1672 new ChangeEventsCommand(m_model, tr("Delete Selected Points")); 1712 auto command =
1713 new ChangeEventsCommand<Model>(m_model, tr("Delete Selected Points"));
1673 1714
1674 EventVector points = 1715 EventVector points =
1675 m_model->getEventsSpanning(s.getStartFrame(), s.getDuration()); 1716 model->getEventsSpanning(s.getStartFrame(), s.getDuration());
1676 1717
1677 for (Event p: points) { 1718 for (Event p: points) {
1678 command->remove(p); 1719 command->remove(p);
1679 } 1720 }
1680 1721
1682 } 1723 }
1683 1724
1684 void 1725 void
1685 FlexiNoteLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) 1726 FlexiNoteLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to)
1686 { 1727 {
1687 if (!m_model) return; 1728 auto model = ModelById::getAs<NoteModel>(m_model);
1729 if (!model) return;
1688 1730
1689 EventVector points = 1731 EventVector points =
1690 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1732 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1691 1733
1692 for (Event p: points) { 1734 for (Event p: points) {
1693 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); 1735 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame())));
1694 } 1736 }
1695 } 1737 }
1696 1738
1697 bool 1739 bool
1698 FlexiNoteLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /*frameOffset */, bool /* interactive */) 1740 FlexiNoteLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /*frameOffset */, bool /* interactive */)
1699 { 1741 {
1700 if (!m_model) return false; 1742 auto model = ModelById::getAs<NoteModel>(m_model);
1743 if (!model) return false;
1701 1744
1702 const EventVector &points = from.getPoints(); 1745 const EventVector &points = from.getPoints();
1703 1746
1704 bool realign = false; 1747 bool realign = false;
1705 1748
1718 if (button == QMessageBox::Yes) { 1761 if (button == QMessageBox::Yes) {
1719 realign = true; 1762 realign = true;
1720 } 1763 }
1721 } 1764 }
1722 1765
1723 ChangeEventsCommand *command = 1766 auto command = new ChangeEventsCommand<Model>(m_model, tr("Paste"));
1724 new ChangeEventsCommand(m_model, tr("Paste"));
1725 1767
1726 for (EventVector::const_iterator i = points.begin(); 1768 for (EventVector::const_iterator i = points.begin();
1727 i != points.end(); ++i) { 1769 i != points.end(); ++i) {
1728 1770
1729 sv_frame_t frame = 0; 1771 sv_frame_t frame = 0;
1743 } 1785 }
1744 1786
1745 Event p = *i; 1787 Event p = *i;
1746 Event newPoint = p; 1788 Event newPoint = p;
1747 if (!p.hasValue()) { 1789 if (!p.hasValue()) {
1748 newPoint = newPoint.withValue((m_model->getValueMinimum() + 1790 newPoint = newPoint.withValue((model->getValueMinimum() +
1749 m_model->getValueMaximum()) / 2); 1791 model->getValueMaximum()) / 2);
1750 } 1792 }
1751 if (!p.hasDuration()) { 1793 if (!p.hasDuration()) {
1752 sv_frame_t nextFrame = frame; 1794 sv_frame_t nextFrame = frame;
1753 EventVector::const_iterator j = i; 1795 EventVector::const_iterator j = i;
1754 for (; j != points.end(); ++j) { 1796 for (; j != points.end(); ++j) {
1756 } 1798 }
1757 if (j != points.end()) { 1799 if (j != points.end()) {
1758 nextFrame = j->getFrame(); 1800 nextFrame = j->getFrame();
1759 } 1801 }
1760 if (nextFrame == frame) { 1802 if (nextFrame == frame) {
1761 newPoint = newPoint.withDuration(m_model->getResolution()); 1803 newPoint = newPoint.withDuration(model->getResolution());
1762 } else { 1804 } else {
1763 newPoint = newPoint.withDuration(nextFrame - frame); 1805 newPoint = newPoint.withDuration(nextFrame - frame);
1764 } 1806 }
1765 } 1807 }
1766 1808
1787 Event p = *i; 1829 Event p = *i;
1788 1830
1789 if (lrintf(p.getValue()) == pitch) { 1831 if (lrintf(p.getValue()) == pitch) {
1790 m_pendingNoteOns.erase(i); 1832 m_pendingNoteOns.erase(i);
1791 Event note = p.withDuration(frame - p.getFrame()); 1833 Event note = p.withDuration(frame - p.getFrame());
1792 if (m_model) { 1834 auto c = new ChangeEventsCommand<Model>
1793 ChangeEventsCommand *c = new ChangeEventsCommand 1835 (m_model, tr("Record Note"));
1794 (m_model, tr("Record Note")); 1836 c->add(note);
1795 c->add(note); 1837 // execute and bundle:
1796 // execute and bundle: 1838 CommandHistory::getInstance()->addCommand(c, true, true);
1797 CommandHistory::getInstance()->addCommand(c, true, true);
1798 }
1799 break; 1839 break;
1800 } 1840 }
1801 } 1841 }
1802 } 1842 }
1803 1843
1838 } 1878 }
1839 1879
1840 void 1880 void
1841 FlexiNoteLayer::setVerticalRangeToNoteRange(LayerGeometryProvider *v) 1881 FlexiNoteLayer::setVerticalRangeToNoteRange(LayerGeometryProvider *v)
1842 { 1882 {
1883 auto model = ModelById::getAs<NoteModel>(m_model);
1884 if (!model) return;
1885
1843 double minf = std::numeric_limits<double>::max(); 1886 double minf = std::numeric_limits<double>::max();
1844 double maxf = 0; 1887 double maxf = 0;
1845 bool hasNotes = 0; 1888 bool hasNotes = 0;
1846 EventVector allPoints = m_model->getAllEvents(); 1889 EventVector allPoints = model->getAllEvents();
1847 for (EventVector::const_iterator i = allPoints.begin(); 1890 for (EventVector::const_iterator i = allPoints.begin();
1848 i != allPoints.end(); ++i) { 1891 i != allPoints.end(); ++i) {
1849 hasNotes = 1; 1892 hasNotes = 1;
1850 Event note = *i; 1893 Event note = *i;
1851 if (note.getValue() < minf) minf = note.getValue(); 1894 if (note.getValue() < minf) minf = note.getValue();