comparison layer/RegionLayer.cpp @ 1486:ac0a8addabcf

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