Mercurial > hg > svgui
diff layer/TimeValueLayer.cpp @ 125:999ae0f7d10c
* Change preferences dialog to ok/apply/cancel model
* Make preferences persist in a config file
* Change instance() to getInstance() for all singleton types
* Make pasting to time-value layer with no values in clipboard ask you how to
generate the values
* Fix bad behaviour caused by importing "data"-type (i.e. 3d dense) model from
annotation file without a fixed window size available
author | Chris Cannam |
---|---|
date | Thu, 27 Jul 2006 16:06:32 +0000 |
parents | 0f36cdf407a6 |
children | 33929e0c3c6b |
line wrap: on
line diff
--- a/layer/TimeValueLayer.cpp Wed Jul 26 16:48:07 2006 +0000 +++ b/layer/TimeValueLayer.cpp Thu Jul 27 16:06:32 2006 +0000 @@ -23,12 +23,14 @@ #include "model/SparseTimeValueModel.h" #include "widgets/ItemEditDialog.h" +#include "widgets/ListInputDialog.h" #include "SpectrogramLayer.h" // for optional frequency alignment #include <QPainter> #include <QPainterPath> #include <QMouseEvent> +#include <QRegExp> #include <iostream> #include <cmath> @@ -1131,16 +1133,143 @@ } } -void -TimeValueLayer::paste(const Clipboard &from, int frameOffset) +bool +TimeValueLayer::paste(const Clipboard &from, int frameOffset, + bool interactive) { - if (!m_model) return; + if (!m_model) return false; const Clipboard::PointList &points = from.getPoints(); SparseTimeValueModel::EditCommand *command = new SparseTimeValueModel::EditCommand(m_model, tr("Paste")); + enum ValueAvailability { + UnknownAvailability, + NoValues, + SomeValues, + AllValues + }; + enum ValueGeneration { + GenerateNone, + GenerateFromCounter, + GenerateFromFrameNumber, + GenerateFromRealTime, + GenerateFromRealTimeDifference, + GenerateFromTempo, + GenerateFromExistingNeighbour, + GenerateFromLabels + }; + + ValueGeneration generation = GenerateNone; + + bool haveUsableLabels = false; + bool haveExistingItems = !(m_model->isEmpty()); + + if (interactive) { + + ValueAvailability availability = UnknownAvailability; + + for (Clipboard::PointList::const_iterator i = points.begin(); + i != points.end(); ++i) { + + if (!i->haveFrame()) continue; + + if (availability == UnknownAvailability) { + if (i->haveValue()) availability = AllValues; + else availability = NoValues; + continue; + } + + if (i->haveValue()) { + if (availability == NoValues) { + availability = SomeValues; + } + } else { + if (availability == AllValues) { + availability = SomeValues; + } + } + + if (!haveUsableLabels) { + if (i->haveLabel()) { + if (i->getLabel().contains(QRegExp("[0-9]"))) { + haveUsableLabels = true; + } + } + } + + if (availability == SomeValues && haveUsableLabels) break; + } + + if (availability == NoValues || availability == SomeValues) { + + QString text; + if (availability == NoValues) { + text = tr("The items you are pasting do not have values.\nWhat values do you want to use for these items?"); + } else { + text = tr("Some of the items you are pasting do not have values.\nWhat values do you want to use for these items?"); + } + + QStringList options; + std::vector<int> genopts; + + options << tr("Zero for all items"); + genopts.push_back(int(GenerateNone)); + + options << tr("Whole numbers counting from 1"); + genopts.push_back(int(GenerateFromCounter)); + + options << tr("Item's audio sample frame number"); + genopts.push_back(int(GenerateFromFrameNumber)); + + options << tr("Item's time in seconds"); + genopts.push_back(int(GenerateFromRealTime)); + + options << tr("Duration from the item to the following item"); + genopts.push_back(int(GenerateFromRealTimeDifference)); + + options << tr("Tempo in bpm derived from the duration"); + genopts.push_back(int(GenerateFromTempo)); + + if (haveExistingItems) { + options << tr("Value of the nearest existing item"); + genopts.push_back(int(GenerateFromExistingNeighbour)); + } + + if (haveUsableLabels) { + options << tr("Value extracted from the item's label (where possible)"); + genopts.push_back(int(GenerateFromLabels)); + } + + + static int prevSelection = 0; + + bool ok = false; + QString selected = ListInputDialog::getItem + (0, tr("Choose value calculation"), + text, options, prevSelection, &ok); + + if (!ok) return false; + int selection = 0; + generation = GenerateNone; + + for (QStringList::const_iterator i = options.begin(); + i != options.end(); ++i) { + if (selected == *i) { + generation = ValueGeneration(genopts[selection]); + break; + } + ++selection; + } + + prevSelection = selection; + } + } + + int counter = 1; + float prevBpm = 120.f; + for (Clipboard::PointList::const_iterator i = points.begin(); i != points.end(); ++i) { @@ -1151,15 +1280,91 @@ } SparseTimeValueModel::Point newPoint(frame); - if (i->haveLabel()) newPoint.label = i->getLabel(); - if (i->haveValue()) newPoint.value = i->getValue(); - else newPoint.value = (m_model->getValueMinimum() + - m_model->getValueMaximum()) / 2; + if (i->haveLabel()) { + newPoint.label = i->getLabel(); + } else if (i->haveValue()) { + newPoint.label = QString("%1").arg(i->getValue()); + } + + if (i->haveValue()) { + newPoint.value = i->getValue(); + } else { + + switch (generation) { + + case GenerateNone: + newPoint.value = 0; + break; + + case GenerateFromCounter: + newPoint.value = counter; + break; + + case GenerateFromFrameNumber: + newPoint.value = frame; + break; + + case GenerateFromRealTime: + newPoint.value = float(frame) / float(m_model->getSampleRate()); + break; + + case GenerateFromRealTimeDifference: + case GenerateFromTempo: + { + size_t nextFrame = frame; + Clipboard::PointList::const_iterator j = i; + for (; j != points.end(); ++j) { + if (!j->haveFrame()) continue; + if (j != i) break; + } + if (j != points.end()) { + nextFrame = j->getFrame(); + } + if (generation == GenerateFromRealTimeDifference) { + newPoint.value = float(nextFrame - frame) / + float(m_model->getSampleRate()); + } else { + float bpm = prevBpm; + if (nextFrame > frame) { + bpm = (60.f * m_model->getSampleRate()) / + (nextFrame - frame); + } + newPoint.value = bpm; + prevBpm = bpm; + } + break; + } + + case GenerateFromExistingNeighbour: + { + SparseTimeValueModel::PointList points = + m_model->getPoints(frame); + if (points.empty()) points = m_model->getPreviousPoints(frame); + if (points.empty()) points = m_model->getNextPoints(frame); + if (points.empty()) { + newPoint.value = 0.f; + } else { + newPoint.value = points.begin()->value; + } + } + + case GenerateFromLabels: + if (i->haveLabel()) { + // more forgiving than QString::toFloat() + newPoint.value = atof(i->getLabel().toLocal8Bit()); + } else { + newPoint.value = 0.f; + } + } + } command->addPoint(newPoint); + + ++counter; } command->finish(); + return true; } QString