Audacity 3.2.0
LabelMenus.cpp
Go to the documentation of this file.
1#include "AudioIO.h"
2#include "../Clipboard.h"
3#include "../CommonCommandFlags.h"
4#include "../LabelTrack.h"
5#include "Prefs.h"
6#include "Project.h"
7#include "ProjectAudioIO.h"
8#include "ProjectHistory.h"
9#include "../ProjectWindow.h"
10#include "../SelectUtilities.h"
11#include "SyncLock.h"
12#include "../TrackPanelAx.h"
13#include "../TrackPanel.h"
14#include "ViewInfo.h"
15#include "WaveTrack.h"
16#include "../commands/CommandContext.h"
17#include "../commands/CommandManager.h"
18#include "../tracks/labeltrack/ui/LabelTrackView.h"
20
23
24// private helper classes and functions
25namespace {
26
29 [](const AudacityProject &project){
30 // At least one label track selected, having at least one label
31 // completely within the time selection.
32 const auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
33 const auto &test = [&]( const LabelTrack *pTrack ){
34 const auto &labels = pTrack->GetLabels();
35 return std::any_of( labels.begin(), labels.end(),
36 [&](const LabelStruct &label){
37 return
38 label.getT0() >= selectedRegion.t0()
39 &&
40 label.getT1() <= selectedRegion.t1()
41 ;
42 }
43 );
44 };
45 auto range = TrackList::Get( project ).Selected<const LabelTrack>()
46 + test;
47 return !range.empty();
48 }
49}; return flag; }
50
51//Adds label and returns index of label in labeltrack.
53 AudacityProject &project, const SelectedRegion &region,
54 bool preserveFocus = false)
55{
56 auto &tracks = TrackList::Get( project );
57 auto &trackFocus = TrackFocus::Get( project );
58 auto &trackPanel = TrackPanel::Get( project );
59
60 wxString title; // of label
61
62 bool useDialog;
63 gPrefs->Read(wxT("/GUI/DialogForNameNewLabel"), &useDialog, false);
64 if (useDialog) {
66 project, region, wxEmptyString, title) == wxID_CANCEL)
67 return -1; // index
68 }
69
70 // If the focused track is a label track, use that
71 const auto pFocusedTrack = trackFocus.Get();
72
73 // Look for a label track at or after the focused track
74 auto iter = pFocusedTrack
75 ? tracks.Find(pFocusedTrack)
76 : tracks.Any().begin();
77 auto lt = * iter.Filter< LabelTrack >();
78
79 // If none found, start a NEW label track and use it
80 if (!lt)
81 lt = LabelTrack::Create(tracks);
82
83// LLL: Commented as it seemed a little forceful to remove users
84// selection when adding the label. This does not happen if
85// you select several tracks and the last one of those is a
86// label track...typing a label will not clear the selections.
87//
88// SelectNone();
89 lt->SetSelected(true);
90
91 int index;
92 if (useDialog) {
93 index = lt->AddLabel(region, title);
94 }
95 else {
96 int focusTrackNumber = -1;
97 if (pFocusedTrack && preserveFocus) {
98 // Must remember the track to re-focus after finishing a label edit.
99 // do NOT identify it by a pointer, which might dangle! Identify
100 // by position.
101 focusTrackNumber = pFocusedTrack->GetIndex();
102 }
103 index =
104 LabelTrackView::Get( *lt ).AddLabel(region, title, focusTrackNumber);
105 }
106
107 ProjectHistory::Get( project )
108 .PushState(XO("Added label"), XO("Label"));
109
110 if (!useDialog) {
111 TrackFocus::Get(project).Set(lt);
112 lt->EnsureVisible();
113 }
114 trackPanel.SetFocus();
115
116 return index;
117}
118
119//get regions selected by selected labels
120//removes unnecessary regions, overlapping regions are merged
122 const TrackList &tracks, const SelectedRegion &selectedRegion,
123 Regions &regions )
124{
125 //determine labeled regions
126 for (auto lt : tracks.Selected< const LabelTrack >()) {
127 for (int i = 0; i < lt->GetNumLabels(); i++)
128 {
129 const LabelStruct *ls = lt->GetLabel(i);
130 if (ls->selectedRegion.t0() >= selectedRegion.t0() &&
131 ls->selectedRegion.t1() <= selectedRegion.t1())
132 regions.push_back(Region(ls->getT0(), ls->getT1()));
133 }
134 }
135
136 //anything to do ?
137 if( regions.size() == 0 )
138 return;
139
140 //sort and remove unnecessary regions
141 std::sort(regions.begin(), regions.end());
142 unsigned int selected = 1;
143 while( selected < regions.size() )
144 {
145 const Region &cur = regions.at( selected );
146 Region &last = regions.at( selected - 1 );
147 if( cur.start < last.end )
148 {
149 if( cur.end > last.end )
150 last.end = cur.end;
151 regions.erase( regions.begin() + selected );
152 }
153 else
154 ++selected;
155 }
156}
157
158using EditFunction = std::function<void(Track *, double, double)>;
159
160//Executes the edit function on all selected wave tracks with
161//regions specified by selected labels
162//If No tracks selected, function is applied on all tracks
163//If the function replaces the selection with audio of a different length,
164// bSyncLockedTracks should be set true to perform the same action on sync-lock
165// selected tracks.
167 TrackList &tracks, const SelectedRegion &selectedRegion,
168 EditFunction action)
169{
170 Regions regions;
171
172 GetRegionsByLabel( tracks, selectedRegion, regions );
173 if( regions.size() == 0 )
174 return;
175
176 const bool notLocked = (!SyncLockState::Get(project).IsSyncLocked() &&
177 (tracks.Selected<PlayableTrack>()).empty());
178
179 //Apply action on tracks starting from
180 //labeled regions in the end. This is to correctly perform
181 //actions like 'Delete' which collapse the track area.
182 for (auto t : tracks.Any())
183 {
184 const bool playable = dynamic_cast<const PlayableTrack *>(t) != nullptr;
185
186 if (SyncLock::IsSyncLockSelected(t) || notLocked && playable)
187 {
188 for (int i = (int)regions.size() - 1; i >= 0; i--)
189 {
190 const Region &region = regions.at(i);
191 action(t, region.start, region.end);
192 }
193 }
194 }
195}
196
197using EditDestFunction = std::function<Track::Holder (Track *, double, double)>;
198
199//Executes the edit function on all selected wave tracks with
200//regions specified by selected labels
201//If No tracks selected, function is applied on all tracks
202//Functions copy the edited regions to clipboard, possibly in multiple tracks
203//This probably should not be called if *action() changes the timeline, because
204// the copy needs to happen by track, and the timeline change by group.
206 TrackList &tracks, const SelectedRegion &selectedRegion,
207 EditDestFunction action )
208{
209 Regions regions;
210
211 GetRegionsByLabel( tracks, selectedRegion, regions );
212 if( regions.size() == 0 )
213 return;
214
215 const bool notLocked = (!SyncLockState::Get(project).IsSyncLocked() &&
216 (tracks.Selected<PlayableTrack>()).empty());
217
218 auto &clipboard = Clipboard::Get();
219 clipboard.Clear();
220
221 auto pNewClipboard = TrackList::Create( nullptr );
222 auto &newClipboard = *pNewClipboard;
223
224 //Apply action on wavetracks starting from
225 //labeled regions in the end. This is to correctly perform
226 //actions like 'Cut' which collapse the track area.
227
228 for( auto t : tracks.Any())
229 {
230 const bool playable = dynamic_cast<const PlayableTrack *>(t) != nullptr;
231
232 if (SyncLock::IsSyncLockSelected(t) || notLocked && playable)
233 {
234 // This track accumulates the needed clips, right to left:
235 Track::Holder merged;
236 for( int i = (int)regions.size() - 1; i >= 0; i-- )
237 {
238 const Region &region = regions.at(i);
239 auto dest = action(t, region.start, region.end );
240 if( dest )
241 {
242 Track::FinishCopy( t, dest.get() );
243 if( !merged )
244 merged = dest;
245 else
246 {
247 // Paste to the beginning; unless this is the first region,
248 // offset the track to account for time between the regions
249 if (i < (int)regions.size() - 1)
250 merged->Offset(
251 regions.at(i + 1).start - region.end);
252
253 // dest may have a placeholder clip at the end that is
254 // removed when pasting, which is okay because we proceed
255 // right to left. Any placeholder already in merged is kept.
256 // Only the rightmost placeholder is important in the final
257 // result.
258 merged->Paste( 0.0 , dest.get() );
259 }
260 }
261 else
262 // nothing copied but there is a 'region', so the 'region' must
263 // be a 'point label' so offset
264 if (i < (int)regions.size() - 1)
265 if (merged)
266 merged->Offset(
267 regions.at(i + 1).start - region.end);
268 }
269 if( merged )
270 newClipboard.Add( merged );
271 }
272 }
273
274 // Survived possibility of exceptions. Commit changes to the clipboard now.
275 clipboard.Assign( std::move( newClipboard ),
276 regions.front().start, regions.back().end, project.shared_from_this() );
277}
278
279}
280
282namespace {
283
284// Menu handler functions
285
286void OnEditLabels(const CommandContext &context)
287{
288 auto &project = context.project;
290}
291
292void OnAddLabel(const CommandContext &context)
293{
294 auto &project = context.project;
295 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
296
297 DoAddLabel(project, selectedRegion);
298}
299
301{
302 auto &project = context.project;
303 auto token = ProjectAudioIO::Get( project ).GetAudioIOToken();
304
305 auto gAudioIO = AudioIO::Get();
306 if (token > 0 &&
307 gAudioIO->IsStreamActive(token)) {
308 double indicator = gAudioIO->GetStreamTime();
309 DoAddLabel(project, SelectedRegion(indicator, indicator), true);
310 }
311}
312
313// Creates a NEW label in each selected label track with text from the system
314// clipboard
315void OnPasteNewLabel(const CommandContext &context)
316{
317 auto &project = context.project;
318 auto &tracks = TrackList::Get( project );
319 auto &trackPanel = TrackPanel::Get( project );
320 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
321
322 bool bPastedSomething = false;
323
324 {
325 auto trackRange = tracks.Selected< const LabelTrack >();
326 if (trackRange.empty())
327 {
328 // If there are no selected label tracks, try to choose the first label
329 // track after some other selected track
330 Track *t = *tracks.Selected().begin()
331 .Filter( &Track::Any )
332 .Filter<LabelTrack>();
333
334 // If no match found, add one
335 if (!t)
336 t = LabelTrack::Create(tracks);
337
338 // Select this track so the loop picks it up
339 t->SetSelected(true);
340 }
341 }
342
343 LabelTrack *plt = NULL; // the previous track
344 for ( auto lt : tracks.Selected< LabelTrack >() )
345 {
346 // Unselect the last label, so we'll have just one active label when
347 // we're done
348 if (plt)
350
351 // Add a NEW label, paste into it
352 // Paul L: copy whatever defines the selected region, not just times
353 auto &view = LabelTrackView::Get( *lt );
354 view.AddLabel(selectedRegion);
355 if (view.PasteSelectedText( context.project, selectedRegion.t0(),
356 selectedRegion.t1() ))
357 bPastedSomething = true;
358
359 // Set previous track
360 plt = lt;
361 }
362
363 // plt should point to the last label track pasted to -- ensure it's visible
364 // and set focus
365 if (plt) {
366 TrackFocus::Get(project).Set(plt);
367 plt->EnsureVisible();
368 trackPanel.SetFocus();
369 }
370
371 if (bPastedSomething) {
373 XO("Pasted from the clipboard"), XO("Paste Text to New Label"));
374 }
375}
376
377void OnToggleTypeToCreateLabel(const CommandContext &WXUNUSED(context) )
378{
379 bool typeToCreateLabel;
380 gPrefs->Read(wxT("/GUI/TypeToCreateLabel"), &typeToCreateLabel, false);
381 gPrefs->Write(wxT("/GUI/TypeToCreateLabel"), !typeToCreateLabel);
382 gPrefs->Flush();
384}
385
386void OnCutLabels(const CommandContext &context)
387{
388 auto &project = context.project;
389 auto &tracks = TrackList::Get( project );
390 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
391
392 if( selectedRegion.isPoint() )
393 return;
394
395 // Because of grouping the copy may need to operate on different tracks than
396 // the clear, so we do these actions separately.
397 auto copyfunc = [&](Track *track, double t0, double t1)
398 {
399 Track::Holder dest = nullptr;
400 track->TypeSwitch(
401 [&](WaveTrack *t)
402 {
403 dest = t->CopyNonconst(t0, t1);
404 }
405 );
406 return dest;
407 };
408 EditClipboardByLabel( project, tracks, selectedRegion, copyfunc );
409
410 bool enableCutlines = gPrefs->ReadBool(wxT( "/GUI/EnableCutLines"), false);
411 auto editfunc = [&](Track *track, double t0, double t1)
412 {
413 track->TypeSwitch(
414 [&](WaveTrack *t)
415 {
416 if (enableCutlines)
417 {
418 t->ClearAndAddCutLine(t0, t1);
419 }
420 else
421 {
422 t->Clear(t0, t1);
423 }
424 },
425 [&](Track *t)
426 {
427 t->Clear(t0, t1);
428 }
429 );
430 };
431 EditByLabel(project, tracks, selectedRegion, editfunc);
432
433 selectedRegion.collapseToT0();
434
436 /* i18n-hint: (verb) past tense. Audacity has just cut the labeled audio
437 regions.*/
438 XO( "Cut labeled audio regions to clipboard" ),
439 /* i18n-hint: (verb)*/
440 XO( "Cut Labeled Audio" ) );
441}
442
443void OnDeleteLabels(const CommandContext &context)
444{
445 auto &project = context.project;
446 auto &tracks = TrackList::Get( project );
447 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
448
449 if( selectedRegion.isPoint() )
450 return;
451
452 auto editfunc = [&](Track *track, double t0, double t1)
453 {
454 track->Clear(t0, t1);
455 };
456 EditByLabel(project, tracks, selectedRegion, editfunc);
457
458 selectedRegion.collapseToT0();
459
461 /* i18n-hint: (verb) Audacity has just deleted the labeled audio regions*/
462 XO( "Deleted labeled audio regions" ),
463 /* i18n-hint: (verb)*/
464 XO( "Delete Labeled Audio" ) );
465}
466
468{
469 auto &project = context.project;
470 auto &tracks = TrackList::Get( project );
471 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
472
473 if( selectedRegion.isPoint() )
474 return;
475
476 auto copyfunc = [&](Track *track, double t0, double t1)
477 {
478 Track::Holder dest = nullptr;
479 track->TypeSwitch(
480 [&](WaveTrack *t)
481 {
482 dest = t->SplitCut(t0, t1);
483 },
484 [&](Track *t)
485 {
486 dest = t->Copy(t0, t1);
487 t->Silence(t0, t1);
488 }
489 );
490 return dest;
491 };
492 EditClipboardByLabel( project, tracks, selectedRegion, copyfunc );
493
495 /* i18n-hint: (verb) Audacity has just split cut the labeled audio
496 regions*/
497 XO( "Split Cut labeled audio regions to clipboard" ),
498 /* i18n-hint: (verb) Do a special kind of cut on the labels*/
499 XO( "Split Cut Labeled Audio" ) );
500}
501
503{
504 auto &project = context.project;
505 auto &tracks = TrackList::Get( project );
506 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
507
508 if( selectedRegion.isPoint() )
509 return;
510
511 auto editfunc = [&](Track *track, double t0, double t1)
512 {
513 track->TypeSwitch(
514 [&](WaveTrack *t)
515 {
516 t->SplitDelete(t0, t1);
517 },
518 [&](Track *t)
519 {
520 t->Silence(t0, t1);
521 }
522 );
523 };
524 EditByLabel(project, tracks, selectedRegion, editfunc);
525
527 /* i18n-hint: (verb) Audacity has just done a special kind of DELETE on
528 the labeled audio regions */
529 XO( "Split Deleted labeled audio regions" ),
530 /* i18n-hint: (verb) Do a special kind of DELETE on labeled audio
531 regions */
532 XO( "Split Delete Labeled Audio" ) );
533}
534
535void OnSilenceLabels(const CommandContext &context)
536{
537 auto &project = context.project;
538 auto &tracks = TrackList::Get( project );
539 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
540
541 if( selectedRegion.isPoint() )
542 return;
543
544 auto editfunc = [&](Track *track, double t0, double t1)
545 {
546 track->TypeSwitch(
547 [&](WaveTrack *t)
548 {
549 t->Silence(t0, t1);
550 }
551 );
552 };
553 EditByLabel(project, tracks, selectedRegion, editfunc);
554
556 /* i18n-hint: (verb)*/
557 XO( "Silenced labeled audio regions" ),
558 /* i18n-hint: (verb)*/
559 XO( "Silence Labeled Audio" ) );
560}
561
562void OnCopyLabels(const CommandContext &context)
563{
564 auto &project = context.project;
565 auto &tracks = TrackList::Get( project );
566 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
567
568 if( selectedRegion.isPoint() )
569 return;
570
571 auto copyfunc = [&](Track *track, double t0, double t1)
572 {
573 Track::Holder dest = nullptr;
574 track->TypeSwitch(
575 [&](WaveTrack *t)
576 {
577 dest = t->CopyNonconst(t0, t1);
578 });
579 return dest;
580 };
581 EditClipboardByLabel( project, tracks, selectedRegion, copyfunc );
582
583 ProjectHistory::Get( project ).PushState( XO( "Copied labeled audio regions to clipboard" ),
584 /* i18n-hint: (verb)*/
585 XO( "Copy Labeled Audio" ) );
586}
587
588void OnSplitLabels(const CommandContext &context)
589{
590 auto &project = context.project;
591 auto &tracks = TrackList::Get( project );
592 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
593
594 if( selectedRegion.isPoint() )
595 return;
596
597 auto editfunc = [&](Track *track, double t0, double t1)
598 {
599 track->TypeSwitch(
600 [&](WaveTrack *t)
601 {
602 t->Split(t0, t1);
603 }
604 );
605 };
606 EditByLabel(project, tracks, selectedRegion, editfunc);
607
609 /* i18n-hint: (verb) past tense. Audacity has just split the labeled
610 audio (a point or a region)*/
611 XO( "Split labeled audio (points or regions)" ),
612 /* i18n-hint: (verb)*/
613 XO( "Split Labeled Audio" ) );
614}
615
616void OnJoinLabels(const CommandContext &context)
617{
618 auto &project = context.project;
619 auto &tracks = TrackList::Get( project );
620 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
621
622 if( selectedRegion.isPoint() )
623 return;
624
625 auto editfunc = [&](Track *track, double t0, double t1)
626 {
627 track->TypeSwitch(
628 [&](WaveTrack *t)
629 {
630 t->Join(t0, t1);
631 }
632 );
633 };
634 EditByLabel(project, tracks, selectedRegion, editfunc);
635
637 /* i18n-hint: (verb) Audacity has just joined the labeled audio (points or
638 regions) */
639 XO( "Joined labeled audio (points or regions)" ),
640 /* i18n-hint: (verb) */
641 XO( "Join Labeled Audio" ) );
642}
643
644void OnDisjoinLabels(const CommandContext &context)
645{
646 auto &project = context.project;
647 auto &tracks = TrackList::Get( project );
648 auto &selectedRegion = ViewInfo::Get( project ).selectedRegion;
649
650 if( selectedRegion.isPoint() )
651 return;
652
653 auto editfunc = [&](Track *track, double t0, double t1)
654 {
655 track->TypeSwitch(
656 [&](WaveTrack *t)
657 {
658 wxBusyCursor busy;
659 t->Disjoin(t0, t1);
660 }
661 );
662 };
663 EditByLabel(project, tracks, selectedRegion, editfunc);
664
666 /* i18n-hint: (verb) Audacity has just detached the labeled audio regions.
667 This message appears in history and tells you about something
668 Audacity has done.*/
669 XO( "Detached labeled audio regions" ),
670 /* i18n-hint: (verb)*/
671 XO( "Detach Labeled Audio" ) );
672}
673
674void OnNewLabelTrack(const CommandContext &context)
675{
676 auto &project = context.project;
677 auto &tracks = TrackList::Get( project );
678
679 auto track = LabelTrack::Create(tracks);
680
682
683 track->SetSelected(true);
684
685 ProjectHistory::Get( project )
686 .PushState(XO("Created new label track"), XO("New Track"));
687
688 TrackFocus::Get(project).Set(track);
689 track->EnsureVisible();
690}
691
692// Menu definitions
693
694using namespace MenuTable;
696{
697 using namespace MenuTable;
699
700 static const auto NotBusyLabelsAndWaveFlags =
703
704 // Returns TWO menus.
705
706 static BaseItemSharedPtr menus{
707 Items( wxT("LabelEditMenus"),
708
709 Menu( wxT("Labels"), XXO("&Labels"),
710 Section( "",
711 Command( wxT("EditLabels"), XXO("&Edit Labels..."), OnEditLabels,
713 ),
714
715 Section( "",
716 Command( wxT("AddLabel"), XXO("Add Label at &Selection"),
717 OnAddLabel, AlwaysEnabledFlag, wxT("Ctrl+B") ),
718 Command( wxT("AddLabelPlaying"),
719 XXO("Add Label at &Playback Position"),
721 #ifdef __WXMAC__
722 wxT("Ctrl+.")
723 #else
724 wxT("Ctrl+M")
725 #endif
726 ),
727 Command( wxT("PasteNewLabel"), XXO("Paste Te&xt to New Label"),
729 AudioIONotBusyFlag(), wxT("Ctrl+Alt+V") )
730 ),
731
732 Section( "",
733 Command( wxT("TypeToCreateLabel"),
734 XXO("&Type to Create a Label (on/off)"),
736 Options{}.CheckTest(wxT("/GUI/TypeToCreateLabel"), false) )
737 )
738 ), // first menu
739
741
742 Menu( wxT("Labeled"), XXO("La&beled Audio"),
743 Section( "",
744 /* i18n-hint: (verb)*/
745 Command( wxT("CutLabels"), XXO("&Cut"), OnCutLabels,
748 Options{ wxT("Alt+X"), XO("Label Cut") } ),
749 Command( wxT("DeleteLabels"), XXO("&Delete"), OnDeleteLabels,
752 Options{ wxT("Alt+K"), XO("Label Delete") } )
753 ),
754
755 Section( "",
756 /* i18n-hint: (verb) A special way to cut out a piece of audio*/
757 Command( wxT("SplitCutLabels"), XXO("&Split Cut"),
758 OnSplitCutLabels, NotBusyLabelsAndWaveFlags,
759 Options{ wxT("Alt+Shift+X"), XO("Label Split Cut") } ),
760 Command( wxT("SplitDeleteLabels"), XXO("Sp&lit Delete"),
761 OnSplitDeleteLabels, NotBusyLabelsAndWaveFlags,
762 Options{ wxT("Alt+Shift+K"), XO("Label Split Delete") } )
763 ),
764
765 Section( "",
766 Command( wxT("SilenceLabels"), XXO("Silence &Audio"),
767 OnSilenceLabels, NotBusyLabelsAndWaveFlags,
768 Options{ wxT("Alt+L"), XO("Label Silence") } ),
769 /* i18n-hint: (verb)*/
770 Command( wxT("CopyLabels"), XXO("Co&py"), OnCopyLabels,
771 NotBusyLabelsAndWaveFlags,
772 Options{ wxT("Alt+Shift+C"), XO("Label Copy") } )
773 ),
774
775 Section( "",
776 /* i18n-hint: (verb)*/
777 Command( wxT("SplitLabels"), XXO("Spli&t"), OnSplitLabels,
779 Options{ wxT("Alt+I"), XO("Label Split") } ),
780 /* i18n-hint: (verb)*/
781 Command( wxT("JoinLabels"), XXO("&Join"), OnJoinLabels,
782 NotBusyLabelsAndWaveFlags,
783 Options{ wxT("Alt+J"), XO("Label Join") } ),
784 Command( wxT("DisjoinLabels"), XXO("Detac&h at Silences"),
785 OnDisjoinLabels, NotBusyLabelsAndWaveFlags,
786 wxT("Alt+Shift+J") )
787 )
788 ) // second menu
789
790 ) }; // two menus
791 return menus;
792}
793
795 { wxT("Edit/Other"),
796 { OrderingHint::Before, wxT("EditMetaData") } },
798};
799
800AttachedItem sAttachment2{ wxT("Tracks/Add/Add"),
801 Command( wxT("NewLabelTrack"), XXO("&Label Track"),
803};
804
805}
wxT("CloseDown"))
AttachedItem sAttachment1
AttachedItem sAttachment2
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:34
const ReservedCommandFlag & AudioIOBusyFlag()
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & WaveTracksExistFlag()
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
WaveTrack::Region Region
Definition: LabelMenus.cpp:21
WaveTrack::Regions Regions
Definition: LabelMenus.cpp:22
static const auto title
FileConfig * gPrefs
Definition: Prefs.cpp:70
TranslatableString label
Definition: TagsEditor.cpp:164
static std::once_flag flag
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static AudioIO * Get()
Definition: AudioIO.cpp:147
static Clipboard & Get()
Definition: Clipboard.cpp:28
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
A LabelStruct holds information for ONE label in a LabelTrack.
Definition: LabelTrack.h:29
double getT1() const
Definition: LabelTrack.h:40
double getT0() const
Definition: LabelTrack.h:39
SelectedRegion selectedRegion
Definition: LabelTrack.h:69
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:87
static LabelTrack * Create(TrackList &trackList, const wxString &name)
Create a new LabelTrack with specified name and append it to the trackList.
Definition: LabelTrack.cpp:66
static LabelTrackView & Get(LabelTrack &)
static int DialogForLabelName(AudacityProject &project, const SelectedRegion &region, const wxString &initialValue, wxString &value)
int AddLabel(const SelectedRegion &region, const wxString &title={}, int restoreFocus=-1)
static void DoEditLabels(AudacityProject &project, LabelTrack *lt=nullptr, int index=-1)
AudioTrack subclass that can also be audibly replayed by the program.
Definition: Track.h:917
int GetAudioIOToken() const
static ProjectAudioIO & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
Defines a selected portion of a project.
double t1() const
double t0() const
static bool IsSyncLockSelected(const Track *pTrack)
Definition: SyncLock.cpp:82
bool IsSyncLocked() const
Definition: SyncLock.cpp:43
static SyncLockState & Get(AudacityProject &project)
Definition: SyncLock.cpp:26
static void ModifyAllProjectToolbarMenus()
Track * Get()
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:226
void EnsureVisible(bool modifyState=false)
Definition: Track.cpp:98
virtual void SetSelected(bool s)
Definition: Track.cpp:88
virtual void Clear(double WXUNUSED(t0), double WXUNUSED(t1))=0
static void FinishCopy(const Track *n, Track *dest)
Definition: Track.cpp:415
R TypeSwitch(const Functions &...functions)
Use this function rather than testing track type explicitly and making down-casts.
Definition: Track.h:833
std::shared_ptr< Track > Holder
Definition: Track.h:369
bool Any() const
Definition: Track.cpp:400
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1339
static std::shared_ptr< TrackList > Create(AudacityProject *pOwner)
Definition: Track.cpp:503
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1440
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:487
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1457
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:231
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:219
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
A Track that contains audio waveform data.
Definition: WaveTrack.h:51
void SplitDelete(double t0, double t1)
Definition: WaveTrack.cpp:970
std::vector< Region > Regions
Definition: WaveTrack.h:69
void Join(double t0, double t1)
Definition: WaveTrack.cpp:1512
void Silence(double t0, double t1) override
Definition: WaveTrack.cpp:1376
void ClearAndAddCutLine(double t0, double t1)
Definition: WaveTrack.cpp:658
void Clear(double t0, double t1) override
Definition: WaveTrack.cpp:652
void Split(double t0, double t1)
Definition: WaveTrack.cpp:2325
void Disjoin(double t0, double t1)
Definition: WaveTrack.cpp:1441
Track::Holder CopyNonconst(double t0, double t1)
Definition: WaveTrack.cpp:646
Track::Holder SplitCut(double t0, double t1)
Definition: WaveTrack.cpp:509
Track::Holder Copy(double t0, double t1, bool forClipboard=true) const override
Definition: WaveTrack.cpp:585
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< MenuItems > Items(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::shared_ptr< BaseItem > BaseItemSharedPtr
Definition: Registry.h:72
void SelectNone(AudacityProject &project)
void OnAddLabel(const CommandContext &context)
Definition: LabelMenus.cpp:292
void OnSplitDeleteLabels(const CommandContext &context)
Definition: LabelMenus.cpp:502
int DoAddLabel(AudacityProject &project, const SelectedRegion &region, bool preserveFocus=false)
Definition: LabelMenus.cpp:52
void EditByLabel(AudacityProject &project, TrackList &tracks, const SelectedRegion &selectedRegion, EditFunction action)
Definition: LabelMenus.cpp:166
void OnSplitCutLabels(const CommandContext &context)
Definition: LabelMenus.cpp:467
void OnCopyLabels(const CommandContext &context)
Definition: LabelMenus.cpp:562
void OnSplitLabels(const CommandContext &context)
Definition: LabelMenus.cpp:588
void OnCutLabels(const CommandContext &context)
Definition: LabelMenus.cpp:386
void GetRegionsByLabel(const TrackList &tracks, const SelectedRegion &selectedRegion, Regions &regions)
Definition: LabelMenus.cpp:121
void OnJoinLabels(const CommandContext &context)
Definition: LabelMenus.cpp:616
std::function< Track::Holder(Track *, double, double)> EditDestFunction
Definition: LabelMenus.cpp:197
void OnPasteNewLabel(const CommandContext &context)
Definition: LabelMenus.cpp:315
void OnDeleteLabels(const CommandContext &context)
Definition: LabelMenus.cpp:443
void OnEditLabels(const CommandContext &context)
Definition: LabelMenus.cpp:286
const ReservedCommandFlag & LabelsSelectedFlag()
Definition: LabelMenus.cpp:28
std::function< void(Track *, double, double)> EditFunction
Definition: LabelMenus.cpp:158
BaseItemSharedPtr LabelEditMenus()
Definition: LabelMenus.cpp:695
void OnSilenceLabels(const CommandContext &context)
Definition: LabelMenus.cpp:535
void OnDisjoinLabels(const CommandContext &context)
Definition: LabelMenus.cpp:644
void EditClipboardByLabel(AudacityProject &project, TrackList &tracks, const SelectedRegion &selectedRegion, EditDestFunction action)
Definition: LabelMenus.cpp:205
void OnAddLabelPlaying(const CommandContext &context)
Definition: LabelMenus.cpp:300
void OnToggleTypeToCreateLabel(const CommandContext &WXUNUSED(context))
Definition: LabelMenus.cpp:377
void OnNewLabelTrack(const CommandContext &context)
Definition: LabelMenus.cpp:674
Options && CheckTest(const CheckFn &fn) &&
Structure to hold region of a wavetrack and a comparison function for sortability.
Definition: WaveTrack.h:56