Audacity 3.2.0
EditMenus.cpp
Go to the documentation of this file.
1#include "../AdornedRulerPanel.h"
2#include "../Clipboard.h"
3#include "../CommonCommandFlags.h"
4#include "../LabelTrack.h"
5#include "../MenuCreator.h"
6#include "NoteTrack.h"
7#include "Project.h"
9#include "ProjectHistory.h"
10#include "ProjectRate.h"
12#include "../ProjectWindows.h"
13#include "../ProjectWindows.h"
14#include "../SelectUtilities.h"
15#include "SyncLock.h"
16#include "TempoChange.h"
17#include "../TrackPanel.h"
18#include "TrackFocus.h"
19#include "UndoManager.h"
20#include "ViewInfo.h"
21#include "WaveTrack.h"
22#include "WaveTrackUtilities.h"
23#include "TimeStretching.h"
24#include "WaveClip.h"
25#include "SampleBlock.h"
26#include "CommandContext.h"
27#include "TimeWarper.h"
28#include "../prefs/PrefsDialog.h"
29#include "../prefs/TracksBehaviorsPrefs.h"
30#include "../tracks/labeltrack/ui/LabelTrackView.h"
31#include "../tracks/playabletrack/wavetrack/ui/WaveChannelView.h"
32#include "AudacityMessageBox.h"
33#include "../AudioPasteDialog.h"
34#include "BasicUI.h"
35#include "Sequence.h"
36#include "UserException.h"
37#include "Viewport.h"
38
39#include <wx/clipbrd.h>
40#include <wx/frame.h>
41
42// private helper classes and functions
43namespace {
44
45// Handle text paste. Return true if did paste.
46// (This was formerly the first part of overly-long OnPaste.)
48{
49 auto &tracks = TrackList::Get( project );
50 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
51 auto &viewport = Viewport::Get(project);
52
53 // Paste into the active label (if any)
54 for (auto pLabelTrack : tracks.Any<LabelTrack>()) {
55 // Does this track have an active label?
56 if (LabelTrackView::Get( *pLabelTrack ).GetTextEditIndex(project) != -1) {
57
58 // Yes, so try pasting into it
59 auto &view = LabelTrackView::Get( *pLabelTrack );
60 if (view.PasteSelectedText( project, selectedRegion.t0(),
61 selectedRegion.t1() ))
62 {
64 .PushState(XO("Pasted text from the clipboard"), XO("Paste"));
65
66 // Make sure caret is in view
67 int x;
68 if (view.CalcCursorX( project, &x )) {
69 viewport.ScrollIntoView(x);
70 }
71
72 return true;
73 }
74 }
75 }
76
77 //Presumably, there might be not more than one track
78 //that expects text input
79 for (auto wt : tracks.Any<WaveTrack>()) {
80 auto& view = WaveChannelView::GetFirst(*wt);
81 if (view.PasteText(project)) {
82 auto &trackPanel = TrackPanel::Get(project);
83 trackPanel.Refresh(false);
84 return true;
85 }
86 }
87
88 return false;
89}
90
91wxULongLong EstimateCopyBytesCount(const TrackList& src, const TrackList& dst)
92{
93 wxULongLong result{};
94 for (auto waveTrack : src.Any<const WaveTrack>()) {
95 const auto samplesCount =
97 result += samplesCount.as_long_long() *
98 SAMPLE_SIZE(waveTrack->GetSampleFormat());
99 }
100 return result;
101}
102
103BlockArray::size_type EstimateCopiedBlocks(const TrackList& src, const TrackList& dst)
104{
105 BlockArray::size_type result{};
106 for (const auto waveTrack : src.Any<const WaveTrack>())
107 result += WaveTrackUtilities::CountBlocks(*waveTrack);
108 return result;
109}
110
111std::shared_ptr<TrackList> DuplicateDiscardTrimmed(const TrackList& src) {
112 auto result = TrackList::Create(nullptr);
113 for (auto track : src) {
114 const auto pTrack =
115 track->Copy(track->GetStartTime(), track->GetEndTime(), false);
116 pTrack->MoveTo(track->GetStartTime());
117 if (const auto waveTrack = dynamic_cast<WaveTrack*>(pTrack.get()))
119 result->Add(pTrack);
120 }
121 return result;
122}
123
124// Create and paste into NEW tracks.
125// Simplified version of DoPaste, used when there is no selection
126// on tracks
127// (This was formerly the second part of overly-long OnPaste.)
128void DoPasteNothingSelected(AudacityProject &project, const TrackList& src, double t0, double t1)
129{
130 auto &tracks = TrackList::Get( project );
131 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
132 auto &viewInfo = ViewInfo::Get( project );
133
134 assert(tracks.Selected().empty());
135
136 Track* pFirstNewTrack = NULL;
137 for (auto pClip : src) {
138 auto pNewTrack = pClip->PasteInto(project, tracks);
139 if (!pFirstNewTrack)
140 pFirstNewTrack = pNewTrack.get();
141 pNewTrack->SetSelected(true);
142 }
143
144 // Select some pasted samples, which is probably impossible to get right
145 // with various project and track sample rates.
146 // So do it at the sample rate of the project
147 const double projRate = ProjectRate::Get( project ).GetRate();
148 const double projTempo = ProjectTimeSignature::Get(project).GetTempo();
149 const double srcTempo =
150 pFirstNewTrack ? GetProjectTempo(*pFirstNewTrack).value_or(projTempo) :
151 projTempo;
152 // Apply adequate stretching to the selection. A selection of 10 seconds of
153 // audio in project A should become 5 seconds in project B if tempo in B is
154 // twice as fast.
155 const double quantT0 = QUANTIZED_TIME(t0 * srcTempo / projTempo, projRate);
156 const double quantT1 = QUANTIZED_TIME(t1 * srcTempo / projTempo, projRate);
157 selectedRegion.setTimes(
158 0.0, // anywhere else and this should be
159 // half a sample earlier
160 quantT1 - quantT0);
161
163 .PushState(XO("Pasted from the clipboard"), XO("Paste"));
164
165 if (pFirstNewTrack) {
166 TrackFocus::Get(project).Set(pFirstNewTrack);
167 Viewport::Get(project).ShowTrack(*pFirstNewTrack);
168 }
169}
170
171bool HasHiddenData(const TrackList& trackList)
172{
173 const auto range = trackList.Any<const WaveTrack>();
174 return std::any_of(range.begin(), range.end(),
175 [](const WaveTrack *pTrack){
176 return WaveTrackUtilities::HasHiddenData(*pTrack);
177 });
178}
179
180// Menu handler functions
181
182void OnUndo(const CommandContext &context)
183{
184 auto &project = context.project;
185 auto &tracks = TrackList::Get( project );
186 auto &trackPanel = TrackPanel::Get( project );
187 auto &undoManager = UndoManager::Get( project );
188
189 if (!ProjectHistory::Get( project ).UndoAvailable()) {
190 AudacityMessageBox( XO("Nothing to undo") );
191 return;
192 }
193
194 // can't undo while dragging
195 if (trackPanel.IsMouseCaptured()) {
196 return;
197 }
198
199 undoManager.Undo(
200 [&]( const UndoStackElem &elem ){
202
203 auto t = *tracks.Selected().begin();
204 if (!t)
205 t = *tracks.begin();
206 TrackFocus::Get(project).Set(t);
207 if (t)
209}
210
211void OnRedo(const CommandContext &context)
212{
213 auto &project = context.project;
214 auto &tracks = TrackList::Get( project );
215 auto &trackPanel = TrackPanel::Get( project );
216 auto &undoManager = UndoManager::Get( project );
217
218 if (!ProjectHistory::Get( project ).RedoAvailable()) {
219 AudacityMessageBox( XO("Nothing to redo") );
220 return;
221 }
222 // Can't redo whilst dragging
223 if (trackPanel.IsMouseCaptured()) {
224 return;
225 }
226
227 undoManager.Redo(
228 [&]( const UndoStackElem &elem ){
230
231 auto t = *tracks.Selected().begin();
232 if (!t)
233 t = *tracks.begin();
234 TrackFocus::Get(project).Set(t);
235 if (t)
237}
238
239void OnCut(const CommandContext &context)
240{
241 auto &project = context.project;
242 auto &tracks = TrackList::Get( project );
243 auto &trackPanel = TrackPanel::Get( project );
244 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
246
247 // This doesn't handle cutting labels, it handles
248 // cutting the _text_ inside of labels, i.e. if you're
249 // in the middle of editing the label text and select "Cut".
250
251 for (auto lt : tracks.Selected<LabelTrack>()) {
252 auto &view = LabelTrackView::Get( *lt );
253 if (view.CutSelectedText( context.project )) {
254 trackPanel.Refresh(false);
255 return;
256 }
257 }
258
259 //Presumably, there might be not more than one track
260 //that expects text input
261 for (auto wt : tracks.Any<WaveTrack>()) {
262 auto& view = WaveChannelView::GetFirst(*wt);
263 if (view.CutSelectedText(context.project)) {
264 trackPanel.Refresh(false);
265 return;
266 }
267 }
268
269 auto &clipboard = Clipboard::Get();
270 clipboard.Clear();
271
272 auto pNewClipboard = TrackList::Create( nullptr );
273 auto &newClipboard = *pNewClipboard;
274
275 tracks.Selected().Visit(
276#if defined(USE_MIDI)
277 [&](NoteTrack &n) {
278 // Since portsmf has a built-in cut operator, we use that instead
279 auto dest = n.Cut(selectedRegion.t0(), selectedRegion.t1());
280 newClipboard.Add(dest);
281 },
282#endif
283 [&](Track &n) {
284 if (n.SupportsBasicEditing()) {
285 auto dest = n.Copy(selectedRegion.t0(), selectedRegion.t1());
286 newClipboard.Add(dest);
287 }
288 }
289 );
290
291 // Survived possibility of exceptions. Commit changes to the clipboard now.
292 clipboard.Assign(
293 std::move( newClipboard ),
294 selectedRegion.t0(),
295 selectedRegion.t1(),
296 project.shared_from_this()
297 );
298
299 // Proceed to change the project. If this throws, the project will be
300 // rolled back by the top level handler.
301
303#if defined(USE_MIDI)
304 [](NoteTrack&) {
305 //if NoteTrack, it was cut, so do not clear anything
306
307 // PRL: But what if it was sync lock selected only, not selected?
308 },
309#endif
310 [&](auto &&fallthrough){ return [&](WaveTrack &wt) {
311 if (gPrefs->Read(wxT("/GUI/EnableCutLines"), (long)0))
312 wt.ClearAndAddCutLine(selectedRegion.t0(), selectedRegion.t1());
313 else
314 fallthrough();
315 }; },
316 [&](Track &n) {
317 if (n.SupportsBasicEditing())
318 n.Clear(selectedRegion.t0(), selectedRegion.t1());
319 }
320 );
321
322 selectedRegion.collapseToT0();
323
325 .PushState(XO("Cut to the clipboard"), XO("Cut"));
326
327 // Bug 1663
328 //mRuler->ClearPlayRegion();
329 ruler.DrawOverlays( true );
330}
331
332void OnDelete(const CommandContext &context)
333{
334 auto &project = context.project;
335 auto &tracks = TrackList::Get( project );
336 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
337
338 for (auto n : tracks) {
339 if (!n->SupportsBasicEditing())
340 continue;
342 n->Clear(selectedRegion.t0(), selectedRegion.t1());
343 }
344 }
345
346 double seconds = selectedRegion.duration();
347
348 selectedRegion.collapseToT0();
349
351 XO("Deleted %.2f seconds at t=%.2f")
352 .Format( seconds, selectedRegion.t0()),
353 XO("Delete"));
354}
355
356
357void OnCopy(const CommandContext &context)
358{
359 if (wxTheClipboard->Open())
360 {
361 // Clear the data from the clipboard, so that the next paste doesn't
362 // attempt to import whatever the user copied from the OS in a prior
363 // action.
364 const auto success = wxTheClipboard->SetData(safenew wxTextDataObject);
365 assert(success);
366 wxTheClipboard->Clear();
367 wxTheClipboard->Close();
368 }
369
370 auto &project = context.project;
371 auto &tracks = TrackList::Get( project );
372 auto &trackPanel = TrackPanel::Get( project );
373 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
374
375 for (auto lt : tracks.Selected<LabelTrack>()) {
376 auto &view = LabelTrackView::Get( *lt );
377 if (view.CopySelectedText( context.project )) {
378 //trackPanel.Refresh(false);
379 return;
380 }
381 }
382 //Presumably, there might be not more than one track
383 //that expects text input
384 for (auto wt : tracks.Any<WaveTrack>()) {
385 auto& view = WaveChannelView::GetFirst(*wt);
386 if (view.CopySelectedText(context.project)) {
387 return;
388 }
389 }
390
391 auto &clipboard = Clipboard::Get();
392 clipboard.Clear();
393
394 auto pNewClipboard = TrackList::Create( nullptr );
395 auto &newClipboard = *pNewClipboard;
396
397 for (auto n : tracks.Selected()) {
398 if (n->SupportsBasicEditing()) {
399 auto dest = n->Copy(selectedRegion.t0(), selectedRegion.t1());
400 newClipboard.Add(dest);
401 }
402 }
403
404 // Survived possibility of exceptions. Commit changes to the clipboard now.
405 clipboard.Assign( std::move( newClipboard ),
406 selectedRegion.t0(), selectedRegion.t1(), project.shared_from_this() );
407
408 //Make sure the menus/toolbar states get updated
409 trackPanel.Refresh(false);
410}
411
412std::pair<double, double> FindSelection(const CommandContext &context)
413{
414 double sel0 = 0.0, sel1 = 0.0;
415
416#if 0
417 // Use the overriding selection if any was given in the context
418 if (auto *pRegion = context.temporarySelection.pSelectedRegion) {
419 auto &selectedRegion = *pRegion;
420 sel0 = selectedRegion.t0();
421 sel1 = selectedRegion.t1();
422 }
423 else
424#endif
425 {
426 auto &selectedRegion = ViewInfo::Get(context.project).selectedRegion;
427 sel0 = selectedRegion.t0();
428 sel1 = selectedRegion.t1();
429 }
430
431 return { sel0, sel1 };
432}
433
434std::shared_ptr<const TrackList> FindSourceTracks(const CommandContext &context)
435{
436 auto &project = context.project;
437 auto &window = GetProjectFrame(project);
439 const auto &clipboard = Clipboard::Get();
440 auto discardTrimmed = false;
441 if (&context.project != &*clipboard.Project().lock()) {
442 const auto waveClipCopyPolicy = TracksBehaviorsAudioTrackPastePolicy.Read();
443 if (waveClipCopyPolicy == wxT("Ask") &&
444 HasHiddenData(clipboard.GetTracks()))
445 {
446 AudioPasteDialog audioPasteDialog(
447 &window,
448 EstimateCopyBytesCount(clipboard.GetTracks(), tracks)
449 );
450 const auto result = audioPasteDialog.ShowModal();
451 if(result == wxID_CANCEL)
452 return {};
453 discardTrimmed =
455 }
456 else if(waveClipCopyPolicy == wxT("Discard"))
457 discardTrimmed = true;
458 }
459
460 std::shared_ptr<const TrackList> srcTracks;
461 if(discardTrimmed)
462 srcTracks = DuplicateDiscardTrimmed(clipboard.GetTracks());
463 else
464 srcTracks = clipboard.GetTracks().shared_from_this();
465
466 return srcTracks;
467}
468
470 const CommandContext &context, const TrackList &srcTracks)
471{
472 auto &project = context.project;
474 auto &trackFactory = WaveTrackFactory::Get(project);
475 auto &pSampleBlockFactory = trackFactory.GetSampleBlockFactory();
476 return pSampleBlockFactory->Subscribe([
477 toCopy = EstimateCopiedBlocks(srcTracks, tracks),
478 nCopied = 0,
479 copyStartTime = std::chrono::system_clock::now(),
480 progressDialog = std::shared_ptr<BasicUI::ProgressDialog>()]
481 (const SampleBlockCreateMessage&) mutable {
482 using namespace std::chrono;
483 constexpr auto ProgressDialogShowDelay = milliseconds { 100 };
484 ++nCopied;
485 if(!progressDialog) {
486 if(duration_cast<milliseconds>(system_clock::now() - copyStartTime) >= ProgressDialogShowDelay)
487 progressDialog = BasicUI::MakeProgress(XO("Paste clip"), XO("Pasting clip contents, please wait"), 0);
488 }
489 else {
490 progressDialog->Poll(nCopied, toCopy);
491 }
492 });
493}
494
496bool FitsInto(const Track &src, const Track &dst)
497{
498 if (!src.SameKindAs(dst))
499 return false;
500 // Mono can "fit" into stereo, by duplication of the channel
501 // Otherwise non-wave tracks always have just one "channel"
502 // Future: Fit stereo into mono too, using mix-down
503 return src.NChannels() <= dst.NChannels();
504}
505
506// First, destination track; second, source
507using Correspondence = std::vector<std::pair<Track*, const Track*>>;
508
510 TrackList &dstTracks, const TrackList &srcTracks)
511{
512 Correspondence result;
513 auto dstRange = dstTracks.Selected();
514 if (dstRange.size() == 1)
515 // Special rule when only one track is selected interprets the user's
516 // intent as pasting into that track and following ones
517 dstRange = dstTracks.Any().StartingWith(*dstRange.begin());
518 auto srcRange = srcTracks.Any();
519 while (!(dstRange.empty() || srcRange.empty())) {
520 auto &dst = **dstRange.begin();
521 auto &src = **srcRange.begin();
522 if (!FitsInto(src, dst)) {
523 // Skip selected track of inappropriate type and try again
524 ++dstRange.first;
525 continue;
526 }
527 result.emplace_back(&dst, &src);
528 ++srcRange.first;
529 ++dstRange.first;
530 }
531
532 if (!srcRange.empty())
533 // Could not fit all source tracks into the selected tracks
534 return {};
535 else
536 return result;
537}
538
539void OnPaste(const CommandContext &context)
540{
541 if (wxTheClipboard->IsSupported(wxDF_FILENAME) && wxTheClipboard->Open())
542 {
543 wxFileDataObject data;
544 const auto hadData = wxTheClipboard->GetData(data);
545 wxTheClipboard->Close();
546 if (hadData)
547 {
548 ProjectFileManager::Get(context.project).Import(data.GetFilenames());
549 return;
550 }
551 }
552
553 auto &project = context.project;
554
555 // Handle text paste first.
556 if (DoPasteText(project))
557 return;
558
559 const auto &clipboard = Clipboard::Get();
560 if (clipboard.GetTracks().empty())
561 return;
562
563 const auto srcTracks = FindSourceTracks(context);
564 if (!srcTracks)
565 // user cancelled
566 return;
567
568 auto notificationScope = NotificationScope(context, *srcTracks);
569
571 // If nothing's selected, we just insert new tracks.
572 if (!tracks.Selected()) {
574 project, *srcTracks, clipboard.T0(), clipboard.T1());
575 return;
576 }
577
578 // Otherwise, paste into the selected tracks.
579 double t0, t1;
580 std::tie(t0, t1) = FindSelection(context);
581 auto newT1 = t0 + clipboard.Duration();
582 const auto isSyncLocked = SyncLockState::Get(project).IsSyncLocked();
583
584 Track *ff = nullptr;
585 bool bPastedSomething = false;
586
587 // Find tracks to paste in
588 auto correspondence = FindCorrespondence(tracks, *srcTracks);
589 if (correspondence.empty()) {
590 if (tracks.Selected().size() == 1)
592"The content you are trying to paste will span across more tracks than you "
593"currently have available. Add more tracks and try again.")
594 );
595 else
597"There are not enough tracks selected to accommodate your copied content. "
598"Select additional tracks and try again.")
599 );
600 return;
601 }
602 auto iPair = correspondence.begin();
603 const auto endPair = correspondence.cend();
604
605 // Outer loop by sync-lock groups
606 auto next = tracks.begin();
607 for (auto range = tracks.Any(); !range.empty();
608 // Skip to next sync lock group
609 range.first = next
610 ) {
611 if (iPair == endPair)
612 // Nothing more to paste
613 break;
614 auto group = SyncLock::Group(**range.first);
615 next = tracks.Find(*group.rbegin());
616 ++next;
617
618 if (!group.contains(iPair->first))
619 // Nothing to paste into this group
620 continue;
621
622 // Inner loop over the sync-lock group by tracks
623 for (auto member : group) {
624 if (iPair == endPair || member != iPair->first) {
625 if (isSyncLocked) {
626 // Track is not pasted into but must be adjusted
627 if (t1 != newT1 && t1 <= member->GetEndTime()) {
628 member->SyncLockAdjust(t1, newT1);
629 bPastedSomething = true;
630 }
631 }
632 }
633 else {
634 // Remember first pasted-into track, to focus it
635 if (!ff)
636 ff = member;
637 // Do the pasting!
638 const auto src = (iPair++)->second;
639 member->TypeSwitch(
640 [&](WaveTrack &wn){
641 bPastedSomething = true;
642 // For correct remapping of preserved split lines:
643 PasteTimeWarper warper{ t1, t0 + src->GetEndTime() };
644 const auto newClipOnPaste =
645 gPrefs->ReadBool(wxT("/GUI/PasteAsNewClips"), false);
646 // The new-clip-on-paste behavior means: not merging the
647 // clipboard data with data at the selection borders; not
648 // reproducing boundaries within the selected region in the
649 // new clip; preserving the data underneath by trimming
650 // (rather than deleting).
651 // The legacy behavior is the opposite.
652 const auto merge = newClipOnPaste ? false : true;
653 const auto preserveExistingBoundaries = newClipOnPaste ? false : true;
654 auto clearByTrimming = newClipOnPaste ? true : false;
655 if(src->NChannels() == 1 && wn.NChannels() == 2)
656 {
657 // When the source is mono, may paste its only channel
658 // repeatedly into a stereo track
659 const auto pastedTrack = std::static_pointer_cast<WaveTrack>(src->Duplicate());
660 pastedTrack->MonoToStereo();
661 wn.ClearAndPaste(
662 t0, t1, *pastedTrack,
663 preserveExistingBoundaries, merge, &warper,
664 clearByTrimming);
665 }
666 else
667 {
668 wn.ClearAndPaste(
669 t0, t1, *static_cast<const WaveTrack*>(src),
670 preserveExistingBoundaries, merge, &warper,
671 clearByTrimming);
672 }
673 },
674 [&](LabelTrack &ln){
675 // Per Bug 293, users expect labels to move on a paste into
676 // a label track.
677 ln.Clear(t0, t1);
678
679 ln.ShiftLabelsOnInsert( clipboard.Duration(), t0 );
680
681 bPastedSomething |= ln.PasteOver(t0, *src);
682 },
683 [&](Track &t){
684 bPastedSomething = true;
685 t.Clear(t0, t1);
686 t.Paste(t0, *src);
687 }
688 );
689 }
690 }
691 }
692
693 // TODO: What if we clicked past the end of the track?
694
695 if (bPastedSomething) {
697 .setTimes( t0, t0 + clipboard.Duration() );
698
700 .PushState(XO("Pasted from the clipboard"), XO("Paste"));
701
702 if (ff) {
703 TrackFocus::Get(project).Set(ff);
705 }
706 }
707}
708
709void OnDuplicate(const CommandContext &context)
710{
711 auto &project = context.project;
713 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
714
715 // This iteration is unusual because we add to the list inside the loop
716 auto range = tracks.Selected();
717 auto last = *range.rbegin();
718 for (auto n : range) {
719 if (!n->SupportsBasicEditing())
720 continue;
721
722 // Make copies not for clipboard but for direct addition to the project
723 auto dest = n->Copy(selectedRegion.t0(), selectedRegion.t1(), false);
724 dest->MoveTo(std::max(selectedRegion.t0(), n->GetStartTime()));
725 tracks.Add(dest);
726
727 // This break is really needed, else we loop infinitely
728 if (n == last)
729 break;
730 }
731
733 .PushState(XO("Duplicated"), XO("Duplicate"));
734}
735
736void OnSplitCut(const CommandContext &context)
737{
738 auto &project = context.project;
740 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
741
742 auto &clipboard = Clipboard::Get();
743 clipboard.Clear();
744
745 auto pNewClipboard = TrackList::Create(nullptr);
746 auto &newClipboard = *pNewClipboard;
747
748 tracks.Selected().Visit(
749 [&](WaveTrack &n) {
750 auto track = n.SplitCut(selectedRegion.t0(), selectedRegion.t1());
751 newClipboard.Add(track);
752 },
753 [&](Track &n) {
754 if (n.SupportsBasicEditing()) {
755 auto dest = n.Copy(selectedRegion.t0(), selectedRegion.t1());
756 n.Silence(selectedRegion.t0(), selectedRegion.t1());
757 newClipboard.Add(dest);
758 }
759 }
760 );
761
762 // Survived possibility of exceptions. Commit changes to the clipboard now.
763 clipboard.Assign(std::move(newClipboard),
764 selectedRegion.t0(), selectedRegion.t1(), project.shared_from_this());
765
767 .PushState(XO("Split-cut to the clipboard"), XO("Split Cut"));
768}
769
770void OnSplitDelete(const CommandContext &context)
771{
772 auto &project = context.project;
774 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
775
776 tracks.Selected().Visit(
777 [&](WaveTrack &wt) {
778 wt.SplitDelete(selectedRegion.t0(), selectedRegion.t1());
779 },
780 [&](Track &n) {
781 if (n.SupportsBasicEditing())
782 n.Silence(selectedRegion.t0(), selectedRegion.t1());
783 }
784 );
785
787 XO("Split-deleted %.2f seconds at t=%.2f")
788 .Format(selectedRegion.duration(), selectedRegion.t0()),
789 XO("Split Delete"));
790}
791
792void OnSilence(const CommandContext &context)
793{
794 auto &project = context.project;
796 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
797
798 const auto selectedWaveTracks = tracks.Selected<WaveTrack>();
800 [&](const ProgressReporter& parent) {
802 selectedWaveTracks.begin(), selectedWaveTracks.end(),
803 [&](WaveTrack* n, const ProgressReporter& child) {
804 n->Silence(selectedRegion.t0(), selectedRegion.t1(), child);
805 },
806 parent);
807 });
808
810 XO("Silenced selected tracks for %.2f seconds at %.2f")
811 .Format(selectedRegion.duration(), selectedRegion.t0()),
812 /* i18n-hint: verb */
813 XC("Silence", "command"));
814}
815
816void OnTrim(const CommandContext &context)
817{
818 auto &project = context.project;
819 auto &tracks = TrackList::Get( project );
820 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
821
822 if (selectedRegion.isPoint())
823 return;
824
825 tracks.Selected().Visit( [&](WaveTrack &wt) {
826 //Hide the section before the left selector
827 wt.Trim(selectedRegion.t0(), selectedRegion.t1());
828 } );
829
831 XO("Trim selected audio tracks from %.2f seconds to %.2f seconds")
832 .Format( selectedRegion.t0(), selectedRegion.t1() ),
833 XO("Trim Audio"));
834}
835
836void OnSplit(const CommandContext &context)
837{
838 auto &project = context.project;
840 auto [sel0, sel1] = FindSelection(context);
841 if (auto *pTrack = context.temporarySelection.pTrack) {
842 if (auto pWaveTrack = dynamic_cast<WaveTrack*>(pTrack))
843 pWaveTrack->Split(sel0, sel1);
844 else
845 // Did nothing, don't push history
846 return;
847 }
848 else
849 for (auto wt : tracks.Selected<WaveTrack>())
850 wt->Split(sel0, sel1);
851
852 ProjectHistory::Get( project ).PushState(XO("Split"), XO("Split"));
853#if 0
854//ANSWER-ME: Do we need to keep this commented out OnSplit() code?
855// This whole section no longer used...
856 /*
857 * Previous (pre-multiclip) implementation of "Split" command
858 * This does work only when a range is selected!
859 *
860 TrackListIterator iter(tracks);
861
862 Track *n = iter.First();
863 Track *dest;
864
865 TrackList newTracks;
866
867 while (n) {
868 if (n->GetSelected()) {
869 double sel0 = selectedRegion.t0();
870 double sel1 = selectedRegion.t1();
871
872 dest = n->Copy(sel0, sel1);
873 dest->Init(*n);
874 dest->MoveTo(std::max(sel0, n->GetOffset()));
875
876 if (sel1 >= n->GetEndTime())
877 n->Clear(sel0, sel1);
878 else if (sel0 <= n->GetOffset()) {
879 n->Clear(sel0, sel1);
880 n->MoveTo(sel1);
881 } else
882 n->Silence(sel0, sel1);
883
884 newTracks.Add(dest);
885 }
886 n = iter.Next();
887 }
888
889 TrackListIterator nIter(&newTracks);
890 n = nIter.First();
891 while (n) {
892 tracks->Add(n);
893 n = nIter.Next();
894 }
895
896 PushState(XO("Split"), XO("Split"));
897 */
898#endif
899}
900
901void OnSplitNew(const CommandContext &context)
902{
903 auto &project = context.project;
905 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
906
907 // This iteration is unusual because we add to the list inside the loop
908 auto range = tracks.Selected();
909 auto last = *range.rbegin();
910 for (auto track : range) {
911 track->TypeSwitch(
912 [&](WaveTrack &wt) {
913 // Clips must be aligned to sample positions or the NEW clip will
914 // not fit in the gap where it came from
915 const double newt0 = wt.SnapToSample(selectedRegion.t0());
916 const double newt1 = wt.SnapToSample(selectedRegion.t1());
917 // Fix issue 2846 by calling copy with forClipboard = false.
918 // This avoids creating the blank placeholder clips
919 const auto dest = wt.Copy(newt0, newt1, false);
920 if (dest) {
921 // The copy function normally puts the clip at time 0
922 // This offset lines it up with the original track's timing
923 dest->MoveTo(newt0);
924 tracks.Add(dest);
925 }
926 wt.SplitDelete(newt0, newt1);
927 }
928#if 0
929 ,
930 // LL: For now, just skip all non-wave tracks since the other do not
931 // yet support proper splitting.
932 [&](Track &n) {
933 dest = n.Cut(viewInfo.selectedRegion.t0(),
934 viewInfo.selectedRegion.t1());
935 if (dest) {
936 dest->MoveTo(std::max(0, n.GetOffset()));
937 tracks.Add(dest);
938 }
939 }
940#endif
941 );
942 if (track == last)
943 break;
944 }
945
947 .PushState(XO("Split to new track"), XO("Split New"));
948}
949
950void OnJoin(const CommandContext &context)
951{
952 auto &project = context.project;
954 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
955 const auto selectedTracks = tracks.Selected<WaveTrack>();
957 [&](const ProgressReporter& reportProgress) {
958 using namespace BasicUI;
960 selectedTracks.begin(), selectedTracks.end(),
961 [&](WaveTrack* wt, const ProgressReporter& childProgress) {
962 wt->Join(
963 selectedRegion.t0(), selectedRegion.t1(), childProgress);
964 },
965 reportProgress);
966 });
967
969 XO("Joined %.2f seconds at t=%.2f")
970 .Format(selectedRegion.duration(), selectedRegion.t0()),
971 XO("Join"));
972}
973
974void OnDisjoin(const CommandContext &context)
975{
976 auto &project = context.project;
978 auto &selectedRegion = ViewInfo::Get(project).selectedRegion;
979
980 for (auto wt : tracks.Selected<WaveTrack>())
981 wt->Disjoin(selectedRegion.t0(), selectedRegion.t1());
982
984 XO("Detached %.2f seconds at t=%.2f")
985 .Format(selectedRegion.duration(), selectedRegion.t0()),
986 XO("Detach"));
987}
988
989void OnPreferences(const CommandContext &context)
990{
991 auto &project = context.project;
992
993 GlobalPrefsDialog dialog(&GetProjectFrame(project) /* parent */, &project );
994
995 if (!dialog.ShowModal()) {
996 // Canceled
997 return;
998 }
999
1000 // LL: Moved from PrefsDialog since wxWidgets on OSX can't deal with
1001 // rebuilding the menus while the PrefsDialog is still in the modal
1002 // state.
1003 for (auto p : AllProjects{}) {
1005// TODO: The comment below suggests this workaround is obsolete.
1006#if defined(__WXGTK__)
1007 // Workaround for:
1008 //
1009 // http://bugzilla.audacityteam.org/show_bug.cgi?id=458
1010 //
1011 // This workaround should be removed when Audacity updates to wxWidgets
1012 // 3.x which has a fix.
1013 auto &window = GetProjectFrame( *p );
1014 wxRect r = window.GetRect();
1015 window.SetSize(wxSize(1,1));
1016 window.SetSize(r.GetSize());
1017#endif
1018 }
1019}
1020
1021// Legacy functions, not used as of version 2.3.0
1022
1023#if 0
1024void OnPasteOver(const CommandContext &context)
1025{
1026 auto &project = context.project;
1027 auto &selectedRegion = project.GetViewInfo().selectedRegion;
1028
1029 if((AudacityProject::msClipT1 - AudacityProject::msClipT0) > 0.0)
1030 {
1031 selectedRegion.setT1(
1032 selectedRegion.t0() +
1033 (AudacityProject::msClipT1 - AudacityProject::msClipT0));
1034 // MJS: pointless, given what we do in OnPaste?
1035 }
1036 OnPaste(context);
1037
1038 return;
1039}
1040#endif
1041
1042// Menu definitions
1043
1046 [](const AudacityProject &project){
1047 auto range = TrackList::Get(project).Any<const LabelTrack>()
1048 + [&](const LabelTrack *pTrack){
1049 return LabelTrackView::Get( *pTrack ).IsTextSelected(
1050 // unhappy const_cast because track focus might be set
1051 const_cast<AudacityProject&>(project)
1052 );
1053 };
1054 if ( !range.empty() )
1055 return true;
1056
1057 if (
1059 &&
1061 )
1062 return true;
1063
1064 return false;
1065 },
1067}; return flag; }
1068
1071 [](const AudacityProject &project)
1072 {
1074 return false;
1075
1076 const auto &viewInfo = ViewInfo::Get(project);
1077 if(viewInfo.selectedRegion.isPoint())
1078 return false;
1079
1080 const auto selectedTracks = TrackList::Get(project).Selected<const WaveTrack>();
1081 for (const auto track : selectedTracks)
1082 {
1083 const auto selectedClips =
1085 viewInfo.selectedRegion.t0(), viewInfo.selectedRegion.t1());
1086 if(selectedClips.size() > 1)
1087 return true;
1088 }
1089 return false;
1090 },
1092}; return flag; }
1093
1094using namespace MenuRegistry;
1096{
1097 static const auto NotBusyTimeAndTracksFlags =
1099
1100 // The default shortcut key for Redo is different on different platforms.
1101 static constexpr auto redoKey =
1102#ifdef __WXMSW__
1103 wxT("Ctrl+Y")
1104#else
1105 wxT("Ctrl+Shift+Z")
1106#endif
1107 ;
1108
1109 // The default shortcut key for Preferences is different on different
1110 // platforms.
1111 static constexpr auto prefKey =
1112#ifdef __WXMAC__
1113 wxT("Ctrl+,")
1114#else
1115 wxT("Ctrl+P")
1116#endif
1117 ;
1118
1119 static auto menu = std::shared_ptr{
1120 Menu( wxT("Edit"), XXO("&Edit"),
1121 Section( "UndoRedo",
1122 Command( wxT("Undo"), XXO("&Undo"), OnUndo,
1123 AudioIONotBusyFlag() | UndoAvailableFlag(), wxT("Ctrl+Z") ),
1124
1125 Command( wxT("Redo"), XXO("&Redo"), OnRedo,
1126 AudioIONotBusyFlag() | RedoAvailableFlag(), redoKey ),
1127
1128 MenuCreator::Special( wxT("UndoItemsUpdateStep"),
1129 [](AudacityProject &project, wxMenu&) {
1130 // Change names in the CommandManager as a side-effect
1132 })
1133 ),
1134
1135 Section( "Basic",
1136 // Basic Edit commands
1137 /* i18n-hint: (verb)*/
1138 Command( wxT("Cut"), XXO("Cu&t"), OnCut,
1140 wxT("Ctrl+X") ),
1141 Command( wxT("Delete"), XXO("&Delete"), OnDelete,
1143 wxT("Ctrl+K") ),
1144 /* i18n-hint: (verb)*/
1145 Command( wxT("Copy"), XXO("&Copy"), OnCopy,
1146 AudioIONotBusyFlag() | CutCopyAvailableFlag(), wxT("Ctrl+C") ),
1147 /* i18n-hint: (verb)*/
1148 Command( wxT("Paste"), XXO("&Paste"), OnPaste,
1149 AudioIONotBusyFlag(), wxT("Ctrl+V") ),
1150 /* i18n-hint: (verb)*/
1151 Command( wxT("Duplicate"), XXO("Duplic&ate"), OnDuplicate,
1152 NotBusyTimeAndTracksFlags, wxT("Ctrl+D") ),
1153
1154 Section( "",
1155 Menu( wxT("RemoveSpecial"), XXO("R&emove Special"),
1156 Section( "",
1157 /* i18n-hint: (verb) Do a special kind of cut*/
1158 Command( wxT("SplitCut"), XXO("Spl&it Cut"), OnSplitCut,
1159 NotBusyTimeAndTracksFlags,
1160 Options{ wxT("Ctrl+Alt+X") } ),
1161 /* i18n-hint: (verb) Do a special kind of DELETE*/
1162 Command( wxT("SplitDelete"), XXO("Split D&elete"), OnSplitDelete,
1163 NotBusyTimeAndTracksFlags,
1164 Options{ wxT("Ctrl+Alt+K") } )
1165 ),
1166
1167 Section( "",
1168 /* i18n-hint: (verb)*/
1169 Command( wxT("Silence"), XXO("Silence Audi&o"), OnSilence,
1171 wxT("Ctrl+L") ),
1172 /* i18n-hint: (verb)*/
1173 Command( wxT("Trim"), XXO("Tri&m Audio"), OnTrim,
1175 Options{ wxT("Ctrl+T") } )
1176 )
1177 )
1178 )
1179 ),
1180
1181
1182 Section( "Other",
1184
1185 Menu( wxT("Clip"), XXO("Audi&o Clips"),
1186 Section( "",
1187 /* i18n-hint: (verb) It's an item on a menu. */
1188 Command( wxT("Split"), XXO("Sp&lit"), OnSplit,
1190 Options{ wxT("Ctrl+I") } ),
1191 Command( wxT("SplitNew"), XXO("Split Ne&w"), OnSplitNew,
1193 Options{ wxT("Ctrl+Alt+I") } )
1194 ),
1195
1196 Section( "",
1197 /* i18n-hint: (verb)*/
1198 Command( wxT("Join"), XXO("&Join"), OnJoin,
1199 JoinClipsAvailableFlag(), wxT("Ctrl+J") ),
1200 Command( wxT("Disjoin"), XXO("Detac&h at Silences"), OnDisjoin,
1201 NotBusyTimeAndTracksFlags, wxT("Ctrl+Alt+J") )
1202 )
1203 )
1204
1205 ),
1206
1207 // Note that on Mac, the Preferences menu item is specially handled in
1208 // CommandManager (assigned a special wxWidgets id) so that it does
1209 // not appear in the Edit menu but instead under Audacity, consistent with
1210 // MacOS conventions.
1211 Section( "Preferences",
1212 Command( wxT("Preferences"), XXO("Pre&ferences"), OnPreferences,
1213 AudioIONotBusyFlag(), prefKey )
1214 )
1215
1216 ) };
1217 return menu;
1218}
1219
1221
1223{
1224 static const auto flags =
1226 static auto menu = std::shared_ptr{
1227 Menu( wxT("Edit"), XXO("&Edit"),
1228 Command( wxT("DeleteKey"), XXO("&Delete Key"), OnDelete,
1229 (flags | NoAutoSelect()),
1230 wxT("Backspace") ),
1231 Command( wxT("DeleteKey2"), XXO("Delete Key&2"), OnDelete,
1232 (flags | NoAutoSelect()),
1233 wxT("Delete") )
1234 ) };
1235 return menu;
1236}
1237
1242 (flagsRqd & NoAutoSelect()).none() )
1244};
1245
1247 []{ return TracksExistFlag(); },
1248 []{ return EditableTracksSelectedFlag(); },
1250 selectAll
1251}};
1252
1253// Including time tracks.
1255 []{ return TracksExistFlag(); },
1256 []{ return AnyTracksSelectedFlag(); },
1258 selectAll
1259}};
1260
1262 []{ return WaveTracksExistFlag(); },
1265 selectAll
1266}};
1267
1268// Also enable select for the noise reduction case.
1270 []{ return WaveTracksExistFlag(); },
1273 selectAll
1274}};
1275
1277 wxT("Optional/Extra/Part1")
1278};
1279
1280}
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Toolkit-neutral facade for basic user interface services.
AttachedItem sAttachment1
AttachedItem sAttachment2
std::bitset< NCommandFlags > CommandFlag
Definition: CommandFlag.h:30
const ReservedCommandFlag & NoAutoSelect()
const ReservedCommandFlag & NoiseReductionTimeSelectedFlag()
bool EditableTracksSelectedPred(const AudacityProject &project)
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & UndoAvailableFlag()
const ReservedCommandFlag & RedoAvailableFlag()
bool AudioIOBusyPred(const AudacityProject &project)
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & EditableTracksSelectedFlag()
const ReservedCommandFlag & AnyTracksSelectedFlag()
const ReservedCommandFlag & TracksExistFlag()
const ReservedCommandFlag & WaveTracksExistFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
bool TimeSelectedPred(const AudacityProject &project)
@ none
Definition: Dither.h:20
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define XC(s, c)
Definition: Internat.h:37
#define safenew
Definition: MemoryX.h:10
#define QUANTIZED_TIME(time, rate)
Definition: MemoryX.h:336
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
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 ...
#define SAMPLE_SIZE(SampleFormat)
Definition: SampleFormat.h:52
const std::optional< double > & GetProjectTempo(const ChannelGroup &group)
Definition: TempoChange.cpp:48
const auto tracks
const auto project
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper,...
std::function< void(double)> ProgressReporter
Definition: Track.h:48
ChoiceSetting TracksBehaviorsAudioTrackPastePolicy
An AudacityException with no visible message.
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:90
virtual size_t NChannels() const =0
Report the number of channels.
wxString Read() const
Definition: Prefs.cpp:388
static Clipboard & Get()
Definition: Clipboard.cpp:28
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
TemporarySelection temporarySelection
AudacityProject & project
static CommandManager & Get(AudacityProject &project)
Abstract base class used in importing a file.
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:95
static LabelTrackView & Get(LabelTrack &)
bool IsTextSelected(AudacityProject &project) const
int GetTextEditIndex(AudacityProject &project) const
static constexpr auto Special
Definition: MenuCreator.h:36
void RebuildMenuBar()
static MenuCreator & Get(AudacityProject &project)
Definition: MenuCreator.cpp:91
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:78
Track::Holder Cut(double t0, double t1) override
Create tracks and modify this track.
Definition: NoteTrack.cpp:320
void Clear(double t0, double t1) override
Definition: NoteTrack.cpp:397
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
Create new tracks and don't modify this track.
Definition: NoteTrack.cpp:350
double duration() const
Definition: ViewInfo.h:41
bool setTimes(double t0, double t1)
Definition: ViewInfo.cpp:51
double t0() const
Definition: ViewInfo.h:35
Unit slope but with either a jump (pasting more) or a flat interval (pasting less)
Definition: TimeWarper.h:181
int ShowModal() override
bool Import(const FilePath &fileName, bool addToHistory=true)
static ProjectFileManager & Get(AudacityProject &project)
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 ProjectTimeSignature & Get(AudacityProject &project)
Generates classes whose instances register items at construction.
Definition: Registry.h:388
static TrackIterRange< Track > Group(Track &track)
Definition: SyncLock.cpp:150
static bool IsSelectedOrSyncLockSelectedP(const Track *pTrack)
Definition: SyncLock.h:61
static bool IsSelectedOrSyncLockSelected(const Track &track)
Definition: SyncLock.cpp:104
bool IsSyncLocked() const
Definition: SyncLock.cpp:44
static SyncLockState & Get(AudacityProject &project)
Definition: SyncLock.cpp:27
Track * Get()
Definition: TrackFocus.cpp:156
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:110
virtual void SetSelected(bool s)
Definition: Track.cpp:83
virtual Holder PasteInto(AudacityProject &project, TrackList &list) const =0
bool SameKindAs(const Track &track) const
Definition: Track.h:373
virtual bool SupportsBasicEditing() const
Whether this track type implements cut-copy-paste; by default, true.
Definition: Track.cpp:797
R TypeSwitch(const Functions &...functions)
Definition: Track.h:381
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:850
static TrackListHolder Create(AudacityProject *pOwner)
Definition: Track.cpp:330
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:950
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:967
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:234
static UndoManager & Get(AudacityProject &project)
Definition: UndoManager.cpp:71
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:216
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
void ShowTrack(const Track &track)
Definition: Viewport.cpp:460
static Viewport & Get(AudacityProject &project)
Definition: Viewport.cpp:33
static WaveChannelView & GetFirst(WaveTrack &wt)
Get the view of the first channel.
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:3358
A Track that contains audio waveform data.
Definition: WaveTrack.h:203
void SplitDelete(double t0, double t1)
Definition: WaveTrack.cpp:1508
void Silence(double t0, double t1, ProgressReporter reportProgress) override
Definition: WaveTrack.cpp:1984
void Trim(double t0, double t1)
Definition: WaveTrack.cpp:962
Holder SplitCut(double t0, double t1)
Definition: WaveTrack.cpp:948
size_t NChannels() const override
A constant property.
Definition: WaveTrack.cpp:530
void ClearAndPaste(double t0, double t1, const WaveTrack &src, bool preserve=true, bool merge=true, const TimeWarper *effectWarper=nullptr, bool clearByTrimming=false)
Definition: WaveTrack.cpp:1201
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
Create new tracks and don't modify this track.
Definition: WaveTrack.cpp:1078
double SnapToSample(double t) const
bool ReadBool(const wxString &key, bool defaultValue) const
virtual bool Read(const wxString &key, bool *value) const =0
std::function< void(double)> ProgressReporter
Definition: BasicUI.h:25
void SplitProgress(ItType first, ItType last, FnType action, ProgressReporter parent)
Helper for the update of a task's progress bar when this task is made of a range's subtasks.
Definition: BasicUI.h:339
std::unique_ptr< ProgressDialog > MakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags=(ProgressShowStop|ProgressShowCancel), const TranslatableString &remainingLabelText={})
Create and display a progress dialog.
Definition: BasicUI.h:302
constexpr auto Section
Definition: MenuRegistry.h:436
constexpr auto Command
Definition: MenuRegistry.h:456
constexpr auto Menu
Items will appear in a main toolbar menu or in a sub-menu.
Definition: MenuRegistry.h:445
MENUS_API void Visit(Visitor< Traits > &visitor, AudacityProject &project)
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
Definition: Registry.h:175
void DoSelectAllAudio(AudacityProject &project)
WAVE_TRACK_API void WithClipRenderingProgress(std::function< void(const ProgressReporter &)> action, TranslatableString title=defaultStretchRenderingTitle)
WAVE_TRACK_API size_t CountBlocks(const WaveTrack &track)
WAVE_TRACK_API sampleCount GetSequenceSamplesCount(const WaveTrack &track)
WAVE_TRACK_API void DiscardTrimmed(WaveTrack &track)
Remove hidden audio from all clips.
WAVE_TRACK_API WaveTrack::IntervalConstHolders GetClipsIntersecting(const WaveTrack &track, double t0, double t1)
std::shared_ptr< const TrackList > FindSourceTracks(const CommandContext &context)
Definition: EditMenus.cpp:434
Correspondence FindCorrespondence(TrackList &dstTracks, const TrackList &srcTracks)
Definition: EditMenus.cpp:509
wxULongLong EstimateCopyBytesCount(const TrackList &src, const TrackList &dst)
Definition: EditMenus.cpp:91
BlockArray::size_type EstimateCopiedBlocks(const TrackList &src, const TrackList &dst)
Definition: EditMenus.cpp:103
void OnDisjoin(const CommandContext &context)
Definition: EditMenus.cpp:974
void DoPasteNothingSelected(AudacityProject &project, const TrackList &src, double t0, double t1)
Definition: EditMenus.cpp:128
bool DoPasteText(AudacityProject &project)
Definition: EditMenus.cpp:47
void OnRedo(const CommandContext &context)
Definition: EditMenus.cpp:211
void OnJoin(const CommandContext &context)
Definition: EditMenus.cpp:950
RegisteredMenuItemEnabler selectWaveTracks
Definition: EditMenus.cpp:1261
std::shared_ptr< TrackList > DuplicateDiscardTrimmed(const TrackList &src)
Definition: EditMenus.cpp:111
bool FitsInto(const Track &src, const Track &dst)
Whether the source track may be pasted into the destination track.
Definition: EditMenus.cpp:496
RegisteredMenuItemEnabler selectTracks
Definition: EditMenus.cpp:1246
void OnDelete(const CommandContext &context)
Definition: EditMenus.cpp:332
auto NotificationScope(const CommandContext &context, const TrackList &srcTracks)
Definition: EditMenus.cpp:469
void OnPaste(const CommandContext &context)
Definition: EditMenus.cpp:539
const ReservedCommandFlag & CutCopyAvailableFlag()
Definition: EditMenus.cpp:1045
void OnSplit(const CommandContext &context)
Definition: EditMenus.cpp:836
std::pair< double, double > FindSelection(const CommandContext &context)
Definition: EditMenus.cpp:412
void OnSilence(const CommandContext &context)
Definition: EditMenus.cpp:792
RegisteredMenuItemEnabler selectWaveTracks2
Definition: EditMenus.cpp:1269
const ReservedCommandFlag & JoinClipsAvailableFlag()
Definition: EditMenus.cpp:1070
void OnTrim(const CommandContext &context)
Definition: EditMenus.cpp:816
void OnSplitDelete(const CommandContext &context)
Definition: EditMenus.cpp:770
std::vector< std::pair< Track *, const Track * > > Correspondence
Definition: EditMenus.cpp:507
void OnCopy(const CommandContext &context)
Definition: EditMenus.cpp:357
void OnUndo(const CommandContext &context)
Definition: EditMenus.cpp:182
void OnSplitCut(const CommandContext &context)
Definition: EditMenus.cpp:736
void OnPreferences(const CommandContext &context)
Definition: EditMenus.cpp:989
void OnDuplicate(const CommandContext &context)
Definition: EditMenus.cpp:709
RegisteredMenuItemEnabler selectAnyTracks
Definition: EditMenus.cpp:1254
bool HasHiddenData(const TrackList &trackList)
Definition: EditMenus.cpp:171
void OnSplitNew(const CommandContext &context)
Definition: EditMenus.cpp:901
void OnCut(const CommandContext &context)
Definition: EditMenus.cpp:239
CommandFlagOptions && DisableDefaultMessage() &&
Definition: CommandFlag.h:53
SelectedRegion * pSelectedRegion
Holds one item with description and time range for the UndoManager.
Definition: UndoManager.h:117
UndoState state
Definition: UndoManager.h:128