Audacity  3.0.3
KeyConfigPrefs.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  KeyConfigPrefs.cpp
6 
7  Brian Gunlogson
8  Dominic Mazzoni
9  James Crook
10 
11 *******************************************************************//*********************************************************************/
21 
22 
23 
24 #include "KeyConfigPrefs.h"
25 
26 #include <wx/setup.h> // for wxUSE_* macros
27 #include <wx/defs.h>
28 #include <wx/ffile.h>
29 #include <wx/intl.h>
30 #include <wx/menu.h>
31 #include <wx/button.h>
32 #include <wx/radiobut.h>
33 #include <wx/stattext.h>
34 #include <wx/statbox.h>
35 #include <wx/textctrl.h>
36 
37 #include "ActiveProject.h"
38 #include "Prefs.h"
39 #include "Project.h"
40 #include "../ProjectWindows.h"
41 #include "../commands/CommandManager.h"
42 #include "XMLFileReader.h"
43 
44 #include "../SelectFile.h"
45 #include "../ShuttleGui.h"
46 
47 #include "FileNames.h"
48 
49 #include "../widgets/BasicMenu.h"
50 #include "../widgets/KeyView.h"
51 #include "../widgets/AudacityMessageBox.h"
52 #include "../widgets/wxWidgetsWindowPlacement.h"
53 
54 #if wxUSE_ACCESSIBILITY
55 #include "../widgets/WindowAccessible.h"
56 #endif
57 
58 //
59 // KeyConfigPrefs
60 //
61 #define AssignDefaultsButtonID 17001
62 #define CurrentComboID 17002
63 #define SetButtonID 17003
64 #define ClearButtonID 17004
65 #define CommandsListID 17005
66 #define ExportButtonID 17006
67 #define ImportButtonID 17007
68 #define FilterID 17008
69 #define ViewByTreeID 17009
70 #define ViewByNameID 17010
71 #define ViewByKeyID 17011
72 #define FilterTimerID 17012
73 
74 // EMPTY_SHORTCUT means "user chose to have no shortcut"
75 #define EMPTY_SHORTCUT ("")
76 // NO_SHORTCUT means "user made no choice"
77 #define NO_SHORTCUT (wxString)((wxChar)7)
78 
79 BEGIN_EVENT_TABLE(KeyConfigPrefs, PrefsPanel)
86  EVT_RADIOBUTTON(ViewByTreeID, KeyConfigPrefs::OnViewBy)
87  EVT_RADIOBUTTON(ViewByNameID, KeyConfigPrefs::OnViewBy)
88  EVT_RADIOBUTTON(ViewByKeyID, KeyConfigPrefs::OnViewBy)
91 
93  wxWindow * parent, wxWindowID winid, AudacityProject *pProject,
94  const CommandID &name)
95 /* i18n-hint: as in computer keyboard (not musical!) */
96 : PrefsPanel(parent, winid, XO("Keyboard")),
97  mView(NULL),
98  mKey(NULL),
99  mFilter(NULL),
100  mFilterTimer(this, FilterTimerID),
101  mFilterPending(false)
102  , mProject{ pProject }
103 {
104  Populate();
105  if (!name.empty()) {
106  auto index = mView->GetIndexByName(name);
107  mView->SelectNode(index);
108  }
109 
110  // See bug #2315 for discussion. This should be reviewed
111  // and (possibly) removed after wx3.1.3.
112  Bind(wxEVT_SHOW, &KeyConfigPrefs::OnShow, this);
113 }
114 
116 {
118 }
119 
121 {
122  return XO("Preferences for KeyConfig");
123 }
124 
126 {
127  return "Keyboard_Preferences";
128 }
129 
131 {
133 
134  if (!mProject) {
135  S.StartVerticalLay(true);
136  {
137  S.StartStatic( {}, true);
138  {
139  S.AddTitle(XO("Keyboard preferences currently unavailable."));
140  S.AddTitle(XO("Open a new project to modify keyboard shortcuts."));
141  }
142  S.EndStatic();
143  }
144  S.EndVerticalLay();
145 
146  return;
147  }
148 
150 
151  mCommandSelected = wxNOT_FOUND;
152 
154 
155  // For speed, don't sort here. We're just creating.
156  // Instead sort when we do SetView later in this function.
157  RefreshBindings(false);
158 
159  if (mViewByTree->GetValue()) {
161  }
162  else if (mViewByName->GetValue()) {
164  }
165  else if (mViewByKey->GetValue()) {
167  mFilterLabel->SetLabel(_("&Hotkey:"));
168  mFilter->SetName(wxStripMenuCodes(mFilterLabel->GetLabel()));
169  }
170 
172 }
173 
179 {
180  S.SetBorder(2);
181 
182  S.StartStatic(XO("Key Bindings"), 1);
183  {
184  S.StartHorizontalLay(wxEXPAND, 0);
185  {
186  S.Position(wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL).AddTitle(XO("View by:"));
187 
188  // Bug 2692: Place button group in panel so tabbing will work and,
189  // on the Mac, VoiceOver will announce as radio buttons.
190  S.StartPanel();
191  {
192  S.StartHorizontalLay();
193  {
195  wxT("/Prefs/KeyConfig/ViewBy"),
196  {
197  { wxT("tree"), XXO("&Tree") },
198  { wxT("name"), XXO("&Name") },
199  { wxT("key"), XXO("&Key") },
200  },
201  0 // tree
202  });
203  {
205  .Name(XO("View by tree"))
206  .TieRadioButton();
208  .Name(XO("View by name"))
209  .TieRadioButton();
211  .Name(XO("View by key"))
212  .TieRadioButton();
213 #if !defined(__WXMAC__) && wxUSE_ACCESSIBILITY
214  // so that name can be set on a standard control
218 #endif
219  }
221  }
222  S.EndHorizontalLay();
223  }
224  S.EndPanel();
225 
226  S.AddSpace(wxDefaultCoord, wxDefaultCoord, 1);
227 
228  S.StartHorizontalLay(wxALIGN_CENTER_VERTICAL, 0);
229  {
230  mFilterLabel = S.Position(wxALIGN_CENTER_VERTICAL).AddVariableText(XO("Searc&h:"));
231 
232  if (!mFilter) {
233  mFilter = safenew wxTextCtrl(S.GetParent(),
234  FilterID,
235  wxT(""),
236  wxDefaultPosition,
237 #if defined(__WXMAC__)
238  wxSize(300, -1),
239 #else
240  wxSize(210, -1),
241 #endif
242  wxTE_PROCESS_ENTER);
243  mFilter->SetName(wxStripMenuCodes(mFilterLabel->GetLabel()));
244  }
245  S.Position(wxALIGN_NOT | wxALIGN_LEFT)
246  .ConnectRoot(wxEVT_KEY_DOWN,
248  .ConnectRoot(wxEVT_CHAR,
250  .AddWindow(mFilter);
251  }
252  S.EndHorizontalLay();
253  }
254  S.EndHorizontalLay();
255 
256  S.AddSpace(wxDefaultCoord, 2);
257 
258  S.StartHorizontalLay(wxEXPAND, 1);
259  {
260  if (!mView) {
262  mView->SetName(_("Bindings"));
263  }
264  S.Prop(true)
265  .Position(wxEXPAND)
266  .AddWindow(mView);
267  }
268  S.EndHorizontalLay();
269 
270  S.StartThreeColumn();
271  {
272  if (!mKey) {
273  mKey = safenew wxTextCtrl(S.GetParent(),
275  wxT(""),
276  wxDefaultPosition,
277 #if defined(__WXMAC__)
278  wxSize(300, -1),
279 #else
280  wxSize(210, -1),
281 #endif
282  wxTE_PROCESS_ENTER);
283 #if !defined(__WXMAC__) && wxUSE_ACCESSIBILITY
284  // so that name can be set on a standard control
285  mKey->SetAccessible(safenew WindowAccessible(mKey));
286 #endif
287  mKey->SetName(_("Short cut"));
288  }
289  S
290  .ConnectRoot(wxEVT_KEY_DOWN,
292  .ConnectRoot(wxEVT_CHAR,
294  .ConnectRoot(wxEVT_KILL_FOCUS,
296  .ConnectRoot(wxEVT_CONTEXT_MENU,
298  .AddWindow(mKey);
299 
300  /* i18n-hint: (verb)*/
301  mSet = S.Id(SetButtonID).AddButton(XXO("&Set"));
302  /* i18n-hint: (verb)*/
303  mClear = S.Id(ClearButtonID).AddButton(XXO("Cl&ear"));
304  }
305  S.EndThreeColumn();
306 
307 #if defined(__WXMAC__)
308  S.AddFixedText(XO("Note: Pressing Cmd+Q will quit. All other keys are valid."));
309 #endif
310 
311  S.StartThreeColumn();
312  {
313  S.Id(ImportButtonID).AddButton(XXO("&Import..."));
314  S.Id(ExportButtonID).AddButton(XXO("&Export..."));
315  S.Id(AssignDefaultsButtonID).AddButton(XXO("&Defaults"));
316  }
317  S.EndThreeColumn();
318  }
319  S.EndStatic();
320 
321 
322  // Need to layout so that the KeyView is properly sized before populating.
323  // Otherwise, the initial selection is not scrolled into view.
324  Layout();
325 }
326 
328 {
329  TranslatableStrings Labels;
330  TranslatableStrings Categories;
331  TranslatableStrings Prefixes;
332 
333  mNames.clear();
334  mKeys.clear();
335  mDefaultKeys.clear();
336  mStandardDefaultKeys.clear();
338  mNames,
339  mKeys,
340  mDefaultKeys,
341  Labels,
342  Categories,
343  Prefixes,
344  true); // True to include effects (list items), false otherwise.
345 
348 
350  Categories,
351  Prefixes,
352  Labels,
353  mKeys,
354  bSort);
355  //Not needed as NEW nodes are already shown expanded.
356  //mView->ExpandAll();
357 
358  mNewKeys = mKeys;
359 }
360 
361 // RefreshKeyInfo is used to update mKeys vector only
362 // Introduced for efficiency purposes to avoid unnecessary usage of RefreshBinding
364 {
365  mKeys.clear();
366 
367  for (const auto & name : mNames)
368  mKeys.push_back(mManager->GetKeyFromName(name));
369 }
370 
371 // Removes all shortcuts
372 // Doesn't call RefreshBindings()
374 {
375  const NormalizedKeyString noKey{ NO_SHORTCUT };
376  for (const auto & command : mNames)
377  mManager->SetKeyFromName(command, noKey);
378 }
379 
380 // Checks if the given vector of keys contains illegal duplicates.
381 // In case it does, stores the prefixed labels of operations
382 // with illegal key duplicates in fMatching and sMatching.
383 // Search for duplicates fully implemented here
384 // to avoid possible problems with legal shortcut duplicates.
386  TranslatableString & fMatching, TranslatableString & sMatching) const
387 {
388  using IndexesArray = std::vector<int>;
389  std::unordered_map<NormalizedKeyString, IndexesArray> seen;
390 
391  for (size_t i{ 0 }; i < mKeys.size(); i++)
392  {
393  if (mKeys[i] == EMPTY_SHORTCUT || mKeys[i] == NO_SHORTCUT)
394  continue;
395 
396  if (seen.count(mKeys[i]) == 0)
397  seen.insert({ mKeys[i], {(int)i} });
398  else
399  {
400  IndexesArray checkMe{ seen.at(mKeys[i]) };
401  for (int index : checkMe)
402  {
403  if (mDefaultKeys[i] == EMPTY_SHORTCUT ||
404  mDefaultKeys[i] != mDefaultKeys[index])
405  {
406  fMatching = mManager->GetPrefixedLabelFromName(mNames[i]);
407  sMatching = mManager->GetPrefixedLabelFromName(mNames[index]);
408  return true;
409  }
410  else
411  seen.at(mKeys[i]).push_back(index);
412  }
413  }
414  }
415  return false;
416 }
417 
418 
419 // This function tries to add the given shortcuts(keys) "toAdd"
420 // to the already existing shortcuts(keys). Shortcuts are added only if
421 // 1. the shortcut for the operation isn't defined already
422 // 2. the added shortcut doesn't create illegal shortcut duplicate
423 // The names of operations for which the second condition was violated
424 // are returned in a single error message
426  const std::vector<NormalizedKeyString> &toAdd)
427 {
428  TranslatableString disabledShortcuts;
429 
430  auto searchAddInKeys = [&](size_t index)
431  {
432  for (size_t k{ 0 }; k < toAdd.size(); k++)
433  if (k == index)
434  continue;
435  else if (toAdd[index] == mKeys[k] &&
436  (mDefaultKeys[k] == EMPTY_SHORTCUT ||
437  mDefaultKeys[k] != mDefaultKeys[index]))
438  return (int)k;
439 
440  return -1;
441  };
442 
443  const NormalizedKeyString noKey{ EMPTY_SHORTCUT };
444 
445  for (size_t i{ 0 }; i < toAdd.size(); i++)
446  {
447  if (mKeys[i] != NO_SHORTCUT)
448  continue;
449  else if (toAdd[i] == EMPTY_SHORTCUT)
450  mManager->SetKeyFromIndex(i, noKey);
451  else
452  {
453  int sRes{ searchAddInKeys(i) };
454 
455  if (sRes == -1)
456  mManager->SetKeyFromIndex(i, toAdd[i]);
457  else
458  {
460 
461  disabledShortcuts +=
462  XO(
463 "\n * \"%s\" (because the shortcut \'%s\' is used by \"%s\")\n")
464  .Format(
466  name,
468 
469  mManager->SetKeyFromIndex(i, noKey);
470  }
471  }
472  }
473 
474  return disabledShortcuts;
475 }
476 
477 // See bug #2315 for discussion. This should be reviewed
478 // and (possibly) removed after wx3.1.3.
479 void KeyConfigPrefs::OnShow(wxShowEvent & event)
480 {
481  event.Skip();
482 
483  // This is required to prevent a crash if Preferences
484  // were opened without a project.
485  if (event.IsShown() && mView != nullptr)
486  {
487  mView->Refresh();
488  }
489 }
490 
491 void KeyConfigPrefs::OnImport(wxCommandEvent & WXUNUSED(event))
492 {
493  wxString file = wxT("Audacity-keys.xml");
494 
495  file = SelectFile(FileNames::Operation::Open,
496  XO("Select an XML file containing Audacity keyboard shortcuts..."),
497  wxEmptyString,
498  file,
499  wxT(""),
501  wxRESIZE_BORDER,
502  this);
503 
504  if (!file) {
505  return;
506  }
507 
508  // this RefreshKeyInfo is here to account for
509  // potential OnSet() function executions before importing
510  RefreshKeyInfo();
511 
512  // saving pre-import settings
513  const std::vector<NormalizedKeyString> oldKeys{ mKeys };
514 
515  // clearing all pre-import settings
516  ClearAllKeys();
517 
518  // getting new settings
519  XMLFileReader reader;
520  if (!reader.Parse(mManager, file)) {
522  reader.GetErrorStr(),
523  XO("Error Importing Keyboard Shortcuts"),
524  wxOK | wxCENTRE,
525  this);
526  }
527 
528  RefreshKeyInfo();
529 
530  // checking new setting for duplicates
531  // if there are duplicates, throwing error and returning to pre-import state
532  TranslatableString fMatching;
533  TranslatableString sMatching;
534 
535  if (ContainsIllegalDups(fMatching, sMatching))
536  {
537  // restore the old pre-import hotkeys stored in oldKeys
538  for (size_t k{ 0 }; k < mNames.size(); k++)
539  mManager->SetKeyFromName(mNames[k], oldKeys[k]);
540  mKeys = oldKeys;
541 
542  // output an error message
544  XO(
545 "The file with the shortcuts contains illegal shortcut duplicates for \"%s\" and \"%s\".\nNothing is imported.")
546  .Format( fMatching, sMatching ),
547  XO("Error Importing Keyboard Shortcuts"),
548  wxICON_ERROR | wxCENTRE, this);
549 
550  // stop the function
551  return;
552  }
553 
554  // adding possible old settings to the new settings and recording the conflicting ones
555  TranslatableString disabledShortcuts{ MergeWithExistingKeys(oldKeys) };
556 
557  RefreshBindings(true);
558 
559  TranslatableString message{
560  XO("Loaded %d keyboard shortcuts\n").Format(mManager->GetNumberOfKeysRead()) };
561 
562  if (disabledShortcuts.Translation() != (""))
563  message += XO("\nThe following commands are not mentioned in the imported file, "
564  "but have their shortcuts removed because of the conflict with other new shortcuts:\n") +
565  disabledShortcuts;
566 
567  AudacityMessageBox(message, XO("Loading Keyboard Shortcuts"), wxOK | wxCENTRE);
568 }
569 
570 void KeyConfigPrefs::OnExport(wxCommandEvent & WXUNUSED(event))
571 {
572  wxString file = wxT("Audacity-keys.xml");
573 
574  file = SelectFile(FileNames::Operation::Export,
575  XO("Export Keyboard Shortcuts As:"),
576  wxEmptyString,
577  file,
578  wxT("xml"),
580  wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
581  this);
582 
583  if (!file) {
584  return;
585  }
586 
587  GuardedCall( [&] {
588  XMLFileWriter prefFile{ file, XO("Error Exporting Keyboard Shortcuts") };
589  mManager->WriteXML(prefFile);
590  prefFile.Commit();
591  } );
592 }
593 
594 
595 
596 // There currently is only one clickable AButton
597 // so we just do what it needs.
598 void KeyConfigPrefs::OnDefaults(wxCommandEvent & WXUNUSED(event))
599 {
600  wxMenu Menu;
601  Menu.Append( 1, _("Standard") );
602  Menu.Append( 2, _("Full") );
603  Menu.Bind( wxEVT_COMMAND_MENU_SELECTED, &KeyConfigPrefs::OnImportDefaults, this );
605 }
606 
607 void KeyConfigPrefs::FilterKeys( std::vector<NormalizedKeyString> & arr )
608 {
609  const auto &MaxListOnly = CommandManager::ExcludedList();
610 
611  // Remove items that are in MaxList.
612  for (size_t i = 0; i < arr.size(); i++) {
613  if( std::binary_search(MaxListOnly.begin(), MaxListOnly.end(), arr[i]) )
614  arr[i] = {};
615  }
616 }
617 
618 void KeyConfigPrefs::OnImportDefaults(wxCommandEvent & event)
619 {
620  gPrefs->DeleteEntry(wxT("/GUI/Shortcuts/FullDefaults"));
621  gPrefs->Flush();
622 
624  if( event.GetId() == 1 )
625  FilterKeys( mNewKeys );
626 
627  for (size_t i = 0; i < mNewKeys.size(); i++) {
629  }
630 
631  RefreshBindings(true);
632 }
633 
635 {
636  wxTextCtrl *t = (wxTextCtrl *)e.GetEventObject();
637 
638  // Make sure we can navigate away from the hotkey textctrl.
639  // On Linux and OSX, it can get stuck, but it doesn't hurt
640  // to do it for Windows as well.
641  //
642  // Mac note: Don't waste time trying to figure out why the
643  // focus goes back to the prefs tree. Unless Voiceover is
644  // active, buttons on the Mac do not accept focus and all the
645  // controls between this one and the tree control are buttons.
646  if (e.GetKeyCode() == WXK_TAB) {
647  t->Navigate(e.ShiftDown()
648  ? wxNavigationKeyEvent::IsBackward
649  : wxNavigationKeyEvent::IsForward);
650  return;
651  }
652 
653  t->SetValue(KeyEventToKeyString(e).Display());
654 }
655 
656 void KeyConfigPrefs::OnHotkeyChar(wxEvent & WXUNUSED(e))
657 {
658  // event.Skip() not performed, so event will not be processed further.
659 }
660 
662 {
663  if (mKey->GetValue().empty() && mCommandSelected != wxNOT_FOUND) {
664  mKey->AppendText(mView->GetKey(mCommandSelected).Display());
665  }
666 
667  e.Skip();
668 }
669 
670 void KeyConfigPrefs::OnHotkeyContext(wxEvent & WXUNUSED(e))
671 {
672  // event.Skip() not performed, so event will not be processed further.
673 }
674 
675 void KeyConfigPrefs::OnFilterTimer(wxTimerEvent & WXUNUSED(e))
676 {
677  // The filter timer has expired, so set the filter
678  if (mFilterPending)
679  {
680  // Do not reset mFilterPending here...possible race
681  mView->SetFilter(mFilter->GetValue());
682  }
683 }
684 
686 {
687  wxTextCtrl *t = (wxTextCtrl *)e.GetEventObject();
688  int keycode = e.GetKeyCode();
689 
690  // Make sure we can navigate away from the hotkey textctrl.
691  // On Linux and OSX, it an get stuck, but it doesn't hurt
692  // to do it for Windows as well.
693  if (keycode == WXK_TAB) {
694  wxNavigationKeyEvent nevent;
695  nevent.SetWindowChange(e.ControlDown());
696  nevent.SetDirection(!e.ShiftDown());
697  nevent.SetEventObject(t);
698  nevent.SetCurrentFocus(t);
699  t->GetParent()->GetEventHandler()->ProcessEvent(nevent);
700 
701  return;
702  }
703 
704  if (mViewType == ViewByKey) {
705  wxString key = KeyEventToKeyString(e).Display();
706  t->SetValue(key);
707 
708  if (!key.empty()) {
709  mView->SetFilter(t->GetValue());
710  }
711  }
712  else
713  {
714  if (keycode == WXK_RETURN) {
715  mFilterPending = false;
716  mView->SetFilter(t->GetValue());
717  }
718  else {
719  mFilterPending = true;
720  mFilterTimer.Start(500, wxTIMER_ONE_SHOT);
721 
722  e.Skip();
723  }
724  }
725 }
726 
728 {
729  if (mViewType != ViewByKey)
730  {
731  e.Skip();
732  }
733 }
734 
735 // Given a hotkey combination, returns the name (description) of the
736 // corresponding command, or the empty string if none is found.
738 {
739  return mView->GetNameByKey(key);
740 }
741 
742 // Sets the selected command to have this key
743 // This is not yet a committed change, which will happen on a save.
745 {
747 
749  {
751  XO("You may not assign a key to this entry"),
752  XO("Error"),
753  wxICON_ERROR | wxCENTRE,
754  this);
755  return;
756  }
757 
760  mNewKeys[ make_iterator_range( mNames ).index( name ) ] = key;
761 }
762 
763 
764 void KeyConfigPrefs::OnSet(wxCommandEvent & WXUNUSED(event))
765 {
766  if (mCommandSelected == wxNOT_FOUND) {
768  XO("You must select a binding before assigning a shortcut"),
769  XO("Error"),
770  wxICON_WARNING | wxCENTRE,
771  this);
772  return;
773  }
774 
775  CommandID newCommand{ mView->GetName(mCommandSelected) };
776  NormalizedKeyString enteredKey{ mKey->GetValue() };
777  NormalizedKeyString newComDefaultKey{
778  mManager->GetDefaultKeyFromName(newCommand) };
779  CommandIDs oldCommands;
780 
781  // collecting commands competing for the same shortcut
782  for (size_t i{ 0 }; i < mNames.size(); i++)
783  {
784  if (mNewKeys[i] == enteredKey)
785  {
786  // ignore the Set button if the same shortcut is used
787  if (mNames[i] == newCommand)
788  return;
789 
790  if (newComDefaultKey == EMPTY_SHORTCUT ||
791  mDefaultKeys[i] != newComDefaultKey)
792  {
793  oldCommands.push_back(mNames[i]);
794  }
795  }
796  }
797 
798  // Prevent same hotkey combination being used twice.
799  if (!oldCommands.empty()) {
800  auto newlabel = Verbatim( wxT("'%s - %s'") )
801  .Format(
802  mManager->GetCategoryFromName(newCommand),
803  mManager->GetPrefixedLabelFromName(newCommand) );
804  auto oldlabel = Verbatim(wxT("'%s - %s'"))
805  .Format(
806  mManager->GetCategoryFromName(oldCommands[0]),
807  mManager->GetPrefixedLabelFromName(oldCommands[0]));
808 
809  for (size_t i{ 1 }; i < oldCommands.size(); i++)
810  oldlabel += XO("\n\n\t and\n\n\t") +
811  Verbatim(wxT("'%s - %s'")).Format(
812  mManager->GetCategoryFromName(oldCommands[i]),
813  mManager->GetPrefixedLabelFromName(oldCommands[i]));
814 
815  if (wxCANCEL == AudacityMessageBox(
816  XO(
817 "The keyboard shortcut '%s' is already assigned to:\n\n\t%s\n\n\nClick OK to assign the shortcut to\n\n\t%s\n\ninstead. Otherwise, click Cancel.")
818  .Format(
819  mKey->GetValue(),
820  oldlabel,
821  newlabel
822  ),
823  XO("Warning"),
824  wxOK | wxCANCEL | wxICON_STOP | wxCENTRE,
825  this))
826  {
827  return;
828  }
829 
830  for (const auto & command : oldCommands)
831  {
832  mView->SetKeyByName(command, {});
833  mManager->SetKeyFromName(command, {});
834  mNewKeys[make_iterator_range(mNames).index(command)] = {};
835  }
836  }
837 
838  SetKeyForSelected(enteredKey);
839 }
840 
841 void KeyConfigPrefs::OnClear(wxCommandEvent& WXUNUSED(event))
842 {
843  mKey->Clear();
844 
845  if (mCommandSelected != wxNOT_FOUND) {
846  SetKeyForSelected({});
847  }
848 }
849 
850 void KeyConfigPrefs::OnSelected(wxCommandEvent & WXUNUSED(e))
851 {
853  mKey->Clear();
854 
855  if (mCommandSelected != wxNOT_FOUND) {
856  bool canset = mView->CanSetKey(mCommandSelected);
857  if (canset) {
858  mKey->AppendText(mView->GetKey(mCommandSelected).Display());
859  }
860 
861  mKey->Enable(canset);
862  mSet->Enable(canset);
863  mClear->Enable(canset);
864  }
865 }
866 
867 void KeyConfigPrefs::OnViewBy(wxCommandEvent & e)
868 {
869  switch (e.GetId())
870  {
871  case ViewByTreeID:
873  mFilterLabel->SetLabel(_("Searc&h:"));
874  break;
875 
876  case ViewByNameID:
878  mFilterLabel->SetLabel(_("Searc&h:"));
879  break;
880 
881  case ViewByKeyID:
883  mFilterLabel->SetLabel(_("&Hotkey:"));
884  break;
885  }
886 
888  mFilter->SetName(wxStripMenuCodes(mFilterLabel->GetLabel()));
889 }
890 
892 {
893  // On the Mac, preferences may be changed without any active
894  // projects. This means that the CommandManager isn't available
895  // either. So we can't attempt to save preferences, otherwise
896  // NULL ptr dereferences will happen in ShuttleGui because the
897  // radio buttons are never created. (See Populate() above.)
898  if ( !mProject ) {
899  return true;
900  }
901 
902  ShuttleGui S(this, eIsSavingToPrefs);
904 
905  bool bFull = gPrefs->ReadBool(wxT("/GUI/Shortcuts/FullDefaults"), false);
906  for (size_t i = 0; i < mNames.size(); i++) {
907  const auto &dkey = bFull ? mDefaultKeys[i] : mStandardDefaultKeys[i];
908  // using GET to interpret CommandID as a config path component
909  auto name = wxT("/NewKeys/") + mNames[i].GET();
910  const auto &key = mNewKeys[i];
911 
912  if (gPrefs->HasEntry(name)) {
913  if (key != NormalizedKeyString{ gPrefs->ReadObject(name, key) } ) {
914  gPrefs->Write(name, key);
915  }
916  if (key == dkey) {
918  }
919  }
920  else {
921  if (key != dkey) {
922  gPrefs->Write(name, key);
923  }
924  }
925  }
926 
927  return gPrefs->Flush();
928 }
929 
931 {
932  // Restore original key values
933  for (size_t i = 0; i < mNames.size(); i++) {
935  }
936 
937  return;
938 }
939 
942 {
943  return [=](wxWindow *parent, wxWindowID winid, AudacityProject *pProject)
944  {
945  wxASSERT(parent); // to justify safenew
946  auto result = safenew KeyConfigPrefs{ parent, winid, pProject, name };
947  return result;
948  };
949 }
950 namespace{
953 };
954 }
EVT_BUTTON
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
ShuttleGuiBase::StartRadioButtonGroup
void StartRadioButtonGroup(const ChoiceSetting &Setting)
Call this before any TieRadioButton calls.
Definition: ShuttleGui.cpp:1595
CommandManager::GetAllCommandData
void GetAllCommandData(CommandIDs &names, std::vector< NormalizedKeyString > &keys, std::vector< NormalizedKeyString > &default_keys, TranslatableStrings &labels, TranslatableStrings &categories, bool includeMultis)
Definition: CommandManager.cpp:1445
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
KeyConfigPrefs::OnDefaults
void OnDefaults(wxCommandEvent &e)
Definition: KeyConfigPrefs.cpp:598
CommandManager::SetKeyFromIndex
void SetKeyFromIndex(int i, const NormalizedKeyString &key)
Definition: CommandManager.cpp:1044
TranslatableString::empty
bool empty() const
Definition: TranslatableString.h:72
ImportButtonID
#define ImportButtonID
Definition: KeyConfigPrefs.cpp:67
ShuttleGuiBase::EndRadioButtonGroup
void EndRadioButtonGroup()
Definition: ShuttleGui.cpp:1612
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1184
KeyView::RefreshBindings
void RefreshBindings(const CommandIDs &names, const TranslatableStrings &categories, const TranslatableStrings &prefixes, const TranslatableStrings &labels, const std::vector< NormalizedKeyString > &keys, bool bSort)
Definition: KeyView.cpp:636
KeyConfigPrefs::mStandardDefaultKeys
std::vector< NormalizedKeyString > mStandardDefaultKeys
Definition: KeyConfigPrefs.h:103
GuardedCall
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), std::function< void(AudacityException *)> delayedHandler=DefaultDelayedHandlerAction{})
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
Definition: AudacityException.h:202
KeyConfigPrefs::NameFromKey
CommandID NameFromKey(const NormalizedKeyString &key)
Definition: KeyConfigPrefs.cpp:737
make_iterator_range
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:551
KeyConfigPrefs::OnShow
void OnShow(wxShowEvent &e)
Definition: KeyConfigPrefs.cpp:479
NormalizedKeyString::Display
wxString Display(bool usesSpecialChars=false) const
Definition: Keyboard.cpp:56
KeyConfigPrefs::OnHotkeyKillFocus
void OnHotkeyKillFocus(wxEvent &e)
Definition: KeyConfigPrefs.cpp:661
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Definition: AudacityMessageBox.cpp:17
KeyConfigPrefs::ContainsIllegalDups
bool ContainsIllegalDups(TranslatableString &fMatching, TranslatableString &sMatching) const
Definition: KeyConfigPrefs.cpp:385
ShuttleGuiBase::EndThreeColumn
void EndThreeColumn()
Definition: ShuttleGui.h:369
ExportButtonID
#define ExportButtonID
Definition: KeyConfigPrefs.cpp:66
ShuttleGuiBase::AddTitle
void AddTitle(const TranslatableString &Prompt, int wrapWidth=0)
Centred text string.
Definition: ShuttleGui.cpp:281
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
KeyConfigPrefs::OnExport
void OnExport(wxCommandEvent &e)
Definition: KeyConfigPrefs.cpp:570
TranslatableStrings
std::vector< TranslatableString > TranslatableStrings
Definition: TranslatableString.h:295
Project.h
KeyView::GetName
wxString GetName() const override
Definition: KeyView.cpp:194
FileConfig::HasEntry
virtual bool HasEntry(const wxString &strName) const wxOVERRIDE
Definition: FileConfig.cpp:138
SelectFile
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
Definition: SelectFile.cpp:17
KeyConfigPrefs::Populate
void Populate()
Definition: KeyConfigPrefs.cpp:130
KeyConfigPrefs::mFilterPending
bool mFilterPending
Definition: KeyConfigPrefs.h:89
Format
Abstract base class used in importing a file.
KeyConfigPrefs::OnFilterTimer
void OnFilterTimer(wxTimerEvent &e)
Definition: KeyConfigPrefs.cpp:675
CommandManager::GetPrefixedLabelFromName
TranslatableString GetPrefixedLabelFromName(const CommandID &name)
Definition: CommandManager.cpp:1492
KeyConfigPrefs::OnViewBy
void OnViewBy(wxCommandEvent &e)
Definition: KeyConfigPrefs.cpp:867
ShuttleGui::AddSpace
wxSizerItem * AddSpace(int width, int height, int prop=0)
Definition: ShuttleGui.cpp:2459
KeyConfigPrefs::GetDescription
TranslatableString GetDescription() override
Definition: KeyConfigPrefs.cpp:120
KeyConfigPrefs::mNames
CommandIDs mNames
Definition: KeyConfigPrefs.h:101
PrefsPanel::Registration
Definition: PrefsPanel.h:84
FileConfig::DeleteEntry
virtual bool DeleteEntry(const wxString &key, bool bDeleteGroupIfEmpty=true) wxOVERRIDE
Definition: FileConfig.cpp:209
XO
#define XO(s)
Definition: Internat.h:31
FileNames::XMLFiles
FILES_API const FileType XMLFiles
Definition: FileNames.h:74
CommandManager::ExcludedList
static const std::vector< NormalizedKeyString > & ExcludedList()
Definition: CommandManager.cpp:253
PrefsPanel::Factory
std::function< PrefsPanel *(wxWindow *parent, wxWindowID winid, AudacityProject *) > Factory
Definition: PrefsPanel.h:79
FilterID
#define FilterID
Definition: KeyConfigPrefs.cpp:68
CommandManager::GetCategoryFromName
TranslatableString GetCategoryFromName(const CommandID &name)
Definition: CommandManager.cpp:1506
KeyConfigPrefs::mFilterLabel
wxStaticText * mFilterLabel
Definition: KeyConfigPrefs.h:87
KeyView::GetSelected
int GetSelected() const
Definition: KeyView.cpp:185
KeyConfigPrefs::OnSelected
void OnSelected(wxCommandEvent &e)
Definition: KeyConfigPrefs.cpp:850
FileNames::AllFiles
FILES_API const FileType AllFiles
Definition: FileNames.h:71
KeyConfigPrefs::mNewKeys
std::vector< NormalizedKeyString > mNewKeys
Definition: KeyConfigPrefs.h:105
CommandManager::GetNumberOfKeysRead
int GetNumberOfKeysRead() const
Definition: CommandManager.cpp:1011
KeyConfigPrefs::OnImport
void OnImport(wxCommandEvent &e)
Definition: KeyConfigPrefs.cpp:491
KeyView::SetKey
bool SetKey(int index, const NormalizedKeyString &key)
Definition: KeyView.cpp:355
ShuttleGuiBase::StartPanel
wxPanel * StartPanel(int iStyle=0)
Definition: ShuttleGui.cpp:990
KeyConfigPrefs::mProject
AudacityProject * mProject
Definition: KeyConfigPrefs.h:96
ShuttleGuiBase::EndPanel
void EndPanel()
Definition: ShuttleGui.cpp:1018
KeyConfigPrefs::Commit
bool Commit() override
Definition: KeyConfigPrefs.cpp:891
KEY_CONFIG_PREFS_PLUGIN_SYMBOL
#define KEY_CONFIG_PREFS_PLUGIN_SYMBOL
Definition: KeyConfigPrefs.h:30
ComponentInterfaceSymbol
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Definition: ComponentInterfaceSymbol.h:27
KeyConfigPrefs::mKey
wxTextCtrl * mKey
Definition: KeyConfigPrefs.h:82
KeyConfigPrefs::ClearAllKeys
void ClearAllKeys()
Definition: KeyConfigPrefs.cpp:373
ShuttleGui::Id
ShuttleGui & Id(int id)
Definition: ShuttleGui.cpp:2274
wxWidgetsWindowPlacement
Window placement information for wxWidgetsBasicUI can be constructed from a wxWindow pointer.
Definition: wxWidgetsWindowPlacement.h:22
KeyView::SetKeyByName
bool SetKeyByName(const CommandID &name, const NormalizedKeyString &key)
Definition: KeyView.cpp:396
XMLFileReader::Parse
bool Parse(XMLTagHandler *baseHandler, const FilePath &fname)
Definition: XMLFileReader.cpp:42
KeyConfigPrefs::FilterKeys
void FilterKeys(std::vector< NormalizedKeyString > &arr)
Definition: KeyConfigPrefs.cpp:607
ViewByKeyID
#define ViewByKeyID
Definition: KeyConfigPrefs.cpp:71
SetButtonID
#define SetButtonID
Definition: KeyConfigPrefs.cpp:63
KeyConfigPrefs::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S) override
Definition: KeyConfigPrefs.cpp:178
CommandIDs
std::vector< CommandID > CommandIDs
Definition: Identifier.h:233
CommandsListID
#define CommandsListID
Definition: KeyConfigPrefs.cpp:65
XXO
#define XXO(s)
Definition: Internat.h:44
KeyConfigPrefs::GetSymbol
ComponentInterfaceSymbol GetSymbol() override
Definition: KeyConfigPrefs.cpp:115
ShuttleGuiBase::EndHorizontalLay
void EndHorizontalLay()
Definition: ShuttleGui.cpp:1177
XMLFileReader::GetErrorStr
const TranslatableString & GetErrorStr() const
Definition: XMLFileReader.cpp:178
anonymous_namespace{KeyConfigPrefs.cpp}::sAttachment
PrefsPanel::Registration sAttachment
Definition: KeyConfigPrefs.cpp:951
KeyConfigPrefs::HelpPageName
ManualPageID HelpPageName() override
If not empty string, the Help button is added below the panel.
Definition: KeyConfigPrefs.cpp:125
KeyConfigPrefs::mViewByTree
wxRadioButton * mViewByTree
Definition: KeyConfigPrefs.h:92
ShuttleGuiBase::StartHorizontalLay
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:1167
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1203
CommandManager::GetKeyFromName
NormalizedKeyString GetKeyFromName(const CommandID &name) const
Definition: CommandManager.cpp:1515
CurrentComboID
#define CurrentComboID
Definition: KeyConfigPrefs.cpp:62
ShuttleGuiBase::AddFixedText
void AddFixedText(const TranslatableString &Str, bool bCenter=false, int wrapWidth=0)
Definition: ShuttleGui.cpp:440
ViewByKey
@ ViewByKey
Definition: KeyView.h:64
KeyConfigPrefsFactory
PrefsPanel::Factory KeyConfigPrefsFactory(const CommandID &name)
Definition: KeyConfigPrefs.cpp:941
KeyConfigPrefs::Cancel
void Cancel() override
Definition: KeyConfigPrefs.cpp:930
name
const TranslatableString name
Definition: Distortion.cpp:98
KeyConfigPrefs::OnClear
void OnClear(wxCommandEvent &e)
Definition: KeyConfigPrefs.cpp:841
KeyView::GetKey
NormalizedKeyString GetKey(int index) const
Definition: KeyView.cpp:322
ShuttleGuiBase::GetParent
wxWindow * GetParent()
Definition: ShuttleGui.h:496
KeyView::GetNameByKey
CommandID GetNameByKey(const NormalizedKeyString &key) const
Definition: KeyView.cpp:282
ShuttleGuiBase::AddWindow
wxWindow * AddWindow(wxWindow *pWindow, int PositionFlags=wxALIGN_CENTRE)
Definition: ShuttleGui.cpp:299
WindowAccessible
An alternative to using wxWindowAccessible, which in wxWidgets 3.1.1 contained GetParent() which was ...
ViewByTree
@ ViewByTree
Definition: KeyView.h:62
KeyConfigPrefs::mViewByName
wxRadioButton * mViewByName
Definition: KeyConfigPrefs.h:93
ShuttleGuiBase::StartThreeColumn
void StartThreeColumn()
Definition: ShuttleGui.h:368
KeyConfigPrefs::OnFilterKeyDown
void OnFilterKeyDown(wxKeyEvent &e)
Definition: KeyConfigPrefs.cpp:685
XMLFileReader.h
KeyConfigPrefs::mFilter
wxTextCtrl * mFilter
Definition: KeyConfigPrefs.h:86
KeyConfigPrefs::mView
KeyView * mView
Definition: KeyConfigPrefs.h:81
NO_SHORTCUT
#define NO_SHORTCUT
Definition: KeyConfigPrefs.cpp:77
ShuttleGui::Prop
ShuttleGui & Prop(int iProp)
Definition: ShuttleGui.h:725
ShuttleGuiBase::AddButton
wxButton * AddButton(const TranslatableString &Text, int PositionFlags=wxALIGN_CENTRE, bool setDefault=false)
Definition: ShuttleGui.cpp:360
Identifier::GET
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
NormalizedKeyString
Definition: Keyboard.h:24
CommandManager::SetKeyFromName
void SetKeyFromName(const CommandID &name, const NormalizedKeyString &key)
Definition: CommandManager.cpp:1035
KeyConfigPrefs
A PrefsPanel for keybindings.
Definition: KeyConfigPrefs.h:33
ShuttleGuiBase::StartStatic
wxStaticBox * StartStatic(const TranslatableString &Str, int iProp=0)
Definition: ShuttleGui.cpp:893
eIsSavingToPrefs
@ eIsSavingToPrefs
Definition: ShuttleGui.h:48
ViewByName
@ ViewByName
Definition: KeyView.h:63
KeyConfigPrefs::RefreshKeyInfo
void RefreshKeyInfo()
Definition: KeyConfigPrefs.cpp:363
ShuttleGui::Name
ShuttleGui & Name(const TranslatableString &name)
Definition: ShuttleGui.h:663
KeyConfigPrefs::mCommandSelected
int mCommandSelected
Definition: KeyConfigPrefs.h:99
CommandManager::WriteXML
void WriteXML(XMLWriter &xmlFile) const
Definition: CommandManager.cpp:1586
CommandManager::GetDefaultKeyFromName
NormalizedKeyString GetDefaultKeyFromName(const CommandID &name)
Definition: CommandManager.cpp:1526
KeyConfigPrefs::mKeys
std::vector< NormalizedKeyString > mKeys
Definition: KeyConfigPrefs.h:104
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
EMPTY_SHORTCUT
#define EMPTY_SHORTCUT
Definition: KeyConfigPrefs.cpp:75
key
static const AudacityProject::AttachedObjects::RegisteredFactory key
Definition: CommandManager.cpp:201
XMLFileReader
Reads a file and passes the results through an XMLTagHandler.
Definition: XMLFileReader.h:18
ShuttleGui::Position
ShuttleGui & Position(int flags)
Definition: ShuttleGui.h:712
KeyConfigPrefs::mDefaultKeys
std::vector< NormalizedKeyString > mDefaultKeys
Definition: KeyConfigPrefs.h:102
TaggedIdentifier< CommandIdTag, false >
KeyView::SetView
void SetView(ViewByType type)
Definition: KeyView.cpp:414
_
#define _(s)
Definition: Internat.h:75
ShuttleGui::ConnectRoot
auto ConnectRoot(wxEventTypeTag< Tag > eventType, void(Handler::*func)(Argument &)) -> typename std::enable_if< std::is_base_of< Argument, Tag >::value, ShuttleGui & >::type
Definition: ShuttleGui.h:699
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:92
KeyConfigPrefs::mClear
wxButton * mClear
Definition: KeyConfigPrefs.h:84
XMLFileWriter
Wrapper to output XML data to files.
Definition: XMLWriter.h:81
KeyConfigPrefs::mSet
wxButton * mSet
Definition: KeyConfigPrefs.h:83
KeyConfigPrefs::OnHotkeyChar
void OnHotkeyChar(wxEvent &e)
Definition: KeyConfigPrefs.cpp:656
FileNames.h
KeyConfigPrefs::OnSet
void OnSet(wxCommandEvent &e)
Definition: KeyConfigPrefs.cpp:764
FilterTimerID
#define FilterTimerID
Definition: KeyConfigPrefs.cpp:72
MenuTable::Menu
std::unique_ptr< MenuItem > Menu(const Identifier &internalName, const TranslatableString &title, Args &&... args)
Definition: CommandManager.h:623
Verbatim
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Definition: TranslatableString.h:321
ActiveProject.h
Handle changing of active project and keep global project pointer.
KeyView
Provides multiple views of keyboard shortcuts.
Definition: KeyView.h:73
KeyConfigPrefs::OnHotkeyContext
void OnHotkeyContext(wxEvent &e)
Definition: KeyConfigPrefs.cpp:670
KeyConfigPrefs::RefreshBindings
void RefreshBindings(bool bSort)
Definition: KeyConfigPrefs.cpp:327
KeyView::SetFilter
void SetFilter(const wxString &filter)
Definition: KeyView.cpp:472
ViewByTreeID
#define ViewByTreeID
Definition: KeyConfigPrefs.cpp:69
KeyEventToKeyString
NormalizedKeyString KeyEventToKeyString(const wxKeyEvent &event)
Definition: Keyboard.cpp:83
PrefsPanel
Base class for a panel in the PrefsDialog. Classes derived from this class include BatchPrefs,...
Definition: PrefsPanel.h:51
Prefs.h
KeyConfigPrefs::mViewByKey
wxRadioButton * mViewByKey
Definition: KeyConfigPrefs.h:94
ViewByNameID
#define ViewByNameID
Definition: KeyConfigPrefs.cpp:70
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:489
TranslatableString::Format
TranslatableString & Format(Args &&...args) &
Capture variadic format arguments (by copy) when there is no plural.
Definition: TranslatableString.h:103
eIsCreatingFromPrefs
@ eIsCreatingFromPrefs
Definition: ShuttleGui.h:47
ShuttleGuiBase::AddVariableText
wxStaticText * AddVariableText(const TranslatableString &Str, bool bCenter=false, int PositionFlags=0, int wrapWidth=0)
Definition: ShuttleGui.cpp:463
KeyConfigPrefs::OnFilterChar
void OnFilterChar(wxEvent &e)
Definition: KeyConfigPrefs.cpp:727
CommandManager::Get
static CommandManager & Get(AudacityProject &project)
Definition: CommandManager.cpp:207
ShuttleGuiBase::EndStatic
void EndStatic()
Definition: ShuttleGui.cpp:922
KeyConfigPrefs::MergeWithExistingKeys
TranslatableString MergeWithExistingKeys(const std::vector< NormalizedKeyString > &toAdd)
Definition: KeyConfigPrefs.cpp:425
safenew
#define safenew
Definition: MemoryX.h:10
KeyConfigPrefs::SetKeyForSelected
void SetKeyForSelected(const NormalizedKeyString &key)
Definition: KeyConfigPrefs.cpp:744
KeyView::CanSetKey
bool CanSetKey(int index) const
Definition: KeyView.cpp:338
BasicMenu::Handle::Popup
void Popup(const BasicUI::WindowPlacement &window, const Point &pos={})
Display the menu at pos, invoke at most one action, then hide it.
Definition: BasicMenu.cpp:207
END_EVENT_TABLE
END_EVENT_TABLE()
KeyConfigPrefs::mFilterTimer
wxTimer mFilterTimer
Definition: KeyConfigPrefs.h:88
ClearButtonID
#define ClearButtonID
Definition: KeyConfigPrefs.cpp:64
KeyConfigPrefs.h
KeyConfigPrefs::mManager
CommandManager * mManager
Definition: KeyConfigPrefs.h:98
AssignDefaultsButtonID
#define AssignDefaultsButtonID
Definition: KeyConfigPrefs.cpp:61
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:631
KeyConfigPrefs::OnImportDefaults
void OnImportDefaults(wxCommandEvent &e)
Definition: KeyConfigPrefs.cpp:618
BasicMenu::Handle
Definition: BasicMenu.h:26
KeyConfigPrefs::mViewType
ViewByType mViewType
Definition: KeyConfigPrefs.h:91
KeyConfigPrefs::OnHotkeyKeyDown
void OnHotkeyKeyDown(wxKeyEvent &e)
Definition: KeyConfigPrefs.cpp:634