comparison layer/FlexiNoteLayer.cpp @ 1486:ac0a8addabcf

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