Audacity  2.2.2
BatchProcessDialog.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  BatchProcessDialog.cpp
6 
7  Dominic Mazzoni
8  James Crook
9 
10 *******************************************************************//*******************************************************************/
16 
17 #include "Audacity.h"
18 #include "BatchProcessDialog.h"
19 
20 #include <wx/defs.h>
21 #include <wx/checkbox.h>
22 #include <wx/choice.h>
23 #include <wx/filedlg.h>
24 #include <wx/intl.h>
25 #include <wx/sizer.h>
26 #include <wx/statbox.h>
27 #include <wx/stattext.h>
28 #include <wx/textctrl.h>
29 #include <wx/listctrl.h>
30 #include <wx/radiobut.h>
31 #include <wx/button.h>
32 #include <wx/imaglist.h>
33 #include <wx/settings.h>
34 
35 #include "AudacityException.h"
36 #include "ShuttleGui.h"
37 #include "Prefs.h"
38 #include "Project.h"
39 #include "Internat.h"
41 #include "effects/Effect.h"
42 #include "../images/Arrow.xpm"
43 #include "../images/Empty9x16.xpm"
44 #include "BatchCommands.h"
45 #include "Track.h"
46 #include "UndoManager.h"
47 
48 #include "Theme.h"
49 #include "AllThemeResources.h"
50 
51 #include "FileDialog.h"
52 #include "FileNames.h"
53 #include "import/Import.h"
54 #include "widgets/ErrorDialog.h"
55 
56 #define ChainsListID 7001
57 #define CommandsListID 7002
58 #define ApplyToProjectID 7003
59 #define ApplyToFilesID 7004
60 
61 BEGIN_EVENT_TABLE(BatchProcessDialog, wxDialogWrapper)
64  EVT_BUTTON(wxID_CANCEL, BatchProcessDialog::OnCancel)
66 
68  wxDialogWrapper(parent, wxID_ANY, _("Apply Chain"),
69  wxDefaultPosition, wxDefaultSize,
70  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
71 {
72  //AudacityProject * p = GetActiveProject();
73 
74  SetLabel(_("Apply Chain")); // Provide visual label
75  SetName(_("Apply Chain")); // Provide audible label
76  Populate();
77 
78  mAbort = false;
79 }
80 
82 {
83 }
84 
86 {
87  //------------------------- Main section --------------------
88  ShuttleGui S(this, eIsCreating);
90  // ----------------------- End of main section --------------
91 }
92 
95 {
96  S.StartVerticalLay(true);
97  {
98  /*i18n-hint: A chain is a sequence of commands that can be applied
99  * to one or more audio files.*/
100  S.StartStatic(_("&Select Chain"), true);
101  {
102  S.SetStyle(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES |
103  wxLC_SINGLE_SEL);
105  mChains->InsertColumn(0, _("Chain"), wxLIST_FORMAT_LEFT);
106  }
107  S.EndStatic();
108 
109  S.StartHorizontalLay(wxALIGN_RIGHT, false);
110  {
111  S.SetBorder(10);
112  S.Id(ApplyToProjectID).AddButton(_("Apply to Current &Project"));
113  S.Id(ApplyToFilesID).AddButton(_("Apply to &Files..."));
114  S.Id(wxID_CANCEL).AddButton(_("&Cancel"));
115  }
116  S.EndHorizontalLay();
117  }
118  S.EndVerticalLay();
119 
120  wxArrayString names = mBatchCommands.GetNames();
121  for (int i = 0; i < (int)names.GetCount(); i++) {
122  mChains->InsertItem(i, names[i]);
123  }
124 
125  // Get and validate the currently active chain
126  wxString name = gPrefs->Read(wxT("/Batch/ActiveChain"), wxT(""));
127 
128  int item = mChains->FindItem(-1, name);
129  if (item == -1) {
130  item = 0;
131  name = mChains->GetItemText(0);
132  }
133 
134  // Select the name in the list...this will fire an event.
135  mChains->SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
136 
137  Layout();
138  Fit();
139  SetSizeHints(GetSize());
140  Center();
141 
142  // Set the column size for the chains list.
143  wxSize sz = mChains->GetClientSize();
144  mChains->SetColumnWidth(0, sz.x);
145 }
146 
147 void BatchProcessDialog::OnApplyToProject(wxCommandEvent & WXUNUSED(event))
148 {
149  long item = mChains->GetNextItem(-1,
150  wxLIST_NEXT_ALL,
151  wxLIST_STATE_SELECTED);
152  if (item == -1) {
153  AudacityMessageBox(_("No chain selected"));
154  return;
155  }
156  wxString name = mChains->GetItemText(item);
157 
158  wxDialog * pD = safenew wxDialogWrapper(this, wxID_ANY, GetTitle());
159  pD->SetName(pD->GetTitle());
160  ShuttleGui S(pD, eIsCreating);
161 
162  S.StartHorizontalLay(wxCENTER, false);
163  {
164  S.StartStatic( {}, false); // deliberately not translated (!)
165  {
166  S.SetBorder(20);
167  S.AddFixedText(wxString::Format(_("Applying '%s' to current project"),
168  name));
169  }
170  S.EndStatic();
171  }
172  S.EndHorizontalLay();
173 
174  pD->Layout();
175  pD->Fit();
176  pD->CenterOnScreen();
177  pD->Move(-1, 0);
178  pD->Show();
179 
180  // The Hide() on the next line seems to tickle a bug in wx3,
181  // giving rise to our Bug #1221. The problem is that on Linux
182  // the 'Hide' converts us from a Modal into a regular dialog,
183  // as far as closing is concerned. On Linux we can't close with
184  // EndModal() anymore after this.
185  Hide();
186 
187  gPrefs->Write(wxT("/Batch/ActiveChain"), name);
188  gPrefs->Flush();
189 
191 
192  // The disabler must get deleted before the EndModal() call. Otherwise,
193  // the menus on OSX will remain disabled.
194  bool success;
195  {
196  wxWindowDisabler wd(pD);
197  success = GuardedCall< bool >(
198  [this]{ return mBatchCommands.ApplyChain(); } );
199  }
200 
201  if (!success) {
202  Show();
203  return;
204  }
205 
206 #if !defined(__WXMAC__)
207  // Under Linux an EndModal() here crashes (Bug #1221).
208  // But sending a close message instead is OK.
209  wxCloseEvent Evt;
210  Evt.SetId( wxID_OK );
211  Evt.SetEventObject( this);
212  ProcessWindowEvent( Evt );
213 #else
214  EndModal(wxID_OK);
215 #endif
216 
217  // Raise myself again, and the parent window with me
218  Show();
219 }
220 
221 void BatchProcessDialog::OnApplyToFiles(wxCommandEvent & WXUNUSED(event))
222 {
223  long item = mChains->GetNextItem(-1,
224  wxLIST_NEXT_ALL,
225  wxLIST_STATE_SELECTED);
226  if (item == -1) {
227  AudacityMessageBox(_("No chain selected"));
228  return;
229  }
230 
231  wxString name = mChains->GetItemText(item);
232  gPrefs->Write(wxT("/Batch/ActiveChain"), name);
233  gPrefs->Flush();
234 
235  AudacityProject *project = GetActiveProject();
236  if (!project->GetIsEmpty()) {
237  AudacityMessageBox(_("Please save and close the current project first."));
238  return;
239  }
240 
241  wxString prompt = _("Select file(s) for batch processing...");
242 
243  FormatList l;
244  wxString filter;
245  wxString all;
246 
248  for (const auto &format : l) {
249  const Format *f = &format;
250 
251  wxString newfilter = f->formatName + wxT("|");
252  for (size_t i = 0; i < f->formatExtensions.size(); i++) {
253  if (!newfilter.Contains(wxT("*.") + f->formatExtensions[i] + wxT(";")))
254  newfilter += wxT("*.") + f->formatExtensions[i] + wxT(";");
255  if (!all.Contains(wxT("*.") + f->formatExtensions[i] + wxT(";")))
256  all += wxT("*.") + f->formatExtensions[i] + wxT(";");
257  }
258  newfilter.RemoveLast(1);
259  filter += newfilter;
260  filter += wxT("|");
261  }
262  all.RemoveLast(1);
263  filter.RemoveLast(1);
264 
265  wxString mask = _("All files|*|All supported files|") +
266  all + wxT("|") +
267  filter;
268 
269  wxString type = gPrefs->Read(wxT("/DefaultOpenType"),mask.BeforeFirst(wxT('|')));
270  // Convert the type to the filter index
271  int index = mask.First(type + wxT("|"));
272  if (index == wxNOT_FOUND) {
273  index = 0;
274  }
275  else {
276  index = mask.Left(index).Freq(wxT('|')) / 2;
277  if (index < 0) {
278  index = 0;
279  }
280  }
281 
283  FileDialogWrapper dlog(this,
284  prompt,
285  path,
286  wxT(""),
287  mask,
288  wxFD_OPEN | wxFD_MULTIPLE | wxRESIZE_BORDER);
289 
290  dlog.SetFilterIndex(index);
291  if (dlog.ShowModal() != wxID_OK) {
292  return;
293  }
294 
295  wxArrayString files;
296  dlog.GetPaths(files);
297 
298  files.Sort();
299 
300  wxDialog * pD = safenew wxDialogWrapper(this, wxID_ANY, GetTitle());
301  pD->SetName(pD->GetTitle());
302  ShuttleGui S(pD, eIsCreating);
303 
304  S.StartVerticalLay(false);
305  {
306  S.StartStatic(_("Applying..."), 1);
307  {
308  auto imageList = std::make_unique<wxImageList>(9, 16);
309  imageList->Add(wxIcon(empty9x16_xpm));
310  imageList->Add(wxIcon(arrow_xpm));
311 
312  S.SetStyle(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES |
313  wxLC_SINGLE_SEL);
315  // AssignImageList takes ownership
316  mList->AssignImageList(imageList.release(), wxIMAGE_LIST_SMALL);
317  mList->InsertColumn(0, _("File"), wxLIST_FORMAT_LEFT);
318  }
319  S.EndStatic();
320 
321  S.StartHorizontalLay(wxCENTER, false);
322  {
323  S.Id(wxID_CANCEL).AddButton(_("&Cancel"));
324  }
325  S.EndHorizontalLay();
326  }
327  S.EndVerticalLay();
328 
329  int i;
330  for (i = 0; i < (int)files.GetCount(); i++ ) {
331  mList->InsertItem(i, files[i], i == 0);
332  }
333 
334  // Set the column size for the files list.
335  mList->SetColumnWidth(0, wxLIST_AUTOSIZE);
336 
337  int width = mList->GetColumnWidth(0);
338  wxSize sz = mList->GetClientSize();
339  if (width > sz.GetWidth() && width < 500) {
340  sz.SetWidth(width);
341  mList->SetInitialSize(sz);
342  }
343 
344  pD->Layout();
345  pD->Fit();
346  pD->SetSizeHints(pD->GetSize());
347  pD->CenterOnScreen();
348  pD->Move(-1, 0);
349  pD->Show();
350  Hide();
351 
353  for (i = 0; i < (int)files.GetCount(); i++) {
354  wxWindowDisabler wd(pD);
355  if (i > 0) {
356  //Clear the arrow in previous item.
357  mList->SetItemImage(i - 1, 0, 0);
358  }
359  mList->SetItemImage(i, 1, 1);
360  mList->EnsureVisible(i);
361 
362  auto success = GuardedCall< bool >( [&] {
363  project->Import(files[i]);
364  project->ZoomAfterImport(nullptr);
365  project->OnSelectAll(*project);
366  if (!mBatchCommands.ApplyChain())
367  return false;
368 
369  if (!pD->IsShown() || mAbort)
370  return false;
371 
372  return true;
373  } );
374 
375  if (!success)
376  break;
377 
378  UndoManager *um = project->GetUndoManager();
379  um->ClearStates();
380  project->OnSelectAll(*project);
381  project->OnRemoveTracks(*project);
382  }
383  project->OnRemoveTracks(*project);
384 
385  // Under Linux an EndModal() here crashes (Bug #1221).
386  // But sending a close message instead is OK.
387 #if !defined(__WXMAC__)
388  wxCloseEvent Evt;
389  Evt.SetId( wxID_OK );
390  Evt.SetEventObject( this);
391  ProcessWindowEvent( Evt );
392 #else
393  EndModal(wxID_OK);
394 #endif
395 
396  // Raise myself again, and the parent window with me
397  Show();
398 }
399 
400 void BatchProcessDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
401 {
402 #if !defined(__WXMAC__)
403  // It is possible that we could just do EndModal()
404  // here even on Linux. However, we know the alternative way of
405  // closing works, if we are hidden, so we hide and then do that.
406  Hide();
407  // Under Linux an EndModal() here potentially crashes (Bug #1221).
408  // But sending a close message instead is OK.
409  wxCloseEvent Evt;
410  Evt.SetId( wxID_CANCEL );
411  Evt.SetEventObject( this);
412  ProcessWindowEvent( Evt );
413 #else
414  EndModal(wxID_CANCEL);
415 #endif
416 }
417 
419 #include <wx/textdlg.h>
420 #include "BatchCommandDialog.h"
421 
422 enum {
423 // ChainsListID 7005
424  AddButtonID = 10000,
426 // CommandsListID, 7002
435 };
436 
437 BEGIN_EVENT_TABLE(EditChainsDialog, wxDialogWrapper)
440  EVT_LIST_BEGIN_LABEL_EDIT(ChainsListID, EditChainsDialog::OnChainsBeginEdit)
441  EVT_LIST_END_LABEL_EDIT(ChainsListID, EditChainsDialog::OnChainsEndEdit)
445  EVT_SIZE(EditChainsDialog::OnSize)
446 
447  EVT_LIST_ITEM_ACTIVATED(CommandsListID, EditChainsDialog::OnCommandActivated)
453 
454  EVT_BUTTON(wxID_OK, EditChainsDialog::OnOK)
455  EVT_BUTTON(wxID_CANCEL, EditChainsDialog::OnCancel)
456 
457  EVT_KEY_DOWN(EditChainsDialog::OnKeyDown)
459 
460 enum {
465 };
466 
469  wxDialogWrapper(parent, wxID_ANY, _("Edit Chains"),
470  wxDefaultPosition, wxDefaultSize,
471  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
472 {
473  SetLabel(_("Edit Chains")); // Provide visual label
474  SetName(_("Edit Chains")); // Provide audible label
475 
476  mChanged = false;
477  mSelectedCommand = 0;
478 
479  Populate();
480 }
481 
483 {
484 }
485 
488 {
490 
491  //------------------------- Main section --------------------
492  ShuttleGui S(this, eIsCreating);
494  // ----------------------- End of main section --------------
495 
496  // Get and validate the currently active chain
497  mActiveChain = gPrefs->Read(wxT("/Batch/ActiveChain"), wxT(""));
498 
499  // Go populate the chains list.
500  PopulateChains();
501 
502  // We have a bare list. We need to add columns and content.
503  PopulateList();
504 
505  // Layout and set minimum size of window
506  Layout();
507  Fit();
508  SetSizeHints(GetSize());
509 
510  // Size and place window
511  SetSize(wxSystemSettings::GetMetric(wxSYS_SCREEN_X) * 3 / 4,
512  wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) * 4 / 5);
513  Center();
514 
515  // Set the column size for the chains list.
516  wxSize sz = mChains->GetClientSize();
517  mChains->SetColumnWidth(0, sz.x);
518 
519  // Size columns properly
520  FitColumns();
521 }
522 
525 {
526  S.StartHorizontalLay(wxEXPAND, 1);
527  {
528  S.StartStatic(_("&Chains"));
529  {
530  // JKC: Experimenting with an alternative way to get multiline
531  // translated strings to work correctly without very long lines.
532  // My appologies Alexandre if this way didn't work either.
533  //
534  // With this method:
535  // 1) it compiles fine under windows unicode and normal mode.
536  // 2) xgettext source code has handling for the trailing '\'
537  //
538  // It remains to see if linux and mac can cope and if xgettext
539  // actually does do fine with strings presented like this.
540  // If it doesn't work out, revert to all-on-one-line.
541  S.SetStyle(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_SINGLE_SEL |
542  wxLC_EDIT_LABELS);
544  // i18n-hint: This is the heading for a column in the edit chains dialog
545  mChains->InsertColumn(0, _("Chain"), wxLIST_FORMAT_LEFT);
546  S.StartHorizontalLay(wxCENTER, false);
547  {
548  S.Id(AddButtonID).AddButton(_("&Add"));
549  mRemove = S.Id(RemoveButtonID).AddButton(_("&Remove"));
550  mRename = S.Id(RenameButtonID).AddButton(_("Re&name"));
551  }
552  S.EndHorizontalLay();
553  }
554  S.EndStatic();
555 
556  S.StartStatic(_("C&hain (Double-Click or press SPACE to edit)"), true);
557  {
558  S.SetStyle(wxSUNKEN_BORDER | wxLC_REPORT | wxLC_HRULES | wxLC_VRULES |
559  wxLC_SINGLE_SEL);
561 
562  //An empty first column is a workaround - under Win98 the first column
563  //can't be right aligned.
564  mList->InsertColumn(BlankColumn, wxT(""), wxLIST_FORMAT_LEFT);
565  /* i18n-hint: This is the number of the command in the list */
566  mList->InsertColumn(ItemNumberColumn, _("Num"), wxLIST_FORMAT_RIGHT);
567  mList->InsertColumn(ActionColumn, _("Command "), wxLIST_FORMAT_RIGHT);
568  mList->InsertColumn(ParamsColumn, _("Parameters"), wxLIST_FORMAT_LEFT);
569 
570  S.StartHorizontalLay(wxCENTER, false);
571  {
572  S.Id(InsertButtonID).AddButton(_("&Insert"), wxALIGN_LEFT);
573  S.Id(DeleteButtonID).AddButton(_("De&lete"), wxALIGN_LEFT);
574  S.Id(UpButtonID).AddButton(_("Move &Up"), wxALIGN_LEFT);
575  S.Id(DownButtonID).AddButton(_("Move &Down"), wxALIGN_LEFT);
576  mDefaults = S.Id(DefaultsButtonID).AddButton(_("De&faults"));
577  }
578  S.EndHorizontalLay();
579  }
580  S.EndStatic();
581  }
582  S.EndHorizontalLay();
583 
584  S.AddStandardButtons();
585 
586  return;
587 }
588 
591 {
592  wxArrayString names = mBatchCommands.GetNames();
593  int i;
594 
595  mChains->DeleteAllItems();
596  for (i = 0; i < (int)names.GetCount(); i++) {
597  mChains->InsertItem(i, names[i]);
598  }
599 
600  int item = mChains->FindItem(-1, mActiveChain);
601  if (item == -1) {
602  item = 0;
603  mActiveChain = mChains->GetItemText(0);
604  }
605 
606  // Select the name in the list...this will fire an event.
607  mChains->SetItemState(item, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
608 }
609 
612 {
613  mList->DeleteAllItems();
614 
615  for (int i = 0; i < mBatchCommands.GetCount(); i++) {
618  }
619  /*i18n-hint: This is the last item in a list.*/
620  AddItem(_("- END -"), wxT(""));
621 
622  // Select the name in the list...this will fire an event.
623  if (mSelectedCommand >= (int)mList->GetItemCount()) {
624  mSelectedCommand = 0;
625  }
626  mList->SetItemState(mSelectedCommand, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
627 }
628 
630 void EditChainsDialog::AddItem(const wxString &Action, const wxString &Params)
631 {
632  // Translate internal command name to a friendly form
633  auto item = make_iterator_range(mCommandNames).index_if(
634  [&](const CommandName &name){ return Action == name.second; }
635  );
636  auto friendlyName = item >= 0
637  ? // wxGetTranslation
638  ( mCommandNames[item].first )
639  : Action;
640 
641  int i = mList->GetItemCount();
642 
643  mList->InsertItem(i, wxT(""));
644  mList->SetItem(i, ItemNumberColumn, wxString::Format(wxT(" %02i"), i + 1));
645  mList->SetItem(i, ActionColumn, friendlyName );
646  mList->SetItem(i, ParamsColumn, Params );
647 }
648 
650 {
651  if (mChanged) {
652  wxString title;
653  wxString msg;
654  int id;
655 
656  title.Printf(_("%s changed"), mActiveChain);
657  msg = _("Do you want to save the changes?");
658 
659  id = AudacityMessageBox(msg, title, wxYES_NO | wxCANCEL);
660  if (id == wxCANCEL) {
661  return false;
662  }
663 
664  if (id == wxYES) {
666  return false;
667  }
668  }
669 
670  mChanged = false;
671  }
672 
673  return true;
674 }
676 void EditChainsDialog::OnChainSelected(wxListEvent & event)
677 {
678  if (!ChangeOK()) {
679  event.Veto();
680  return;
681  }
682 
683  int item = event.GetIndex();
684 
685  mActiveChain = mChains->GetItemText(item);
687 
689  mRemove->Disable();
690  mRename->Disable();
691  mDefaults->Enable();
692  }
693  else {
694  mRemove->Enable();
695  mRename->Enable();
696  mDefaults->Disable();
697  }
698 
699  PopulateList();
700 }
701 
703 void EditChainsDialog::OnListSelected(wxListEvent & WXUNUSED(event))
704 {
705  FitColumns();
706 }
707 
709 void EditChainsDialog::OnSize(wxSizeEvent & WXUNUSED(event))
710 {
711  // Refrsh the layout and re-fit the columns.
712  Layout();
713  FitColumns();
714 }
715 
717 {
718  mList->SetColumnWidth(0, 0); // First column width is zero, to hide it.
719 
720 #if defined(__WXMAC__)
721  // wxMac uses a hard coded width of 150 when wxLIST_AUTOSIZE_USEHEADER
722  // is specified, so we calculate the width ourselves. This method may
723  // work equally well on other platforms.
724  for (size_t c = 1; c < mList->GetColumnCount(); c++) {
725  wxListItem info;
726  int width;
727 
728  mList->SetColumnWidth(c, wxLIST_AUTOSIZE);
729  info.Clear();
730  info.SetId(c);
731  info.SetMask(wxLIST_MASK_TEXT | wxLIST_MASK_WIDTH);
732  mList->GetColumn(c, info);
733 
734  mList->GetTextExtent(info.GetText(), &width, NULL);
735  width += 2 * 4; // 2 * kItemPadding - see listctrl_mac.cpp
736  width += 16; // kIconWidth - see listctrl_mac.cpp
737 
738  mList->SetColumnWidth(c, wxMax(width, mList->GetColumnWidth(c)));
739  }
740 
741  // Looks strange, but it forces the horizontal scrollbar to get
742  // drawn. If not done, strange column sizing can occur if the
743  // user attempts to resize the columns.
744  mList->SetClientSize(mList->GetClientSize());
745 #else
746  mList->SetColumnWidth(1, wxLIST_AUTOSIZE_USEHEADER);
747  mList->SetColumnWidth(2, wxLIST_AUTOSIZE_USEHEADER);
748  mList->SetColumnWidth(3, wxLIST_AUTOSIZE);
749 #endif
750 
751  int bestfit = mList->GetColumnWidth(3);
752  int clientsize = mList->GetClientSize().GetWidth();
753  int col1 = mList->GetColumnWidth(1);
754  int col2 = mList->GetColumnWidth(2);
755  bestfit = (bestfit > clientsize-col1-col2)? bestfit : clientsize-col1-col2;
756  mList->SetColumnWidth(3, bestfit);
757 
758 }
759 
761 void EditChainsDialog::OnChainsBeginEdit(wxListEvent &event)
762 {
763  int itemNo = event.GetIndex();
764 
765  wxString chain = mChains->GetItemText(itemNo);
766 
768  wxBell();
769  event.Veto();
770  }
771 }
772 
774 void EditChainsDialog::OnChainsEndEdit(wxListEvent &event)
775 {
776  if (event.IsEditCancelled()) {
777  return;
778  }
779 
780  wxString newname = event.GetLabel();
781 
783 
784  mActiveChain = newname;
785 
786  PopulateChains();
787 }
788 
790 void EditChainsDialog::OnAdd(wxCommandEvent & WXUNUSED(event))
791 {
792  while (true) {
794  _("Enter name of new chain"),
795  _("Name of new chain"));
796  d.SetName(d.GetTitle());
797  wxString name;
798 
799  if (d.ShowModal() == wxID_CANCEL) {
800  return;
801  }
802 
803  name = d.GetValue().Strip(wxString::both);
804 
805  if (name.Length() == 0) {
806  AudacityMessageBox(_("Name must not be blank"),
807  GetTitle(),
808  wxOK | wxICON_ERROR,
809  this);
810  continue;
811  }
812 
813  if (name.Contains(wxFILE_SEP_PATH) ||
814  name.Contains(wxFILE_SEP_PATH_UNIX)) {
815  /*i18n-hint: The %c will be replaced with 'forbidden characters', like '/' and '\'.*/
816  AudacityMessageBox(wxString::Format(_("Names may not contain '%c' and '%c'"),
817  wxFILE_SEP_PATH, wxFILE_SEP_PATH_UNIX),
818  GetTitle(),
819  wxOK | wxICON_ERROR,
820  this);
821  continue;
822  }
823 
824  mBatchCommands.AddChain(name);
825 
826  mActiveChain = name;
827 
828  PopulateChains();
829 
830  break;
831  }
832 }
833 
835 void EditChainsDialog::OnRemove(wxCommandEvent & WXUNUSED(event))
836 {
837  long item = mChains->GetNextItem(-1,
838  wxLIST_NEXT_ALL,
839  wxLIST_STATE_SELECTED);
840  if (item == -1) {
841  return;
842  }
843 
844  wxString name = mChains->GetItemText(item);
845  AudacityMessageDialog m(this,
846  /*i18n-hint: %s will be replaced by the name of a file.*/
847  wxString::Format(_("Are you sure you want to delete %s?"), name),
848  GetTitle(),
849  wxYES_NO | wxICON_QUESTION);
850  if (m.ShowModal() == wxID_NO) {
851  return;
852  }
853 
855 
856  if (item >= (mChains->GetItemCount() - 1) && item >= 0) {
857  item--;
858  }
859 
860  mActiveChain = mChains->GetItemText(item);
861 
862  PopulateChains();
863 }
864 
866 void EditChainsDialog::OnRename(wxCommandEvent & WXUNUSED(event))
867 {
868  long item = mChains->GetNextItem(-1,
869  wxLIST_NEXT_ALL,
870  wxLIST_STATE_SELECTED);
871  if (item == -1) {
872  return;
873  }
874 
875  mChains->EditLabel(item);
876 }
877 
880 void EditChainsDialog::OnCommandActivated(wxListEvent &event)
881 {
882  int item = event.GetIndex();
883 
884  BatchCommandDialog d(this, wxID_ANY);
886  mBatchCommands.GetParams(item));
887 
888  if (!d.ShowModal()) {
889  return;
890  }
891 
895  item);
896 
897  mChanged = true;
898 
899  mSelectedCommand = item;
900 
901  PopulateList();
902 }
903 
905 void EditChainsDialog::OnInsert(wxCommandEvent & WXUNUSED(event))
906 {
907  long item = mList->GetNextItem(-1,
908  wxLIST_NEXT_ALL,
909  wxLIST_STATE_SELECTED);
910  if (item == -1) {
911  return;
912  }
913 
914  BatchCommandDialog d(this, wxID_ANY);
915 
916  if (!d.ShowModal()) {
917  return;
918  }
919 
920  if(d.mSelectedCommand != wxT(""))
921  {
924  item);
925  mChanged = true;
926 
927  mSelectedCommand = item + 1;
928 
929  PopulateList();
930  }
931 }
932 
934 void EditChainsDialog::OnDelete(wxCommandEvent & WXUNUSED(event))
935 {
936  long item = mList->GetNextItem(-1,
937  wxLIST_NEXT_ALL,
938  wxLIST_STATE_SELECTED);
939  if (item == -1 || item + 1 == mList->GetItemCount()) {
940  return;
941  }
942 
944 
945  mChanged = true;
946 
947  if (item >= (mList->GetItemCount() - 2) && item >= 0) {
948  item--;
949  }
950 
951  mSelectedCommand = item;
952 
953  PopulateList();
954 }
955 
957 void EditChainsDialog::OnUp(wxCommandEvent & WXUNUSED(event))
958 {
959  long item = mList->GetNextItem(-1,
960  wxLIST_NEXT_ALL,
961  wxLIST_STATE_SELECTED);
962  if (item == -1 || item == 0 || item + 1 == mList->GetItemCount()) {
963  return;
964  }
965 
968  item - 1);
970 
971  mChanged = true;
972 
973  mSelectedCommand = item - 1;
974 
975  PopulateList();
976 }
977 
979 void EditChainsDialog::OnDown(wxCommandEvent & WXUNUSED(event))
980 {
981  long item = mList->GetNextItem(-1,
982  wxLIST_NEXT_ALL,
983  wxLIST_STATE_SELECTED);
984  if (item == -1 || item + 2 >= mList->GetItemCount()) {
985  return;
986  }
987 
990  item + 2);
992 
993  mChanged = true;
994 
995  mSelectedCommand = item + 1;
996 
997  PopulateList();
998 }
999 
1001 void EditChainsDialog::OnDefaults(wxCommandEvent & WXUNUSED(event))
1002 {
1004 
1005  mChanged = true;
1006 
1007  PopulateList();
1008 }
1009 
1011 void EditChainsDialog::OnOK(wxCommandEvent & WXUNUSED(event))
1012 {
1013  gPrefs->Write(wxT("/Batch/ActiveChain"), mActiveChain);
1014  gPrefs->Flush();
1015 
1016  if (mChanged) {
1018  return;
1019  }
1020  }
1021 
1022  EndModal(true);
1023 }
1024 
1026 void EditChainsDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
1027 {
1028  if (!ChangeOK()) {
1029  return;
1030  }
1031 
1032  EndModal(false);
1033 }
1034 
1036 void EditChainsDialog::OnKeyDown(wxKeyEvent &event)
1037 {
1038  if (event.GetKeyCode() == WXK_DELETE) {
1039  wxLogDebug(wxT("wxKeyEvent"));
1040  }
1041 
1042  event.Skip();
1043 }
bool ReadChain(const wxString &chain)
void OnChainsEndEdit(wxListEvent &event)
void PopulateList()
This clears and updates the contents of mList.
static wxString FindDefaultPath(Operation op)
Definition: FileNames.cpp:384
wxString GetCommand(int index)
static wxArrayString names()
Definition: Tags.cpp:697
EditChainsDialog(wxWindow *parent)
Constructor.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:366
Abstract base class used in importing a file.
Definition: Import.h:32
void OnCancel(wxCommandEvent &event)
void SetCommandAndParams(const wxString &Command, const wxString &Params)
void AddItem(const wxString &command, wxString const &params)
Add one item into mList.
std::pair< wxString, wxString > CommandName
#define ChainsListID
void OnDefaults(wxCommandEvent &event)
Select the empty Command chain.
#define CommandsListID
void AddToChain(const wxString &command, int before=-1)
void OnUp(wxCommandEvent &event)
CommandNameVector mCommandNames
void OnListSelected(wxListEvent &event)
An item in the chains list has been selected.
void PopulateOrExchange(ShuttleGui &S)
Defines the dialog and does data exchange with it.
void OnDown(wxCommandEvent &event)
bool WriteChain(const wxString &chain)
int AudacityMessageBox(const wxString &message, const wxString &caption=AudacityMessageBoxCaptionStr(), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: ErrorDialog.h:92
void Populate()
Creates the dialog and its contents.
void OnInsert(wxCommandEvent &event)
void ClearStates()
bool RenameChain(const wxString &oldchain, const wxString &newchain)
Definition: ErrorDialog.h:105
Shows progress in executing commands in BatchCommands.
void OnAdd(wxCommandEvent &event)
void OnSize(wxSizeEvent &event)
The window has been resized.
void OnApplyToFiles(wxCommandEvent &event)
#define safenew
Definition: Audacity.h:223
void EndHorizontalLay()
Definition: ShuttleGui.cpp:975
wxButton * mRemove
List of commands in current command chain.
void GetSupportedImportFormats(FormatList *formatList)
Definition: Import.cpp:124
Provides a list of configurable commands for use with BatchCommands.
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:161
void EndVerticalLay()
Definition: ShuttleGui.cpp:991
wxString GetParams(int index)
#define ApplyToFilesID
void OnChainsBeginEdit(wxListEvent &event)
bool GetIsEmpty()
Definition: Project.cpp:1485
wxFileConfig * gPrefs
Definition: Prefs.cpp:72
void ZoomAfterImport(Track *pTrack)
Definition: Project.cpp:4230
int format
Definition: ExportPCM.cpp:56
bool Import(const wxString &fileName, WaveTrackArray *pTrackArray=NULL)
Definition: Project.cpp:4242
static wxArrayString GetNames()
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:966
void OnRename(wxCommandEvent &event)
wxListCtrl * AddListControlReportMode()
Definition: ShuttleGui.cpp:627
static CommandNameVector GetAllCommands()
BatchCommands mBatchCommands
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:1058
ShuttleGui & Id(int id)
void SetStyle(int Style)
Definition: ShuttleGui.h:252
wxListCtrl * mList
List of chains.
void OnKeyDown(wxKeyEvent &event)
void OnRemove(wxCommandEvent &event)
bool DeleteChain(const wxString &name)
void AddFixedText(const wxString &Str, bool bCenter=false)
Definition: ShuttleGui.cpp:356
#define ApplyToProjectID
EVT_LIST_ITEM_ACTIVATED(wxID_ANY, SuccessDialog::OnItemActivated) ExportMultiple
bool ApplyChain(const wxString &filename=wxT(""))
BatchCommands mBatchCommands
void OnDelete(const CommandContext &)
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
void OnDelete(wxCommandEvent &event)
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
void PopulateOrExchange(ShuttleGui &S)
Defines the dialog and does data exchange with it.
void OnApplyToProject(wxCommandEvent &event)
const wxChar * name
Definition: Distortion.cpp:94
void OnOK(wxCommandEvent &event)
Send changed values back to Prefs, and update Audacity.
void OnSelectAll(const CommandContext &)
Definition: Menus.cpp:6012
UndoManager * GetUndoManager()
Definition: Project.h:180
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:302
void DeleteFromChain(int index)
wxStaticBox * StartStatic(const wxString &Str, int iProp=0)
Definition: ShuttleGui.cpp:701
bool IsFixed(const wxString &name)
wxArrayString formatExtensions
Definition: Import.h:35
Works with HistoryWindow to provide the Undo functionality.
Definition: UndoManager.h:93
wxString mActiveChain
Provides list of available commands.
void PopulateChains()
This clears and updates the contents of mChains.
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxButton *extra=NULL)
END_EVENT_TABLE()
void RestoreChain(const wxString &name)
void OnRemoveTracks(const CommandContext &)
Definition: Menus.cpp:8301
static Importer & Get()
Definition: Import.cpp:72
void SetBorder(int Border)
Definition: ShuttleGui.h:251
bool AddChain(const wxString &chain)
void OnCommandActivated(wxListEvent &event)
wxButton * AddButton(const wxString &Text, int PositionFlags=wxALIGN_CENTRE)
Definition: ShuttleGui.cpp:301
void OnCancel(wxCommandEvent &event)
std::vector< Format > FormatList
Definition: Import.h:46
wxString formatName
Definition: Import.h:34
EVT_LIST_ITEM_SELECTED(CurvesListID, EditCurvesDialog::OnListSelectionChange) EVT_LIST_ITEM_DESELECTED(CurvesListID
Constructor.
void OnChainSelected(wxListEvent &event)
An item in the chains list has been selected.
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:982