Audacity 3.2.0
BatchProcessDialog.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ApplyMacroDialog.cpp
6
7 Dominic Mazzoni
8 James Crook
9
10*******************************************************************//*******************************************************************/
16#include "BatchProcessDialog.h"
17
18#include <wx/setup.h> // for wxUSE_* macros
19
20#ifdef __WXMSW__
21 #include <wx/ownerdrw.h>
22#endif
23
24#include <wx/defs.h>
25#include <wx/checkbox.h>
26#include <wx/choice.h>
27#include <wx/frame.h>
28#include <wx/log.h>
29#include <wx/statbox.h>
30#include <wx/stattext.h>
31#include <wx/textctrl.h>
32#include <wx/listctrl.h>
33#include <wx/button.h>
34#include <wx/imaglist.h>
35#include <wx/settings.h>
36
37#include "Clipboard.h"
38#include "ShuttleGui.h"
39#include "MenuCreator.h"
40#include "Prefs.h"
41#include "Project.h"
42#include "ProjectFileManager.h"
43#include "ProjectHistory.h"
44#include "ProjectManager.h"
45#include "ProjectWindows.h"
46#include "SelectUtilities.h"
47#include "Track.h"
48#include "CommandManager.h"
49#include "Effect.h"
50#include "effects/EffectUI.h"
51#include "../images/Arrow.xpm"
52#include "../images/Empty9x16.xpm"
53#include "UndoManager.h"
54#include "Viewport.h"
55
56#include "AllThemeResources.h"
57
59#include "FileNames.h"
60#include "Import.h"
61#include "AudacityMessageBox.h"
63#include "HelpSystem.h"
64
65#if wxUSE_ACCESSIBILITY
66#include "WindowAccessible.h"
67#endif
68
69#define MacrosPaletteTitle XO("Macros Palette")
70#define ManageMacrosTitle XO("Manage Macros")
71
72
73// Separate numerical range from the additional buttons
74// in the expanded view (which start at 10,000).
75#define MacrosListID 7001
76#define CommandsListID 7002
77#define ApplyToProjectID 7003
78#define ApplyToFilesID 7004
79#define ExpandID 7005
80#define ShrinkID 7006
81
82BEGIN_EVENT_TABLE(ApplyMacroDialog, wxDialogWrapper)
89
91 wxWindow * parent, AudacityProject &project, bool bInherited):
92 wxDialogWrapper(parent, wxID_ANY, MacrosPaletteTitle,
93 wxDefaultPosition, wxDefaultSize,
94 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
95 , mMacroCommands{ project }
96 , mProject{ project }
97 , mCatalog( &project )
98{
99 mAbort = false;
100 mbExpanded = false;
101 if( bInherited )
102 return;
103 SetLabel(MacrosPaletteTitle); // Provide visual label
104 SetName(MacrosPaletteTitle); // Provide audible label
105 Populate();
106
107}
108
110{
111}
112
114{
115 //------------------------- Main section --------------------
116 ShuttleGui S(this, eIsCreating);
118 // ----------------------- End of main section --------------
119 // Get and validate the currently active macro
120 mActiveMacro = gPrefs->Read(wxT("/Batch/ActiveMacro"), wxT(""));
121 // Go populate the macros list.
123
124 Layout();
125 Fit();
126 wxSize sz = GetSize();
127 SetSizeHints( sz );
128
129 // Size and place window
130 SetSize(std::min(wxSystemSettings::GetMetric(wxSYS_SCREEN_X) * 3 / 4, sz.GetWidth()),
131 std::min(wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) * 4 / 5, 400));
132
133 Center();
134
135 // Set the column size for the macros list.
136 sz = mMacros->GetClientSize();
137 mMacros->SetColumnWidth(0, sz.x);
138}
139
142{
143 /*i18n-hint: A macro is a sequence of commands that can be applied
144 * to one or more audio files.*/
145 S.StartStatic(XO("Select Macro"), 1);
146 {
147 mMacros = S.Id(MacrosListID).Prop(1)
148 .Style(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES |
149 wxLC_SINGLE_SEL)
150 // i18n-hint: This is the heading for a column in the edit macros dialog
151 .AddListControlReportMode( { XO("Macro") } );
152 }
153 S.EndStatic();
154
155 S.StartHorizontalLay(wxEXPAND, 0);
156 {
157 S.AddPrompt( XXO("Apply Macro to:") );
158 wxButton* btn = S.Id(ApplyToProjectID)
159 .Name(XO("Apply macro to project"))
160 .AddButton(XXO("&Project"));
161#if wxUSE_ACCESSIBILITY
162 // so that name can be set on a standard control
163 btn->SetAccessible(safenew WindowAccessible(btn));
164#endif
165
166 btn = S.Id(ApplyToFilesID)
167 .Name(XO("Apply macro to files..."))
168 .AddButton(XXO("&Files..."));
169#if wxUSE_ACCESSIBILITY
170 // so that name can be set on a standard control
171 btn->SetAccessible(safenew WindowAccessible(btn));
172#endif
173 }
174 S.EndHorizontalLay();
175
176 S.StartHorizontalLay(wxEXPAND, 0);
177 {
178 /* i18n-hint: The Expand button makes the dialog bigger, with more in it */
179 mResize = S.Id(ExpandID).AddButton(XXO("&Expand"));
180 S.AddSpace( 10,10,1 );
181 S.AddStandardButtons( eCloseButton | eHelpButton);
182 }
183 S.EndHorizontalLay();
184}
185
190{
192 int i;
193
194 int topItem = mMacros->GetTopItem();
195 mMacros->DeleteAllItems();
196 for (i = 0; i < (int)names.size(); i++) {
197 mMacros->InsertItem(i, names[i]);
198 }
199
200 int item = mMacros->FindItem(-1, mActiveMacro);
201 bool bFound = item >=0;
202 if (item == -1) {
203 item = 0;
204 mActiveMacro = mMacros->GetItemText(0);
205 }
206
207 // Select the name in the list...this will fire an event.
208 mMacros->SetItemState(item, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
209 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
210
211 if( 0 <= topItem && topItem < (int)mMacros->GetItemCount())
212 {
213 // Workaround for scrolling being windows only.
214 // Try to scroll back to where we once were...
215 mMacros->EnsureVisible( (int)mMacros->GetItemCount() -1 );
216 mMacros->EnsureVisible( topItem );
217 // And then make sure whatever is selected is still visible...
218 if( bFound )
219 mMacros->EnsureVisible( item );
220 }
221}
222
223void ApplyMacroDialog::OnHelp(wxCommandEvent & WXUNUSED(event))
224{
225 const auto &page = GetHelpPageName();
226 HelpSystem::ShowHelp(this, page, true);
227}
228
229void ApplyMacroDialog::OnApplyToProject(wxCommandEvent & WXUNUSED(event))
230{
231 long item = mMacros->GetNextItem(-1,
232 wxLIST_NEXT_ALL,
233 wxLIST_STATE_SELECTED);
234
235 if (item == -1) {
236 AudacityMessageBox(XO("No macro selected"));
237 return;
238 }
239 ApplyMacroToProject( item );
240}
241
242CommandID ApplyMacroDialog::MacroIdOfName( const wxString & MacroName )
243{
244 wxString Temp = MacroName;
245 Temp.Replace(" ","");
246 Temp = wxString( "Macro_" ) + Temp;
247 return Temp;
248}
249
250// Apply macro, given its ID.
251// Does nothing if not found, rather than returning an error.
253{
254 for( int i=0;i<mMacros->GetItemCount();i++){
255 wxString name = mMacros->GetItemText(i);
256 if( MacroIdOfName( name ) == MacroID ){
257 ApplyMacroToProject( i, bHasGui );
258 return;
259 }
260 }
261}
262
263// Apply macro, given its number in the list.
264void ApplyMacroDialog::ApplyMacroToProject( int iMacro, bool bHasGui )
265{
266 wxString name = mMacros->GetItemText(iMacro);
267 if( name.empty() )
268 return;
269
270#ifdef OPTIONAL_ACTIVITY_WINDOW
271 wxDialogWrapper activityWin( this, wxID_ANY, GetTitle());
272 activityWin.SetName();
273 ShuttleGui S(&activityWin, eIsCreating);
274
275 S.StartHorizontalLay(wxCENTER, false);
276 {
277 S.StartStatic( {}, false); // deliberately not translated (!)
278 {
279 S.SetBorder(20);
280 S.AddFixedText(XO("Applying '%s' to current project")
281 .Format( name ) );
282 }
283 S.EndStatic();
284 }
285 S.EndHorizontalLay();
286
287 activityWin.Layout();
288 activityWin.Fit();
289 activityWin.CenterOnScreen();
290 // Avoid overlap with progress.
291 int x,y;
292 activityWin.GetPosition( &x, &y );
293 activityWin.Move(wxMax(0,x-300), 0);
294 activityWin.Show();
295
296 // Without this the newly created dialog may not show completely.
297 wxYield();
298#endif
299
300 //Since we intend to keep this dialog open, there is no reason to hide it
301 //and then show it again.
302 //if( bHasGui )
303 // Hide();
304
305 gPrefs->Write(wxT("/Batch/ActiveMacro"), name);
306 gPrefs->Flush();
307
309
310 // The disabler must get deleted before the EndModal() call. Otherwise,
311 // the menus on OSX will remain disabled.
312 bool success;
313 {
314#ifdef OPTIONAL_ACTIVITY_WINDOW
315 wxWindowDisabler wd(&activityWin);
316#endif
317 success = GuardedCall< bool >(
318 [this]{ return mMacroCommands.ApplyMacro(mCatalog); } );
319 }
320
321 if( !bHasGui )
322 return;
323
324 Show();
325 Raise();
326}
327
328void ApplyMacroDialog::OnApplyToFiles(wxCommandEvent & WXUNUSED(event))
329{
330 long item = mMacros->GetNextItem(-1,
331 wxLIST_NEXT_ALL,
332 wxLIST_STATE_SELECTED);
333 if (item == -1) {
334 AudacityMessageBox( XO("No macro selected") );
335 return;
336 }
337
338 wxString name = mMacros->GetItemText(item);
339 gPrefs->Write(wxT("/Batch/ActiveMacro"), name);
340 gPrefs->Flush();
341
343 if (!TrackList::Get( *project ).empty()) {
345 XO("Please save and close the current project first.") );
346 return;
347 }
348
349 // This insures that we start with an empty and temporary project
352
353 auto prompt = XO("Select file(s) for batch processing...");
354
355 const auto fileTypes = Importer::Get().GetFileTypes();
356
357 auto path = FileNames::FindDefaultPath(FileNames::Operation::Open);
358 FileDialogWrapper dlog(this,
359 prompt,
360 path,
361 wxT(""),
362 fileTypes,
363 wxFD_OPEN | wxFD_MULTIPLE | wxRESIZE_BORDER);
364
366 if (dlog.ShowModal() != wxID_OK) {
367 Raise();
368 return;
369 }
370 Raise();
371
372 wxArrayString files;
373 dlog.GetPaths(files);
374
375 files.Sort();
376
377 wxDialogWrapper activityWin(this, wxID_ANY, Verbatim( GetTitle() ),
378 wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER
379 );
380 activityWin.SetName();
381 ShuttleGui S(&activityWin, eIsCreating);
382
383 wxListCtrl * fileList = NULL;
384
385 S.StartVerticalLay(1);
386 {
387 S.StartStatic(XO("Applying..."), 1);
388 {
389 auto imageList = std::make_unique<wxImageList>(9, 16);
390 imageList->Add(wxIcon(empty9x16_xpm));
391 imageList->Add(wxIcon(arrow_xpm));
392
393 fileList = S.Id(CommandsListID)
394 .Style(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES |
395 wxLC_SINGLE_SEL)
396 .AddListControlReportMode( { XO("File") } );
397 // AssignImageList takes ownership
398 fileList->AssignImageList(imageList.release(), wxIMAGE_LIST_SMALL);
399 }
400 S.EndStatic();
401
402 S.StartHorizontalLay(wxCENTER, 0);
403 {
404 S.Id(wxID_CANCEL).AddButton(XXO("&Cancel"));
405 }
406 S.EndHorizontalLay();
407 }
408 S.EndVerticalLay();
409
410 int i;
411 for (i = 0; i < (int)files.size(); i++ ) {
412 fileList->InsertItem(i, files[i], i == 0);
413 }
414
415 // Set the column size for the files list.
416 fileList->SetColumnWidth(0, wxLIST_AUTOSIZE);
417
418 int width = wxMin( fileList->GetColumnWidth(0), 1000);
419 wxSize sz = fileList->GetClientSize();
420 if (sz.GetWidth() < width ) {
421 sz.SetWidth(width);
422 if (sz.GetHeight() < width *0.7)
423 sz.SetHeight(width * 0.7);
424 fileList->SetInitialSize(sz);
425 }
426
427 activityWin.Layout();
428 activityWin.Fit();
429 activityWin.CenterOnScreen();
430 // Avoid overlap with progress.
431 int x,y;
432 activityWin.GetPosition( &x, &y );
433 activityWin.Move(wxMax(0,x-300), 0);
434 activityWin.Show();
435
436 // Without this the newly created dialog may not show completely.
437 wxYield();
438 // We could avoid hiding, but there are many dialogs on screen,
439 // and hiding this one temporarily has some advantages.
440 Hide();
441
443 {
444 auto &globalClipboard = Clipboard::Get();
445
446 // DV: Macro invocation on file will reset the project to the
447 // initial state. There is a possibility, that clipboard will contain
448 // references to the data removed
449 if (globalClipboard.Project().lock().get() == project)
450 globalClipboard.Clear();
451
452 // Move global clipboard contents aside temporarily
454
455 wxWindowDisabler wd(&activityWin);
456 for (i = 0; i < (int)files.size(); i++) {
457 if (i > 0) {
458 //Clear the arrow in previous item.
459 fileList->SetItemImage(i - 1, 0, 0);
460 }
461 fileList->SetItemImage(i, 1, 1);
462 fileList->EnsureVisible(i);
463
464 auto success = GuardedCall<bool>([&] {
465 ProjectFileManager::Get(*project).Import(files[i]);
469 return false;
470
471 if (!activityWin.IsShown() || mAbort)
472 return false;
473
474 return true;
475 });
476
477 // Ensure project is completely reset
479 // Bug2567:
480 // Must also destroy the clipboard, to be sure sample blocks are
481 // all freed and their ids can be reused safely in the next pass
482 globalClipboard.Clear();
483
484 if (!success)
485 break;
486 }
487 }
488
489 Show();
490 Raise();
491}
492
493void ApplyMacroDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
494{
495 Hide();
496}
497
499#include <wx/textdlg.h>
500#include "BatchCommandDialog.h"
501
502enum {
503 AddButtonID = 10000,
510
512
518
519// MacrosListID 7005
520// CommandsListID, 7002
521// Re-Use IDs from ApplyMacroDialog.
524};
525
526BEGIN_EVENT_TABLE(MacrosWindow, ApplyMacroDialog)
529 EVT_LIST_BEGIN_LABEL_EDIT(MacrosListID, MacrosWindow::OnMacrosBeginEdit)
530 EVT_LIST_END_LABEL_EDIT(MacrosListID, MacrosWindow::OnMacrosEndEdit)
538
541 EVT_SIZE(MacrosWindow::OnSize)
542
543 EVT_LIST_ITEM_ACTIVATED(CommandsListID, MacrosWindow::OnCommandActivated)
549
553
554 EVT_KEY_DOWN(MacrosWindow::OnKeyDown)
556
557enum {
561};
562
565 wxWindow * parent, AudacityProject &project, bool bExpanded):
566 ApplyMacroDialog(parent, project, true)
567 , mProject{ project }
568{
569 mbExpanded = bExpanded;
570 auto Title = WindowTitle();
571 SetLabel( Title ); // Provide visual label
572 SetName( Title ); // Provide audible label
573 SetTitle( Title );
574
575 mChanged = false;
577
578 if( mbExpanded )
579 Populate();
580 else
582}
583
585{
586}
587
590{
591 //------------------------- Main section --------------------
592 ShuttleGui S(this, eIsCreating);
594 // ----------------------- End of main section --------------
595
596 // Get and validate the currently active macro
597 mActiveMacro = gPrefs->Read(wxT("/Batch/ActiveMacro"), wxT(""));
598 // Go populate the macros list.
600
601 // We have a bare list. We need to add columns and content.
602 PopulateList();
603
604 // Layout and set minimum size of window
605 Layout();
606 Fit();
607 SetSizeHints(GetSize());
608
609 // Size and place window
610 SetSize(std::min(wxSystemSettings::GetMetric(wxSYS_SCREEN_X) * 3 / 4, 800),
611 std::min(wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) * 4 / 5, 400));
612 Center();
613
614 // Set the column size for the macros list.
615 wxSize sz = mMacros->GetClientSize();
616 mMacros->SetColumnWidth(0, sz.x);
617
618 // Size columns properly
619 FitColumns();
620}
621
624{
625 S.StartHorizontalLay(wxEXPAND, 1);
626 {
627 S.StartStatic(XO("Select Macro"),0);
628 {
629 S.StartHorizontalLay(wxEXPAND,1);
630 {
631 mMacros = S.Id(MacrosListID).Prop(1)
632 .Style(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES
633 | wxLC_SINGLE_SEL | wxLC_EDIT_LABELS)
634 // i18n-hint: This is the heading for a column in the edit macros dialog
635 .AddListControlReportMode( { XO("Macro") } );
636 S.StartVerticalLay(wxALIGN_TOP, 0);
637 {
638 S.Id(AddButtonID).AddButton(XXO("&New"), wxALIGN_LEFT);
639 mRemove = S.Id(RemoveButtonID).AddButton(XXO("Remo&ve"), wxALIGN_LEFT);
640 mRename = S.Id(RenameButtonID).AddButton(XXO("&Rename..."), wxALIGN_LEFT);
641 mRestore = S.Id(RestoreButtonID).AddButton(XXO("Re&store"), wxALIGN_LEFT);
642 mImport = S.Id(ImportButtonID).AddButton(XO("I&mport..."), wxALIGN_LEFT);
643 mExport = S.Id(ExportButtonID).AddButton(XO("E&xport..."), wxALIGN_LEFT);
644 }
645 S.EndVerticalLay();
646 }
647 S.EndHorizontalLay();
648 }
649 S.EndStatic();
650
651 S.StartStatic(XO("Edit Steps"), true);
652 {
653 S.StartHorizontalLay(wxEXPAND,1);
654 {
656 .Style(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES |
657 wxLC_SINGLE_SEL)
658 .AddListControlReportMode({
659 /* i18n-hint: This is the number of the command in the list */
660 { XO("Num"), wxLIST_FORMAT_RIGHT },
661 { XO("Command "), wxLIST_FORMAT_RIGHT },
662 { XO("Parameters"), wxLIST_FORMAT_LEFT }
663 });
664
665 S.StartVerticalLay(wxALIGN_TOP, 0);
666 {
667 S.Id(InsertButtonID).AddButton(XXO("&Insert"), wxALIGN_LEFT);
668 S.Id(EditButtonID).AddButton(XXO("&Edit..."), wxALIGN_LEFT);
669 S.Id(DeleteButtonID).AddButton(XXO("De&lete"), wxALIGN_LEFT);
670 S.Id(UpButtonID).AddButton(XXO("Move &Up"), wxALIGN_LEFT);
671 S.Id(DownButtonID).AddButton(XXO("Move &Down"), wxALIGN_LEFT);
672 mSave = S.Id(SaveButtonID).AddButton(XO("&Save"), wxALIGN_LEFT);
673 mSave->Enable( mChanged );
674 }
675 S.EndVerticalLay();
676 }
677 S.EndHorizontalLay();
678 }
679 S.EndStatic();
680 }
681 S.EndHorizontalLay();
682
683 S.StartHorizontalLay(wxEXPAND, 0);
684 {
685 /* i18n-hint: The Shrink button makes the dialog smaller, with less in it */
686 mResize = S.Id(ShrinkID).AddButton(XXO("Shrin&k"));
687 // Using variable text just to get the positioning options.
688 S.Prop(0).AddVariableText(
689 XO("Apply Macro to:"), false, wxALL | wxALIGN_CENTRE_VERTICAL );
690 wxButton* btn = S.Id(ApplyToProjectID)
691 .Name(XO("Apply macro to project"))
692 .AddButton(XXO("&Project"));
693#if wxUSE_ACCESSIBILITY
694 // so that name can be set on a standard control
695 btn->SetAccessible(safenew WindowAccessible(btn));
696#endif
697
698 btn = S.Id(ApplyToFilesID)
699 .Name(XO("Apply macro to files..."))
700 .AddButton(XXO("&Files..."));
701#if wxUSE_ACCESSIBILITY
702 // so that name can be set on a standard control
703 btn->SetAccessible(safenew WindowAccessible(btn));
704#endif
705 S.AddSpace( 10,10,1 );
706 // Bug 2524 OK button does much the same as cancel, so remove it.
707 // OnCancel prompts you if there has been a change.
708 // OnOK saves without prompting.
709 // That difference is too slight to merit a button, and with the OK
710 // button, people might expect the dialog to apply the macro too.
711 S.AddStandardButtons( /*eOkButton |*/ eCloseButton | eHelpButton);
712 }
713
714 S.EndHorizontalLay();
715
716
717 return;
718}
719
722{
723 int topItem = mList->GetTopItem();
724 mList->DeleteAllItems();
725
726 for (int i = 0; i < mMacroCommands.GetCount(); i++) {
729 }
730 /*i18n-hint: This is the last item in a list.*/
731 AddItem(_("- END -"), wxT(""));
732
733 // Select the name in the list...this will fire an event.
734 if (mSelectedCommand >= (int)mList->GetItemCount()) {
736 }
737 mList->SetItemState(mSelectedCommand,
738 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED,
739 wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
740 if( 0 <= topItem && topItem < (int)mList->GetItemCount())
741 {
742 // Workaround for scrolling being windows only.
743 // Try to scroll back to where we once were...
744 mList->EnsureVisible( (int)mList->GetItemCount() -1 );
745 mList->EnsureVisible( topItem );
746 // And then make sure whatever is selected is still visible...
747 if (mSelectedCommand >= 0) {
748 mList->EnsureVisible( mSelectedCommand );
749 }
750 }
751}
752
754void MacrosWindow::AddItem(const CommandID &Action, const wxString &Params)
755{
757 auto friendlyName = entry != mCatalog.end()
758 ? entry->name.StrippedTranslation()
759 :
760 // uh oh, using GET to expose an internal name to the user!
761 // in default of any better friendly name
762 Action.GET();
763
764 int i = mList->GetItemCount();
765
766 mList->InsertItem(i, wxString::Format(wxT(" %02i"), i + 1));
767 mList->SetItem(i, ActionColumn, friendlyName );
768 mList->SetItem(i, ParamsColumn, Params );
769}
770
772{
773 // OK even on mac, as dialog is modal.
774 auto p = &mProject;
776}
777
778void MacrosWindow::UpdateDisplay( bool bExpanded )
779{
780 // If we failed to save changes, we abandon the attempt to
781 // change the expand/shrink state of the GUI.
782 if( !SaveChanges() )
783 return;
784
785 mbExpanded = bExpanded;
786
787 mChanged = false;
788 // if we try to access the about to be destroyed mSave button
789 // inappropriately, we need to crash rather than (sometimes) silently
790 // succeed.
791 mSave = nullptr;
792
793 DestroyChildren();
794 SetSizer( nullptr );
795
797 SetMinSize( wxSize( 200,200 ));
798
799 // Get and set position for optical stability.
800 // Expanded and shrunk dialogs 'stay where they were'.
801 // That's OK , and what we want, even if we exapnd off-screen.
802 // We won't shrink to being off-screen, since the shrink button
803 // was clicked, so must have been on screen.
804 wxPoint p = GetPosition( );
805 if( mbExpanded )
806 Populate();
807 else
809 SetPosition( p );
810 mResize->SetFocus();
811
812 auto Title = WindowTitle();
813 SetLabel( Title ); // Provide visual label
814 SetName( Title ); // Provide audible label
815 SetTitle( Title );
816}
817
818void MacrosWindow::OnExpand(wxCommandEvent &WXUNUSED(event))
819{ UpdateDisplay( true );}
820
821void MacrosWindow::OnShrink(wxCommandEvent &WXUNUSED(event))
822{
823 if( ChangeOK() )
824 UpdateDisplay( false );
825}
826
827
829{
830 if (mChanged) {
831 int id;
832
833 auto title = XO("%s changed").Format( mActiveMacro );
834 auto msg = XO("Do you want to save the changes?");
835
837 msg,
838 title,
839 wxYES_NO | wxCANCEL);
840 if (id == wxCANCEL) {
841 return false;
842 }
843
844 if (id == wxYES) {
846 return false;
847 }
848 }
849
850 mChanged = false;
851 mSave->Enable( mChanged );
852 }
853
854 return true;
855}
857void MacrosWindow::OnMacroSelected(wxListEvent & event)
858{
859 if (!ChangeOK()) {
860 event.Veto();
861 return;
862 }
863
864 int item = event.GetIndex();
865
866 mActiveMacro = mMacros->GetItemText(item);
868}
869
871{
873 if( !mbExpanded )
874 return;
875
877 mRemove->Disable();
878 mRename->Disable();
879 mRestore->Enable();
880 }
881 else {
882 mRemove->Enable();
883 mRename->Enable();
884 mRestore->Disable();
885 }
886
887 PopulateList();
888}
889
891void MacrosWindow::OnListSelected(wxListEvent & WXUNUSED(event))
892{
893 FitColumns();
894}
895
897void MacrosWindow::OnSize(wxSizeEvent & WXUNUSED(event))
898{
899 // Refresh the layout and re-fit the columns.
900 Layout();
901 if( !mbExpanded )
902 return;
903 FitColumns();
904}
905
907{
908
909#if defined(__WXMAC__)
910 // wxMac uses a hard coded width of 150 when wxLIST_AUTOSIZE_USEHEADER
911 // is specified, so we calculate the width ourselves. This method may
912 // work equally well on other platforms.
913 for (size_t c = 0; c < mList->GetColumnCount(); c++) {
914 wxListItem info;
915 int width;
916
917 mList->SetColumnWidth(c, wxLIST_AUTOSIZE);
918 info.Clear();
919 info.SetId(c);
920 info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_WIDTH);
921 mList->GetColumn(c, info);
922
923 mList->GetTextExtent(info.GetText(), &width, NULL);
924 width += 2 * 4; // 2 * kItemPadding - see listctrl_mac.cpp
925 width += 16; // kIconWidth - see listctrl_mac.cpp
926
927 mList->SetColumnWidth(c, wxMax(width, mList->GetColumnWidth(c)));
928 }
929
930 // Looks strange, but it forces the horizontal scrollbar to get
931 // drawn. If not done, strange column sizing can occur if the
932 // user attempts to resize the columns.
933 mList->SetClientSize(mList->GetClientSize());
934#else
935 mList->SetColumnWidth(0, wxLIST_AUTOSIZE_USEHEADER);
936 mList->SetColumnWidth(1, wxLIST_AUTOSIZE_USEHEADER);
937 mList->SetColumnWidth(2, wxLIST_AUTOSIZE);
938#endif
939
940 int bestfit = mList->GetColumnWidth(2);
941 int clientsize = mList->GetClientSize().GetWidth();
942 int col0 = mList->GetColumnWidth(0);
943 int col1 = mList->GetColumnWidth(1);
944 bestfit = (bestfit > clientsize-col0-col1)? bestfit : clientsize-col0-col1;
945 mList->SetColumnWidth(2, bestfit);
946
947}
948
950void MacrosWindow::OnMacrosBeginEdit(wxListEvent &event)
951{
952 int itemNo = event.GetIndex();
953
954 wxString macro = mMacros->GetItemText(itemNo);
955
956 if (mMacroCommands.IsFixed(macro)) {
957 wxBell();
958 event.Veto();
959 }
960 if( mMacroBeingRenamed.IsEmpty())
961 mMacroBeingRenamed = macro;
962}
963
965void MacrosWindow::OnMacrosEndEdit(wxListEvent &event)
966{
967 if (event.IsEditCancelled()) {
969 return;
970 }
971
972 if( mMacroBeingRenamed.IsEmpty())
973 return;
974
975 wxString newname = event.GetLabel();
976
979 mActiveMacro = newname;
982 UpdateMenus();
983 event.Veto();
984}
985
987void MacrosWindow::OnAdd(wxCommandEvent & WXUNUSED(event))
988{
989 // Similar to Bug 2284 we may need to save a changed macro.
990 if (!ChangeOK()) {
991 return;
992 }
993
994 while (true) {
996 XO("Enter name of new macro"),
997 XO("Name of new macro"));
998 d.SetName(d.GetTitle());
999 wxString name;
1000
1001 if (d.ShowModal() == wxID_CANCEL) {
1002 Raise();
1003 return;
1004 }
1005 Raise();
1006
1007 name = d.GetValue().Strip(wxString::both);
1008
1009 if (name.length() == 0) {
1011 XO("Name must not be blank"),
1012 WindowTitle(),
1013 wxOK | wxICON_ERROR,
1014 this);
1015 continue;
1016 }
1017
1018 if (name.Contains(wxFILE_SEP_PATH) ||
1019 name.Contains(wxFILE_SEP_PATH_UNIX)) {
1021 /*i18n-hint: The %c will be replaced with 'forbidden characters', like '/' and '\'.*/
1022 XO("Names may not contain '%c' and '%c'")
1023 .Format(wxFILE_SEP_PATH, wxFILE_SEP_PATH_UNIX),
1024 WindowTitle(),
1025 wxOK | wxICON_ERROR,
1026 this);
1027 continue;
1028 }
1029
1031
1033
1035 UpdateMenus();
1036
1037 break;
1038 }
1039}
1040
1042void MacrosWindow::OnRemove(wxCommandEvent & WXUNUSED(event))
1043{
1044 long item = mMacros->GetNextItem(-1,
1045 wxLIST_NEXT_ALL,
1046 wxLIST_STATE_SELECTED);
1047 if (item == -1) {
1048 return;
1049 }
1050
1051 wxString name = mMacros->GetItemText(item);
1053 this,
1054 /*i18n-hint: %s will be replaced by the name of a file.*/
1055 XO("Are you sure you want to delete %s?").Format( name ),
1056 Verbatim( GetTitle() ),
1057 wxYES_NO | wxICON_QUESTION );
1058 if (m.ShowModal() == wxID_NO) {
1059 Raise();
1060 return;
1061 }
1062 Raise();
1063
1065
1066 item++;
1067 if (item >= (mMacros->GetItemCount() - 1) && item >= 0) {
1068 item--;
1069 }
1070
1071 // Bug 2284. The macro we have just removed might have been
1072 // changed. Since we've just deleted the macro, we should
1073 // forget about that change.
1074 mChanged = false;
1075 mSave->Enable( mChanged );
1076 mActiveMacro = mMacros->GetItemText(item);
1077
1079 UpdateMenus();
1080}
1081
1083void MacrosWindow::OnRename(wxCommandEvent & WXUNUSED(event))
1084{
1085 long item = mMacros->GetNextItem(-1,
1086 wxLIST_NEXT_ALL,
1087 wxLIST_STATE_SELECTED);
1088 if (item == -1) {
1089 return;
1090 }
1091
1092 mMacros->EditLabel(item);
1093 UpdateMenus();
1094}
1095
1097void MacrosWindow::OnRestore(wxCommandEvent & WXUNUSED(event))
1098{
1100
1101 mChanged = true;
1102 mSave->Enable( mChanged );
1103
1104 PopulateList();
1105}
1106
1108void MacrosWindow::OnImport(wxCommandEvent & WXUNUSED(event))
1109{
1110 if (!ChangeOK()) {
1111 return;
1112 }
1113
1114 long item = mMacros->GetNextItem(-1,
1115 wxLIST_NEXT_ALL,
1116 wxLIST_STATE_SELECTED);
1117 if (item == -1) {
1118 return;
1119 }
1120
1121 wxString name = mMacros->GetItemText(item);
1122
1123 name = mMacroCommands.ReadMacro({}, this);
1124 if (name == wxEmptyString) {
1125 return;
1126 }
1127
1129
1131 UpdateMenus();
1132}
1133
1135void MacrosWindow::OnExport(wxCommandEvent & WXUNUSED(event))
1136{
1137 long item = mMacros->GetNextItem(-1,
1138 wxLIST_NEXT_ALL,
1139 wxLIST_STATE_SELECTED);
1140 if (item == -1) {
1141 return;
1142 }
1143
1144 mMacroCommands.WriteMacro(mMacros->GetItemText(item), this);
1145}
1146
1147void MacrosWindow::OnSave(wxCommandEvent & WXUNUSED(event))
1148{
1149 SaveChanges();
1150}
1151
1152
1155void MacrosWindow::OnCommandActivated(wxListEvent & WXUNUSED(event))
1156{
1157 wxCommandEvent dummy;
1158 OnEditCommandParams( dummy );
1159}
1160
1162void MacrosWindow::OnInsert(wxCommandEvent & WXUNUSED(event))
1163{
1164 long item = mList->GetNextItem(-1,
1165 wxLIST_NEXT_ALL,
1166 wxLIST_STATE_SELECTED);
1167 if (item == -1) {
1168 item = mList->GetItemCount()-1;
1169 }
1170 InsertCommandAt( item );
1171}
1172
1174{
1175 if (item == -1) {
1176 return;
1177 }
1178
1179 MacroCommandDialog d(this, wxID_ANY, mProject);
1180
1181 if (!d.ShowModal()) {
1182 Raise();
1183 return;
1184 }
1185 Raise();
1186
1187 if(!d.mSelectedCommand.empty())
1188 {
1191 item);
1192 mChanged = true;
1193 mSave->Enable( mChanged );
1194
1195 mSelectedCommand = item + 1;
1196 PopulateList();
1197 }
1198
1199}
1200
1201void MacrosWindow::OnEditCommandParams(wxCommandEvent & WXUNUSED(event))
1202{
1203 int item = mList->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
1204
1205 // LAST command in list is END.
1206 // If nothing selected, add at END.
1207 // If END selected, add at END.
1208 // When adding at end we use InsertCommandAt, so that a new command
1209 // can be chosen.
1210 int lastItem = mList->GetItemCount()-1;
1211 if( (item<0) || (item+1) == mList->GetItemCount() )
1212 {
1213 InsertCommandAt( lastItem );
1214 return;
1215 }
1216
1217 // Just edit the parameters, and not the command.
1218 auto command = mMacroCommands.GetCommand(item);
1219 wxString params = mMacroCommands.GetParams(item);
1220 wxString oldParams = params;
1221
1222 params = MacroCommands::PromptForParamsFor(command, params, *this).Trim();
1223 Raise();
1224
1225 if (oldParams == params)
1226 return; // They did not actually make any changes..
1227
1229 mMacroCommands.AddToMacro(command,
1230 params,
1231 item);
1232
1233 mChanged = true;
1234 mSave->Enable( mChanged );
1235
1236 mSelectedCommand = item;
1237 PopulateList();
1238}
1239
1241void MacrosWindow::OnDelete(wxCommandEvent & WXUNUSED(event))
1242{
1243 long item = mList->GetNextItem(-1,
1244 wxLIST_NEXT_ALL,
1245 wxLIST_STATE_SELECTED);
1246 if (item == -1 || item + 1 == mList->GetItemCount()) {
1247 return;
1248 }
1249
1251
1252 mChanged = true;
1253 mSave->Enable( mChanged );
1254
1255 if (item >= (mList->GetItemCount() - 2) && item >= 0) {
1256 item--;
1257 }
1258 mSelectedCommand = item;
1259 PopulateList();
1260}
1261
1263void MacrosWindow::OnUp(wxCommandEvent & WXUNUSED(event))
1264{
1265 long item = mList->GetNextItem(-1,
1266 wxLIST_NEXT_ALL,
1267 wxLIST_STATE_SELECTED);
1268 if (item == -1 || item == 0 || item + 1 == mList->GetItemCount()) {
1269 return;
1270 }
1271
1274 item - 1);
1276
1277 mChanged = true;
1278 mSave->Enable( mChanged );
1279
1280 mSelectedCommand = item - 1;
1281 PopulateList();
1282}
1283
1285void MacrosWindow::OnDown(wxCommandEvent & WXUNUSED(event))
1286{
1287 long item = mList->GetNextItem(-1,
1288 wxLIST_NEXT_ALL,
1289 wxLIST_STATE_SELECTED);
1290 if (item == -1 || item + 2 >= mList->GetItemCount()) {
1291 return;
1292 }
1293
1296 item + 2);
1298
1299 mChanged = true;
1300 mSave->Enable( mChanged );
1301
1302 mSelectedCommand = item + 1;
1303 PopulateList();
1304}
1305
1306void MacrosWindow::OnApplyToProject(wxCommandEvent & event)
1307{
1308 if( !SaveChanges() )
1309 return;
1311}
1312
1313void MacrosWindow::OnApplyToFiles(wxCommandEvent & event)
1314{
1315 if( !SaveChanges() )
1316 return;
1318}
1319
1321 gPrefs->Write(wxT("/Batch/ActiveMacro"), mActiveMacro);
1322 gPrefs->Flush();
1323
1324 if (mChanged) {
1326 return false;
1327 }
1328 }
1329
1330 mChanged = false;
1331 if( mSave )
1332 mSave->Enable( mChanged );
1333
1334 return true;
1335}
1336
1338void MacrosWindow::OnOK(wxCommandEvent & WXUNUSED(event))
1339{
1340 if( !SaveChanges() )
1341 return;
1342 Hide();
1343 //EndModal(true);
1344}
1345
1347void MacrosWindow::OnCancel(wxCommandEvent &WXUNUSED(event))
1348{
1349 bool bWasChanged = mChanged;
1350 if (!ChangeOK()) {
1351 return;
1352 }
1353 // If we've rejected a change, we need to restore the display
1354 // of the active macro.
1355 // That's because next time we open this dialog we want to see the
1356 // unedited macro.
1357 if( bWasChanged )
1359 Hide();
1360}
1361
1363void MacrosWindow::OnKeyDown(wxKeyEvent &event)
1364{
1365 if (event.GetKeyCode() == WXK_DELETE) {
1366 wxLogDebug(wxT("wxKeyEvent"));
1367 }
1368
1369 event.Skip();
1370}
1371
1373{
1375}
1376
1377// PrefsListener implementation
1379{
1381}
1382
1383// The rest of this file installs hooks
1384
1385#include "CommonCommandFlags.h"
1386#include "CommandContext.h"
1387#include "effects/EffectManager.h"
1388namespace {
1389
1390AttachedWindows::RegisteredFactory sMacrosWindowKey{
1391 []( AudacityProject &parent ) -> wxWeakRef< wxWindow > {
1392 auto &window = GetProjectFrame(parent);
1393 return safenew MacrosWindow(
1394 &window, parent, true
1395 );
1396 }
1397};
1398
1399using MacroID = wxString;
1400
1402 const CommandContext& context, const MacroID& Name);
1403
1405{
1406 auto& commandManager = CommandManager::Get(context.project);
1407 switch (commandManager.mLastToolRegistration) {
1409 {
1410 auto lastEffect = commandManager.mLastTool;
1411 if (!lastEffect.empty())
1412 {
1414 lastEffect, context, commandManager.mRepeatToolFlags);
1415 }
1416 }
1417 break;
1420 commandManager.mLastToolRegisteredId);
1421 break;
1423 OnApplyMacroDirectlyByName(context, commandManager.mLastTool);
1424 break;
1425 }
1426}
1427
1428void OnManageMacros(const CommandContext &context )
1429{
1430 auto &project = context.project;
1431 CommandManager::Get(project).RegisterLastTool(context); //Register Macros as Last Tool
1432 auto macrosWindow = &GetAttachedWindows(project)
1433 .AttachedWindows::Get< MacrosWindow >( sMacrosWindowKey );
1434 if (macrosWindow) {
1435 macrosWindow->Show();
1436 macrosWindow->Raise();
1437 macrosWindow->UpdateDisplay( true );
1438 }
1439}
1440
1442{
1443 auto &project = context.project;
1444 CommandManager::Get(project).RegisterLastTool(context); //Register Palette as Last Tool
1445 auto macrosWindow = &GetAttachedWindows(project)
1446 .AttachedWindows::Get< MacrosWindow >( sMacrosWindowKey );
1447 if (macrosWindow) {
1448 macrosWindow->Show();
1449 macrosWindow->Raise();
1450 macrosWindow->UpdateDisplay( false );
1451 }
1452}
1453
1455{
1456 const MacroID& Name = context.parameter.GET();
1457 OnApplyMacroDirectlyByName(context, Name);
1458}
1459
1460void OnApplyMacroDirectlyByName(const CommandContext& context, const MacroID& Name)
1461
1462{
1463 auto &project = context.project;
1464 auto &window = GetProjectFrame(project);
1465 //wxLogDebug( "Macro was: %s", context.parameter);
1466 ApplyMacroDialog dlg( &window, project );
1467 //const auto &Name = context.parameter;
1468
1469// We used numbers previously, but macros could get renumbered, making
1470// macros containing macros unpredictable.
1471#ifdef MACROS_BY_NUMBERS
1472 long item=0;
1473 // Take last three letters (of e.g. Macro007) and convert to a number.
1474 Name.Mid( Name.length() - 3 ).ToLong( &item, 10 );
1475 dlg.ApplyMacroToProject( item, false );
1476#else
1477 dlg.ApplyMacroToProject( Name, false );
1478#endif
1479 /* i18n-hint: %s will be the name of the macro which will be
1480 * repeated if this menu item is chosen */
1482
1485 auto shortDesc = em.GetCommandName(Name);
1486 auto& undoManager = UndoManager::Get(project);
1487 auto& commandManager = CommandManager::Get(project);
1488 int cur = undoManager.GetCurrentState();
1489 if (undoManager.UndoAvailable()) {
1490 undoManager.GetShortDescription(cur, &desc);
1491 commandManager.Modify(wxT("RepeatLastTool"), XXO("&Repeat %s")
1492 .Format(desc));
1493 auto& commandManager = CommandManager::Get(project);
1494 commandManager.mLastTool = Name;
1495 commandManager.mLastToolRegistration =
1497 }
1498
1499}
1500
1502{
1503 using namespace MenuRegistry;
1504 auto names = MacroCommands::GetNames(); // these names come from filenames
1505 for (const auto &name : names) {
1508 Verbatim(name), // file name verbatim
1510 flags,
1512 ));
1513 }
1514}
1515
1518 [](const AudacityProject &project) {
1519 auto& commandManager = CommandManager::Get(project);
1520 if (commandManager.mLastToolRegistration ==
1522 return true;
1523 return !commandManager.mLastTool.empty();
1524 }
1525 }; return flag;
1526}
1527}
1528
1529using namespace MenuRegistry;
1530
1532{
1533 static auto items = std::shared_ptr{
1534 Items( "Macros",
1535 Section( "RepeatLast",
1536 // Delayed evaluation:
1538 {
1539 const auto &lastTool = CommandManager::Get(project).mLastTool;
1540 TranslatableString buildMenuLabel;
1541 if (!lastTool.empty())
1542 buildMenuLabel = XO("Repeat %s")
1543 .Format( EffectManager::Get().GetCommandName(lastTool) );
1544 else
1545 buildMenuLabel = XO("Repeat Last Tool");
1546
1547 return Command( wxT("RepeatLastTool"), buildMenuLabel,
1551 Options{}.IsGlobal() );
1552 }
1553 ),
1554
1555 Command( wxT("ManageMacros"), XXO("&Macro Manager"),
1557
1558 Menu( wxT("Macros"), XXO("&Apply Macro"),
1559 // Palette has no access key to ensure first letter navigation of
1560 // sub menu
1561 Section( "",
1562 Command( wxT("ApplyMacrosPalette"), XXO("Palette..."),
1564 ),
1565
1566 Section( "",
1567 // Delayed evaluation:
1568 [](AudacityProject&) {
1569 auto result = Items("");
1571 return result;
1572 }
1573 )
1574 )
1575 ) };
1576 return items;
1577}
1578
1580
1582{
1583 // These are the more useful to VI user Scriptables.
1584 static auto menu = std::shared_ptr{
1585 // i18n-hint: Scriptables are commands normally used from Python, Perl etc.
1586 Menu( wxT("Scriptables1"), XXO("Script&ables I") )
1587 };
1588 return menu;
1589}
1590
1592 wxT("Optional/Extra/Part2")
1593};
1594
1596{
1597 // Less useful to VI users.
1598 static auto menu = std::shared_ptr{
1599 // i18n-hint: Scriptables are commands normally used from Python, Perl etc.
1600 Menu( wxT("Scriptables2"), XXO("Scripta&bles II") )
1601 };
1602 return menu;
1603}
1604
1606 wxT("Optional/Extra/Part2")
1607};
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
END_EVENT_TABLE()
#define ApplyToFilesID
AttachedItem sAttachment1
auto ExtraScriptablesIMenu()
AttachedItem sAttachment3
AttachedItem sAttachment2
auto ExtraScriptablesIIMenu()
#define MacrosListID
@ ActionColumn
@ ParamsColumn
@ ItemNumberColumn
#define CommandsListID
#define ApplyToProjectID
#define MacrosPaletteTitle
#define ShrinkID
#define ExpandID
auto PluginMenuItems()
#define ManageMacrosTitle
@ SaveButtonID
@ UpButtonID
@ ImportButtonID
@ DownButtonID
@ RestoreButtonID
@ RenameButtonID
@ AddButtonID
@ EditButtonID
@ DefaultsButtonID
@ RemoveButtonID
@ ApplyToProjectButtonID
@ DeleteButtonID
@ InsertButtonID
@ ApplyToFilesButtonID
@ ExportButtonID
std::bitset< NCommandFlags > CommandFlag
Definition: CommandFlag.h:30
const ReservedCommandFlag & AudioIONotBusyFlag()
int min(int a, int b)
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
EffectDistortionSettings params
Definition: Distortion.cpp:77
const TranslatableString name
Definition: Distortion.cpp:76
EVT_LIST_ITEM_SELECTED(CurvesListID, EqualizationCurvesDialog::OnListSelectionChange) EVT_LIST_ITEM_DESELECTED(CurvesListID
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
static ProjectFileIORegistry::AttributeWriterEntry entry
#define _(s)
Definition: Internat.h:73
#define safenew
Definition: MemoryX.h:9
static const auto title
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
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 ...
AUDACITY_DLL_API AttachedWindows & GetAttachedWindows(AudacityProject &project)
accessors for certain important windows associated with each project
@ eIsCreating
Definition: ShuttleGui.h:37
@ eCloseButton
Definition: ShuttleGui.h:619
@ eHelpButton
Definition: ShuttleGui.h:613
static TranslatableStrings names
Definition: TagsEditor.cpp:153
const auto project
#define S(N)
Definition: ToChars.cpp:64
declares abstract base class Track, TrackList, and iterators over TrackList
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
int id
static std::once_flag flag
Shows progress in executing commands in MacroCommands.
wxButton * mResize
Provides list of available commands.
virtual void OnApplyToFiles(wxCommandEvent &event)
MacroCommands mMacroCommands
AudacityProject & mProject
wxListCtrl * mMacros
void ApplyMacroToProject(int iMacro, bool bHasGui=true)
virtual void OnCancel(wxCommandEvent &event)
virtual void OnApplyToProject(wxCommandEvent &event)
const MacroCommandsCatalog mCatalog
virtual void OnHelp(wxCommandEvent &event)
void PopulateOrExchange(ShuttleGui &S)
Defines the dialog and does data exchange with it.
virtual ManualPageID GetHelpPageName()
static CommandID MacroIdOfName(const wxString &MacroName)
Wrap wxMessageDialog so that caption IS translatable.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
Wrap wxTextEntryDialog so that caption IS translatable.
static Clipboard & Get()
Definition: Clipboard.cpp:28
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
CommandParameter parameter
AudacityProject & project
void RegisterLastTool(const CommandContext &context)
PluginID mLastTool
void DoRepeatProcess(const CommandContext &context, int)
static CommandManager & Get(AudacityProject &project)
EffectManager is the class that handles effects and effect categories.
Definition: EffectManager.h:48
static EffectManager & Get()
TranslatableString GetCommandName(const PluginID &ID)
virtual void GetPaths(wxArrayString &paths) const
virtual void SetFilterIndex(int filterIndex)
virtual int ShowModal()
Abstract base class used in importing a file.
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:231
bool empty() const
Definition: Identifier.h:61
const wxString & GET() const
Explicit conversion to wxString, meant to be ugly-looking and demanding of a comment why it's correct...
Definition: Identifier.h:66
static Importer & Get()
Definition: Import.cpp:102
FileNames::FileTypes GetFileTypes(const FileNames::FileType &extraType={})
Definition: Import.cpp:208
static size_t SelectDefaultOpenType(const FileNames::FileTypes &fileTypes)
Definition: Import.cpp:273
Provides a list of configurable commands for use with MacroCommands.
Entries::const_iterator ByCommandId(const CommandID &commandId) const
Entries::const_iterator end() const
Definition: BatchCommands.h:49
bool IsFixed(const wxString &name)
void AddToMacro(const CommandID &command, int before=-1)
wxString GetParams(int index)
void DeleteFromMacro(int index)
bool RenameMacro(const wxString &oldmacro, const wxString &newmacro)
CommandID GetCommand(int index)
static wxArrayString GetNames()
bool DeleteMacro(const wxString &name)
wxString WriteMacro(const wxString &macro, wxWindow *parent=nullptr)
bool ApplyMacro(const MacroCommandsCatalog &catalog, const wxString &filename={})
static wxString PromptForParamsFor(const CommandID &command, const wxString &params, wxWindow &parent)
bool AddMacro(const wxString &macro)
wxString ReadMacro(const wxString &macro, wxWindow *parent=nullptr)
void RestoreMacro(const wxString &name)
void PopulateList()
This clears and updates the contents of mList, the commands for the current macro.
TranslatableString WindowTitle() const
void OnDelete(wxCommandEvent &event)
void OnListSelected(wxListEvent &event)
An item in the macros list has been selected.
void OnShrink(wxCommandEvent &event)
void OnExport(wxCommandEvent &event)
wxButton * mRemove
void PopulateOrExchange(ShuttleGui &S)
Defines the dialog and does data exchange with it.
void OnRestore(wxCommandEvent &event)
Reset a built in macro.
void OnCommandActivated(wxListEvent &event)
AudacityProject & mProject
void OnAdd(wxCommandEvent &event)
void OnUp(wxCommandEvent &event)
void OnCancel(wxCommandEvent &event) override
void OnApplyToProject(wxCommandEvent &event) override
void OnMacroSelected(wxListEvent &event)
An item in the macros list has been selected.
void OnExpand(wxCommandEvent &event)
wxButton * mRestore
wxButton * mImport
void OnSave(wxCommandEvent &event)
void OnApplyToFiles(wxCommandEvent &event) override
void UpdateDisplay(bool bExpanded)
void UpdatePrefs() override
void OnMacrosBeginEdit(wxListEvent &event)
void OnSize(wxSizeEvent &event)
The window has been resized.
wxButton * mRename
wxButton * mExport
void OnMacrosEndEdit(wxListEvent &event)
void OnImport(wxCommandEvent &event)
MacrosWindow(wxWindow *parent, AudacityProject &project, bool bExpanded=true)
Constructor.
void OnDown(wxCommandEvent &event)
void OnEditCommandParams(wxCommandEvent &event)
void OnInsert(wxCommandEvent &event)
void OnRemove(wxCommandEvent &event)
void InsertCommandAt(int item)
void Populate()
Creates the dialog and its contents.
void AddItem(const CommandID &command, wxString const &params)
Add one item into mList.
void OnKeyDown(wxKeyEvent &event)
void OnOK(wxCommandEvent &event)
Send changed values back to Prefs, and update Audacity.
void OnRename(wxCommandEvent &event)
void RebuildMenuBar()
static MenuCreator & Get(AudacityProject &project)
Definition: MenuCreator.cpp:91
bool Import(const std::vector< FilePath > &fileNames, bool addToHistory=true)
static ProjectFileManager & Get(AudacityProject &project)
static ProjectManager & Get(AudacityProject &project)
void ResetProjectToEmpty()
Generates classes whose instances register items at construction.
Definition: Registry.h:388
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
bool empty() const
Definition: Track.cpp:758
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:314
Holds a msgid for the translation catalog; may also bind format arguments.
static UndoManager & Get(AudacityProject &project)
Definition: UndoManager.cpp:71
void ZoomFitHorizontallyAndShowTrack(Track *pTrack)
Definition: Viewport.cpp:439
static Viewport & Get(AudacityProject &project)
Definition: Viewport.cpp:33
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0
virtual bool Read(const wxString &key, bool *value) const =0
void SetTitle(const TranslatableString &title)
void SetLabel(const TranslatableString &title)
void SetName(const TranslatableString &title)
std::function< void()> Action
Definition: BasicUI.h:24
AUDACITY_DLL_API bool DoEffect(const PluginID &ID, const CommandContext &context, unsigned flags)
'Repeat Last Effect'.
Definition: EffectUI.cpp:1148
IMPORT_EXPORT_API ExportResult Show(ExportTask exportTask)
FILES_API FilePath FindDefaultPath(Operation op)
constexpr auto Section
Definition: MenuRegistry.h:436
constexpr auto Items
Definition: MenuRegistry.h:427
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
std::unique_ptr< detail::IndirectItem< Item > > Indirect(const std::shared_ptr< Item > &ptr)
A convenience function.
Definition: Registry.h:175
void DoSelectAll(AudacityProject &project)
void OnRepeatLastTool(const CommandContext &context)
void OnApplyMacroDirectlyByName(const CommandContext &context, const MacroID &Name)
void OnApplyMacrosPalette(const CommandContext &context)
void OnManageMacros(const CommandContext &context)
void OnApplyMacroDirectly(const CommandContext &context)
AttachedWindows::RegisteredFactory sMacrosWindowKey
void PopulateMacrosMenu(MenuRegistry::MenuItems &items, CommandFlag flags)
const TranslatableString desc
Definition: ExportPCM.cpp:51
static CommandContext::TargetFactory::SubstituteInUnique< InteractiveOutputTargets > scope
Empty the clipboard at start of scope; restore its contents after.
Definition: Clipboard.h:70
auto push_back(Arg &&arg) -> std::enable_if_t< Traits< Base, Derived > ::template enables_item_type_v< Arg >, void >
Definition: Composite.h:105
Options && IsGlobal() &&
Definition: MenuRegistry.h:56
Options && AllowInMacros(int value=1) &&
Definition: MenuRegistry.h:69