Mercurial > hg > svgui
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 ¬e) const | 1486 FlexiNoteLayer::updateNoteValueFromPitchCurve(LayerGeometryProvider *v, Event ¬e) 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 ¬e, int x, int y, bool &closeToLeft, bool &closeToRight, bool &closeToTop, bool &closeToBottom) const | 1566 FlexiNoteLayer::getRelativeMousePosition(LayerGeometryProvider *v, Event ¬e, 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(); |