comparison layer/RegionLayer.cpp @ 1471:f2525e6cbdf1 by-id

More layer updates
author Chris Cannam
date Mon, 01 Jul 2019 14:17:13 +0100
parents 696e569ff21b
children e540aa5d89cd
comparison
equal deleted inserted replaced
1470:696e569ff21b 1471:f2525e6cbdf1
44 #include <iostream> 44 #include <iostream>
45 #include <cmath> 45 #include <cmath>
46 46
47 RegionLayer::RegionLayer() : 47 RegionLayer::RegionLayer() :
48 SingleColourLayer(), 48 SingleColourLayer(),
49 m_model(nullptr),
50 m_editing(false), 49 m_editing(false),
51 m_dragPointX(0), 50 m_dragPointX(0),
52 m_dragPointY(0), 51 m_dragPointY(0),
53 m_dragStartX(0), 52 m_dragStartX(0),
54 m_dragStartY(0), 53 m_dragStartY(0),
70 if (model) return model->getCompletion(); 69 if (model) return model->getCompletion();
71 else return 0; 70 else return 0;
72 } 71 }
73 72
74 void 73 void
75 RegionLayer::setModel(RegionModel *model) 74 RegionLayer::setModel(ModelId modelId)
76 { 75 {
77 if (m_model == model) return; 76 auto oldModel = ModelById::getAs<RegionModel>(m_model);
78 m_model = model; 77 auto newModel = ModelById::getAs<RegionModel>(modelId);
79 78
80 connectSignals(m_model); 79 if (!modelId.isNone() && !newModel) {
81 80 throw std::logic_error("Not a RegionModel");
82 connect(m_model, SIGNAL(modelChanged()), this, SLOT(recalcSpacing())); 81 }
83 recalcSpacing(); 82
84 83 if (m_model == modelId) return;
85 // SVDEBUG << "RegionLayer::setModel(" << model << ")" << endl; 84 m_model = modelId;
86 85
87 if (m_model && m_model->getRDFTypeURI().endsWith("Segment")) { 86 if (newModel) {
88 setPlotStyle(PlotSegmentation); 87
89 } 88 connectSignals(m_model);
90 if (m_model && m_model->getRDFTypeURI().endsWith("Change")) { 89
91 setPlotStyle(PlotSegmentation); 90 connect(newModel.get(), SIGNAL(modelChanged()),
92 } 91 this, SLOT(recalcSpacing()));
93 92
93 recalcSpacing();
94
95 if (newModel->getRDFTypeURI().endsWith("Segment")) {
96 setPlotStyle(PlotSegmentation);
97 }
98 if (newModel->getRDFTypeURI().endsWith("Change")) {
99 setPlotStyle(PlotSegmentation);
100 }
101 }
102
94 emit modelReplaced(); 103 emit modelReplaced();
95 } 104 }
96 105
97 Layer::PropertyList 106 Layer::PropertyList
98 RegionLayer::getProperties() const 107 RegionLayer::getProperties() const
163 val = int(m_verticalScale); 172 val = int(m_verticalScale);
164 173
165 } else if (name == "Scale Units") { 174 } else if (name == "Scale Units") {
166 175
167 if (deflt) *deflt = 0; 176 if (deflt) *deflt = 0;
168 if (m_model) { 177 auto model = ModelById::getAs<RegionModel>(m_model);
178 if (model) {
169 val = UnitDatabase::getInstance()->getUnitId 179 val = UnitDatabase::getInstance()->getUnitId
170 (getScaleUnits()); 180 (model->getScaleUnits());
171 } 181 }
172 182
173 } else { 183 } else {
174 184
175 val = SingleColourLayer::getPropertyRangeAndValue(name, min, max, deflt); 185 val = SingleColourLayer::getPropertyRangeAndValue(name, min, max, deflt);
212 } else if (name == "Plot Type") { 222 } else if (name == "Plot Type") {
213 setPlotStyle(PlotStyle(value)); 223 setPlotStyle(PlotStyle(value));
214 } else if (name == "Vertical Scale") { 224 } else if (name == "Vertical Scale") {
215 setVerticalScale(VerticalScale(value)); 225 setVerticalScale(VerticalScale(value));
216 } else if (name == "Scale Units") { 226 } else if (name == "Scale Units") {
217 if (m_model) { 227 auto model = ModelById::getAs<RegionModel>(m_model);
218 m_model->setScaleUnits 228 if (model) {
229 model->setScaleUnits
219 (UnitDatabase::getInstance()->getUnitById(value)); 230 (UnitDatabase::getInstance()->getUnitById(value));
220 emit modelChanged(); 231 emit modelChanged();
221 } 232 }
222 } else { 233 } else {
223 return SingleColourLayer::setProperty(name, value); 234 return SingleColourLayer::setProperty(name, value);
263 void 274 void
264 RegionLayer::recalcSpacing() 275 RegionLayer::recalcSpacing()
265 { 276 {
266 m_spacingMap.clear(); 277 m_spacingMap.clear();
267 m_distributionMap.clear(); 278 m_distributionMap.clear();
268 if (!m_model) return; 279
280 auto model = ModelById::getAs<RegionModel>(m_model);
281 if (!model) return;
269 282
270 // SVDEBUG << "RegionLayer::recalcSpacing" << endl; 283 // SVDEBUG << "RegionLayer::recalcSpacing" << endl;
271 284
272 EventVector allEvents = m_model->getAllEvents(); 285 EventVector allEvents = model->getAllEvents();
273 for (const Event &e: allEvents) { 286 for (const Event &e: allEvents) {
274 m_distributionMap[e.getValue()]++; 287 m_distributionMap[e.getValue()]++;
275 // SVDEBUG << "RegionLayer::recalcSpacing: value found: " << e.getValue() << " (now have " << m_distributionMap[e.getValue()] << " of this value)" << endl; 288 // SVDEBUG << "RegionLayer::recalcSpacing: value found: " << e.getValue() << " (now have " << m_distributionMap[e.getValue()] << " of this value)" << endl;
276 } 289 }
277 290
286 299
287 bool 300 bool
288 RegionLayer::getValueExtents(double &min, double &max, 301 RegionLayer::getValueExtents(double &min, double &max,
289 bool &logarithmic, QString &unit) const 302 bool &logarithmic, QString &unit) const
290 { 303 {
291 if (!m_model) return false; 304 auto model = ModelById::getAs<RegionModel>(m_model);
292 min = m_model->getValueMinimum(); 305 if (!model) return false;
293 max = m_model->getValueMaximum(); 306 min = model->getValueMinimum();
307 max = model->getValueMaximum();
294 unit = getScaleUnits(); 308 unit = getScaleUnits();
295 309
296 if (m_verticalScale == LogScale) logarithmic = true; 310 if (m_verticalScale == LogScale) logarithmic = true;
297 311
298 return true; 312 return true;
299 } 313 }
300 314
301 bool 315 bool
302 RegionLayer::getDisplayExtents(double &min, double &max) const 316 RegionLayer::getDisplayExtents(double &min, double &max) const
303 { 317 {
304 if (!m_model || 318 auto model = ModelById::getAs<RegionModel>(m_model);
319 if (!model ||
305 m_verticalScale == AutoAlignScale || 320 m_verticalScale == AutoAlignScale ||
306 m_verticalScale == EqualSpaced) return false; 321 m_verticalScale == EqualSpaced) return false;
307 322
308 min = m_model->getValueMinimum(); 323 min = model->getValueMinimum();
309 max = m_model->getValueMaximum(); 324 max = model->getValueMaximum();
310 325
311 return true; 326 return true;
312 } 327 }
313 328
314 EventVector 329 EventVector
315 RegionLayer::getLocalPoints(LayerGeometryProvider *v, int x) const 330 RegionLayer::getLocalPoints(LayerGeometryProvider *v, int x) const
316 { 331 {
317 if (!m_model) return EventVector(); 332 auto model = ModelById::getAs<RegionModel>(m_model);
333 if (!model) return EventVector();
318 334
319 sv_frame_t frame = v->getFrameForX(x); 335 sv_frame_t frame = v->getFrameForX(x);
320 336
321 EventVector local = m_model->getEventsCovering(frame); 337 EventVector local = model->getEventsCovering(frame);
322 if (!local.empty()) return local; 338 if (!local.empty()) return local;
323 339
324 int fuzz = ViewManager::scalePixelSize(2); 340 int fuzz = ViewManager::scalePixelSize(2);
325 sv_frame_t start = v->getFrameForX(x - fuzz); 341 sv_frame_t start = v->getFrameForX(x - fuzz);
326 sv_frame_t end = v->getFrameForX(x + fuzz); 342 sv_frame_t end = v->getFrameForX(x + fuzz);
327 343
328 local = m_model->getEventsStartingWithin(frame, end - frame); 344 local = model->getEventsStartingWithin(frame, end - frame);
329 if (!local.empty()) return local; 345 if (!local.empty()) return local;
330 346
331 local = m_model->getEventsSpanning(start, frame - start); 347 local = model->getEventsSpanning(start, frame - start);
332 if (!local.empty()) return local; 348 if (!local.empty()) return local;
333 349
334 return {}; 350 return {};
335 } 351 }
336 352
337 bool 353 bool
338 RegionLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &point) const 354 RegionLayer::getPointToDrag(LayerGeometryProvider *v, int x, int y, Event &point) const
339 { 355 {
340 if (!m_model) return false; 356 auto model = ModelById::getAs<RegionModel>(m_model);
357 if (!model) return false;
341 358
342 sv_frame_t frame = v->getFrameForX(x); 359 sv_frame_t frame = v->getFrameForX(x);
343 360
344 EventVector onPoints = m_model->getEventsCovering(frame); 361 EventVector onPoints = model->getEventsCovering(frame);
345 if (onPoints.empty()) return false; 362 if (onPoints.empty()) return false;
346 363
347 int nearestDistance = -1; 364 int nearestDistance = -1;
348 for (const auto &p: onPoints) { 365 for (const auto &p: onPoints) {
349 int distance = getYForValue(v, p.getValue()) - y; 366 int distance = getYForValue(v, p.getValue()) - y;
358 } 375 }
359 376
360 QString 377 QString
361 RegionLayer::getLabelPreceding(sv_frame_t frame) const 378 RegionLayer::getLabelPreceding(sv_frame_t frame) const
362 { 379 {
363 if (!m_model) return ""; 380 auto model = ModelById::getAs<RegionModel>(m_model);
364 EventVector points = m_model->getEventsStartingWithin 381 if (!model) return "";
365 (m_model->getStartFrame(), frame - m_model->getStartFrame()); 382 EventVector points = model->getEventsStartingWithin
383 (model->getStartFrame(), frame - model->getStartFrame());
366 if (!points.empty()) { 384 if (!points.empty()) {
367 for (auto i = points.rbegin(); i != points.rend(); ++i) { 385 for (auto i = points.rbegin(); i != points.rend(); ++i) {
368 if (i->getLabel() != QString()) { 386 if (i->getLabel() != QString()) {
369 return i->getLabel(); 387 return i->getLabel();
370 } 388 }
376 QString 394 QString
377 RegionLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const 395 RegionLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const
378 { 396 {
379 int x = pos.x(); 397 int x = pos.x();
380 398
381 if (!m_model || !m_model->getSampleRate()) return ""; 399 auto model = ModelById::getAs<RegionModel>(m_model);
400 if (!model || !model->getSampleRate()) return "";
382 401
383 EventVector points = getLocalPoints(v, x); 402 EventVector points = getLocalPoints(v, x);
384 403
385 if (points.empty()) { 404 if (points.empty()) {
386 if (!m_model->isReady()) { 405 if (!model->isReady()) {
387 return tr("In progress"); 406 return tr("In progress");
388 } else { 407 } else {
389 return tr("No local points"); 408 return tr("No local points");
390 } 409 }
391 } 410 }
399 for (i = points.begin(); i != points.end(); ++i) { 418 for (i = points.begin(); i != points.end(); ++i) {
400 419
401 int y = getYForValue(v, i->getValue()); 420 int y = getYForValue(v, i->getValue());
402 int h = 3; 421 int h = 3;
403 422
404 if (m_model->getValueQuantization() != 0.0) { 423 if (model->getValueQuantization() != 0.0) {
405 h = y - getYForValue 424 h = y - getYForValue
406 (v, i->getValue() + m_model->getValueQuantization()); 425 (v, i->getValue() + model->getValueQuantization());
407 if (h < 3) h = 3; 426 if (h < 3) h = 3;
408 } 427 }
409 428
410 if (pos.y() >= y - h && pos.y() <= y) { 429 if (pos.y() >= y - h && pos.y() <= y) {
411 region = *i; 430 region = *i;
414 } 433 }
415 434
416 if (i == points.end()) return tr("No local points"); 435 if (i == points.end()) return tr("No local points");
417 436
418 RealTime rt = RealTime::frame2RealTime(region.getFrame(), 437 RealTime rt = RealTime::frame2RealTime(region.getFrame(),
419 m_model->getSampleRate()); 438 model->getSampleRate());
420 RealTime rd = RealTime::frame2RealTime(region.getDuration(), 439 RealTime rd = RealTime::frame2RealTime(region.getDuration(),
421 m_model->getSampleRate()); 440 model->getSampleRate());
422 441
423 QString valueText; 442 QString valueText;
424 443
425 valueText = tr("%1 %2").arg(region.getValue()).arg(getScaleUnits()); 444 valueText = tr("%1 %2").arg(region.getValue()).arg(getScaleUnits());
426 445
447 bool 466 bool
448 RegionLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, 467 RegionLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame,
449 int &resolution, 468 int &resolution,
450 SnapType snap) const 469 SnapType snap) const
451 { 470 {
452 if (!m_model) { 471 auto model = ModelById::getAs<RegionModel>(m_model);
472 if (!model) {
453 return Layer::snapToFeatureFrame(v, frame, resolution, snap); 473 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
454 } 474 }
455 475
456 // SnapLeft / SnapRight: return frame of nearest feature in that 476 // SnapLeft / SnapRight: return frame of nearest feature in that
457 // direction no matter how far away 477 // direction no matter how far away
458 // 478 //
459 // SnapNeighbouring: return frame of feature that would be used in 479 // SnapNeighbouring: return frame of feature that would be used in
460 // an editing operation, i.e. closest feature in either direction 480 // an editing operation, i.e. closest feature in either direction
461 // but only if it is "close enough" 481 // but only if it is "close enough"
462 482
463 resolution = m_model->getResolution(); 483 resolution = model->getResolution();
464 484
465 if (snap == SnapNeighbouring) { 485 if (snap == SnapNeighbouring) {
466 EventVector points = getLocalPoints(v, v->getXForFrame(frame)); 486 EventVector points = getLocalPoints(v, v->getXForFrame(frame));
467 if (points.empty()) return false; 487 if (points.empty()) return false;
468 frame = points.begin()->getFrame(); 488 frame = points.begin()->getFrame();
475 // left is closer than the start frame of the next event to the 495 // left is closer than the start frame of the next event to the
476 // right, then we snap to that frame instead. Clear? 496 // right, then we snap to that frame instead. Clear?
477 497
478 Event left; 498 Event left;
479 bool haveLeft = false; 499 bool haveLeft = false;
480 if (m_model->getNearestEventMatching 500 if (model->getNearestEventMatching
481 (frame, [](Event) { return true; }, EventSeries::Backward, left)) { 501 (frame, [](Event) { return true; }, EventSeries::Backward, left)) {
482 haveLeft = true; 502 haveLeft = true;
483 } 503 }
484 504
485 if (snap == SnapLeft) { 505 if (snap == SnapLeft) {
487 return haveLeft; 507 return haveLeft;
488 } 508 }
489 509
490 Event right; 510 Event right;
491 bool haveRight = false; 511 bool haveRight = false;
492 if (m_model->getNearestEventMatching 512 if (model->getNearestEventMatching
493 (frame, [](Event) { return true; }, EventSeries::Forward, right)) { 513 (frame, [](Event) { return true; }, EventSeries::Forward, right)) {
494 haveRight = true; 514 haveRight = true;
495 } 515 }
496 516
497 if (haveLeft) { 517 if (haveLeft) {
521 bool 541 bool
522 RegionLayer::snapToSimilarFeature(LayerGeometryProvider *v, sv_frame_t &frame, 542 RegionLayer::snapToSimilarFeature(LayerGeometryProvider *v, sv_frame_t &frame,
523 int &resolution, 543 int &resolution,
524 SnapType snap) const 544 SnapType snap) const
525 { 545 {
526 if (!m_model) { 546 auto model = ModelById::getAs<RegionModel>(m_model);
547 if (!model) {
527 return Layer::snapToSimilarFeature(v, frame, resolution, snap); 548 return Layer::snapToSimilarFeature(v, frame, resolution, snap);
528 } 549 }
529 550
530 // snap is only permitted to be SnapLeft or SnapRight here. We 551 // snap is only permitted to be SnapLeft or SnapRight here. We
531 // don't do the same trick as in snapToFeatureFrame, of snapping 552 // don't do the same trick as in snapToFeatureFrame, of snapping
532 // to the end of a feature sometimes. 553 // to the end of a feature sometimes.
533 554
534 resolution = m_model->getResolution(); 555 resolution = model->getResolution();
535 556
536 Event ref; 557 Event ref;
537 Event e; 558 Event e;
538 float matchvalue; 559 float matchvalue;
539 bool found; 560 bool found;
540 561
541 found = m_model->getNearestEventMatching 562 found = model->getNearestEventMatching
542 (frame, [](Event) { return true; }, EventSeries::Backward, ref); 563 (frame, [](Event) { return true; }, EventSeries::Backward, ref);
543 564
544 if (!found) { 565 if (!found) {
545 return false; 566 return false;
546 } 567 }
547 568
548 matchvalue = ref.getValue(); 569 matchvalue = ref.getValue();
549 570
550 found = m_model->getNearestEventMatching 571 found = model->getNearestEventMatching
551 (frame, 572 (frame,
552 [matchvalue](Event e) { 573 [matchvalue](Event e) {
553 double epsilon = 0.0001; 574 double epsilon = 0.0001;
554 return fabs(e.getValue() - matchvalue) < epsilon; 575 return fabs(e.getValue() - matchvalue) < epsilon;
555 }, 576 },
565 } 586 }
566 587
567 QString 588 QString
568 RegionLayer::getScaleUnits() const 589 RegionLayer::getScaleUnits() const
569 { 590 {
570 if (m_model) return m_model->getScaleUnits(); 591 auto model = ModelById::getAs<RegionModel>(m_model);
592 if (model) return model->getScaleUnits();
571 else return ""; 593 else return "";
572 } 594 }
573 595
574 void 596 void
575 RegionLayer::getScaleExtents(LayerGeometryProvider *v, double &min, double &max, bool &log) const 597 RegionLayer::getScaleExtents(LayerGeometryProvider *v, double &min, double &max, bool &log) const
576 { 598 {
577 min = 0.0; 599 min = 0.0;
578 max = 0.0; 600 max = 0.0;
579 log = false; 601 log = false;
580 602
603 auto model = ModelById::getAs<RegionModel>(m_model);
604 if (!model) return;
605
581 QString queryUnits; 606 QString queryUnits;
582 queryUnits = getScaleUnits(); 607 queryUnits = getScaleUnits();
583 608
584 if (m_verticalScale == AutoAlignScale) { 609 if (m_verticalScale == AutoAlignScale) {
585 610
586 if (!v->getValueExtents(queryUnits, min, max, log)) { 611 if (!v->getValueExtents(queryUnits, min, max, log)) {
587 612
588 min = m_model->getValueMinimum(); 613 min = model->getValueMinimum();
589 max = m_model->getValueMaximum(); 614 max = model->getValueMaximum();
590 615
591 // cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << endl; 616 // cerr << "RegionLayer[" << this << "]::getScaleExtents: min = " << min << ", max = " << max << ", log = " << log << endl;
592 617
593 } else if (log) { 618 } else if (log) {
594 619
609 // cerr << "RegionLayer[" << this << "]::getScaleExtents: equal spaced; min = " << min << ", max = " << max << ", log = " << log << endl; 634 // cerr << "RegionLayer[" << this << "]::getScaleExtents: equal spaced; min = " << min << ", max = " << max << ", log = " << log << endl;
610 } 635 }
611 636
612 } else { 637 } else {
613 638
614 min = m_model->getValueMinimum(); 639 min = model->getValueMinimum();
615 max = m_model->getValueMaximum(); 640 max = model->getValueMaximum();
616 641
617 if (m_verticalScale == LogScale) { 642 if (m_verticalScale == LogScale) {
618 LogRange::mapRange(min, max); 643 LogRange::mapRange(min, max);
619 log = true; 644 log = true;
620 } 645 }
814 } 839 }
815 840
816 void 841 void
817 RegionLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const 842 RegionLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
818 { 843 {
819 if (!m_model || !m_model->isOK()) return; 844 auto model = ModelById::getAs<RegionModel>(m_model);
820 845 if (!model || !model->isOK()) return;
821 sv_samplerate_t sampleRate = m_model->getSampleRate(); 846
847 sv_samplerate_t sampleRate = model->getSampleRate();
822 if (!sampleRate) return; 848 if (!sampleRate) return;
823 849
824 // Profiler profiler("RegionLayer::paint", true); 850 // Profiler profiler("RegionLayer::paint", true);
825 851
826 int x0 = rect.left() - 40, x1 = rect.right(); 852 int x0 = rect.left() - 40, x1 = rect.right();
827 853
828 sv_frame_t wholeFrame0 = v->getFrameForX(0); 854 sv_frame_t wholeFrame0 = v->getFrameForX(0);
829 sv_frame_t wholeFrame1 = v->getFrameForX(v->getPaintWidth()); 855 sv_frame_t wholeFrame1 = v->getFrameForX(v->getPaintWidth());
830 856
831 EventVector points(m_model->getEventsSpanning(wholeFrame0, 857 EventVector points(model->getEventsSpanning(wholeFrame0,
832 wholeFrame1 - wholeFrame0)); 858 wholeFrame1 - wholeFrame0));
833 if (points.empty()) return; 859 if (points.empty()) return;
834 860
835 paint.setPen(getBaseQColor()); 861 paint.setPen(getBaseQColor());
836 862
837 QColor brushColour(getBaseQColor()); 863 QColor brushColour(getBaseQColor());
838 brushColour.setAlpha(80); 864 brushColour.setAlpha(80);
839 865
840 // SVDEBUG << "RegionLayer::paint: resolution is " 866 // SVDEBUG << "RegionLayer::paint: resolution is "
841 // << m_model->getResolution() << " frames" << endl; 867 // << model->getResolution() << " frames" << endl;
842 868
843 double min = m_model->getValueMinimum(); 869 double min = model->getValueMinimum();
844 double max = m_model->getValueMaximum(); 870 double max = model->getValueMaximum();
845 if (max == min) max = min + 1.0; 871 if (max == min) max = min + 1.0;
846 872
847 QPoint localPos; 873 QPoint localPos;
848 Event illuminatePoint(0); 874 Event illuminatePoint(0);
849 bool shouldIlluminate = false; 875 bool shouldIlluminate = false;
884 const Event &q(*j); 910 const Event &q(*j);
885 int nx = v->getXForFrame(q.getFrame()); 911 int nx = v->getXForFrame(q.getFrame());
886 if (nx < ex) ex = nx; 912 if (nx < ex) ex = nx;
887 } 913 }
888 914
889 if (m_model->getValueQuantization() != 0.0) { 915 if (model->getValueQuantization() != 0.0) {
890 h = y - getYForValue 916 h = y - getYForValue
891 (v, p.getValue() + m_model->getValueQuantization()); 917 (v, p.getValue() + model->getValueQuantization());
892 if (h < 3) h = 3; 918 if (h < 3) h = 3;
893 } 919 }
894 920
895 if (w < 1) w = 1; 921 if (w < 1) w = 1;
896 922
922 948
923 if (shouldIlluminate && illuminatePoint == p) { 949 if (shouldIlluminate && illuminatePoint == p) {
924 950
925 paint.setPen(v->getForeground()); 951 paint.setPen(v->getForeground());
926 paint.setBrush(v->getForeground()); 952 paint.setBrush(v->getForeground());
953
954 // Qt 5.13 deprecates QFontMetrics::width(), but its suggested
955 // replacement (horizontalAdvance) was only added in Qt 5.11
956 // which is too new for us
957 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
927 958
928 QString vlabel = 959 QString vlabel =
929 QString("%1%2").arg(p.getValue()).arg(getScaleUnits()); 960 QString("%1%2").arg(p.getValue()).arg(getScaleUnits());
930 PaintAssistant::drawVisibleText(v, paint, 961 PaintAssistant::drawVisibleText(v, paint,
931 x - paint.fontMetrics().width(vlabel) - gap, 962 x - paint.fontMetrics().width(vlabel) - gap,
932 y + paint.fontMetrics().height()/2 963 y + paint.fontMetrics().height()/2
933 - paint.fontMetrics().descent(), 964 - paint.fontMetrics().descent(),
934 vlabel, PaintAssistant::OutlinedText); 965 vlabel, PaintAssistant::OutlinedText);
935 966
936 QString hlabel = RealTime::frame2RealTime 967 QString hlabel = RealTime::frame2RealTime
937 (p.getFrame(), m_model->getSampleRate()).toText(true).c_str(); 968 (p.getFrame(), model->getSampleRate()).toText(true).c_str();
938 PaintAssistant::drawVisibleText(v, paint, 969 PaintAssistant::drawVisibleText(v, paint,
939 x, 970 x,
940 y - h/2 - paint.fontMetrics().descent() - gap, 971 y - h/2 - paint.fontMetrics().descent() - gap,
941 hlabel, PaintAssistant::OutlinedText); 972 hlabel, PaintAssistant::OutlinedText);
942 } 973 }
1015 } 1046 }
1016 1047
1017 int 1048 int
1018 RegionLayer::getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &paint) const 1049 RegionLayer::getVerticalScaleWidth(LayerGeometryProvider *v, bool, QPainter &paint) const
1019 { 1050 {
1020 if (!m_model || 1051 auto model = ModelById::getAs<RegionModel>(m_model);
1052 if (!model ||
1021 m_verticalScale == AutoAlignScale || 1053 m_verticalScale == AutoAlignScale ||
1022 m_verticalScale == EqualSpaced) { 1054 m_verticalScale == EqualSpaced) {
1023 return 0; 1055 return 0;
1024 } else if (m_plotStyle == PlotSegmentation) { 1056 } else if (m_plotStyle == PlotSegmentation) {
1025 if (m_verticalScale == LogScale) { 1057 if (m_verticalScale == LogScale) {
1037 } 1069 }
1038 1070
1039 void 1071 void
1040 RegionLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const 1072 RegionLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const
1041 { 1073 {
1042 if (!m_model || m_model->isEmpty()) return; 1074 auto model = ModelById::getAs<RegionModel>(m_model);
1075 if (!model || model->isEmpty()) return;
1043 1076
1044 QString unit; 1077 QString unit;
1045 double min, max; 1078 double min, max;
1046 bool logarithmic; 1079 bool logarithmic;
1047 1080
1080 } 1113 }
1081 1114
1082 void 1115 void
1083 RegionLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e) 1116 RegionLayer::drawStart(LayerGeometryProvider *v, QMouseEvent *e)
1084 { 1117 {
1085 if (!m_model) return; 1118 auto model = ModelById::getAs<RegionModel>(m_model);
1119 if (!model) return;
1086 1120
1087 sv_frame_t frame = v->getFrameForX(e->x()); 1121 sv_frame_t frame = v->getFrameForX(e->x());
1088 if (frame < 0) frame = 0; 1122 if (frame < 0) frame = 0;
1089 frame = frame / m_model->getResolution() * m_model->getResolution(); 1123 frame = frame / model->getResolution() * model->getResolution();
1090 1124
1091 double value = getValueForY(v, e->y()); 1125 double value = getValueForY(v, e->y());
1092 1126
1093 m_editingPoint = Event(frame, float(value), 0, ""); 1127 m_editingPoint = Event(frame, float(value), 0, "");
1094 m_originalPoint = m_editingPoint; 1128 m_originalPoint = m_editingPoint;
1095 1129
1096 if (m_editingCommand) finish(m_editingCommand); 1130 if (m_editingCommand) finish(m_editingCommand);
1097 m_editingCommand = new ChangeEventsCommand(m_model, 1131 m_editingCommand = new ChangeEventsCommand(m_model.untyped, tr("Draw Region"));
1098 tr("Draw Region"));
1099 m_editingCommand->add(m_editingPoint); 1132 m_editingCommand->add(m_editingPoint);
1100 1133
1101 recalcSpacing(); 1134 recalcSpacing();
1102 1135
1103 m_editing = true; 1136 m_editing = true;
1104 } 1137 }
1105 1138
1106 void 1139 void
1107 RegionLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e) 1140 RegionLayer::drawDrag(LayerGeometryProvider *v, QMouseEvent *e)
1108 { 1141 {
1109 if (!m_model || !m_editing) return; 1142 auto model = ModelById::getAs<RegionModel>(m_model);
1143 if (!model || !m_editing) return;
1110 1144
1111 sv_frame_t frame = v->getFrameForX(e->x()); 1145 sv_frame_t frame = v->getFrameForX(e->x());
1112 if (frame < 0) frame = 0; 1146 if (frame < 0) frame = 0;
1113 frame = frame / m_model->getResolution() * m_model->getResolution(); 1147 frame = frame / model->getResolution() * model->getResolution();
1114 1148
1115 double newValue = m_editingPoint.getValue(); 1149 double newValue = m_editingPoint.getValue();
1116 if (m_verticalScale != EqualSpaced) newValue = getValueForY(v, e->y()); 1150 if (m_verticalScale != EqualSpaced) newValue = getValueForY(v, e->y());
1117 1151
1118 sv_frame_t newFrame = m_editingPoint.getFrame(); 1152 sv_frame_t newFrame = m_editingPoint.getFrame();
1135 } 1169 }
1136 1170
1137 void 1171 void
1138 RegionLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) 1172 RegionLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *)
1139 { 1173 {
1140 if (!m_model || !m_editing) return; 1174 auto model = ModelById::getAs<RegionModel>(m_model);
1175 if (!model || !m_editing) return;
1141 finish(m_editingCommand); 1176 finish(m_editingCommand);
1142 m_editingCommand = nullptr; 1177 m_editingCommand = nullptr;
1143 m_editing = false; 1178 m_editing = false;
1144 1179
1145 recalcSpacing(); 1180 recalcSpacing();
1146 } 1181 }
1147 1182
1148 void 1183 void
1149 RegionLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) 1184 RegionLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e)
1150 { 1185 {
1151 if (!m_model) return; 1186 auto model = ModelById::getAs<RegionModel>(m_model);
1187 if (!model) return;
1152 1188
1153 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return; 1189 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) return;
1154 1190
1155 if (m_editingCommand) { 1191 if (m_editingCommand) {
1156 finish(m_editingCommand); 1192 finish(m_editingCommand);
1167 } 1203 }
1168 1204
1169 void 1205 void
1170 RegionLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e) 1206 RegionLayer::eraseEnd(LayerGeometryProvider *v, QMouseEvent *e)
1171 { 1207 {
1172 if (!m_model || !m_editing) return; 1208 auto model = ModelById::getAs<RegionModel>(m_model);
1209 if (!model || !m_editing) return;
1173 1210
1174 m_editing = false; 1211 m_editing = false;
1175 1212
1176 Event p(0); 1213 Event p(0);
1177 if (!getPointToDrag(v, e->x(), e->y(), p)) return; 1214 if (!getPointToDrag(v, e->x(), e->y(), p)) return;
1178 if (p.getFrame() != m_editingPoint.getFrame() || 1215 if (p.getFrame() != m_editingPoint.getFrame() ||
1179 p.getValue() != m_editingPoint.getValue()) return; 1216 p.getValue() != m_editingPoint.getValue()) return;
1180 1217
1181 m_editingCommand = new ChangeEventsCommand 1218 m_editingCommand = new ChangeEventsCommand
1182 (m_model, tr("Erase Region")); 1219 (m_model.untyped, tr("Erase Region"));
1183 1220
1184 m_editingCommand->remove(m_editingPoint); 1221 m_editingCommand->remove(m_editingPoint);
1185 1222
1186 finish(m_editingCommand); 1223 finish(m_editingCommand);
1187 m_editingCommand = nullptr; 1224 m_editingCommand = nullptr;
1190 } 1227 }
1191 1228
1192 void 1229 void
1193 RegionLayer::editStart(LayerGeometryProvider *v, QMouseEvent *e) 1230 RegionLayer::editStart(LayerGeometryProvider *v, QMouseEvent *e)
1194 { 1231 {
1195 if (!m_model) return; 1232 auto model = ModelById::getAs<RegionModel>(m_model);
1233 if (!model) return;
1196 1234
1197 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) { 1235 if (!getPointToDrag(v, e->x(), e->y(), m_editingPoint)) {
1198 return; 1236 return;
1199 } 1237 }
1200 1238
1215 } 1253 }
1216 1254
1217 void 1255 void
1218 RegionLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e) 1256 RegionLayer::editDrag(LayerGeometryProvider *v, QMouseEvent *e)
1219 { 1257 {
1220 if (!m_model || !m_editing) return; 1258 auto model = ModelById::getAs<RegionModel>(m_model);
1259 if (!model || !m_editing) return;
1221 1260
1222 int xdist = e->x() - m_dragStartX; 1261 int xdist = e->x() - m_dragStartX;
1223 int ydist = e->y() - m_dragStartY; 1262 int ydist = e->y() - m_dragStartY;
1224 int newx = m_dragPointX + xdist; 1263 int newx = m_dragPointX + xdist;
1225 int newy = m_dragPointY + ydist; 1264 int newy = m_dragPointY + ydist;
1226 1265
1227 sv_frame_t frame = v->getFrameForX(newx); 1266 sv_frame_t frame = v->getFrameForX(newx);
1228 if (frame < 0) frame = 0; 1267 if (frame < 0) frame = 0;
1229 frame = frame / m_model->getResolution() * m_model->getResolution(); 1268 frame = frame / model->getResolution() * model->getResolution();
1230 1269
1231 // Do not bisect between two values, if one of those values is 1270 // Do not bisect between two values, if one of those values is
1232 // that of the point we're actually moving ... 1271 // that of the point we're actually moving ...
1233 int avoid = m_spacingMap[m_editingPoint.getValue()]; 1272 int avoid = m_spacingMap[m_editingPoint.getValue()];
1234 1273
1236 if (m_distributionMap[m_editingPoint.getValue()] > 1) avoid = -1; 1275 if (m_distributionMap[m_editingPoint.getValue()] > 1) avoid = -1;
1237 1276
1238 double value = getValueForY(v, newy, avoid); 1277 double value = getValueForY(v, newy, avoid);
1239 1278
1240 if (!m_editingCommand) { 1279 if (!m_editingCommand) {
1241 m_editingCommand = new ChangeEventsCommand(m_model, 1280 m_editingCommand = new ChangeEventsCommand(m_model.untyped,
1242 tr("Drag Region")); 1281 tr("Drag Region"));
1243 } 1282 }
1244 1283
1245 m_editingCommand->remove(m_editingPoint); 1284 m_editingCommand->remove(m_editingPoint);
1246 m_editingPoint = m_editingPoint 1285 m_editingPoint = m_editingPoint
1251 } 1290 }
1252 1291
1253 void 1292 void
1254 RegionLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) 1293 RegionLayer::editEnd(LayerGeometryProvider *, QMouseEvent *)
1255 { 1294 {
1256 if (!m_model || !m_editing) return; 1295 auto model = ModelById::getAs<RegionModel>(m_model);
1296 if (!model || !m_editing) return;
1257 1297
1258 if (m_editingCommand) { 1298 if (m_editingCommand) {
1259 1299
1260 QString newName = m_editingCommand->getName(); 1300 QString newName = m_editingCommand->getName();
1261 1301
1279 } 1319 }
1280 1320
1281 bool 1321 bool
1282 RegionLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) 1322 RegionLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e)
1283 { 1323 {
1284 if (!m_model) return false; 1324 auto model = ModelById::getAs<RegionModel>(m_model);
1325 if (!model) return false;
1285 1326
1286 Event region(0); 1327 Event region(0);
1287 if (!getPointToDrag(v, e->x(), e->y(), region)) return false; 1328 if (!getPointToDrag(v, e->x(), e->y(), region)) return false;
1288 1329
1289 ItemEditDialog *dialog = new ItemEditDialog 1330 ItemEditDialog *dialog = new ItemEditDialog
1290 (m_model->getSampleRate(), 1331 (model->getSampleRate(),
1291 ItemEditDialog::ShowTime | 1332 ItemEditDialog::ShowTime |
1292 ItemEditDialog::ShowDuration | 1333 ItemEditDialog::ShowDuration |
1293 ItemEditDialog::ShowValue | 1334 ItemEditDialog::ShowValue |
1294 ItemEditDialog::ShowText, 1335 ItemEditDialog::ShowText,
1295 getScaleUnits()); 1336 getScaleUnits());
1306 .withValue(dialog->getValue()) 1347 .withValue(dialog->getValue())
1307 .withDuration(dialog->getFrameDuration()) 1348 .withDuration(dialog->getFrameDuration())
1308 .withLabel(dialog->getText()); 1349 .withLabel(dialog->getText());
1309 1350
1310 ChangeEventsCommand *command = new ChangeEventsCommand 1351 ChangeEventsCommand *command = new ChangeEventsCommand
1311 (m_model, tr("Edit Region")); 1352 (m_model.untyped, tr("Edit Region"));
1312 command->remove(region); 1353 command->remove(region);
1313 command->add(newRegion); 1354 command->add(newRegion);
1314 finish(command); 1355 finish(command);
1315 } 1356 }
1316 1357
1320 } 1361 }
1321 1362
1322 void 1363 void
1323 RegionLayer::moveSelection(Selection s, sv_frame_t newStartFrame) 1364 RegionLayer::moveSelection(Selection s, sv_frame_t newStartFrame)
1324 { 1365 {
1325 if (!m_model) return; 1366 auto model = ModelById::getAs<RegionModel>(m_model);
1367 if (!model) return;
1326 1368
1327 ChangeEventsCommand *command = 1369 ChangeEventsCommand *command =
1328 new ChangeEventsCommand(m_model, tr("Drag Selection")); 1370 new ChangeEventsCommand(m_model.untyped, tr("Drag Selection"));
1329 1371
1330 EventVector points = 1372 EventVector points =
1331 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1373 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1332 1374
1333 for (EventVector::iterator i = points.begin(); 1375 for (EventVector::iterator i = points.begin();
1334 i != points.end(); ++i) { 1376 i != points.end(); ++i) {
1335 1377
1336 Event newPoint = (*i) 1378 Event newPoint = (*i)
1344 } 1386 }
1345 1387
1346 void 1388 void
1347 RegionLayer::resizeSelection(Selection s, Selection newSize) 1389 RegionLayer::resizeSelection(Selection s, Selection newSize)
1348 { 1390 {
1349 if (!m_model || !s.getDuration()) return; 1391 auto model = ModelById::getAs<RegionModel>(m_model);
1392 if (!model || !s.getDuration()) return;
1350 1393
1351 ChangeEventsCommand *command = 1394 ChangeEventsCommand *command =
1352 new ChangeEventsCommand(m_model, tr("Resize Selection")); 1395 new ChangeEventsCommand(m_model.untyped, tr("Resize Selection"));
1353 1396
1354 EventVector points = 1397 EventVector points =
1355 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1398 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1356 1399
1357 double ratio = double(newSize.getDuration()) / double(s.getDuration()); 1400 double ratio = double(newSize.getDuration()) / double(s.getDuration());
1358 double oldStart = double(s.getStartFrame()); 1401 double oldStart = double(s.getStartFrame());
1359 double newStart = double(newSize.getStartFrame()); 1402 double newStart = double(newSize.getStartFrame());
1360 1403
1375 } 1418 }
1376 1419
1377 void 1420 void
1378 RegionLayer::deleteSelection(Selection s) 1421 RegionLayer::deleteSelection(Selection s)
1379 { 1422 {
1380 if (!m_model) return; 1423 auto model = ModelById::getAs<RegionModel>(m_model);
1424 if (!model) return;
1381 1425
1382 ChangeEventsCommand *command = 1426 ChangeEventsCommand *command =
1383 new ChangeEventsCommand(m_model, tr("Delete Selected Points")); 1427 new ChangeEventsCommand(m_model.untyped, tr("Delete Selected Points"));
1384 1428
1385 EventVector points = 1429 EventVector points =
1386 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1430 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1387 1431
1388 for (EventVector::iterator i = points.begin(); 1432 for (EventVector::iterator i = points.begin();
1389 i != points.end(); ++i) { 1433 i != points.end(); ++i) {
1390 1434
1391 if (s.contains(i->getFrame())) { 1435 if (s.contains(i->getFrame())) {
1398 } 1442 }
1399 1443
1400 void 1444 void
1401 RegionLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) 1445 RegionLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to)
1402 { 1446 {
1403 if (!m_model) return; 1447 auto model = ModelById::getAs<RegionModel>(m_model);
1448 if (!model) return;
1404 1449
1405 EventVector points = 1450 EventVector points =
1406 m_model->getEventsStartingWithin(s.getStartFrame(), s.getDuration()); 1451 model->getEventsStartingWithin(s.getStartFrame(), s.getDuration());
1407 1452
1408 for (Event p: points) { 1453 for (Event p: points) {
1409 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame()))); 1454 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame())));
1410 } 1455 }
1411 } 1456 }
1412 1457
1413 bool 1458 bool
1414 RegionLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */, bool /* interactive */) 1459 RegionLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */, bool /* interactive */)
1415 { 1460 {
1416 if (!m_model) return false; 1461 auto model = ModelById::getAs<RegionModel>(m_model);
1462 if (!model) return false;
1417 1463
1418 const EventVector &points = from.getPoints(); 1464 const EventVector &points = from.getPoints();
1419 1465
1420 bool realign = false; 1466 bool realign = false;
1421 1467
1435 realign = true; 1481 realign = true;
1436 } 1482 }
1437 } 1483 }
1438 1484
1439 ChangeEventsCommand *command = 1485 ChangeEventsCommand *command =
1440 new ChangeEventsCommand(m_model, tr("Paste")); 1486 new ChangeEventsCommand(m_model.untyped, tr("Paste"));
1441 1487
1442 for (EventVector::const_iterator i = points.begin(); 1488 for (EventVector::const_iterator i = points.begin();
1443 i != points.end(); ++i) { 1489 i != points.end(); ++i) {
1444 1490
1445 sv_frame_t frame = 0; 1491 sv_frame_t frame = 0;
1459 } 1505 }
1460 1506
1461 Event p = *i; 1507 Event p = *i;
1462 Event newPoint = p; 1508 Event newPoint = p;
1463 if (!p.hasValue()) { 1509 if (!p.hasValue()) {
1464 newPoint = newPoint.withValue((m_model->getValueMinimum() + 1510 newPoint = newPoint.withValue((model->getValueMinimum() +
1465 m_model->getValueMaximum()) / 2); 1511 model->getValueMaximum()) / 2);
1466 } 1512 }
1467 if (!p.hasDuration()) { 1513 if (!p.hasDuration()) {
1468 sv_frame_t nextFrame = frame; 1514 sv_frame_t nextFrame = frame;
1469 EventVector::const_iterator j = i; 1515 EventVector::const_iterator j = i;
1470 for (; j != points.end(); ++j) { 1516 for (; j != points.end(); ++j) {
1472 } 1518 }
1473 if (j != points.end()) { 1519 if (j != points.end()) {
1474 nextFrame = j->getFrame(); 1520 nextFrame = j->getFrame();
1475 } 1521 }
1476 if (nextFrame == frame) { 1522 if (nextFrame == frame) {
1477 newPoint = newPoint.withDuration(m_model->getResolution()); 1523 newPoint = newPoint.withDuration(model->getResolution());
1478 } else { 1524 } else {
1479 newPoint = newPoint.withDuration(nextFrame - frame); 1525 newPoint = newPoint.withDuration(nextFrame - frame);
1480 } 1526 }
1481 } 1527 }
1482 1528