comparison layer/TimeValueLayer.cpp @ 1459:42c87368287c

Merge from branch single-point
author Chris Cannam
date Fri, 17 May 2019 10:02:52 +0100
parents 9abddbd57667
children 696e569ff21b
comparison
equal deleted inserted replaced
1441:8d5bf4ab98ef 1459:42c87368287c
529 } 529 }
530 530
531 return mapper; 531 return mapper;
532 } 532 }
533 533
534 SparseTimeValueModel::PointList 534 EventVector
535 TimeValueLayer::getLocalPoints(LayerGeometryProvider *v, int x) const 535 TimeValueLayer::getLocalPoints(LayerGeometryProvider *v, int x) const
536 { 536 {
537 if (!m_model) return SparseTimeValueModel::PointList(); 537 if (!m_model) return {};
538 538
539 // Return all points at a frame f, where f is the closest frame to
540 // pixel coordinate x whose pixel coordinate is both within a
541 // small (but somewhat arbitrary) fuzz distance from x and within
542 // the current view. If there is no such frame, return an empty
543 // vector.
544
539 sv_frame_t frame = v->getFrameForX(x); 545 sv_frame_t frame = v->getFrameForX(x);
540 546
541 SparseTimeValueModel::PointList onPoints = 547 EventVector exact = m_model->getEventsStartingAt(frame);
542 m_model->getPoints(frame); 548 if (!exact.empty()) return exact;
543 549
544 if (!onPoints.empty()) { 550 // overspill == 1, so one event either side of the given span
545 return onPoints; 551 EventVector neighbouring = m_model->getEventsWithin
546 } 552 (frame, m_model->getResolution(), 1);
547 553
548 SparseTimeValueModel::PointList prevPoints = 554 double fuzz = v->scaleSize(2);
549 m_model->getPreviousPoints(frame); 555 sv_frame_t suitable = 0;
550 SparseTimeValueModel::PointList nextPoints = 556 bool have = false;
551 m_model->getNextPoints(frame); 557
552 558 for (Event e: neighbouring) {
553 SparseTimeValueModel::PointList usePoints = prevPoints; 559 sv_frame_t f = e.getFrame();
554 560 if (f < v->getStartFrame() || f > v->getEndFrame()) {
555 if (prevPoints.empty()) { 561 continue;
556 usePoints = nextPoints; 562 }
557 } else if (nextPoints.empty()) { 563 int px = v->getXForFrame(f);
558 // stick with prevPoints 564 if ((px > x && px - x > fuzz) || (px < x && x - px > fuzz + 3)) {
559 } else if (prevPoints.begin()->frame < v->getStartFrame() && 565 continue;
560 !(nextPoints.begin()->frame > v->getEndFrame())) { 566 }
561 usePoints = nextPoints; 567 if (!have) {
562 } else if (nextPoints.begin()->frame - frame < 568 suitable = f;
563 frame - prevPoints.begin()->frame) { 569 have = true;
564 usePoints = nextPoints; 570 } else if (llabs(frame - f) < llabs(suitable - f)) {
565 } 571 suitable = f;
566 572 }
567 if (!usePoints.empty()) { 573 }
568 double fuzz = v->scaleSize(2); 574
569 int px = v->getXForFrame(usePoints.begin()->frame); 575 if (have) {
570 if ((px > x && px - x > fuzz) || 576 return m_model->getEventsStartingAt(suitable);
571 (px < x && x - px > fuzz + 3)) { 577 } else {
572 usePoints.clear(); 578 return {};
573 } 579 }
574 }
575
576 return usePoints;
577 } 580 }
578 581
579 QString 582 QString
580 TimeValueLayer::getLabelPreceding(sv_frame_t frame) const 583 TimeValueLayer::getLabelPreceding(sv_frame_t frame) const
581 { 584 {
582 if (!m_model) return ""; 585 if (!m_model || !m_model->hasTextLabels()) return "";
583 SparseTimeValueModel::PointList points = m_model->getPreviousPoints(frame); 586
584 for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); 587 Event e;
585 i != points.end(); ++i) { 588 if (m_model->getNearestEventMatching
586 if (i->label != "") return i->label; 589 (frame,
587 } 590 [](Event e) { return e.hasLabel() && e.getLabel() != ""; },
591 EventSeries::Backward,
592 e)) {
593 return e.getLabel();
594 }
595
588 return ""; 596 return "";
589 } 597 }
590 598
591 QString 599 QString
592 TimeValueLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const 600 TimeValueLayer::getFeatureDescription(LayerGeometryProvider *v, QPoint &pos) const
593 { 601 {
594 int x = pos.x(); 602 int x = pos.x();
595 603
596 if (!m_model || !m_model->getSampleRate()) return ""; 604 if (!m_model || !m_model->getSampleRate()) return "";
597 605
598 SparseTimeValueModel::PointList points = getLocalPoints(v, x); 606 EventVector points = getLocalPoints(v, x);
599 607
600 if (points.empty()) { 608 if (points.empty()) {
601 if (!m_model->isReady()) { 609 if (!m_model->isReady()) {
602 return tr("In progress"); 610 return tr("In progress");
603 } else { 611 } else {
604 return tr("No local points"); 612 return tr("No local points");
605 } 613 }
606 } 614 }
607 615
608 sv_frame_t useFrame = points.begin()->frame; 616 sv_frame_t useFrame = points.begin()->getFrame();
609 617
610 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate()); 618 RealTime rt = RealTime::frame2RealTime(useFrame, m_model->getSampleRate());
611 619
612 QString valueText; 620 QString valueText;
613 float value = points.begin()->value; 621 float value = points.begin()->getValue();
614 QString unit = getScaleUnits(); 622 QString unit = getScaleUnits();
615 623
616 if (unit == "Hz") { 624 if (unit == "Hz") {
617 valueText = tr("%1 Hz (%2, %3)") 625 valueText = tr("%1 Hz (%2, %3)")
618 .arg(value) 626 .arg(value)
624 valueText = tr("%1").arg(value); 632 valueText = tr("%1").arg(value);
625 } 633 }
626 634
627 QString text; 635 QString text;
628 636
629 if (points.begin()->label == "") { 637 if (points.begin()->getLabel() == "") {
630 text = QString(tr("Time:\t%1\nValue:\t%2\nNo label")) 638 text = QString(tr("Time:\t%1\nValue:\t%2\nNo label"))
631 .arg(rt.toText(true).c_str()) 639 .arg(rt.toText(true).c_str())
632 .arg(valueText); 640 .arg(valueText);
633 } else { 641 } else {
634 text = QString(tr("Time:\t%1\nValue:\t%2\nLabel:\t%4")) 642 text = QString(tr("Time:\t%1\nValue:\t%2\nLabel:\t%4"))
635 .arg(rt.toText(true).c_str()) 643 .arg(rt.toText(true).c_str())
636 .arg(valueText) 644 .arg(valueText)
637 .arg(points.begin()->label); 645 .arg(points.begin()->getLabel());
638 } 646 }
639 647
640 pos = QPoint(v->getXForFrame(useFrame), 648 pos = QPoint(v->getXForFrame(useFrame),
641 getYForValue(v, points.begin()->value)); 649 getYForValue(v, points.begin()->getValue()));
642 return text; 650 return text;
643 } 651 }
644 652
645 bool 653 bool
646 TimeValueLayer::snapToFeatureFrame(LayerGeometryProvider *v, sv_frame_t &frame, 654 TimeValueLayer::snapToFeatureFrame(LayerGeometryProvider *v,
655 sv_frame_t &frame,
647 int &resolution, 656 int &resolution,
648 SnapType snap) const 657 SnapType snap) const
649 { 658 {
650 if (!m_model) { 659 if (!m_model) {
651 return Layer::snapToFeatureFrame(v, frame, resolution, snap); 660 return Layer::snapToFeatureFrame(v, frame, resolution, snap);
652 } 661 }
653 662
663 // SnapLeft / SnapRight: return frame of nearest feature in that
664 // direction no matter how far away
665 //
666 // SnapNeighbouring: return frame of feature that would be used in
667 // an editing operation, i.e. closest feature in either direction
668 // but only if it is "close enough"
669
654 resolution = m_model->getResolution(); 670 resolution = m_model->getResolution();
655 SparseTimeValueModel::PointList points;
656 671
657 if (snap == SnapNeighbouring) { 672 if (snap == SnapNeighbouring) {
658 673 EventVector points = getLocalPoints(v, v->getXForFrame(frame));
659 points = getLocalPoints(v, v->getXForFrame(frame));
660 if (points.empty()) return false; 674 if (points.empty()) return false;
661 frame = points.begin()->frame; 675 frame = points.begin()->getFrame();
662 return true; 676 return true;
663 } 677 }
664 678
665 points = m_model->getPoints(frame, frame); 679 Event e;
666 sv_frame_t snapped = frame; 680 if (m_model->getNearestEventMatching
667 bool found = false; 681 (frame,
668 682 [](Event) { return true; },
669 for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); 683 snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward,
670 i != points.end(); ++i) { 684 e)) {
671 685 frame = e.getFrame();
672 if (snap == SnapRight) { 686 return true;
673 687 }
674 if (i->frame > frame) { 688
675 snapped = i->frame; 689 return false;
676 found = true;
677 break;
678 }
679
680 } else if (snap == SnapLeft) {
681
682 if (i->frame <= frame) {
683 snapped = i->frame;
684 found = true; // don't break, as the next may be better
685 } else {
686 break;
687 }
688
689 } else { // nearest
690
691 SparseTimeValueModel::PointList::const_iterator j = i;
692 ++j;
693
694 if (j == points.end()) {
695
696 snapped = i->frame;
697 found = true;
698 break;
699
700 } else if (j->frame >= frame) {
701
702 if (j->frame - frame < frame - i->frame) {
703 snapped = j->frame;
704 } else {
705 snapped = i->frame;
706 }
707 found = true;
708 break;
709 }
710 }
711 }
712
713 frame = snapped;
714 return found;
715 } 690 }
716 691
717 bool 692 bool
718 TimeValueLayer::snapToSimilarFeature(LayerGeometryProvider *v, sv_frame_t &frame, 693 TimeValueLayer::snapToSimilarFeature(LayerGeometryProvider *v,
694 sv_frame_t &frame,
719 int &resolution, 695 int &resolution,
720 SnapType snap) const 696 SnapType snap) const
721 { 697 {
722 if (!m_model) { 698 if (!m_model) {
723 return Layer::snapToSimilarFeature(v, frame, resolution, snap); 699 return Layer::snapToSimilarFeature(v, frame, resolution, snap);
724 } 700 }
725 701
702 // snap is only permitted to be SnapLeft or SnapRight here.
703
726 resolution = m_model->getResolution(); 704 resolution = m_model->getResolution();
727 705
728 const SparseTimeValueModel::PointList &points = m_model->getPoints(); 706 Event ref;
729 SparseTimeValueModel::PointList close = m_model->getPoints(frame, frame); 707 Event e;
730 708 float matchvalue;
731 SparseTimeValueModel::PointList::const_iterator i; 709 bool found;
732 710
733 sv_frame_t matchframe = frame; 711 found = m_model->getNearestEventMatching
734 double matchvalue = 0.0; 712 (frame, [](Event) { return true; }, EventSeries::Backward, ref);
735 713
736 for (i = close.begin(); i != close.end(); ++i) { 714 if (!found) {
737 if (i->frame > frame) break; 715 return false;
738 matchvalue = i->value; 716 }
739 matchframe = i->frame; 717
740 } 718 matchvalue = ref.getValue();
741 719
742 sv_frame_t snapped = frame; 720 found = m_model->getNearestEventMatching
743 bool found = false; 721 (frame,
744 bool distant = false; 722 [matchvalue](Event e) {
745 double epsilon = 0.0001; 723 double epsilon = 0.0001;
746 724 return fabs(e.getValue() - matchvalue) < epsilon;
747 i = close.begin(); 725 },
748 726 snap == SnapLeft ? EventSeries::Backward : EventSeries::Forward,
749 // Scan through the close points first, then the more distant ones 727 e);
750 // if no suitable close one is found. So the while-termination 728
751 // condition here can only happen once i has passed through the 729 if (!found) {
752 // whole of the close container and then the whole of the separate 730 return false;
753 // points container. The two iterators are totally distinct, but 731 }
754 // have the same type so we cheekily use the same variable and a 732
755 // single loop for both. 733 frame = e.getFrame();
756 734 return true;
757 while (i != points.end()) {
758
759 if (!distant) {
760 if (i == close.end()) {
761 // switch from the close container to the points container
762 i = points.begin();
763 distant = true;
764 }
765 }
766
767 if (snap == SnapRight) {
768
769 if (i->frame > matchframe &&
770 fabs(i->value - matchvalue) < epsilon) {
771 snapped = i->frame;
772 found = true;
773 break;
774 }
775
776 } else if (snap == SnapLeft) {
777
778 if (i->frame < matchframe) {
779 if (fabs(i->value - matchvalue) < epsilon) {
780 snapped = i->frame;
781 found = true; // don't break, as the next may be better
782 }
783 } else if (found || distant) {
784 break;
785 }
786
787 } else {
788 // no other snap types supported
789 }
790
791 ++i;
792 }
793
794 frame = snapped;
795 return found;
796 } 735 }
797 736
798 void 737 void
799 TimeValueLayer::getScaleExtents(LayerGeometryProvider *v, double &min, double &max, bool &log) const 738 TimeValueLayer::getScaleExtents(LayerGeometryProvider *v, double &min, double &max, bool &log) const
800 { 739 {
924 int x0 = rect.left(), x1 = rect.right(); 863 int x0 = rect.left(), x1 = rect.right();
925 sv_frame_t frame0 = v->getFrameForX(x0); 864 sv_frame_t frame0 = v->getFrameForX(x0);
926 sv_frame_t frame1 = v->getFrameForX(x1); 865 sv_frame_t frame1 = v->getFrameForX(x1);
927 if (m_derivative) --frame0; 866 if (m_derivative) --frame0;
928 867
929 SparseTimeValueModel::PointList points(m_model->getPoints 868 EventVector points(m_model->getEventsWithin(frame0, frame1 - frame0, 1));
930 (frame0, frame1));
931 if (points.empty()) return; 869 if (points.empty()) return;
932 870
933 paint.setPen(getBaseQColor()); 871 paint.setPen(getBaseQColor());
934 872
935 QColor brushColour(getBaseQColor()); 873 QColor brushColour(getBaseQColor());
936 brushColour.setAlpha(80); 874 brushColour.setAlpha(80);
937 paint.setBrush(brushColour); 875 paint.setBrush(brushColour);
938 876
939 #ifdef DEBUG_TIME_VALUE_LAYER 877 #ifdef DEBUG_TIME_VALUE_LAYER
940 cerr << "TimeValueLayer::paint: resolution is " 878 cerr << "TimeValueLayer::paint: resolution is "
941 << m_model->getResolution() << " frames" << endl; 879 << m_model->getResolution() << " frames" << endl;
942 #endif 880 #endif
943 881
944 double min = m_model->getValueMinimum(); 882 double min = m_model->getValueMinimum();
945 double max = m_model->getValueMaximum(); 883 double max = m_model->getValueMaximum();
946 if (max == min) max = min + 1.0; 884 if (max == min) max = min + 1.0;
950 888
951 QPoint localPos; 889 QPoint localPos;
952 sv_frame_t illuminateFrame = -1; 890 sv_frame_t illuminateFrame = -1;
953 891
954 if (v->shouldIlluminateLocalFeatures(this, localPos)) { 892 if (v->shouldIlluminateLocalFeatures(this, localPos)) {
955 SparseTimeValueModel::PointList localPoints = 893 EventVector localPoints = getLocalPoints(v, localPos.x());
956 getLocalPoints(v, localPos.x());
957 #ifdef DEBUG_TIME_VALUE_LAYER 894 #ifdef DEBUG_TIME_VALUE_LAYER
958 cerr << "TimeValueLayer: " << localPoints.size() << " local points" << endl; 895 cerr << "TimeValueLayer: " << localPoints.size() << " local points" << endl;
959 #endif 896 #endif
960 if (!localPoints.empty()) illuminateFrame = localPoints.begin()->frame; 897 if (!localPoints.empty()) {
898 illuminateFrame = localPoints.begin()->getFrame();
899 }
961 } 900 }
962 901
963 int w = 902 int w =
964 v->getXForFrame(frame0 + m_model->getResolution()) - 903 v->getXForFrame(frame0 + m_model->getResolution()) -
965 v->getXForFrame(frame0); 904 v->getXForFrame(frame0);
988 } 927 }
989 } 928 }
990 929
991 sv_frame_t prevFrame = 0; 930 sv_frame_t prevFrame = 0;
992 931
993 for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); 932 for (EventVector::const_iterator i = points.begin();
994 i != points.end(); ++i) { 933 i != points.end(); ++i) {
995 934
996 if (m_derivative && i == points.begin()) continue; 935 if (m_derivative && i == points.begin()) continue;
997 936
998 const SparseTimeValueModel::Point &p(*i); 937 Event p(*i);
999 938
1000 double value = p.value; 939 double value = p.getValue();
1001 if (m_derivative) { 940 if (m_derivative) {
1002 SparseTimeValueModel::PointList::const_iterator j = i; 941 EventVector::const_iterator j = i;
1003 --j; 942 --j;
1004 value -= j->value; 943 value -= j->getValue();
1005 } 944 }
1006 945
1007 int x = v->getXForFrame(p.frame); 946 int x = v->getXForFrame(p.getFrame());
1008 int y = getYForValue(v, value); 947 int y = getYForValue(v, value);
1009 948
1010 bool gap = false; 949 bool gap = false;
1011 if (m_plotStyle == PlotDiscreteCurves) { 950 if (m_plotStyle == PlotDiscreteCurves) {
1012 if (value == 0.0) { 951 if (value == 0.0) {
1013 // Treat zeros as gaps 952 // Treat zeros as gaps
1014 continue; 953 continue;
1015 } 954 }
1016 gap = (p.frame > prevFrame && 955 gap = (p.getFrame() > prevFrame &&
1017 (p.frame - prevFrame >= m_model->getResolution() * 2)); 956 (p.getFrame() - prevFrame >= m_model->getResolution() * 2));
1018 } 957 }
1019 958
1020 if (m_plotStyle != PlotSegmentation) { 959 if (m_plotStyle != PlotSegmentation) {
1021 textY = y - paint.fontMetrics().height() 960 textY = y - paint.fontMetrics().height()
1022 + paint.fontMetrics().ascent() - 1; 961 + paint.fontMetrics().ascent() - 1;
1029 double nvalue = 0.f; 968 double nvalue = 0.f;
1030 sv_frame_t nf = v->getModelsEndFrame(); 969 sv_frame_t nf = v->getModelsEndFrame();
1031 int nx = v->getXForFrame(nf); 970 int nx = v->getXForFrame(nf);
1032 int ny = y; 971 int ny = y;
1033 972
1034 SparseTimeValueModel::PointList::const_iterator j = i; 973 EventVector::const_iterator j = i;
1035 ++j; 974 ++j;
1036 975
1037 if (j != points.end()) { 976 if (j != points.end()) {
1038 const SparseTimeValueModel::Point &q(*j); 977 Event q(*j);
1039 nvalue = q.value; 978 nvalue = q.getValue();
1040 if (m_derivative) nvalue -= p.value; 979 if (m_derivative) nvalue -= p.getValue();
1041 nf = q.frame; 980 nf = q.getFrame();
1042 nx = v->getXForFrame(nf); 981 nx = v->getXForFrame(nf);
1043 ny = getYForValue(v, nvalue); 982 ny = getYForValue(v, nvalue);
1044 haveNext = true; 983 haveNext = true;
1045 } 984 }
1046 985
1047 // cout << "frame = " << p.frame << ", x = " << x << ", haveNext = " << haveNext 986 // cout << "frame = " << p.getFrame() << ", x = " << x << ", haveNext = " << haveNext
1048 // << ", nx = " << nx << endl; 987 // << ", nx = " << nx << endl;
1049 988
1050 QPen pen(getBaseQColor()); 989 QPen pen(getBaseQColor());
1051 QBrush brush(brushColour); 990 QBrush brush(brushColour);
1052 991
1072 } 1011 }
1073 } 1012 }
1074 1013
1075 bool illuminate = false; 1014 bool illuminate = false;
1076 1015
1077 if (illuminateFrame == p.frame) { 1016 if (illuminateFrame == p.getFrame()) {
1078 1017
1079 // not equipped to illuminate the right section in line 1018 // not equipped to illuminate the right section in line
1080 // or curve mode 1019 // or curve mode
1081 1020
1082 if (m_plotStyle != PlotCurve && 1021 if (m_plotStyle != PlotCurve &&
1136 double y1 = ny; 1075 double y1 = ny;
1137 1076
1138 if (m_plotStyle == PlotDiscreteCurves) { 1077 if (m_plotStyle == PlotDiscreteCurves) {
1139 bool nextGap = 1078 bool nextGap =
1140 (nvalue == 0.0) || 1079 (nvalue == 0.0) ||
1141 (nf - p.frame >= m_model->getResolution() * 2); 1080 (nf - p.getFrame() >= m_model->getResolution() * 2);
1142 if (nextGap) { 1081 if (nextGap) {
1143 x1 = x0; 1082 x1 = x0;
1144 y1 = y0; 1083 y1 = y0;
1145 } 1084 }
1146 } 1085 }
1186 paint.drawRect(x, -1, nx - x, v->getPaintHeight() + 1); 1125 paint.drawRect(x, -1, nx - x, v->getPaintHeight() + 1);
1187 } 1126 }
1188 1127
1189 if (v->shouldShowFeatureLabels()) { 1128 if (v->shouldShowFeatureLabels()) {
1190 1129
1191 QString label = p.label; 1130 QString label = p.getLabel();
1192 bool italic = false; 1131 bool italic = false;
1193 1132
1194 if (label == "" && 1133 if (label == "" &&
1195 (m_plotStyle == PlotPoints || 1134 (m_plotStyle == PlotPoints ||
1196 m_plotStyle == PlotSegmentation || 1135 m_plotStyle == PlotSegmentation ||
1197 m_plotStyle == PlotConnectedPoints)) { 1136 m_plotStyle == PlotConnectedPoints)) {
1198 char lc[20]; 1137 char lc[20];
1199 snprintf(lc, 20, "%.3g", p.value); 1138 snprintf(lc, 20, "%.3g", p.getValue());
1200 label = lc; 1139 label = lc;
1201 italic = true; 1140 italic = true;
1202 } 1141 }
1203 1142
1204 if (label != "") { 1143 if (label != "") {
1207 haveRoom = (haveRoom && 1146 haveRoom = (haveRoom &&
1208 (nx > x + 6 + paint.fontMetrics().width(label))); 1147 (nx > x + 6 + paint.fontMetrics().width(label)));
1209 if (haveRoom || 1148 if (haveRoom ||
1210 (!haveNext && 1149 (!haveNext &&
1211 (pointCount == 0 || !italic))) { 1150 (pointCount == 0 || !italic))) {
1212 PaintAssistant::drawVisibleText(v, paint, x + 5, textY, label, 1151 PaintAssistant::drawVisibleText
1213 italic ? 1152 (v, paint, x + 5, textY, label,
1214 PaintAssistant::OutlinedItalicText : 1153 italic ?
1215 PaintAssistant::OutlinedText); 1154 PaintAssistant::OutlinedItalicText :
1155 PaintAssistant::OutlinedText);
1216 } 1156 }
1217 } 1157 }
1218 } 1158 }
1219 1159
1220 prevFrame = p.frame; 1160 prevFrame = p.getFrame();
1221 ++pointCount; 1161 ++pointCount;
1222 } 1162 }
1223 1163
1224 if (m_plotStyle == PlotDiscreteCurves) { 1164 if (m_plotStyle == PlotDiscreteCurves) {
1225 paint.setRenderHint(QPainter::Antialiasing, true); 1165 paint.setRenderHint(QPainter::Antialiasing, true);
1259 } 1199 }
1260 1200
1261 void 1201 void
1262 TimeValueLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const 1202 TimeValueLayer::paintVerticalScale(LayerGeometryProvider *v, bool, QPainter &paint, QRect) const
1263 { 1203 {
1264 if (!m_model || m_model->getPoints().empty()) return; 1204 if (!m_model || m_model->isEmpty()) return;
1265 1205
1266 QString unit; 1206 QString unit;
1267 double min, max; 1207 double min, max;
1268 bool logarithmic; 1208 bool logarithmic;
1269 1209
1326 1266
1327 double value = getValueForY(v, e->y()); 1267 double value = getValueForY(v, e->y());
1328 1268
1329 bool havePoint = false; 1269 bool havePoint = false;
1330 1270
1331 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x()); 1271 EventVector points = getLocalPoints(v, e->x());
1332 if (!points.empty()) { 1272 if (!points.empty()) {
1333 for (SparseTimeValueModel::PointList::iterator i = points.begin(); 1273 for (EventVector::iterator i = points.begin();
1334 i != points.end(); ++i) { 1274 i != points.end(); ++i) {
1335 if (((i->frame / resolution) * resolution) != frame) { 1275 if (((i->getFrame() / resolution) * resolution) != frame) {
1336 #ifdef DEBUG_TIME_VALUE_LAYER 1276 #ifdef DEBUG_TIME_VALUE_LAYER
1337 cerr << "ignoring out-of-range frame at " << i->frame << endl; 1277 cerr << "ignoring out-of-range frame at " << i->getFrame() << endl;
1338 #endif 1278 #endif
1339 continue; 1279 continue;
1340 } 1280 }
1341 m_editingPoint = *i; 1281 m_editingPoint = *i;
1342 havePoint = true; 1282 havePoint = true;
1343 } 1283 }
1344 } 1284 }
1345 1285
1346 if (!havePoint) { 1286 if (!havePoint) {
1347 m_editingPoint = SparseTimeValueModel::Point 1287 m_editingPoint = Event(frame, float(value), tr("New Point"));
1348 (frame, float(value), tr("New Point"));
1349 } 1288 }
1350 1289
1351 m_originalPoint = m_editingPoint; 1290 m_originalPoint = m_editingPoint;
1352 1291
1353 if (m_editingCommand) finish(m_editingCommand); 1292 if (m_editingCommand) finish(m_editingCommand);
1354 m_editingCommand = new SparseTimeValueModel::EditCommand(m_model, 1293 m_editingCommand = new ChangeEventsCommand(m_model, tr("Draw Point"));
1355 tr("Draw Point"));
1356 if (!havePoint) { 1294 if (!havePoint) {
1357 m_editingCommand->addPoint(m_editingPoint); 1295 m_editingCommand->add(m_editingPoint);
1358 } 1296 }
1359 1297
1360 m_editing = true; 1298 m_editing = true;
1361 } 1299 }
1362 1300
1374 if (frame < 0) frame = 0; 1312 if (frame < 0) frame = 0;
1375 frame = (frame / resolution) * resolution; 1313 frame = (frame / resolution) * resolution;
1376 1314
1377 double value = getValueForY(v, e->y()); 1315 double value = getValueForY(v, e->y());
1378 1316
1379 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x()); 1317 EventVector points = getLocalPoints(v, e->x());
1380 1318
1381 #ifdef DEBUG_TIME_VALUE_LAYER 1319 #ifdef DEBUG_TIME_VALUE_LAYER
1382 cerr << points.size() << " points" << endl; 1320 cerr << points.size() << " points" << endl;
1383 #endif 1321 #endif
1384 1322
1385 bool havePoint = false; 1323 bool havePoint = false;
1386 1324
1387 if (!points.empty()) { 1325 if (!points.empty()) {
1388 for (SparseTimeValueModel::PointList::iterator i = points.begin(); 1326 for (EventVector::iterator i = points.begin();
1389 i != points.end(); ++i) { 1327 i != points.end(); ++i) {
1390 if (i->frame == m_editingPoint.frame && 1328 if (i->getFrame() == m_editingPoint.getFrame() &&
1391 i->value == m_editingPoint.value) { 1329 i->getValue() == m_editingPoint.getValue()) {
1392 #ifdef DEBUG_TIME_VALUE_LAYER 1330 #ifdef DEBUG_TIME_VALUE_LAYER
1393 cerr << "ignoring current editing point at " << i->frame << ", " << i->value << endl; 1331 cerr << "ignoring current editing point at " << i->getFrame() << ", " << i->getValue() << endl;
1394 #endif 1332 #endif
1395 continue; 1333 continue;
1396 } 1334 }
1397 if (((i->frame / resolution) * resolution) != frame) { 1335 if (((i->getFrame() / resolution) * resolution) != frame) {
1398 #ifdef DEBUG_TIME_VALUE_LAYER 1336 #ifdef DEBUG_TIME_VALUE_LAYER
1399 cerr << "ignoring out-of-range frame at " << i->frame << endl; 1337 cerr << "ignoring out-of-range frame at " << i->getFrame() << endl;
1400 #endif 1338 #endif
1401 continue; 1339 continue;
1402 } 1340 }
1403 #ifdef DEBUG_TIME_VALUE_LAYER 1341 #ifdef DEBUG_TIME_VALUE_LAYER
1404 cerr << "adjusting to new point at " << i->frame << ", " << i->value << endl; 1342 cerr << "adjusting to new point at " << i->getFrame() << ", " << i->getValue() << endl;
1405 #endif 1343 #endif
1406 m_editingPoint = *i; 1344 m_editingPoint = *i;
1407 m_originalPoint = m_editingPoint; 1345 m_originalPoint = m_editingPoint;
1408 m_editingCommand->deletePoint(m_editingPoint); 1346 m_editingCommand->remove(m_editingPoint);
1409 havePoint = true; 1347 havePoint = true;
1410 } 1348 }
1411 } 1349 }
1412 1350
1413 if (!havePoint) { 1351 if (!havePoint) {
1414 if (frame == m_editingPoint.frame) { 1352 if (frame == m_editingPoint.getFrame()) {
1415 m_editingCommand->deletePoint(m_editingPoint); 1353 m_editingCommand->remove(m_editingPoint);
1416 } 1354 }
1417 } 1355 }
1418 1356
1419 // m_editingCommand->deletePoint(m_editingPoint); 1357 m_editingPoint = m_editingPoint
1420 m_editingPoint.frame = frame; 1358 .withFrame(frame)
1421 m_editingPoint.value = float(value); 1359 .withValue(float(value));
1422 m_editingCommand->addPoint(m_editingPoint); 1360 m_editingCommand->add(m_editingPoint);
1423 } 1361 }
1424 1362
1425 void 1363 void
1426 TimeValueLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *) 1364 TimeValueLayer::drawEnd(LayerGeometryProvider *, QMouseEvent *)
1427 { 1365 {
1437 void 1375 void
1438 TimeValueLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e) 1376 TimeValueLayer::eraseStart(LayerGeometryProvider *v, QMouseEvent *e)
1439 { 1377 {
1440 if (!m_model) return; 1378 if (!m_model) return;
1441 1379
1442 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x()); 1380 EventVector points = getLocalPoints(v, e->x());
1443 if (points.empty()) return; 1381 if (points.empty()) return;
1444 1382
1445 m_editingPoint = *points.begin(); 1383 m_editingPoint = *points.begin();
1446 1384
1447 if (m_editingCommand) { 1385 if (m_editingCommand) {
1462 { 1400 {
1463 if (!m_model || !m_editing) return; 1401 if (!m_model || !m_editing) return;
1464 1402
1465 m_editing = false; 1403 m_editing = false;
1466 1404
1467 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x()); 1405 EventVector points = getLocalPoints(v, e->x());
1468 if (points.empty()) return; 1406 if (points.empty()) return;
1469 if (points.begin()->frame != m_editingPoint.frame || 1407 if (points.begin()->getFrame() != m_editingPoint.getFrame() ||
1470 points.begin()->value != m_editingPoint.value) return; 1408 points.begin()->getValue() != m_editingPoint.getValue()) return;
1471 1409
1472 m_editingCommand = new SparseTimeValueModel::EditCommand 1410 m_editingCommand = new ChangeEventsCommand(m_model, tr("Erase Point"));
1473 (m_model, tr("Erase Point")); 1411 m_editingCommand->remove(m_editingPoint);
1474
1475 m_editingCommand->deletePoint(m_editingPoint);
1476
1477 finish(m_editingCommand); 1412 finish(m_editingCommand);
1478 m_editingCommand = nullptr; 1413 m_editingCommand = nullptr;
1479 m_editing = false; 1414 m_editing = false;
1480 } 1415 }
1481 1416
1486 cerr << "TimeValueLayer::editStart(" << e->x() << "," << e->y() << ")" << endl; 1421 cerr << "TimeValueLayer::editStart(" << e->x() << "," << e->y() << ")" << endl;
1487 #endif 1422 #endif
1488 1423
1489 if (!m_model) return; 1424 if (!m_model) return;
1490 1425
1491 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x()); 1426 EventVector points = getLocalPoints(v, e->x());
1492 if (points.empty()) return; 1427 if (points.empty()) return;
1493 1428
1494 m_editingPoint = *points.begin(); 1429 m_editingPoint = *points.begin();
1495 m_originalPoint = m_editingPoint; 1430 m_originalPoint = m_editingPoint;
1496 1431
1516 frame = frame / m_model->getResolution() * m_model->getResolution(); 1451 frame = frame / m_model->getResolution() * m_model->getResolution();
1517 1452
1518 double value = getValueForY(v, e->y()); 1453 double value = getValueForY(v, e->y());
1519 1454
1520 if (!m_editingCommand) { 1455 if (!m_editingCommand) {
1521 m_editingCommand = new SparseTimeValueModel::EditCommand(m_model, 1456 m_editingCommand = new ChangeEventsCommand(m_model, tr("Drag Point"));
1522 tr("Drag Point")); 1457 }
1523 } 1458
1524 1459 m_editingCommand->remove(m_editingPoint);
1525 m_editingCommand->deletePoint(m_editingPoint); 1460 m_editingPoint = m_editingPoint
1526 m_editingPoint.frame = frame; 1461 .withFrame(frame)
1527 m_editingPoint.value = float(value); 1462 .withValue(float(value));
1528 m_editingCommand->addPoint(m_editingPoint); 1463 m_editingCommand->add(m_editingPoint);
1529 } 1464 }
1530 1465
1531 void 1466 void
1532 TimeValueLayer::editEnd(LayerGeometryProvider *, QMouseEvent *) 1467 TimeValueLayer::editEnd(LayerGeometryProvider *, QMouseEvent *)
1533 { 1468 {
1538 1473
1539 if (m_editingCommand) { 1474 if (m_editingCommand) {
1540 1475
1541 QString newName = m_editingCommand->getName(); 1476 QString newName = m_editingCommand->getName();
1542 1477
1543 if (m_editingPoint.frame != m_originalPoint.frame) { 1478 if (m_editingPoint.getFrame() != m_originalPoint.getFrame()) {
1544 if (m_editingPoint.value != m_originalPoint.value) { 1479 if (m_editingPoint.getValue() != m_originalPoint.getValue()) {
1545 newName = tr("Edit Point"); 1480 newName = tr("Edit Point");
1546 } else { 1481 } else {
1547 newName = tr("Relocate Point"); 1482 newName = tr("Relocate Point");
1548 } 1483 }
1549 } else { 1484 } else {
1561 bool 1496 bool
1562 TimeValueLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e) 1497 TimeValueLayer::editOpen(LayerGeometryProvider *v, QMouseEvent *e)
1563 { 1498 {
1564 if (!m_model) return false; 1499 if (!m_model) return false;
1565 1500
1566 SparseTimeValueModel::PointList points = getLocalPoints(v, e->x()); 1501 EventVector points = getLocalPoints(v, e->x());
1567 if (points.empty()) return false; 1502 if (points.empty()) return false;
1568 1503
1569 SparseTimeValueModel::Point point = *points.begin(); 1504 Event point = *points.begin();
1570 1505
1571 ItemEditDialog *dialog = new ItemEditDialog 1506 ItemEditDialog *dialog = new ItemEditDialog
1572 (m_model->getSampleRate(), 1507 (m_model->getSampleRate(),
1573 ItemEditDialog::ShowTime | 1508 ItemEditDialog::ShowTime |
1574 ItemEditDialog::ShowValue | 1509 ItemEditDialog::ShowValue |
1575 ItemEditDialog::ShowText, 1510 ItemEditDialog::ShowText,
1576 getScaleUnits()); 1511 getScaleUnits());
1577 1512
1578 dialog->setFrameTime(point.frame); 1513 dialog->setFrameTime(point.getFrame());
1579 dialog->setValue(point.value); 1514 dialog->setValue(point.getValue());
1580 dialog->setText(point.label); 1515 dialog->setText(point.getLabel());
1581 1516
1582 if (dialog->exec() == QDialog::Accepted) { 1517 if (dialog->exec() == QDialog::Accepted) {
1583 1518
1584 SparseTimeValueModel::Point newPoint = point; 1519 Event newPoint = point
1585 newPoint.frame = dialog->getFrameTime(); 1520 .withFrame(dialog->getFrameTime())
1586 newPoint.value = dialog->getValue(); 1521 .withValue(dialog->getValue())
1587 newPoint.label = dialog->getText(); 1522 .withLabel(dialog->getText());
1588 1523
1589 SparseTimeValueModel::EditCommand *command = 1524 ChangeEventsCommand *command =
1590 new SparseTimeValueModel::EditCommand(m_model, tr("Edit Point")); 1525 new ChangeEventsCommand(m_model, tr("Edit Point"));
1591 command->deletePoint(point); 1526 command->remove(point);
1592 command->addPoint(newPoint); 1527 command->add(newPoint);
1593 finish(command); 1528 finish(command);
1594 } 1529 }
1595 1530
1596 delete dialog; 1531 delete dialog;
1597 return true; 1532 return true;
1600 void 1535 void
1601 TimeValueLayer::moveSelection(Selection s, sv_frame_t newStartFrame) 1536 TimeValueLayer::moveSelection(Selection s, sv_frame_t newStartFrame)
1602 { 1537 {
1603 if (!m_model) return; 1538 if (!m_model) return;
1604 1539
1605 SparseTimeValueModel::EditCommand *command = 1540 ChangeEventsCommand *command =
1606 new SparseTimeValueModel::EditCommand(m_model, 1541 new ChangeEventsCommand(m_model, tr("Drag Selection"));
1607 tr("Drag Selection")); 1542
1608 1543 EventVector points =
1609 SparseTimeValueModel::PointList points = 1544 m_model->getEventsWithin(s.getStartFrame(), s.getDuration());
1610 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); 1545
1611 1546 for (Event p: points) {
1612 for (SparseTimeValueModel::PointList::iterator i = points.begin(); 1547
1613 i != points.end(); ++i) { 1548 Event newPoint = p.withFrame
1614 1549 (p.getFrame() + newStartFrame - s.getStartFrame());
1615 if (s.contains(i->frame)) { 1550 command->remove(p);
1616 SparseTimeValueModel::Point newPoint(*i); 1551 command->add(newPoint);
1617 newPoint.frame = i->frame + newStartFrame - s.getStartFrame();
1618 command->deletePoint(*i);
1619 command->addPoint(newPoint);
1620 }
1621 } 1552 }
1622 1553
1623 finish(command); 1554 finish(command);
1624 } 1555 }
1625 1556
1626 void 1557 void
1627 TimeValueLayer::resizeSelection(Selection s, Selection newSize) 1558 TimeValueLayer::resizeSelection(Selection s, Selection newSize)
1628 { 1559 {
1560 if (!m_model || !s.getDuration()) return;
1561
1562 ChangeEventsCommand *command =
1563 new ChangeEventsCommand(m_model, tr("Resize Selection"));
1564
1565 EventVector points =
1566 m_model->getEventsWithin(s.getStartFrame(), s.getDuration());
1567
1568 double ratio = double(newSize.getDuration()) / double(s.getDuration());
1569 double oldStart = double(s.getStartFrame());
1570 double newStart = double(newSize.getStartFrame());
1571
1572 for (Event p: points) {
1573
1574 double newFrame = (double(p.getFrame()) - oldStart) * ratio + newStart;
1575
1576 Event newPoint = p
1577 .withFrame(lrint(newFrame));
1578 command->remove(p);
1579 command->add(newPoint);
1580 }
1581
1582 finish(command);
1583 }
1584
1585 void
1586 TimeValueLayer::deleteSelection(Selection s)
1587 {
1629 if (!m_model) return; 1588 if (!m_model) return;
1630 1589
1631 SparseTimeValueModel::EditCommand *command = 1590 ChangeEventsCommand *command =
1632 new SparseTimeValueModel::EditCommand(m_model, 1591 new ChangeEventsCommand(m_model, tr("Delete Selected Points"));
1633 tr("Resize Selection")); 1592
1634 1593 EventVector points =
1635 SparseTimeValueModel::PointList points = 1594 m_model->getEventsWithin(s.getStartFrame(), s.getDuration());
1636 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); 1595
1637 1596 for (Event p: points) {
1638 double ratio = 1597 command->remove(p);
1639 double(newSize.getEndFrame() - newSize.getStartFrame()) /
1640 double(s.getEndFrame() - s.getStartFrame());
1641
1642 for (SparseTimeValueModel::PointList::iterator i = points.begin();
1643 i != points.end(); ++i) {
1644
1645 if (s.contains(i->frame)) {
1646
1647 double target = double(i->frame);
1648 target = double(newSize.getStartFrame()) +
1649 target - double(s.getStartFrame()) * ratio;
1650
1651 SparseTimeValueModel::Point newPoint(*i);
1652 newPoint.frame = lrint(target);
1653 command->deletePoint(*i);
1654 command->addPoint(newPoint);
1655 }
1656 }
1657
1658 finish(command);
1659 }
1660
1661 void
1662 TimeValueLayer::deleteSelection(Selection s)
1663 {
1664 if (!m_model) return;
1665
1666 SparseTimeValueModel::EditCommand *command =
1667 new SparseTimeValueModel::EditCommand(m_model,
1668 tr("Delete Selected Points"));
1669
1670 SparseTimeValueModel::PointList points =
1671 m_model->getPoints(s.getStartFrame(), s.getEndFrame());
1672
1673 for (SparseTimeValueModel::PointList::iterator i = points.begin();
1674 i != points.end(); ++i) {
1675
1676 if (s.contains(i->frame)) {
1677 command->deletePoint(*i);
1678 }
1679 } 1598 }
1680 1599
1681 finish(command); 1600 finish(command);
1682 } 1601 }
1683 1602
1684 void 1603 void
1685 TimeValueLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to) 1604 TimeValueLayer::copy(LayerGeometryProvider *v, Selection s, Clipboard &to)
1686 { 1605 {
1687 if (!m_model) return; 1606 if (!m_model) return;
1688 1607
1689 SparseTimeValueModel::PointList points = 1608 EventVector points =
1690 m_model->getPoints(s.getStartFrame(), s.getEndFrame()); 1609 m_model->getEventsWithin(s.getStartFrame(), s.getDuration());
1691 1610
1692 for (SparseTimeValueModel::PointList::iterator i = points.begin(); 1611 for (Event p: points) {
1693 i != points.end(); ++i) { 1612 to.addPoint(p.withReferenceFrame(alignToReference(v, p.getFrame())));
1694 if (s.contains(i->frame)) {
1695 Clipboard::Point point(i->frame, i->value, i->label);
1696 point.setReferenceFrame(alignToReference(v, i->frame));
1697 to.addPoint(point);
1698 }
1699 } 1613 }
1700 } 1614 }
1701 1615
1702 bool 1616 bool
1703 TimeValueLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */, 1617 TimeValueLayer::paste(LayerGeometryProvider *v, const Clipboard &from, sv_frame_t /* frameOffset */,
1704 bool interactive) 1618 bool interactive)
1705 { 1619 {
1706 if (!m_model) return false; 1620 if (!m_model) return false;
1707 1621
1708 const Clipboard::PointList &points = from.getPoints(); 1622 EventVector points = from.getPoints();
1709 1623
1710 bool realign = false; 1624 bool realign = false;
1711 1625
1712 if (clipboardHasDifferentAlignment(v, from)) { 1626 if (clipboardHasDifferentAlignment(v, from)) {
1713 1627
1724 if (button == QMessageBox::Yes) { 1638 if (button == QMessageBox::Yes) {
1725 realign = true; 1639 realign = true;
1726 } 1640 }
1727 } 1641 }
1728 1642
1729 SparseTimeValueModel::EditCommand *command = 1643 ChangeEventsCommand *command =
1730 new SparseTimeValueModel::EditCommand(m_model, tr("Paste")); 1644 new ChangeEventsCommand(m_model, tr("Paste"));
1731 1645
1732 enum ValueAvailability { 1646 enum ValueAvailability {
1733 UnknownAvailability, 1647 UnknownAvailability,
1734 NoValues, 1648 NoValues,
1735 SomeValues, 1649 SomeValues,
1744 1658
1745 if (interactive) { 1659 if (interactive) {
1746 1660
1747 ValueAvailability availability = UnknownAvailability; 1661 ValueAvailability availability = UnknownAvailability;
1748 1662
1749 for (Clipboard::PointList::const_iterator i = points.begin(); 1663 for (EventVector::const_iterator i = points.begin();
1750 i != points.end(); ++i) { 1664 i != points.end(); ++i) {
1751 1665
1752 if (!i->haveFrame()) continue;
1753
1754 if (availability == UnknownAvailability) { 1666 if (availability == UnknownAvailability) {
1755 if (i->haveValue()) availability = AllValues; 1667 if (i->hasValue()) availability = AllValues;
1756 else availability = NoValues; 1668 else availability = NoValues;
1757 continue; 1669 continue;
1758 } 1670 }
1759 1671
1760 if (i->haveValue()) { 1672 if (i->hasValue()) {
1761 if (availability == NoValues) { 1673 if (availability == NoValues) {
1762 availability = SomeValues; 1674 availability = SomeValues;
1763 } 1675 }
1764 } else { 1676 } else {
1765 if (availability == AllValues) { 1677 if (availability == AllValues) {
1766 availability = SomeValues; 1678 availability = SomeValues;
1767 } 1679 }
1768 } 1680 }
1769 1681
1770 if (!haveUsableLabels) { 1682 if (!haveUsableLabels) {
1771 if (i->haveLabel()) { 1683 if (i->hasLabel()) {
1772 if (i->getLabel().contains(QRegExp("[0-9]"))) { 1684 if (i->getLabel().contains(QRegExp("[0-9]"))) {
1773 haveUsableLabels = true; 1685 haveUsableLabels = true;
1774 } 1686 }
1775 } 1687 }
1776 } 1688 }
1834 1746
1835 prevSelection = selection; 1747 prevSelection = selection;
1836 } 1748 }
1837 } 1749 }
1838 1750
1839 SparseTimeValueModel::Point prevPoint(0); 1751 Event prevPoint;
1840 1752
1841 for (Clipboard::PointList::const_iterator i = points.begin(); 1753 for (EventVector::const_iterator i = points.begin();
1842 i != points.end(); ++i) { 1754 i != points.end(); ++i) {
1843 1755
1844 if (!i->haveFrame()) continue;
1845
1846 sv_frame_t frame = 0; 1756 sv_frame_t frame = 0;
1847 1757
1848 if (!realign) { 1758 if (!realign) {
1849 1759
1850 frame = i->getFrame(); 1760 frame = i->getFrame();
1851 1761
1852 } else { 1762 } else {
1853 1763
1854 if (i->haveReferenceFrame()) { 1764 if (i->hasReferenceFrame()) {
1855 frame = i->getReferenceFrame(); 1765 frame = i->getReferenceFrame();
1856 frame = alignFromReference(v, frame); 1766 frame = alignFromReference(v, frame);
1857 } else { 1767 } else {
1858 frame = i->getFrame(); 1768 frame = i->getFrame();
1859 } 1769 }
1860 } 1770 }
1861 1771
1862 SparseTimeValueModel::Point newPoint(frame); 1772 Event newPoint = *i;
1863 1773 if (!i->hasLabel() && i->hasValue()) {
1864 if (i->haveLabel()) { 1774 newPoint = newPoint.withLabel(QString("%1").arg(i->getValue()));
1865 newPoint.label = i->getLabel();
1866 } else if (i->haveValue()) {
1867 newPoint.label = QString("%1").arg(i->getValue());
1868 } 1775 }
1869 1776
1870 bool usePrev = false; 1777 bool usePrev = false;
1871 SparseTimeValueModel::Point formerPrevPoint = prevPoint; 1778 Event formerPrevPoint = prevPoint;
1872 1779
1873 if (i->haveValue()) { 1780 if (!i->hasValue()) {
1874 newPoint.value = i->getValue(); 1781 #ifdef DEBUG_TIME_VALUE_LAYER
1875 } else { 1782 cerr << "Setting value on point at " << newPoint.getFrame() << " from labeller";
1876 #ifdef DEBUG_TIME_VALUE_LAYER
1877 cerr << "Setting value on point at " << newPoint.frame << " from labeller";
1878 if (i == points.begin()) { 1783 if (i == points.begin()) {
1879 cerr << ", no prev point" << endl; 1784 cerr << ", no prev point" << endl;
1880 } else { 1785 } else {
1881 cerr << ", prev point is at " << prevPoint.frame << endl; 1786 cerr << ", prev point is at " << prevPoint.getFrame() << endl;
1882 } 1787 }
1883 #endif 1788 #endif
1884 labeller.setValue<SparseTimeValueModel::Point> 1789
1790 Labeller::Revaluing valuing =
1791 labeller.revalue
1885 (newPoint, (i == points.begin()) ? nullptr : &prevPoint); 1792 (newPoint, (i == points.begin()) ? nullptr : &prevPoint);
1886 #ifdef DEBUG_TIME_VALUE_LAYER 1793
1887 cerr << "New point value = " << newPoint.value << endl; 1794 #ifdef DEBUG_TIME_VALUE_LAYER
1888 #endif 1795 cerr << "New point value = " << newPoint.getValue() << endl;
1889 if (labeller.actingOnPrevPoint() && i != points.begin()) { 1796 #endif
1797 if (valuing.first == Labeller::AppliesToPreviousEvent) {
1890 usePrev = true; 1798 usePrev = true;
1799 prevPoint = valuing.second;
1800 } else {
1801 newPoint = valuing.second;
1891 } 1802 }
1892 } 1803 }
1893 1804
1894 if (usePrev) { 1805 if (usePrev) {
1895 command->deletePoint(formerPrevPoint); 1806 command->remove(formerPrevPoint);
1896 command->addPoint(prevPoint); 1807 command->add(prevPoint);
1897 } 1808 }
1898 1809
1899 prevPoint = newPoint; 1810 prevPoint = newPoint;
1900 command->addPoint(newPoint); 1811 command->add(newPoint);
1901 } 1812 }
1902 1813
1903 finish(command); 1814 finish(command);
1904 return true; 1815 return true;
1905 } 1816 }