1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-06 14:52:34 +02:00

Clarify paste logic, throw to rollback on error, keep TimeTrack unique...

... though TimeTracks are not yet ever cut or copied; but next commit will
change that.
This commit is contained in:
Paul Licameli 2017-03-31 14:58:01 -04:00
parent 608dcc9b3f
commit ad34145ded

View File

@ -4351,31 +4351,29 @@ void AudacityProject::OnPaste()
if (c == NULL)
return;
Track *ff = NULL;
const Track *tmpSrc = NULL;
const Track *tmpC = NULL;
const Track *prev = NULL;
const Track *lastClipBeforeMismatch = NULL;
const Track *mismatchedClip = NULL;
const Track *prevClip = NULL;
bool bAdvanceClipboard = true;
bool bPastedSomething = false;
bool bTrackTypeMismatch = false;
while (n && c) {
if (n->GetSelected()) {
bAdvanceClipboard = true;
if (tmpC)
c = tmpC;
if (mismatchedClip)
c = mismatchedClip;
if (c->GetKind() != n->GetKind()) {
if (!bTrackTypeMismatch) {
tmpSrc = prev;
tmpC = c;
if (!mismatchedClip) {
lastClipBeforeMismatch = prevClip;
mismatchedClip = c;
}
bTrackTypeMismatch = true;
bAdvanceClipboard = false;
c = tmpSrc;
c = lastClipBeforeMismatch;
// If the types still don't match...
while (c && c->GetKind() != n->GetKind()) {
prev = c;
prevClip = c;
c = clipIter.Next();
}
}
@ -4383,7 +4381,7 @@ void AudacityProject::OnPaste()
// Handle case where the first track in clipboard
// is of different type than the first selected track
if (!c) {
c = tmpC;
c = mismatchedClip;
while (n && (c->GetKind() != n->GetKind() || !n->GetSelected()))
{
// Must perform sync-lock adjustment before incrementing n
@ -4399,39 +4397,40 @@ void AudacityProject::OnPaste()
// The last possible case for cross-type pastes: triggered when we try to
// paste 1+ tracks from one type into 1+ tracks of another type. If
// there's a mix of types, this shouldn't run.
if (!c) {
wxMessageBox(
_("Pasting one type of track into another is not allowed."),
_("Error"), wxICON_ERROR, this);
c = n;//so we don't trigger any !c conditions on our way out
break;
}
if (!c)
// Throw, so that any previous changes to the project in this loop
// are discarded.
throw SimpleMessageBoxException{
_("Pasting one type of track into another is not allowed.")
};
// When trying to copy from stereo to mono track, show error and exit
// TODO: Automatically offer user to mix down to mono (unfortunately
// this is not easy to implement
if (c->GetLinked() && !n->GetLinked())
{
wxMessageBox(
_("Copying stereo audio into a mono track is not allowed."),
_("Error"), wxICON_ERROR, this);
break;
}
// Throw, so that any previous changes to the project in this loop
// are discarded.
throw SimpleMessageBoxException{
_("Copying stereo audio into a mono track is not allowed.")
};
if (!ff)
ff = n;
Maybe<WaveTrack::Locker> locker;
if (msClipProject != this && c->GetKind() == Track::Wave)
// Cause duplication of block files on disk, when copy is
// between projects
locker.create(static_cast<const WaveTrack*>(c));
if (c->GetKind() == Track::Wave && n && n->GetKind() == Track::Wave)
wxASSERT( n && c );
if (c->GetKind() == Track::Wave && n->GetKind() == Track::Wave)
{
bPastedSomething |=
((WaveTrack*)n)->ClearAndPaste(t0, t1, (WaveTrack*)c, true, true);
}
else if (c->GetKind() == Track::Label &&
n && n->GetKind() == Track::Label)
n->GetKind() == Track::Label)
{
((LabelTrack *)n)->Clear(t0, t1);
@ -4444,6 +4443,7 @@ void AudacityProject::OnPaste()
}
else
{
n->Clear(t0, t1);
bPastedSomething |= n->Paste(t0, c);
}
@ -4464,7 +4464,7 @@ void AudacityProject::OnPaste()
}
if (bAdvanceClipboard){
prev = c;
prevClip = c;
c = clipIter.Next();
}
} // if (n->GetSelected())
@ -4487,7 +4487,8 @@ void AudacityProject::OnPaste()
while (n) {
if (n->GetSelected() && n->GetKind()==Track::Wave) {
if (c && c->GetKind() == Track::Wave) {
if (c) {
wxASSERT(c->GetKind() == Track::Wave);
bPastedSomething |=
((WaveTrack *)n)->ClearAndPaste(t0, t1, (WaveTrack *)c, true, true);
}
@ -4598,29 +4599,40 @@ bool AudacityProject::HandlePasteNothingSelected()
while (pClip) {
Maybe<WaveTrack::Locker> locker;
if ((msClipProject != this) && (pClip->GetKind() == Track::Wave))
// Cause duplication of block files on disk, when copy is
// between projects
locker.create(static_cast<const WaveTrack*>(pClip));
Track::Holder pNewTrack;
Track::Holder uNewTrack;
Track *pNewTrack;
switch (pClip->GetKind()) {
case Track::Wave:
{
WaveTrack *w = (WaveTrack *)pClip;
pNewTrack = mTrackFactory->NewWaveTrack(w->GetSampleFormat(), w->GetRate());
uNewTrack = mTrackFactory->NewWaveTrack(w->GetSampleFormat(), w->GetRate()),
pNewTrack = uNewTrack.get();
}
break;
#ifdef USE_MIDI
case Track::Note:
pNewTrack = mTrackFactory->NewNoteTrack();
uNewTrack = mTrackFactory->NewNoteTrack(),
pNewTrack = uNewTrack.get();
break;
#endif // USE_MIDI
case Track::Label:
pNewTrack = mTrackFactory->NewLabelTrack();
uNewTrack = mTrackFactory->NewLabelTrack(),
pNewTrack = uNewTrack.get();
break;
case Track::Time:
pNewTrack = mTrackFactory->NewTimeTrack();
case Track::Time: {
// Maintain uniqueness of the time track!
pNewTrack = GetTracks()->GetTimeTrack();
if (!pNewTrack)
uNewTrack = mTrackFactory->NewTimeTrack(),
pNewTrack = uNewTrack.get();
break;
}
default:
pClip = iterClip.Next();
continue;
@ -4632,10 +4644,13 @@ bool AudacityProject::HandlePasteNothingSelected()
wxUnusedVar(bResult);
if (!pFirstNewTrack)
pFirstNewTrack = pNewTrack.get();
pFirstNewTrack = pNewTrack;
pNewTrack->SetSelected(true);
FinishCopy(pClip, std::move(pNewTrack), *mTracks);
if (uNewTrack)
FinishCopy(pClip, std::move(uNewTrack), *mTracks);
else
FinishCopy(pClip, pNewTrack);
pClip = iterClip.Next();
}