Mercurial > hg > svgui
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 } |