Mercurial > hg > svgui
changeset 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 | 67834ac56f2b |
files | layer/ImageLayer.cpp layer/Layer.cpp layer/Layer.h layer/LayerFactory.cpp layer/LayerFactory.h layer/NoteLayer.cpp layer/TextLayer.cpp layer/TimeInstantLayer.cpp layer/TimeValueLayer.cpp widgets/PropertyStack.cpp |
diffstat | 10 files changed, 259 insertions(+), 152 deletions(-) [+] |
line wrap: on
line diff
--- a/layer/ImageLayer.cpp Wed Feb 06 12:49:49 2008 +0000 +++ b/layer/ImageLayer.cpp Wed Feb 06 14:15:09 2008 +0000 @@ -30,6 +30,7 @@ #include <QInputDialog> #include <QMutexLocker> #include <QTextStream> +#include <QMessageBox> #include <iostream> #include <cmath> @@ -812,9 +813,8 @@ for (ImageModel::PointList::iterator i = points.begin(); i != points.end(); ++i) { if (s.contains(i->frame)) { - //!!! inadequate Clipboard::Point point(i->frame, i->label); - point.setReferenceFrame(m_model->alignToReference(i->frame)); + point.setReferenceFrame(alignToReference(v, i->frame)); to.addPoint(point); } } @@ -827,6 +827,25 @@ const Clipboard::PointList &points = from.getPoints(); + bool realign = false; + + if (clipboardHasDifferentAlignment(v, from)) { + + QMessageBox::StandardButton button = + QMessageBox::question(v, tr("Re-align pasted items?"), + tr("The items 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?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, + QMessageBox::Yes); + + if (button == QMessageBox::Cancel) { + return false; + } + + if (button == QMessageBox::Yes) { + realign = true; + } + } + ImageModel::EditCommand *command = new ImageModel::EditCommand(m_model, tr("Paste")); @@ -834,10 +853,23 @@ i != points.end(); ++i) { if (!i->haveFrame()) continue; + size_t frame = 0; - if (frameOffset > 0 || -frameOffset < i->getFrame()) { - frame = i->getFrame() + frameOffset; + + if (!realign) { + + frame = i->getFrame(); + + } else { + + if (i->haveReferenceFrame()) { + frame = i->getReferenceFrame(); + frame = alignFromReference(v, frame); + } else { + frame = i->getFrame(); + } } + ImageModel::Point newPoint(frame); //!!! inadequate
--- a/layer/Layer.cpp Wed Feb 06 12:49:49 2008 +0000 +++ b/layer/Layer.cpp Wed Feb 06 14:15:09 2008 +0000 @@ -184,6 +184,82 @@ } bool +Layer::clipboardHasDifferentAlignment(View *v, const Clipboard &clip) const +{ + // Notes on pasting to an aligned layer: + // + // Each point may have a reference frame that may differ from the + // point's given frame (in its source model). If it has no + // reference frame, we have to assume the source model was not + // aligned or was the reference model: when cutting or copying + // points from a layer, we must always set their reference frame + // correctly if we are aligned. + // + // When pasting: + // - if point's reference and aligned frames differ: + // - if this layer is aligned: + // - if point's aligned frame matches this layer's aligned version + // of point's reference frame: + // - we can paste at reference frame or our frame + // - else + // - we can paste at reference frame, result of aligning reference + // frame in our model, or literal source frame + // - else + // - we can paste at reference (our) frame, or literal source frame + // - else + // - if this layer is aligned: + // - we can paste at reference (point's only available) frame, + // or result of aligning reference frame in our model + // - else + // - we can only paste at reference frame + // + // Which of these alternatives are useful? + // + // Example: we paste between two tracks that are aligned to the + // same reference, and the points are at 10s and 20s in the source + // track, corresponding to 5s and 10s in the reference but 20s and + // 30s in the target track. + // + // The obvious default is to paste at 20s and 30s; if we aren't + // doing that, would it be better to paste at 5s and 10s or at 10s + // and 20s? We probably don't ever want to do the former, do we? + // We either want to be literal all the way through, or aligned + // all the way through. + + for (Clipboard::PointList::const_iterator i = clip.getPoints().begin(); + i != clip.getPoints().end(); ++i) { + + // In principle, we want to know whether the aligned version + // of the reference frame in our layer is the same as the + // source frame contained in the clipboard point. However, + // because of rounding during alignment, that won't + // necessarily be the case even if the clipboard point came + // from our layer! What we need to check is whether, if we + // aligned the clipboard point's frame back to the reference + // using this layer's alignment, we would obtain the same + // reference frame as that for the clipboard point. + + // What if the clipboard point has no reference frame? Then + // we have to treat it as having its own frame as the + // reference (i.e. having been copied from the reference + // model). + + long sourceFrame = i->getFrame(); + long referenceFrame = sourceFrame; + if (i->haveReferenceFrame()) { + referenceFrame = i->getReferenceFrame(); + } + long myMappedFrame = alignToReference(v, sourceFrame); + +// std::cerr << "sourceFrame = " << sourceFrame << ", referenceFrame = " << referenceFrame << " (have = " << i->haveReferenceFrame() << "), myMappedFrame = " << myMappedFrame << std::endl; + + if (myMappedFrame != referenceFrame) return true; + } + + return false; +} + +bool Layer::MeasureRect::operator<(const MeasureRect &mr) const { if (haveFrames) {
--- a/layer/Layer.h Wed Feb 06 12:49:49 2008 +0000 +++ b/layer/Layer.h Wed Feb 06 14:15:09 2008 +0000 @@ -468,6 +468,7 @@ virtual size_t alignToReference(View *v, size_t frame) const; virtual size_t alignFromReference(View *v, size_t frame) const; + bool clipboardHasDifferentAlignment(View *v, const Clipboard &clip) const; struct MeasureRect {
--- a/layer/LayerFactory.cpp Wed Feb 06 12:49:49 2008 +0000 +++ b/layer/LayerFactory.cpp Wed Feb 06 14:15:09 2008 +0000 @@ -28,6 +28,8 @@ #include "SliceLayer.h" #include "SliceableLayer.h" +#include "base/Clipboard.h" + #include "data/model/RangeSummarisableTimeValueModel.h" #include "data/model/DenseTimeValueModel.h" #include "data/model/SparseOneDimensionalModel.h" @@ -482,3 +484,24 @@ settings.endGroup(); } +LayerFactory::LayerType +LayerFactory::getLayerTypeForClipboardContents(const Clipboard &clip) +{ + const Clipboard::PointList &contents = clip.getPoints(); + + bool haveFrame = false; + bool haveValue = false; + bool haveDuration = false; + + for (Clipboard::PointList::const_iterator i = contents.begin(); + i != contents.end(); ++i) { + if (i->haveFrame()) haveFrame = true; + if (i->haveValue()) haveValue = true; + if (i->haveDuration()) haveDuration = true; + } + + if (haveFrame && haveValue && haveDuration) return Notes; + if (haveFrame && haveValue) return TimeValues; + return TimeInstants; +} +
--- a/layer/LayerFactory.h Wed Feb 06 12:49:49 2008 +0000 +++ b/layer/LayerFactory.h Wed Feb 06 14:15:09 2008 +0000 @@ -21,6 +21,7 @@ class Layer; class Model; +class Clipboard; class LayerFactory { @@ -76,6 +77,8 @@ QString getLayerTypeName(LayerType); LayerType getLayerTypeForName(QString); + LayerType getLayerTypeForClipboardContents(const Clipboard &); + protected: template <typename LayerClass, typename ModelClass> bool trySetModel(Layer *layerBase, Model *modelBase) {
--- a/layer/NoteLayer.cpp Wed Feb 06 12:49:49 2008 +0000 +++ b/layer/NoteLayer.cpp Wed Feb 06 14:15:09 2008 +0000 @@ -33,6 +33,7 @@ #include <QPainterPath> #include <QMouseEvent> #include <QTextStream> +#include <QMessageBox> #include <iostream> #include <cmath> @@ -927,7 +928,7 @@ i != points.end(); ++i) { if (s.contains(i->frame)) { Clipboard::Point point(i->frame, i->value, i->duration, i->level, i->label); - point.setReferenceFrame(m_model->alignToReference(i->frame)); + point.setReferenceFrame(alignToReference(v, i->frame)); to.addPoint(point); } } @@ -940,6 +941,25 @@ const Clipboard::PointList &points = from.getPoints(); + bool realign = false; + + if (clipboardHasDifferentAlignment(v, from)) { + + QMessageBox::StandardButton button = + QMessageBox::question(v, tr("Re-align pasted items?"), + tr("The items 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?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, + QMessageBox::Yes); + + if (button == QMessageBox::Cancel) { + return false; + } + + if (button == QMessageBox::Yes) { + realign = true; + } + } + NoteModel::EditCommand *command = new NoteModel::EditCommand(m_model, tr("Paste")); @@ -948,9 +968,21 @@ if (!i->haveFrame()) continue; size_t frame = 0; - if (frameOffset > 0 || -frameOffset < i->getFrame()) { - frame = i->getFrame() + frameOffset; + + if (!realign) { + + frame = i->getFrame(); + + } else { + + if (i->haveReferenceFrame()) { + frame = i->getReferenceFrame(); + frame = alignFromReference(v, frame); + } else { + frame = i->getFrame(); + } } + NoteModel::Point newPoint(frame); if (i->haveLabel()) newPoint.label = i->getLabel();
--- a/layer/TextLayer.cpp Wed Feb 06 12:49:49 2008 +0000 +++ b/layer/TextLayer.cpp Wed Feb 06 14:15:09 2008 +0000 @@ -27,6 +27,7 @@ #include <QMouseEvent> #include <QInputDialog> #include <QTextStream> +#include <QMessageBox> #include <iostream> #include <cmath> @@ -682,7 +683,7 @@ i != points.end(); ++i) { if (s.contains(i->frame)) { Clipboard::Point point(i->frame, i->height, i->label); - point.setReferenceFrame(m_model->alignToReference(i->frame)); + point.setReferenceFrame(alignToReference(v, i->frame)); to.addPoint(point); } } @@ -695,6 +696,25 @@ const Clipboard::PointList &points = from.getPoints(); + bool realign = false; + + if (clipboardHasDifferentAlignment(v, from)) { + + QMessageBox::StandardButton button = + QMessageBox::question(v, tr("Re-align pasted items?"), + tr("The items 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?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, + QMessageBox::Yes); + + if (button == QMessageBox::Cancel) { + return false; + } + + if (button == QMessageBox::Yes) { + realign = true; + } + } + TextModel::EditCommand *command = new TextModel::EditCommand(m_model, tr("Paste")); @@ -713,9 +733,21 @@ if (!i->haveFrame()) continue; size_t frame = 0; - if (frameOffset > 0 || -frameOffset < i->getFrame()) { - frame = i->getFrame() + frameOffset; + + if (!realign) { + + frame = i->getFrame(); + + } else { + + if (i->haveReferenceFrame()) { + frame = i->getReferenceFrame(); + frame = alignFromReference(v, frame); + } else { + frame = i->getFrame(); + } } + TextModel::Point newPoint(frame); if (i->haveValue()) {
--- a/layer/TimeInstantLayer.cpp Wed Feb 06 12:49:49 2008 +0000 +++ b/layer/TimeInstantLayer.cpp Wed Feb 06 14:15:09 2008 +0000 @@ -30,6 +30,7 @@ #include <QPainter> #include <QMouseEvent> #include <QTextStream> +#include <QMessageBox> #include <iostream> #include <cmath> @@ -723,148 +724,36 @@ i != points.end(); ++i) { if (s.contains(i->frame)) { Clipboard::Point point(i->frame, i->label); - - //!!! This fails, because simply being "on the same pane as" a - // particular model is not enough to give this layer the same - // alignment as it. If it was generated by deriving from another - // layer's model, that would be... but it wasn't necessarily - point.setReferenceFrame(alignToReference(v, i->frame)); - - std::cerr << "TimeInstantLayer::copy: frame = " << i->frame << ", reference frame = " << point.getReferenceFrame() << std::endl; - to.addPoint(point); } } } bool -TimeInstantLayer::clipboardAlignmentDiffers(View *v, const Clipboard &clip) const -{ - //!!! hoist -- all pastable layers will need this - - //!!! This fails, because simply being "on the same pane as" a - // particular model is not enough to give this layer the same - // alignment as it. If it was generated by deriving from another - // layer's model, that would be... but it wasn't necessarily - - if (!m_model) return false; - - std::cerr << "TimeInstantLayer::clipboardAlignmentDiffers" << std::endl; - - for (Clipboard::PointList::const_iterator i = clip.getPoints().begin(); - i != clip.getPoints().end(); ++i) { - - // In principle, we want to know whether the aligned version - // of the reference frame in our model is the same as the - // source frame contained in the clipboard point. However, - // because of rounding during alignment, that won't - // necessarily be the case even if the clipboard point came - // from our model! What we need to check is whether, if we - // aligned the clipboard point's frame back to the reference - // using this model's alignment, we would obtain the same - // reference frame as that for the clipboard point. - - // What if the clipboard point has no reference frame? Then - // we have to treat it as having its own frame as the - // reference (i.e. having been copied from the reference - // model). - - long sourceFrame = i->getFrame(); - long referenceFrame = sourceFrame; - if (i->haveReferenceFrame()) { - referenceFrame = i->getReferenceFrame(); - } - long myMappedFrame = alignToReference(v, sourceFrame); - - std::cerr << "sourceFrame = " << sourceFrame << ", referenceFrame = " << referenceFrame << " (have = " << i->haveReferenceFrame() << "), myMappedFrame = " << myMappedFrame << std::endl; - - if (myMappedFrame != referenceFrame) return true; - } - - return false; -} - -bool TimeInstantLayer::paste(View *v, const Clipboard &from, int frameOffset, bool) { if (!m_model) return false; const Clipboard::PointList &points = from.getPoints(); - //!!! - - // Clipboard::haveReferenceFrames() will return true if any of the - // items in the clipboard came from an aligned, non-reference model. - - // We need to know whether these points came from our model or not - // -- if they did, we don't want to align them. - - // If they didn't come from our model, and if reference frames are - // available, then we want to offer to align them. If reference - // frames are unavailable but they came from the reference model, - // we want to offer to align them too. - - - //!!! - - // Each point may have a reference frame that may differ from the - // point's given frame (in its source model). If it has no - // reference frame, we have to assume the source model was not - // aligned or was the reference model: when cutting or copying - // points from a layer, we must always set their reference frame - // correctly if we are aligned. - // - // When pasting: - // - if point's reference and aligned frames differ: - // - if this layer is aligned: - // - if point's aligned frame matches this layer's aligned version - // of point's reference frame: - // - we can paste at reference frame or our frame - // - else - // - we can paste at reference frame, result of aligning reference - // frame in our model, or literal source frame - // - else - // - we can paste at reference (our) frame, or literal source frame - // - else - // - if this layer is aligned: - // - we can paste at reference (point's only available) frame, - // or result of aligning reference frame in our model - // - else - // - we can only paste at reference frame - // - // Which of these alternatives are useful? - // - // Example: we paste between two tracks that are aligned to the - // same reference, and the points are at 10s and 20s in the source - // track, corresponding to 5s and 10s in the reference but 20s and - // 30s in the target track. - // - // The obvious default is to paste at 20s and 30s; if we aren't - // doing that, would it be better to paste at 5s and 10s or at 10s - // and 20s? We probably don't ever want to do the former, do we? - // We either want to be literal all the way through, or aligned - // all the way through. - bool realign = false; - if (clipboardAlignmentDiffers(v, from)) { + if (clipboardHasDifferentAlignment(v, from)) { - std::cerr << "Offer alignment option..." << std::endl; + QMessageBox::StandardButton button = + QMessageBox::question(v, tr("Re-align pasted instants?"), + 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?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, + QMessageBox::Yes); - QStringList options; - options << "Use times unchanged from the original layer"; - options << "Re-align times to match the same points in the reference layer"; + if (button == QMessageBox::Cancel) { + return false; + } - bool ok = false; - - QString selected = ListInputDialog::getItem - (0, tr("Choose alignment"), - 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?"), - options, 0, &ok); - if (!ok) return false; - - if (selected == options[1]) realign = true; + if (button == QMessageBox::Yes) { + realign = true; + } } SparseOneDimensionalModel::EditCommand *command =
--- a/layer/TimeValueLayer.cpp Wed Feb 06 12:49:49 2008 +0000 +++ b/layer/TimeValueLayer.cpp Wed Feb 06 14:15:09 2008 +0000 @@ -36,6 +36,7 @@ #include <QMouseEvent> #include <QRegExp> #include <QTextStream> +#include <QMessageBox> #include <QInputDialog> #include <iostream> @@ -1196,7 +1197,7 @@ i != points.end(); ++i) { if (s.contains(i->frame)) { Clipboard::Point point(i->frame, i->value, i->label); - point.setReferenceFrame(m_model->alignToReference(i->frame)); + point.setReferenceFrame(alignToReference(v, i->frame)); to.addPoint(point); } } @@ -1210,6 +1211,25 @@ const Clipboard::PointList &points = from.getPoints(); + bool realign = false; + + if (clipboardHasDifferentAlignment(v, from)) { + + QMessageBox::StandardButton button = + QMessageBox::question(v, tr("Re-align pasted items?"), + tr("The items 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?"), + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, + QMessageBox::Yes); + + if (button == QMessageBox::Cancel) { + return false; + } + + if (button == QMessageBox::Yes) { + realign = true; + } + } + SparseTimeValueModel::EditCommand *command = new SparseTimeValueModel::EditCommand(m_model, tr("Paste")); @@ -1324,10 +1344,23 @@ i != points.end(); ++i) { if (!i->haveFrame()) continue; + size_t frame = 0; - if (frameOffset > 0 || -frameOffset < i->getFrame()) { - frame = i->getFrame() + frameOffset; + + if (!realign) { + + frame = i->getFrame(); + + } else { + + if (i->haveReferenceFrame()) { + frame = i->getReferenceFrame(); + frame = alignFromReference(v, frame); + } else { + frame = i->getFrame(); + } } + SparseTimeValueModel::Point newPoint(frame); if (i->haveLabel()) { @@ -1349,7 +1382,7 @@ command->finish(); return true; - } +} void TimeValueLayer::toXml(QTextStream &stream,
--- a/widgets/PropertyStack.cpp Wed Feb 06 12:49:49 2008 +0000 +++ b/widgets/PropertyStack.cpp Wed Feb 06 14:15:09 2008 +0000 @@ -114,18 +114,6 @@ shortName = QString("&%1 %2").arg(i + 1).arg(shortName); -//!!! We'll comment this out until it's been tested with Qt 4.3.3 -#ifdef Q_WS_MAC___NOT_DEFINED - - // Qt 4.2 on OS/X doesn't show the icons in the tab bar, and - // I'm not sure why -- use labels instead - - addTab(box, shortName); - -#else - - // Icons on other platforms - QString iconName = container->getPropertyContainerIconName(); QIcon icon(IconLoader().load(iconName)); @@ -136,8 +124,6 @@ setTabToolTip(i, name); } -#endif - m_boxes.push_back(box); }