Audacity 3.2.0
EditMenus.cpp
Go to the documentation of this file.
1
2#include "../AdornedRulerPanel.h"
3#include "../Clipboard.h"
4#include "../CommonCommandFlags.h"
5#include "../LabelTrack.h"
6#include "../Menus.h"
7#include "../NoteTrack.h"
8#include "Prefs.h"
9#include "Project.h"
10#include "ProjectHistory.h"
11#include "ProjectRate.h"
12#include "../ProjectSettings.h"
13#include "../ProjectWindow.h"
14#include "../ProjectWindows.h"
15#include "../SelectUtilities.h"
16#include "../SyncLock.h"
17#include "../TrackPanel.h"
18#include "../TrackPanelAx.h"
19#include "UndoManager.h"
20#include "ViewInfo.h"
21#include "../WaveTrack.h"
22#include "../commands/CommandContext.h"
23#include "../commands/CommandManager.h"
24#include "TimeWarper.h"
25#include "../export/Export.h"
26#include "../prefs/PrefsDialog.h"
27#include "../tracks/labeltrack/ui/LabelTrackView.h"
28#include "../tracks/playabletrack/wavetrack/ui/WaveTrackView.h"
29#include "../widgets/AudacityMessageBox.h"
30#include "../widgets/VetoDialogHook.h"
31
32// private helper classes and functions
33namespace {
35 (const Track *n, const Track::Holder &dest, TrackList &list)
36{
37 Track::FinishCopy( n, dest.get() );
38 if (dest)
39 list.Add( dest );
40}
41
42// Handle text paste (into active label), if any. Return true if did paste.
43// (This was formerly the first part of overly-long OnPaste.)
45{
46 auto &tracks = TrackList::Get( project );
47 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
48 auto &window = ProjectWindow::Get( project );
49
50 for (auto pLabelTrack : tracks.Any<LabelTrack>())
51 {
52 // Does this track have an active label?
53 if (LabelTrackView::Get( *pLabelTrack ).GetTextEditIndex(project) != -1) {
54
55 // Yes, so try pasting into it
56 auto &view = LabelTrackView::Get( *pLabelTrack );
57 if (view.PasteSelectedText( project, selectedRegion.t0(),
58 selectedRegion.t1() ))
59 {
60 ProjectHistory::Get( project )
61 .PushState(XO("Pasted text from the clipboard"), XO("Paste"));
62
63 // Make sure caret is in view
64 int x;
65 if (view.CalcCursorX( project, &x )) {
66 window.ScrollIntoView(x);
67 }
68
69 return true;
70 }
71 }
72 }
73 return false;
74}
75
76// Return true if nothing selected, regardless of paste result.
77// If nothing was selected, create and paste into NEW tracks.
78// (This was formerly the second part of overly-long OnPaste.)
80{
81 auto &tracks = TrackList::Get( project );
82 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
83 auto &viewInfo = ViewInfo::Get( project );
84 auto &window = ProjectWindow::Get( project );
85
86 // First check whether anything's selected.
87 if (tracks.Selected())
88 return false;
89 else
90 {
91 const auto &clipboard = Clipboard::Get();
92 auto clipTrackRange = clipboard.GetTracks().Any< const Track >();
93 if (clipTrackRange.empty())
94 return true; // nothing to paste
95
96 Track* pFirstNewTrack = NULL;
97 for (auto pClip : clipTrackRange) {
98 auto pNewTrack = pClip->PasteInto( project );
99 bool newTrack = (pNewTrack.use_count() == 1);
100 wxASSERT(pClip);
101
102 if (!pFirstNewTrack)
103 pFirstNewTrack = pNewTrack.get();
104
105 pNewTrack->SetSelected(true);
106 if (newTrack)
107 FinishCopy(pClip, pNewTrack, tracks);
108 else
109 Track::FinishCopy(pClip, pNewTrack.get());
110 }
111
112 // Select some pasted samples, which is probably impossible to get right
113 // with various project and track sample rates.
114 // So do it at the sample rate of the project
115 double projRate = ProjectRate::Get( project ).GetRate();
116 double quantT0 = QUANTIZED_TIME(clipboard.T0(), projRate);
117 double quantT1 = QUANTIZED_TIME(clipboard.T1(), projRate);
118 selectedRegion.setTimes(
119 0.0, // anywhere else and this should be
120 // half a sample earlier
121 quantT1 - quantT0);
122
123 ProjectHistory::Get( project )
124 .PushState(XO("Pasted from the clipboard"), XO("Paste"));
125
126 if (pFirstNewTrack) {
127 TrackFocus::Get(project).Set(pFirstNewTrack);
128 pFirstNewTrack->EnsureVisible();
129 }
130
131 return true;
132 }
133}
134
135}
136
137namespace EditActions {
138
139// Menu handler functions
140
142void OnUndo(const CommandContext &context)
143{
144 auto &project = context.project;
145 auto &tracks = TrackList::Get( project );
146 auto &trackPanel = TrackPanel::Get( project );
147 auto &undoManager = UndoManager::Get( project );
148 auto &window = ProjectWindow::Get( project );
149
150 if (!ProjectHistory::Get( project ).UndoAvailable()) {
151 AudacityMessageBox( XO("Nothing to undo") );
152 return;
153 }
154
155 // can't undo while dragging
156 if (trackPanel.IsMouseCaptured()) {
157 return;
158 }
159
160 undoManager.Undo(
161 [&]( const UndoStackElem &elem ){
162 ProjectHistory::Get( project ).PopState( elem.state ); } );
163
164 auto t = *tracks.Selected().begin();
165 if (!t)
166 t = *tracks.Any().begin();
167 TrackFocus::Get(project).Set(t);
168 if (t) {
169 t->EnsureVisible();
170 }
171}
172
173void OnRedo(const CommandContext &context)
174{
175 auto &project = context.project;
176 auto &tracks = TrackList::Get( project );
177 auto &trackPanel = TrackPanel::Get( project );
178 auto &undoManager = UndoManager::Get( project );
179 auto &window = ProjectWindow::Get( project );
180
181 if (!ProjectHistory::Get( project ).RedoAvailable()) {
182 AudacityMessageBox( XO("Nothing to redo") );
183 return;
184 }
185 // Can't redo whilst dragging
186 if (trackPanel.IsMouseCaptured()) {
187 return;
188 }
189
190 undoManager.Redo(
191 [&]( const UndoStackElem &elem ){
192 ProjectHistory::Get( project ).PopState( elem.state ); } );
193
194 auto t = *tracks.Selected().begin();
195 if (!t)
196 t = *tracks.Any().begin();
197 TrackFocus::Get(project).Set(t);
198 if (t) {
199 t->EnsureVisible();
200 }
201}
202
203void OnCut(const CommandContext &context)
204{
205 auto &project = context.project;
206 auto &tracks = TrackList::Get( project );
207 auto &trackPanel = TrackPanel::Get( project );
208 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
209 auto &ruler = AdornedRulerPanel::Get( project );
210 auto &window = ProjectWindow::Get( project );
211
212 // This doesn't handle cutting labels, it handles
213 // cutting the _text_ inside of labels, i.e. if you're
214 // in the middle of editing the label text and select "Cut".
215
216 for (auto lt : tracks.Selected< LabelTrack >()) {
217 auto &view = LabelTrackView::Get( *lt );
218 if (view.CutSelectedText( context.project )) {
219 trackPanel.Refresh(false);
220 return;
221 }
222 }
223
224 //Presumably, there might be not more than one track
225 //that expects text input
226 for (auto wt : tracks.Any<WaveTrack>()) {
227 auto& view = WaveTrackView::Get(*wt);
228 if (view.CutSelectedText(context.project)) {
229 trackPanel.Refresh(false);
230 return;
231 }
232 }
233
234 auto &clipboard = Clipboard::Get();
235 clipboard.Clear();
236
237 auto pNewClipboard = TrackList::Create( nullptr );
238 auto &newClipboard = *pNewClipboard;
239
240 tracks.Selected().Visit(
241#if defined(USE_MIDI)
242 [&](NoteTrack *n) {
243 // Since portsmf has a built-in cut operator, we use that instead
244 auto dest = n->Cut(selectedRegion.t0(),
245 selectedRegion.t1());
246 FinishCopy(n, dest, newClipboard);
247 },
248#endif
249 [&](Track *n) {
250 if (n->SupportsBasicEditing()) {
251 auto dest = n->Copy(selectedRegion.t0(),
252 selectedRegion.t1());
253 FinishCopy(n, dest, newClipboard);
254 }
255 }
256 );
257
258 // Survived possibility of exceptions. Commit changes to the clipboard now.
259 clipboard.Assign(
260 std::move( newClipboard ),
261 selectedRegion.t0(),
262 selectedRegion.t1(),
263 project.shared_from_this()
264 );
265
266 // Proceed to change the project. If this throws, the project will be
267 // rolled back by the top level handler.
268
270#if defined(USE_MIDI)
271 [](NoteTrack*) {
272 //if NoteTrack, it was cut, so do not clear anything
273
274 // PRL: But what if it was sync lock selected only, not selected?
275 },
276#endif
277 [&](WaveTrack *wt, const Track::Fallthrough &fallthrough) {
278 if (gPrefs->Read(wxT("/GUI/EnableCutLines"), (long)0)) {
280 selectedRegion.t0(),
281 selectedRegion.t1());
282 }
283 else
284 fallthrough();
285 },
286 [&](Track *n) {
287 if (n->SupportsBasicEditing())
288 n->Clear(selectedRegion.t0(), selectedRegion.t1());
289 }
290 );
291
292 selectedRegion.collapseToT0();
293
294 ProjectHistory::Get( project )
295 .PushState(XO("Cut to the clipboard"), XO("Cut"));
296
297 // Bug 1663
298 //mRuler->ClearPlayRegion();
299 ruler.DrawOverlays( true );
300}
301
302void OnDelete(const CommandContext &context)
303{
304 auto &project = context.project;
305 auto &tracks = TrackList::Get( project );
306 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
307 auto &window = ProjectWindow::Get( project );
308
309 for (auto n : tracks.Any()) {
310 if (!n->SupportsBasicEditing())
311 continue;
313 n->Clear(selectedRegion.t0(), selectedRegion.t1());
314 }
315 }
316
317 double seconds = selectedRegion.duration();
318
319 selectedRegion.collapseToT0();
320
322 XO("Deleted %.2f seconds at t=%.2f")
323 .Format( seconds, selectedRegion.t0()),
324 XO("Delete"));
325}
326
327
328void OnCopy(const CommandContext &context)
329{
330 auto &project = context.project;
331 auto &tracks = TrackList::Get( project );
332 auto &trackPanel = TrackPanel::Get( project );
333 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
334
335 for (auto lt : tracks.Selected< LabelTrack >()) {
336 auto &view = LabelTrackView::Get( *lt );
337 if (view.CopySelectedText( context.project )) {
338 //trackPanel.Refresh(false);
339 return;
340 }
341 }
342 //Presumably, there might be not more than one track
343 //that expects text input
344 for (auto wt : tracks.Any<WaveTrack>()) {
345 auto& view = WaveTrackView::Get(*wt);
346 if (view.CopySelectedText(context.project)) {
347 return;
348 }
349 }
350
351 auto &clipboard = Clipboard::Get();
352 clipboard.Clear();
353
354 auto pNewClipboard = TrackList::Create( nullptr );
355 auto &newClipboard = *pNewClipboard;
356
357 for (auto n : tracks.Selected()) {
358 if (n->SupportsBasicEditing()) {
359 auto dest = n->Copy(selectedRegion.t0(),
360 selectedRegion.t1());
361 FinishCopy(n, dest, newClipboard);
362 }
363 }
364
365 // Survived possibility of exceptions. Commit changes to the clipboard now.
366 clipboard.Assign( std::move( newClipboard ),
367 selectedRegion.t0(), selectedRegion.t1(), project.shared_from_this() );
368
369 //Make sure the menus/toolbar states get updated
370 trackPanel.Refresh(false);
371}
372
373std::pair<double, double> FindSelection(const CommandContext &context)
374{
375 double sel0 = 0.0, sel1 = 0.0;
376
377#if 0
378 // Use the overriding selection if any was given in the context
379 if (auto *pRegion = context.temporarySelection.pSelectedRegion) {
380 auto &selectedRegion = *pRegion;
381 sel0 = selectedRegion.t0();
382 sel1 = selectedRegion.t1();
383 }
384 else
385#endif
386 {
387 auto &selectedRegion = ViewInfo::Get(context.project).selectedRegion;
388 sel0 = selectedRegion.t0();
389 sel1 = selectedRegion.t1();
390 }
391
392 return { sel0, sel1 };
393}
394
395void OnPaste(const CommandContext &context)
396{
397 auto &project = context.project;
398 auto &tracks = TrackList::Get( project );
399 auto& trackPanel = TrackPanel::Get(project);
400 auto &trackFactory = WaveTrackFactory::Get( project );
401 auto &pSampleBlockFactory = trackFactory.GetSampleBlockFactory();
402 const auto &settings = ProjectSettings::Get( project );
403 auto &window = ProjectWindow::Get( project );
404
405 auto isSyncLocked = settings.IsSyncLocked();
406
407 // Handle text paste (into active label) first.
408 if (DoPasteText(project))
409 return;
410
411 //Presumably, there might be not more than one track
412 //that expects text input
413 for (auto wt : tracks.Any<WaveTrack>()) {
414 auto& view = WaveTrackView::Get(*wt);
415 if (view.PasteText(context.project)) {
416 trackPanel.Refresh(false);
417 return;
418 }
419 }
420
421 // If nothing's selected, we just insert NEW tracks.
422 if (DoPasteNothingSelected(project))
423 return;
424
425 const auto &clipboard = Clipboard::Get();
426 auto clipTrackRange = clipboard.GetTracks().Any< const Track >();
427 if (clipTrackRange.empty())
428 return;
429
430 // Otherwise, paste into the selected tracks.
431 double t0, t1;
432 std::tie(t0, t1) = FindSelection(context);
433
434 auto pN = tracks.Any().begin();
435
436 Track *ff = NULL;
437 const Track *lastClipBeforeMismatch = NULL;
438 const Track *mismatchedClip = NULL;
439 const Track *prevClip = NULL;
440
441 bool bAdvanceClipboard = true;
442 bool bPastedSomething = false;
443
444 auto pasteWaveTrack = [&](WaveTrack *dst, const Track *src){
445 bPastedSomething = true;
446 // For correct remapping of preserved split lines:
447 PasteTimeWarper warper{ t1, t0 + src->GetEndTime() };
448 dst->ClearAndPaste(t0, t1, src, true, true, &warper);
449 };
450
451 auto pC = clipTrackRange.begin();
452 size_t nnChannels=0, ncChannels=0;
453 while (*pN && *pC) {
454 auto n = *pN;
455 auto c = *pC;
456 if (n->GetSelected()) {
457 bAdvanceClipboard = true;
458 if (mismatchedClip)
459 c = mismatchedClip;
460 if (!c->SameKindAs(*n)) {
461 if (!mismatchedClip) {
462 lastClipBeforeMismatch = prevClip;
463 mismatchedClip = c;
464 }
465 bAdvanceClipboard = false;
466 c = lastClipBeforeMismatch;
467
468
469 // If the types still don't match...
470 while (c && !c->SameKindAs(*n)) {
471 prevClip = c;
472 c = * ++ pC;
473 }
474 }
475
476 // Handle case where the first track in clipboard
477 // is of different type than the first selected track
478 if (!c) {
479 c = mismatchedClip;
480 while (n && (!c->SameKindAs(*n) || !n->GetSelected()))
481 {
482 // Must perform sync-lock adjustment before incrementing n
484 auto newT1 = t0 + clipboard.Duration();
485 if (t1 != newT1 && t1 <= n->GetEndTime()) {
486 n->SyncLockAdjust(t1, newT1);
487 bPastedSomething = true;
488 }
489 }
490 n = * ++ pN;
491 }
492 if (!n)
493 c = NULL;
494 }
495
496 // The last possible case for cross-type pastes: triggered when we try
497 // to paste 1+ tracks from one type into 1+ tracks of another type. If
498 // there's a mix of types, this shouldn't run.
499 if (!c)
500 // Throw, so that any previous changes to the project in this loop
501 // are discarded.
504 XO("Pasting one type of track into another is not allowed."),
505 XO("Warning"),
506 "Error:_Copying_or_Pasting"
507 };
508
509 // We should need this check only each time we visit the leading
510 // channel
511 if ( n->IsLeader() ) {
512 wxASSERT( c->IsLeader() ); // the iteration logic should ensure this
513
514 auto cChannels = TrackList::Channels(c);
515 ncChannels = cChannels.size();
516 auto nChannels = TrackList::Channels(n);
517 nnChannels = nChannels.size();
518
519 // When trying to copy from stereo to mono track, show error and
520 // exit
521 // TODO: Automatically offer user to mix down to mono (unfortunately
522 // this is not easy to implement
523 if (ncChannels > nnChannels)
524 {
525 if (ncChannels > 2) {
526 // TODO: more-than-two-channels-message
527 // Re-word the error message
528 }
529 // else
530
531 // Throw, so that any previous changes to the project in this
532 // loop are discarded.
535 XO("Copying stereo audio into a mono track is not allowed."),
536 XO("Warning"),
537 "Error:_Copying_or_Pasting"
538 };
539 }
540 }
541
542 if (!ff)
543 ff = n;
544
545 wxASSERT( n && c && n->SameKindAs(*c) );
546 n->TypeSwitch(
547 [&](WaveTrack *wn){
548 pasteWaveTrack(wn, static_cast<const WaveTrack *>(c));
549 },
550 [&](LabelTrack *ln){
551 // Per Bug 293, users expect labels to move on a paste into
552 // a label track.
553 ln->Clear(t0, t1);
554
555 ln->ShiftLabelsOnInsert( clipboard.Duration(), t0 );
556
557 bPastedSomething |= ln->PasteOver(t0, c);
558 },
559 [&](Track *){
560 bPastedSomething = true;
561 n->Clear(t0, t1);
562 n->Paste(t0, c);
563 }
564 );
565
566 --nnChannels;
567 --ncChannels;
568
569 // When copying from mono to stereo track, paste the wave form
570 // to both channels
571 // TODO: more-than-two-channels
572 // This will replicate the last pasted channel as many times as needed
573 while (nnChannels > 0 && ncChannels == 0)
574 {
575 n = * ++ pN;
576 --nnChannels;
577
578 n->TypeSwitch(
579 [&](WaveTrack *wn){
580 pasteWaveTrack(wn, c);
581 },
582 [&](Track *){
583 n->Clear(t0, t1);
584 bPastedSomething = true;
585 n->Paste(t0, c);
586 }
587 );
588 }
589
590 if (bAdvanceClipboard) {
591 prevClip = c;
592 c = * ++ pC;
593 }
594 } // if (n->GetSelected())
596 {
597 auto newT1 = t0 + clipboard.Duration();
598 if (t1 != newT1 && t1 <= n->GetEndTime()) {
599 n->SyncLockAdjust(t1, newT1);
600 bPastedSomething = true;
601 }
602 }
603 ++pN;
604 }
605
606 // This block handles the cases where our clipboard is smaller
607 // than the amount of selected destination tracks. We take the
608 // last wave track, and paste that one into the remaining
609 // selected tracks.
610 if ( *pN && ! *pC )
611 {
612 const auto wc =
613 *clipboard.GetTracks().Any< const WaveTrack >().rbegin();
614
615 tracks.Any().StartingWith(*pN).Visit(
616 [&](WaveTrack *wt, const Track::Fallthrough &fallthrough) {
617 if (!wt->GetSelected())
618 return fallthrough();
619
620 if (wc) {
621 pasteWaveTrack(wt, wc);
622 }
623 else {
624 auto tmp = wt->EmptyCopy( pSampleBlockFactory );
625 tmp->InsertSilence( 0.0,
626 // MJS: Is this correct?
627 clipboard.Duration() );
628 tmp->Flush();
629
630 pasteWaveTrack(wt, tmp.get());
631 }
632 },
633 [&](LabelTrack *lt, const Track::Fallthrough &fallthrough) {
635 return fallthrough();
636
637 lt->Clear(t0, t1);
638
639 // As above, only shift labels if sync-lock is on.
640 if (isSyncLocked)
642 clipboard.Duration(), t0);
643 },
644 [&](Track *n) {
646 n->SyncLockAdjust(t1, t0 + clipboard.Duration() );
647 }
648 );
649 }
650
651 // TODO: What if we clicked past the end of the track?
652
653 if (bPastedSomething)
654 {
656 .setTimes( t0, t0 + clipboard.Duration() );
657
658 ProjectHistory::Get( project )
659 .PushState(XO("Pasted from the clipboard"), XO("Paste"));
660
661 if (ff) {
662 TrackFocus::Get(project).Set(ff);
663 ff->EnsureVisible();
664 ff->LinkConsistencyFix();
665 }
666 }
667}
668
669void OnDuplicate(const CommandContext &context)
670{
671 auto &project = context.project;
672 auto &tracks = TrackList::Get( project );
673 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
674 auto &window = ProjectWindow::Get( project );
675
676 // This iteration is unusual because we add to the list inside the loop
677 auto range = tracks.Selected();
678 auto last = *range.rbegin();
679 for (auto n : range) {
680 if (!n->SupportsBasicEditing())
681 continue;
682
683 // Make copies not for clipboard but for direct addition to the project
684 auto dest = n->Copy(selectedRegion.t0(),
685 selectedRegion.t1(), false);
686 dest->Init(*n);
687 dest->SetOffset(wxMax(selectedRegion.t0(), n->GetOffset()));
688 tracks.Add( dest );
689
690 // This break is really needed, else we loop infinitely
691 if (n == last)
692 break;
693 }
694
695 ProjectHistory::Get( project )
696 .PushState(XO("Duplicated"), XO("Duplicate"));
697}
698
699void OnSplitCut(const CommandContext &context)
700{
701 auto &project = context.project;
702 auto &tracks = TrackList::Get( project );
703 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
704 auto &window = ProjectWindow::Get( project );
705
706 auto &clipboard = Clipboard::Get();
707 clipboard.Clear();
708
709 auto pNewClipboard = TrackList::Create( nullptr );
710 auto &newClipboard = *pNewClipboard;
711
712 Track::Holder dest;
713
714 tracks.Selected().Visit(
715 [&](WaveTrack *n) {
716 dest = n->SplitCut(
717 selectedRegion.t0(),
718 selectedRegion.t1());
719 if (dest)
720 FinishCopy(n, dest, newClipboard);
721 },
722 [&](Track *n) {
723 if (n->SupportsBasicEditing()) {
724 dest = n->Copy(selectedRegion.t0(),
725 selectedRegion.t1());
726 n->Silence(selectedRegion.t0(),
727 selectedRegion.t1());
728 if (dest)
729 FinishCopy(n, dest, newClipboard);
730 }
731 }
732 );
733
734 // Survived possibility of exceptions. Commit changes to the clipboard now.
735 clipboard.Assign( std::move( newClipboard ),
736 selectedRegion.t0(), selectedRegion.t1(), project.shared_from_this() );
737
738 ProjectHistory::Get( project )
739 .PushState(XO("Split-cut to the clipboard"), XO("Split Cut"));
740}
741
742void OnSplitDelete(const CommandContext &context)
743{
744 auto &project = context.project;
745 auto &tracks = TrackList::Get( project );
746 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
747 auto &window = ProjectWindow::Get( project );
748
749 tracks.Selected().Visit(
750 [&](WaveTrack *wt) {
751 wt->SplitDelete(selectedRegion.t0(),
752 selectedRegion.t1());
753 },
754 [&](Track *n) {
755 if (n->SupportsBasicEditing())
756 n->Silence(selectedRegion.t0(),
757 selectedRegion.t1());
758 }
759 );
760
762 XO("Split-deleted %.2f seconds at t=%.2f")
763 .Format( selectedRegion.duration(), selectedRegion.t0() ),
764 XO("Split Delete"));
765}
766
767void OnSilence(const CommandContext &context)
768{
769 auto &project = context.project;
770 auto &tracks = TrackList::Get( project );
771 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
772
773 for ( auto n : tracks.Selected< WaveTrack >() )
774 n->Silence(selectedRegion.t0(), selectedRegion.t1());
775
777 XO("Silenced selected tracks for %.2f seconds at %.2f")
778 .Format( selectedRegion.duration(), selectedRegion.t0() ),
779 /* i18n-hint: verb */
780 XC("Silence", "command"));
781}
782
783void OnTrim(const CommandContext &context)
784{
785 auto &project = context.project;
786 auto &tracks = TrackList::Get( project );
787 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
788 auto &window = ProjectWindow::Get( project );
789
790 if (selectedRegion.isPoint())
791 return;
792
793 tracks.Selected().Visit(
794 [&](WaveTrack *wt) {
795 //Hide the section before the left selector
796 wt->Trim(selectedRegion.t0(),
797 selectedRegion.t1());
798 }
799 );
800
802 XO("Trim selected audio tracks from %.2f seconds to %.2f seconds")
803 .Format( selectedRegion.t0(), selectedRegion.t1() ),
804 XO("Trim Audio"));
805}
806
807void OnSplit(const CommandContext &context)
808{
809 auto &project = context.project;
810 auto &tracks = TrackList::Get( project );
811
812 auto [sel0, sel1] = FindSelection(context);
813
814 if (auto *pTrack = context.temporarySelection.pTrack) {
815 if (auto pWaveTrack = dynamic_cast<WaveTrack*>(pTrack))
816 for (auto pChannel : TrackList::Channels(pWaveTrack))
817 pChannel->Split( sel0, sel1 );
818 else
819 // Did nothing, don't push history
820 return;
821 }
822 else {
823 for (auto wt : tracks.Selected< WaveTrack >())
824 wt->Split( sel0, sel1 );
825 }
826
827 ProjectHistory::Get( project ).PushState(XO("Split"), XO("Split"));
828#if 0
829//ANSWER-ME: Do we need to keep this commented out OnSplit() code?
830// This whole section no longer used...
831 /*
832 * Previous (pre-multiclip) implementation of "Split" command
833 * This does work only when a range is selected!
834 *
835 TrackListIterator iter(tracks);
836
837 Track *n = iter.First();
838 Track *dest;
839
840 TrackList newTracks;
841
842 while (n) {
843 if (n->GetSelected()) {
844 double sel0 = selectedRegion.t0();
845 double sel1 = selectedRegion.t1();
846
847 dest = n->Copy(sel0, sel1);
848 dest->Init(*n);
849 dest->SetOffset(wxMax(sel0, n->GetOffset()));
850
851 if (sel1 >= n->GetEndTime())
852 n->Clear(sel0, sel1);
853 else if (sel0 <= n->GetOffset()) {
854 n->Clear(sel0, sel1);
855 n->SetOffset(sel1);
856 } else
857 n->Silence(sel0, sel1);
858
859 newTracks.Add(dest);
860 }
861 n = iter.Next();
862 }
863
864 TrackListIterator nIter(&newTracks);
865 n = nIter.First();
866 while (n) {
867 tracks->Add(n);
868 n = nIter.Next();
869 }
870
871 PushState(XO("Split"), XO("Split"));
872 */
873#endif
874}
875
876void OnSplitNew(const CommandContext &context)
877{
878 auto &project = context.project;
879 auto &tracks = TrackList::Get( project );
880 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
881 auto &window = ProjectWindow::Get( project );
882
883 Track::Holder dest;
884
885 // This iteration is unusual because we add to the list inside the loop
886 auto range = tracks.Selected();
887 auto last = *range.rbegin();
888 for (auto track : range) {
889 track->TypeSwitch(
890 [&](WaveTrack *wt) {
891 // Clips must be aligned to sample positions or the NEW clip will
892 // not fit in the gap where it came from
893 double offset = wt->GetOffset();
894 offset = wt->LongSamplesToTime(wt->TimeToLongSamples(offset));
895 double newt0 = wt->LongSamplesToTime(wt->TimeToLongSamples(
896 selectedRegion.t0()));
897 double newt1 = wt->LongSamplesToTime(wt->TimeToLongSamples(
898 selectedRegion.t1()));
899 dest = wt->SplitCut(newt0, newt1);
900 if (dest) {
901 dest->SetOffset(wxMax(newt0, offset));
902 FinishCopy(wt, dest, tracks);
903 }
904 }
905#if 0
906 ,
907 // LL: For now, just skip all non-wave tracks since the other do not
908 // yet support proper splitting.
909 [&](Track *n) {
910 dest = n->Cut(viewInfo.selectedRegion.t0(),
911 viewInfo.selectedRegion.t1());
912 if (dest) {
913 dest->SetOffset(wxMax(0, n->GetOffset()));
914 FinishCopy(n, dest, *tracks);
915 }
916 }
917#endif
918 );
919 if (track == last)
920 break;
921 }
922
923 ProjectHistory::Get( project )
924 .PushState(XO("Split to new track"), XO("Split New"));
925}
926
927void OnJoin(const CommandContext &context)
928{
929 auto &project = context.project;
930 auto &tracks = TrackList::Get( project );
931 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
932 auto &window = ProjectWindow::Get( project );
933
934 for (auto wt : tracks.Selected< WaveTrack >())
935 wt->Join(selectedRegion.t0(),
936 selectedRegion.t1());
937
939 XO("Joined %.2f seconds at t=%.2f")
940 .Format( selectedRegion.duration(), selectedRegion.t0() ),
941 XO("Join"));
942}
943
944void OnDisjoin(const CommandContext &context)
945{
946 auto &project = context.project;
947 auto &tracks = TrackList::Get( project );
948 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
949 auto &window = ProjectWindow::Get( project );
950
951 for (auto wt : tracks.Selected< WaveTrack >())
952 wt->Disjoin(selectedRegion.t0(),
953 selectedRegion.t1());
954
956 XO("Detached %.2f seconds at t=%.2f")
957 .Format( selectedRegion.duration(), selectedRegion.t0() ),
958 XO("Detach"));
959}
960
961void OnEditMetadata(const CommandContext &context)
962{
963 auto &project = context.project;
964 (void)Exporter::DoEditMetadata( project,
965 XO("Edit Metadata Tags"), XO("Metadata Tags"), true);
966}
967
968void OnPreferences(const CommandContext &context)
969{
970 auto &project = context.project;
971
972 GlobalPrefsDialog dialog(&GetProjectFrame( project ) /* parent */, &project );
973
974 if( VetoDialogHook::Call( &dialog ) )
975 return;
976
977 if (!dialog.ShowModal()) {
978 // Canceled
979 return;
980 }
981
982 // LL: Moved from PrefsDialog since wxWidgets on OSX can't deal with
983 // rebuilding the menus while the PrefsDialog is still in the modal
984 // state.
985 for (auto p : AllProjects{}) {
987// TODO: The comment below suggests this workaround is obsolete.
988#if defined(__WXGTK__)
989 // Workaround for:
990 //
991 // http://bugzilla.audacityteam.org/show_bug.cgi?id=458
992 //
993 // This workaround should be removed when Audacity updates to wxWidgets
994 // 3.x which has a fix.
995 auto &window = GetProjectFrame( *p );
996 wxRect r = window.GetRect();
997 window.SetSize(wxSize(1,1));
998 window.SetSize(r.GetSize());
999#endif
1000 }
1001}
1002
1003// Legacy functions, not used as of version 2.3.0
1004
1005#if 0
1006void OnPasteOver(const CommandContext &context)
1007{
1008 auto &project = context.project;
1009 auto &selectedRegion = project.GetViewInfo().selectedRegion;
1010
1011 if((AudacityProject::msClipT1 - AudacityProject::msClipT0) > 0.0)
1012 {
1013 selectedRegion.setT1(
1014 selectedRegion.t0() +
1015 (AudacityProject::msClipT1 - AudacityProject::msClipT0));
1016 // MJS: pointless, given what we do in OnPaste?
1017 }
1018 OnPaste(context);
1019
1020 return;
1021}
1022#endif
1023
1024}; // struct Handler
1025
1026} // namespace
1027
1029 // Handler is not stateful. Doesn't need a factory registered with
1030 // AudacityProject.
1031 static EditActions::Handler instance;
1032 return instance;
1033};
1034
1035// Menu definitions
1036
1037#define FN(X) (& EditActions::Handler :: X)
1038
1039static const ReservedCommandFlag
1041 [](const AudacityProject &project){
1042 auto range = TrackList::Get( project ).Any<const LabelTrack>()
1043 + [&](const LabelTrack *pTrack){
1044 return LabelTrackView::Get( *pTrack ).IsTextSelected(
1045 // unhappy const_cast because track focus might be set
1046 const_cast<AudacityProject&>(project)
1047 );
1048 };
1049 if ( !range.empty() )
1050 return true;
1051
1052 if (
1053 TimeSelectedPred( project )
1054 &&
1056 )
1057 return true;
1058
1059 return false;
1060 },
1062}; return flag; }
1063
1064namespace {
1065using namespace MenuTable;
1067{
1069
1070 static const auto NotBusyTimeAndTracksFlags =
1072
1073 // The default shortcut key for Redo is different on different platforms.
1074 static constexpr auto redoKey =
1075#ifdef __WXMSW__
1076 wxT("Ctrl+Y")
1077#else
1078 wxT("Ctrl+Shift+Z")
1079#endif
1080 ;
1081
1082 // The default shortcut key for Preferences is different on different
1083 // platforms.
1084 static constexpr auto prefKey =
1085#ifdef __WXMAC__
1086 wxT("Ctrl+,")
1087#else
1088 wxT("Ctrl+P")
1089#endif
1090 ;
1091
1092 static BaseItemSharedPtr menu{
1094 Menu( wxT("Edit"), XXO("&Edit"),
1095 Section( "UndoRedo",
1096 Command( wxT("Undo"), XXO("&Undo"), FN(OnUndo),
1097 AudioIONotBusyFlag() | UndoAvailableFlag(), wxT("Ctrl+Z") ),
1098
1099 Command( wxT("Redo"), XXO("&Redo"), FN(OnRedo),
1100 AudioIONotBusyFlag() | RedoAvailableFlag(), redoKey ),
1101
1102 Special( wxT("UndoItemsUpdateStep"),
1103 [](AudacityProject &project, wxMenu&) {
1104 // Change names in the CommandManager as a side-effect
1106 })
1107 ),
1108
1109 Section( "Basic",
1110 // Basic Edit commands
1111 /* i18n-hint: (verb)*/
1112 Command( wxT("Cut"), XXO("Cu&t"), FN(OnCut),
1114 wxT("Ctrl+X") ),
1115 Command( wxT("Delete"), XXO("&Delete"), FN(OnDelete),
1117 wxT("Ctrl+K") ),
1118 /* i18n-hint: (verb)*/
1119 Command( wxT("Copy"), XXO("&Copy"), FN(OnCopy),
1120 AudioIONotBusyFlag() | CutCopyAvailableFlag(), wxT("Ctrl+C") ),
1121 /* i18n-hint: (verb)*/
1122 Command( wxT("Paste"), XXO("&Paste"), FN(OnPaste),
1123 AudioIONotBusyFlag(), wxT("Ctrl+V") ),
1124 /* i18n-hint: (verb)*/
1125 Command( wxT("Duplicate"), XXO("Duplic&ate"), FN(OnDuplicate),
1126 NotBusyTimeAndTracksFlags, wxT("Ctrl+D") ),
1127
1128 Section( "",
1129 Menu( wxT("RemoveSpecial"), XXO("R&emove Special"),
1130 Section( "",
1131 /* i18n-hint: (verb) Do a special kind of cut*/
1132 Command( wxT("SplitCut"), XXO("Spl&it Cut"), FN(OnSplitCut),
1133 NotBusyTimeAndTracksFlags,
1134 Options{ wxT("Ctrl+Alt+X") } ),
1135 /* i18n-hint: (verb) Do a special kind of DELETE*/
1136 Command( wxT("SplitDelete"), XXO("Split D&elete"), FN(OnSplitDelete),
1137 NotBusyTimeAndTracksFlags,
1138 Options{ wxT("Ctrl+Alt+K") } )
1139 ),
1140
1141 Section( "",
1142 /* i18n-hint: (verb)*/
1143 Command( wxT("Silence"), XXO("Silence Audi&o"), FN(OnSilence),
1145 wxT("Ctrl+L") ),
1146 /* i18n-hint: (verb)*/
1147 Command( wxT("Trim"), XXO("Tri&m Audio"), FN(OnTrim),
1149 Options{ wxT("Ctrl+T") } )
1150 )
1151 )
1152 )
1153 ),
1154
1155
1156 Section( "Other",
1158
1159 Menu( wxT("Clip"), XXO("Audi&o Clips"),
1160 Section( "",
1161 /* i18n-hint: (verb) It's an item on a menu. */
1162 Command( wxT("Split"), XXO("Sp&lit"), FN(OnSplit),
1164 Options{ wxT("Ctrl+I") } ),
1165 Command( wxT("SplitNew"), XXO("Split Ne&w"), FN(OnSplitNew),
1167 Options{ wxT("Ctrl+Alt+I") } )
1168 ),
1169
1170 Section( "",
1171 /* i18n-hint: (verb)*/
1172 Command( wxT("Join"), XXO("&Join"), FN(OnJoin),
1173 NotBusyTimeAndTracksFlags, wxT("Ctrl+J") ),
1174 Command( wxT("Disjoin"), XXO("Detac&h at Silences"), FN(OnDisjoin),
1175 NotBusyTimeAndTracksFlags, wxT("Ctrl+Alt+J") )
1176 )
1177 ),
1178
1180
1181 Command( wxT("EditMetaData"), XXO("&Metadata"), FN(OnEditMetadata),
1183
1185
1186 ),
1187
1188 // Note that on Mac, the Preferences menu item is specially handled in
1189 // CommandManager (assigned a special wxWidgets id) so that it does
1190 // not appear in the Edit menu but instead under Audacity, consistent with
1191 // MacOS conventions.
1192 Section( "Preferences",
1193 Command( wxT("Preferences"), XXO("Pre&ferences"), FN(OnPreferences),
1194 AudioIONotBusyFlag(), prefKey )
1195 )
1196
1197 ) ) };
1198 return menu;
1199}
1200
1202 wxT(""),
1203 Shared( EditMenu() )
1204};
1205
1207{
1209 static const auto flags =
1211 static BaseItemSharedPtr menu{
1213 Menu( wxT("Edit"), XXO("&Edit"),
1214 Command( wxT("DeleteKey"), XXO("&Delete Key"), FN(OnDelete),
1215 (flags | NoAutoSelect()),
1216 wxT("Backspace") ),
1217 Command( wxT("DeleteKey2"), XXO("Delete Key&2"), FN(OnDelete),
1218 (flags | NoAutoSelect()),
1219 wxT("Delete") )
1220 ) ) };
1221 return menu;
1222}
1223
1224auto canSelectAll = [](const AudacityProject &project){
1225 return MenuManager::Get( project ).mWhatIfNoSelection != 0; };
1226auto selectAll = []( AudacityProject &project, CommandFlag flagsRqd ){
1227 if ( MenuManager::Get( project ).mWhatIfNoSelection == 1 &&
1228 (flagsRqd & NoAutoSelect()).none() )
1230};
1231
1233 []{ return TracksExistFlag(); },
1234 []{ return EditableTracksSelectedFlag(); },
1236 selectAll
1237}};
1238
1239// Including time tracks.
1241 []{ return TracksExistFlag(); },
1242 []{ return AnyTracksSelectedFlag(); },
1244 selectAll
1245}};
1246
1248 []{ return WaveTracksExistFlag(); },
1251 selectAll
1252}};
1253
1254// Also enable select for the noise reduction case.
1256 []{ return WaveTracksExistFlag(); },
1259 selectAll
1260}};
1261
1263 wxT("Optional/Extra/Part1"),
1265};
1266
1267}
1268#undef FN
wxT("CloseDown"))
@ BadUserAction
Indicates that the user performed an action that is not allowed.
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
std::bitset< NCommandFlags > CommandFlag
Definition: CommandFlag.h:31
wxEvtHandler CommandHandlerObject
const ReservedCommandFlag & NoAutoSelect()
const ReservedCommandFlag & NoiseReductionTimeSelectedFlag()
bool EditableTracksSelectedPred(const AudacityProject &project)
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & UndoAvailableFlag()
const ReservedCommandFlag & RedoAvailableFlag()
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & EditableTracksSelectedFlag()
const ReservedCommandFlag & AnyTracksSelectedFlag()
const CommandFlagOptions & cutCopyOptions()
const ReservedCommandFlag & TracksExistFlag()
const ReservedCommandFlag & WaveTracksExistFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
bool TimeSelectedPred(const AudacityProject &project)
@ none
Definition: Dither.h:20
static CommandHandlerObject & findCommandHandler(AudacityProject &)
Definition: EditMenus.cpp:1028
static const ReservedCommandFlag & CutCopyAvailableFlag()
Definition: EditMenus.cpp:1040
#define FN(X)
Definition: EditMenus.cpp:1037
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
#define XC(s, c)
Definition: Internat.h:37
auto Visit(Visitor &&vis, Variant &&var)
Mimic some of std::visit, for the case of one visitor only.
Definition: MemoryX.h:611
#define QUANTIZED_TIME(time, rate)
Definition: MemoryX.h:541
FileConfig * gPrefs
Definition: Prefs.cpp:71
an object holding per-project preferred sample rate
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper,...
static Settings & settings()
Definition: TrackInfo.cpp:87
static std::once_flag flag
static AdornedRulerPanel & Get(AudacityProject &project)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
static Clipboard & Get()
Definition: Clipboard.cpp:29
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
TemporarySelection temporarySelection
AudacityProject & project
static bool DoEditMetadata(AudacityProject &project, const TranslatableString &title, const TranslatableString &shortUndoDescription, bool force)
Definition: Export.cpp:405
Abstract base class used in importing a file.
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:89
void ShiftLabelsOnInsert(double length, double pt)
Definition: LabelTrack.cpp:231
void Clear(double t0, double t1) override
Definition: LabelTrack.cpp:182
static LabelTrackView & Get(LabelTrack &)
bool IsTextSelected(AudacityProject &project) const
int GetTextEditIndex(AudacityProject &project) const
void RebuildMenuBar(AudacityProject &project)
Definition: Menus.cpp:486
int mWhatIfNoSelection
Definition: Menus.h:124
static MenuManager & Get(AudacityProject &project)
Definition: Menus.cpp:71
static void ModifyUndoMenuItems(AudacityProject &project)
Definition: Menus.cpp:444
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:63
Track::Holder Cut(double t0, double t1) override
Definition: NoteTrack.cpp:444
void Clear(double t0, double t1) override
Definition: NoteTrack.cpp:521
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
Definition: NoteTrack.cpp:474
bool setTimes(double t0, double t1)
Definition: ViewInfo.cpp:51
double t0() const
Definition: ViewInfo.h:34
Unit slope but with either a jump (pasting more) or a flat interval (pasting less)
Definition: TimeWarper.h:181
int ShowModal() override
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
void PopState(const UndoState &state, bool doAutosave=true)
static ProjectHistory & Get(AudacityProject &project)
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
double GetRate() const
Definition: ProjectRate.cpp:53
static ProjectSettings & Get(AudacityProject &project)
static ProjectWindow & Get(AudacityProject &project)
double LongSamplesToTime(sampleCount pos) const
Convert correctly between a number of samples and an (absolute) time in seconds.
Definition: SampleTrack.cpp:47
sampleCount TimeToLongSamples(double t0) const
Convert correctly between an (absolute) time in seconds and a number of samples.
Definition: SampleTrack.cpp:42
A MessageBoxException that shows a given, unvarying string.
static bool IsSelectedOrSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:73
static bool IsSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:43
Track * Get()
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:225
void EnsureVisible(bool modifyState=false)
Definition: Track.cpp:97
virtual void SetSelected(bool s)
Definition: Track.cpp:87
virtual Holder PasteInto(AudacityProject &) const =0
Find or create the destination track for a paste, maybe in a different project.
static void FinishCopy(const Track *n, Track *dest)
Definition: Track.cpp:414
virtual bool SupportsBasicEditing() const
Whether this track type implements cut-copy-paste; by default, true.
Definition: Track.cpp:1258
virtual void SyncLockAdjust(double oldT1, double newT1)
Definition: Track.cpp:285
std::shared_ptr< Track > Holder
Definition: Track.h:368
Continuation<> Fallthrough
Type of arguments passed as optional second parameter to TypeSwitch<void>() cases.
Definition: Track.h:541
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1338
static std::shared_ptr< TrackList > Create(AudacityProject *pOwner)
Definition: Track.cpp:502
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
Definition: Track.h:1564
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1437
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:486
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1541
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:230
static UndoManager & Get(AudacityProject &project)
Definition: UndoManager.cpp:67
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:216
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:2810
A Track that contains audio waveform data.
Definition: WaveTrack.h:57
void SplitDelete(double t0, double t1)
Definition: WaveTrack.cpp:1175
void Silence(double t0, double t1) override
Definition: WaveTrack.cpp:1582
void ClearAndAddCutLine(double t0, double t1)
Definition: WaveTrack.cpp:794
double GetOffset() const override
Definition: WaveTrack.cpp:237
void Trim(double t0, double t1)
Definition: WaveTrack.cpp:673
void ClearAndPaste(double t0, double t1, const Track *src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=NULL)
Definition: WaveTrack.cpp:915
Track::Holder SplitCut(double t0, double t1)
Definition: WaveTrack.cpp:640
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
Definition: WaveTrack.cpp:716
static WaveTrackView & Get(WaveTrack &track)
std::unique_ptr< MenuItem > Menu(const Identifier &internalName, const TranslatableString &title, Args &&... args)
std::unique_ptr< MenuPart > Section(const Identifier &internalName, Args &&... args)
std::unique_ptr< CommandItem > Command(const CommandID &name, const TranslatableString &label_in, void(Handler::*pmf)(const CommandContext &), CommandFlag flags, const CommandManager::Options &options={}, CommandHandlerFinder finder=FinderScope::DefaultFinder())
std::unique_ptr< SpecialItem > Special(const Identifier &name, const SpecialItem::Appender &fn)
std::shared_ptr< BaseItem > BaseItemSharedPtr
Definition: Registry.h:72
void DoSelectAllAudio(AudacityProject &project)
bool DoPasteText(AudacityProject &project)
Definition: EditMenus.cpp:44
RegisteredMenuItemEnabler selectWaveTracks
Definition: EditMenus.cpp:1247
bool DoPasteNothingSelected(AudacityProject &project)
Definition: EditMenus.cpp:79
void FinishCopy(const Track *n, const Track::Holder &dest, TrackList &list)
Definition: EditMenus.cpp:35
RegisteredMenuItemEnabler selectTracks
Definition: EditMenus.cpp:1232
RegisteredMenuItemEnabler selectWaveTracks2
Definition: EditMenus.cpp:1255
RegisteredMenuItemEnabler selectAnyTracks
Definition: EditMenus.cpp:1240
BaseItemSharedPtr ExtraEditMenu()
Definition: EditMenus.cpp:1206
std::vector< CommandFlagOptions > & Options()
Definition: Menus.cpp:535
void OnSplitCut(const CommandContext &context)
Definition: EditMenus.cpp:699
void OnCopy(const CommandContext &context)
Definition: EditMenus.cpp:328
void OnTrim(const CommandContext &context)
Definition: EditMenus.cpp:783
void OnPreferences(const CommandContext &context)
Definition: EditMenus.cpp:968
void OnSilence(const CommandContext &context)
Definition: EditMenus.cpp:767
void OnRedo(const CommandContext &context)
Definition: EditMenus.cpp:173
std::pair< double, double > FindSelection(const CommandContext &context)
Definition: EditMenus.cpp:373
void OnDisjoin(const CommandContext &context)
Definition: EditMenus.cpp:944
void OnSplit(const CommandContext &context)
Definition: EditMenus.cpp:807
void OnEditMetadata(const CommandContext &context)
Definition: EditMenus.cpp:961
void OnDelete(const CommandContext &context)
Definition: EditMenus.cpp:302
void OnSplitNew(const CommandContext &context)
Definition: EditMenus.cpp:876
void OnCut(const CommandContext &context)
Definition: EditMenus.cpp:203
void OnDuplicate(const CommandContext &context)
Definition: EditMenus.cpp:669
void OnPaste(const CommandContext &context)
Definition: EditMenus.cpp:395
void OnSplitDelete(const CommandContext &context)
Definition: EditMenus.cpp:742
void OnUndo(const CommandContext &context)
Definition: EditMenus.cpp:142
void OnJoin(const CommandContext &context)
Definition: EditMenus.cpp:927
SelectedRegion * pSelectedRegion
Holds one item with description and time range for the UndoManager.
Definition: UndoManager.h:127
UndoState state
Definition: UndoManager.h:140