comparison layer/TimeInstantLayer.cpp @ 360:d58701996fae

* Update remaining editable layers to support proper realignment on copy/paste * Permit pasting when no suitable layer is current: create a new layer on paste * Add preference for showing the splash screen or not * Rename spectrogram smoothing prefs (partly following Craig's suggestions)
author Chris Cannam
date Wed, 06 Feb 2008 14:15:09 +0000
parents 020c485aa7e0
children e1a9e478b7f2
comparison
equal deleted inserted replaced
359:020c485aa7e0 360:d58701996fae
28 #include "widgets/ListInputDialog.h" 28 #include "widgets/ListInputDialog.h"
29 29
30 #include <QPainter> 30 #include <QPainter>
31 #include <QMouseEvent> 31 #include <QMouseEvent>
32 #include <QTextStream> 32 #include <QTextStream>
33 #include <QMessageBox>
33 34
34 #include <iostream> 35 #include <iostream>
35 #include <cmath> 36 #include <cmath>
36 37
37 TimeInstantLayer::TimeInstantLayer() : 38 TimeInstantLayer::TimeInstantLayer() :
721 722
722 for (SparseOneDimensionalModel::PointList::iterator i = points.begin(); 723 for (SparseOneDimensionalModel::PointList::iterator i = points.begin();
723 i != points.end(); ++i) { 724 i != points.end(); ++i) {
724 if (s.contains(i->frame)) { 725 if (s.contains(i->frame)) {
725 Clipboard::Point point(i->frame, i->label); 726 Clipboard::Point point(i->frame, i->label);
726
727 //!!! This fails, because simply being "on the same pane as" a
728 // particular model is not enough to give this layer the same
729 // alignment as it. If it was generated by deriving from another
730 // layer's model, that would be... but it wasn't necessarily
731
732 point.setReferenceFrame(alignToReference(v, i->frame)); 727 point.setReferenceFrame(alignToReference(v, i->frame));
733
734 std::cerr << "TimeInstantLayer::copy: frame = " << i->frame << ", reference frame = " << point.getReferenceFrame() << std::endl;
735
736 to.addPoint(point); 728 to.addPoint(point);
737 } 729 }
738 } 730 }
739 } 731 }
740 732
741 bool 733 bool
742 TimeInstantLayer::clipboardAlignmentDiffers(View *v, const Clipboard &clip) const 734 TimeInstantLayer::paste(View *v, const Clipboard &from, int frameOffset, bool)
743 { 735 {
744 //!!! hoist -- all pastable layers will need this
745
746 //!!! This fails, because simply being "on the same pane as" a
747 // particular model is not enough to give this layer the same
748 // alignment as it. If it was generated by deriving from another
749 // layer's model, that would be... but it wasn't necessarily
750
751 if (!m_model) return false; 736 if (!m_model) return false;
752 737
753 std::cerr << "TimeInstantLayer::clipboardAlignmentDiffers" << std::endl; 738 const Clipboard::PointList &points = from.getPoints();
754 739
755 for (Clipboard::PointList::const_iterator i = clip.getPoints().begin(); 740 bool realign = false;
756 i != clip.getPoints().end(); ++i) { 741
757 742 if (clipboardHasDifferentAlignment(v, from)) {
758 // In principle, we want to know whether the aligned version 743
759 // of the reference frame in our model is the same as the 744 QMessageBox::StandardButton button =
760 // source frame contained in the clipboard point. However, 745 QMessageBox::question(v, tr("Re-align pasted instants?"),
761 // because of rounding during alignment, that won't 746 tr("The instants you are pasting came from a layer with different source material from this one. Do you want to re-align them in time, to match the source material for this layer?"),
762 // necessarily be the case even if the clipboard point came 747 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
763 // from our model! What we need to check is whether, if we 748 QMessageBox::Yes);
764 // aligned the clipboard point's frame back to the reference 749
765 // using this model's alignment, we would obtain the same 750 if (button == QMessageBox::Cancel) {
766 // reference frame as that for the clipboard point. 751 return false;
767
768 // What if the clipboard point has no reference frame? Then
769 // we have to treat it as having its own frame as the
770 // reference (i.e. having been copied from the reference
771 // model).
772
773 long sourceFrame = i->getFrame();
774 long referenceFrame = sourceFrame;
775 if (i->haveReferenceFrame()) {
776 referenceFrame = i->getReferenceFrame();
777 } 752 }
778 long myMappedFrame = alignToReference(v, sourceFrame); 753
779 754 if (button == QMessageBox::Yes) {
780 std::cerr << "sourceFrame = " << sourceFrame << ", referenceFrame = " << referenceFrame << " (have = " << i->haveReferenceFrame() << "), myMappedFrame = " << myMappedFrame << std::endl; 755 realign = true;
781 756 }
782 if (myMappedFrame != referenceFrame) return true;
783 }
784
785 return false;
786 }
787
788 bool
789 TimeInstantLayer::paste(View *v, const Clipboard &from, int frameOffset, bool)
790 {
791 if (!m_model) return false;
792
793 const Clipboard::PointList &points = from.getPoints();
794
795 //!!!
796
797 // Clipboard::haveReferenceFrames() will return true if any of the
798 // items in the clipboard came from an aligned, non-reference model.
799
800 // We need to know whether these points came from our model or not
801 // -- if they did, we don't want to align them.
802
803 // If they didn't come from our model, and if reference frames are
804 // available, then we want to offer to align them. If reference
805 // frames are unavailable but they came from the reference model,
806 // we want to offer to align them too.
807
808
809 //!!!
810
811 // Each point may have a reference frame that may differ from the
812 // point's given frame (in its source model). If it has no
813 // reference frame, we have to assume the source model was not
814 // aligned or was the reference model: when cutting or copying
815 // points from a layer, we must always set their reference frame
816 // correctly if we are aligned.
817 //
818 // When pasting:
819 // - if point's reference and aligned frames differ:
820 // - if this layer is aligned:
821 // - if point's aligned frame matches this layer's aligned version
822 // of point's reference frame:
823 // - we can paste at reference frame or our frame
824 // - else
825 // - we can paste at reference frame, result of aligning reference
826 // frame in our model, or literal source frame
827 // - else
828 // - we can paste at reference (our) frame, or literal source frame
829 // - else
830 // - if this layer is aligned:
831 // - we can paste at reference (point's only available) frame,
832 // or result of aligning reference frame in our model
833 // - else
834 // - we can only paste at reference frame
835 //
836 // Which of these alternatives are useful?
837 //
838 // Example: we paste between two tracks that are aligned to the
839 // same reference, and the points are at 10s and 20s in the source
840 // track, corresponding to 5s and 10s in the reference but 20s and
841 // 30s in the target track.
842 //
843 // The obvious default is to paste at 20s and 30s; if we aren't
844 // doing that, would it be better to paste at 5s and 10s or at 10s
845 // and 20s? We probably don't ever want to do the former, do we?
846 // We either want to be literal all the way through, or aligned
847 // all the way through.
848
849 bool realign = false;
850
851 if (clipboardAlignmentDiffers(v, from)) {
852
853 std::cerr << "Offer alignment option..." << std::endl;
854
855 QStringList options;
856 options << "Use times unchanged from the original layer";
857 options << "Re-align times to match the same points in the reference layer";
858
859 bool ok = false;
860
861 QString selected = ListInputDialog::getItem
862 (0, tr("Choose alignment"),
863 tr("The points you are pasting originated in a layer with different alignment from the current layer. Would you like to re-align them when pasting?"),
864 options, 0, &ok);
865 if (!ok) return false;
866
867 if (selected == options[1]) realign = true;
868 } 757 }
869 758
870 SparseOneDimensionalModel::EditCommand *command = 759 SparseOneDimensionalModel::EditCommand *command =
871 new SparseOneDimensionalModel::EditCommand(m_model, tr("Paste")); 760 new SparseOneDimensionalModel::EditCommand(m_model, tr("Paste"));
872 761