Audacity 3.2.0
HelpMenus.cpp
Go to the documentation of this file.
1
2#include <wx/app.h>
3#include <wx/bmpbuttn.h>
4#include <wx/textctrl.h>
5#include <wx/frame.h>
6
7#include "../AboutDialog.h"
8#include "AllThemeResources.h"
9#include "AudioIOBase.h"
10#include "../CommonCommandFlags.h"
11#include "../CrashReport.h" // for HAS_CRASH_REPORT
12#include "FileNames.h"
13#include "../HelpText.h"
14#include "../HelpUtilities.h"
15#include "../LogWindow.h"
16#include "../Menus.h"
17#include "../NoteTrack.h"
18#include "Prefs.h"
19#include "Project.h"
20#include "../ProjectSelectionManager.h"
21#include "../ProjectWindows.h"
22#include "../SelectFile.h"
23#include "../ShuttleGui.h"
24#include "../SplashDialog.h"
25#include "Theme.h"
26#include "../commands/CommandContext.h"
27#include "../commands/CommandManager.h"
28#include "../prefs/PrefsDialog.h"
29#include "../widgets/AudacityMessageBox.h"
30#include "../widgets/HelpSystem.h"
31
33
34#if defined(HAVE_UPDATES_CHECK)
36#endif
37
38#ifdef HAS_AUDIOCOM_UPLOAD
40#endif
41
42// private helper classes and functions
43namespace
44{
45
54{
55public:
56 using PrefSetter = std::function< void() > ;
57
58 QuickFixDialog(wxWindow * pParent, AudacityProject &project);
59 void Populate();
60 void PopulateOrExchange(ShuttleGui & S);
61 void AddStuck( ShuttleGui & S, bool & bBool,
62 const PrefSetter &prefSetter,
63 const TranslatableString &Prompt, const ManualPageID &Help );
64
65 void OnOk(wxCommandEvent &event);
66 void OnCancel(wxCommandEvent &event);
67 void OnHelp(const ManualPageID &Str);
68 void OnFix(const PrefSetter &setter, wxWindowID id);
69
71
72 int mItem;
76 DECLARE_EVENT_TABLE()
77};
78
79
80#define FixButtonID 7001
81#define HelpButtonID 7011
82
83BEGIN_EVENT_TABLE(QuickFixDialog, wxDialogWrapper)
84 EVT_BUTTON(wxID_OK, QuickFixDialog::OnOk)
85 EVT_BUTTON(wxID_CANCEL, QuickFixDialog::OnCancel)
87
88QuickFixDialog::QuickFixDialog(wxWindow * pParent, AudacityProject &project) :
89 wxDialogWrapper(pParent, wxID_ANY, XO("Do you have these problems?"),
90 wxDefaultPosition, wxDefaultSize,
91 wxDEFAULT_DIALOG_STYLE )
92 , mProject{ project }
93{
94 const long SNAP_OFF = 0;
95
96 gPrefs->Read(wxT("/GUI/SyncLockTracks"), &mbSyncLocked, false);
97 mbInSnapTo = gPrefs->Read(wxT("/SnapTo"), SNAP_OFF) !=0;
98 gPrefs->Read(wxT("/AudioIO/SoundActivatedRecord"), &mbSoundActivated, false);
99
100 ShuttleGui S(this, eIsCreating);
101 PopulateOrExchange(S);
102
103 Fit();
104 auto sz = GetSize();
105 SetMinSize( sz );
106 SetMaxSize( sz );
107
108 // The close button has the cancel id and acts exactly the same as cancel.
109 wxButton * pWin = (wxButton*)FindWindowById( wxID_CANCEL );
110 if( pWin )
111 pWin->SetFocus( );
112 Center();
113}
114
115void QuickFixDialog::AddStuck( ShuttleGui & S, bool & bBool,
116 const PrefSetter &prefSetter,
117 const TranslatableString &Prompt, const ManualPageID &Help )
118{
119 mItem++;
120 wxWindowID id = FixButtonID + mItem;
121 if( !bBool)
122 return;
123
124 S
125 .AddFixedText( Prompt );
126
127 S
128 .Id( id )
129 .AddButton( XXO("Fix") )
130 ->Bind( wxEVT_BUTTON, [this, prefSetter, id](wxCommandEvent&){
131 OnFix( prefSetter, id );
132 } );
133
134 {
135 // Replace standard Help button with smaller icon button.
136 // bs->AddButton(safenew wxButton(parent, wxID_HELP));
137 auto b = safenew wxBitmapButton(S.GetParent(), HelpButtonID+mItem, theTheme.Bitmap( bmpHelpIcon ));
138 b->SetToolTip( _("Help") );
139 b->SetLabel(_("Help")); // for screen readers
140 b->Bind( wxEVT_BUTTON, [this, Help](const wxCommandEvent&){
141 OnHelp( Help );
142 } );
143 S.AddWindow( b );
144 }
145}
146
147void QuickFixDialog::PopulateOrExchange(ShuttleGui & S)
148{
149
150 S.StartVerticalLay(1);
151 S.StartStatic( XO("Quick Fixes"));
152
153 // These aren't all possible modes one can be stuck in, but they are some of them.
154 bool bStuckInMode = mbSyncLocked || mbInSnapTo || mbSoundActivated;
155
156 if( !bStuckInMode ){
157 SetLabel(XO("Nothing to do"));
158 S.AddFixedText(XO("No quick, easily fixed problems were found"));
159 }
160 else {
161 S.StartMultiColumn(3, wxALIGN_CENTER);
162 {
163 mItem = -1;
164
165 auto defaultAction =
166 [](AudacityProject *pProject, const wxString &path){ return
167 [pProject, path]{
168 gPrefs->Write(path, 0);
169 gPrefs->Flush();
170 // This is overkill (aka slow), as all preferences are
171 // reloaded and all
172 // toolbars recreated.
173 // Overkill probably doesn't matter, as this command is
174 // infrequently used.
175 DoReloadPreferences( *pProject );
176 };
177 };
178
179 // Use # in the URLs to ensure we go to the online version of help.
180 // Local help may well not be installed.
181 auto pProject = &mProject;
182 AddStuck( S, mbSyncLocked,
183 defaultAction( pProject, "/GUI/SyncLockTracks" ),
184 XO("Clocks on the Tracks"), "Quick_Fix#sync_lock" );
185 AddStuck( S, mbInSnapTo,
186 [pProject] {
187 gPrefs->Write( "/SnapTo", 0 );
188 gPrefs->Flush();
189 // Sadly SnapTo has to be handled specially,
190 // as it is not part of the standard
191 // preference dialogs.
193 },
194 XO("Can't select precisely"), "Quick_Fix#snap_to" );
195 AddStuck( S, mbSoundActivated,
196 defaultAction( pProject, "/AudioIO/SoundActivatedRecord" ),
197 XO("Recording stops and starts"),
198 "Quick_Fix#sound_activated_recording" );
199 }
200 S.EndMultiColumn();
201 }
202 S.EndStatic();
203
204 S.StartHorizontalLay(wxALIGN_CENTER_HORIZONTAL, 0);
205 S.AddStandardButtons(eCloseButton + (bStuckInMode ? 0 : eHelpButton));
206 S.EndHorizontalLay();
207
208 S.EndVerticalLay();
209
210 wxButton * pBtn = (wxButton*)FindWindowById( wxID_HELP );
211 if( pBtn )
212 pBtn->Bind( wxEVT_BUTTON, [this]( const wxCommandEvent & ){
213 OnHelp( "Quick_Fix#" );
214 } );
215}
216
217void QuickFixDialog::OnOk(wxCommandEvent &event)
218{
219 (void)event;// Compiler food
220 EndModal(wxID_OK);
221}
222
223void QuickFixDialog::OnCancel(wxCommandEvent &event)
224{
225 (void)event;// Compiler food
226 EndModal(wxID_CANCEL);
227}
228
229void QuickFixDialog::OnHelp(const ManualPageID &Str)
230{
231 HelpSystem::ShowHelp(this, Str, true);
232}
233
234void QuickFixDialog::OnFix(const PrefSetter &setter, wxWindowID id)
235{
236 if ( setter )
237 setter();
238
239 // Change the label after doing the fix, as the fix may take a second or two.
240 auto pBtn = FindWindow(id);
241 if( pBtn )
242 pBtn->SetLabel( _("Fixed") );
243
244 // The close button has the cancel id and acts exactly the same as cancel.
245 wxButton * pWin = (wxButton*)FindWindowById( wxID_CANCEL );
246 if( pWin )
247 pWin->SetFocus( );
248}
249
250}
251
252namespace HelpActions {
253
254// exported helper functions
255
256// Menu handler functions
257
259
260void OnQuickFix(const CommandContext &context)
261{
262 auto &project = context.project;
263 QuickFixDialog dlg( &GetProjectFrame( project ), project );
264 dlg.ShowModal();
265}
266
267void OnQuickHelp(const CommandContext &context)
268{
269 auto &project = context.project;
271 &GetProjectFrame( project ),
272 L"Quick_Help");
273}
274
275void OnManual(const CommandContext &context)
276{
277 auto &project = context.project;
279 &GetProjectFrame( project ),
280 L"Main_Page");
281}
282
284{
285 auto &project = context.project;
286 auto gAudioIO = AudioIOBase::Get();
287 wxString info = gAudioIO->GetDeviceInfo();
288 ShowDiagnostics( project, info,
289 XO("Audio Device Info"), wxT("deviceinfo.txt") );
290}
291
292void OnShowLog( const CommandContext &context )
293{
295}
296
297#if defined(HAS_CRASH_REPORT)
298void OnCrashReport(const CommandContext &WXUNUSED(context) )
299{
300// Change to "1" to test a real crash
301#if 0
302 char *p = 0;
303 *p = 1234;
304#endif
305 CrashReport::Generate(wxDebugReport::Context_Current);
306}
307#endif
308
309#ifdef IS_ALPHA
310void OnSegfault(const CommandContext &)
311{
312 unsigned *p = nullptr;
313 *p = 0xDEADBEEF;
314}
315
316void OnException(const CommandContext &)
317{
318 // Throw an exception that can be caught only as (...)
319 // The intent is to exercise detection of unhandled exceptions by the
320 // crash reporter
321 struct Unique{};
322 throw Unique{};
323}
324
325void OnAssertion(const CommandContext &)
326{
327 // We don't use assert() much directly, but Breakpad does detect it
328 // This may crash the program only in debug builds
329 // See also wxSetAssertHandler, and wxApp::OnAssertFailure()
330 assert(false);
331}
332#endif
333
334void OnMenuTree(const CommandContext &context)
335{
336 auto &project = context.project;
337
338 using namespace MenuTable;
339 struct MyVisitor : ToolbarMenuVisitor
340 {
342
343 enum : unsigned { TAB = 3 };
344 void DoBeginGroup( GroupItem &item, const Path& ) override
345 {
346 if ( dynamic_cast<MenuItem*>( &item ) ) {
347 Indent();
348 // using GET for alpha only diagnostic tool
349 info += item.name.GET();
350 Return();
351 indentation = wxString{ ' ', TAB * ++level };
352 }
353 }
354
355 void DoEndGroup( GroupItem &item, const Path& ) override
356 {
357 if ( dynamic_cast<MenuItem*>( &item ) )
358 indentation = wxString{ ' ', TAB * --level };
359 }
360
361 void DoVisit( SingleItem &item, const Path& ) override
362 {
363 // using GET for alpha only diagnostic tool
364 Indent();
365 info += item.name.GET();
366 Return();
367 }
368
369 void DoSeparator() override
370 {
371 static const wxString separatorName{ '=', 20 };
372 Indent();
373 info += separatorName;
374 Return();
375 }
376
377 void Indent() { info += indentation; }
378 void Return() { info += '\n'; }
379
380 unsigned level{};
381 wxString indentation;
382 wxString info;
383 } visitor{ project };
384
385 MenuManager::Visit( visitor );
386
387 ShowDiagnostics( project, visitor.info,
388 Verbatim("Menu Tree"), wxT("menutree.txt"), true );
389}
390
392{
394}
395
396#if defined(HAVE_UPDATES_CHECK)
397void OnCheckForUpdates(const CommandContext &WXUNUSED(context))
398{
400}
401#endif
402
403#ifdef HAS_AUDIOCOM_UPLOAD
404void OnLinkAccount(const CommandContext&)
405{
407 dialog.ShowModal();
408}
409#endif
410
411void OnAbout(const CommandContext &context)
412{
413#ifdef __WXMAC__
414 // Modeless dialog, consistent with other Mac applications
415 // Simulate the application Exit menu item
416 wxCommandEvent evt{ wxEVT_MENU, wxID_ABOUT };
417 wxTheApp->AddPendingEvent( evt );
418#else
419 auto &project = context.project;
420 auto &window = GetProjectFrame( project );
421
422 // Windows and Linux still modal.
423 AboutDialog dlog( &window );
424 dlog.ShowModal();
425#endif
426}
427
428#if 0
429// Legacy handlers, not used as of version 2.3.0
430
431// Only does the update checks if it's an ALPHA build and not disabled by
432// preferences.
433void MayCheckForUpdates(AudacityProject &project)
434{
435#ifdef IS_ALPHA
436 OnCheckForUpdates(project);
437#endif
438}
439
440void OnHelpWelcome(const CommandContext &context)
441{
443}
444
445#endif
446
447}; // struct Handler
448
449} // namespace
450
452 // Handler is not stateful. Doesn't need a factory registered with
453 // AudacityProject.
454 static HelpActions::Handler instance;
455 return instance;
456};
457
458// Menu definitions
459
460#define FN(X) (& HelpActions::Handler :: X)
461
462namespace {
463using namespace MenuTable;
465{
466 static BaseItemSharedPtr menu{
468 Menu( wxT("Help"), XXO("&Help"),
469 Section( "Basic",
470 // QuickFix menu item not in Audacity 2.3.1 whilst we discuss further.
471 #ifdef EXPERIMENTAL_DA
472 // DA: Has QuickFix menu item.
473 Command( wxT("QuickFix"), XXO("&Quick Fix..."), FN(OnQuickFix),
475 // DA: 'Getting Started' rather than 'Quick Help'.
476 Command( wxT("QuickHelp"), XXO("&Getting Started"), FN(OnQuickHelp),
478 // DA: Emphasise it is the Audacity Manual (No separate DA manual).
479 Command( wxT("Manual"), XXO("Audacity &Manual"), FN(OnManual),
481
482 #else
483 Command( wxT("QuickHelp"), XXO("&Quick Help..."), FN(OnQuickHelp),
485 Command( wxT("Manual"), XXO("&Manual..."), FN(OnManual),
487 #endif
488 ),
489
490 #ifdef __WXMAC__
491 Items
492 #else
493 Section
494 #endif
495 ( "Other",
496 Menu( wxT("Diagnostics"), XXO("&Diagnostics"),
497 Command( wxT("DeviceInfo"), XXO("Au&dio Device Info..."),
498 FN(OnAudioDeviceInfo),
500 Command( wxT("Log"), XXO("Show &Log..."), FN(OnShowLog),
502 #if defined(HAS_CRASH_REPORT)
503 Command( wxT("CrashReport"), XXO("&Generate Support Data..."),
504 FN(OnCrashReport), AlwaysEnabledFlag )
505 #endif
506
507 #ifdef IS_ALPHA
508 ,
509 // alpha-only items don't need to internationalize, so use
510 // Verbatim for labels
511
512 Command( wxT("RaiseSegfault"), Verbatim("Test segfault report"),
513 FN(OnSegfault), AlwaysEnabledFlag ),
514
515 Command( wxT("ThrowException"), Verbatim("Test exception report"),
516 FN(OnException), AlwaysEnabledFlag ),
517
518 Command( wxT("ViolateAssertion"), Verbatim("Test assertion report"),
519 FN(OnAssertion), AlwaysEnabledFlag ),
520
521 // Menu explorer. Perhaps this should become a macro command
522 Command( wxT("MenuTree"), Verbatim("Menu Tree..."),
523 FN(OnMenuTree),
525
526 Command(
527 wxT("FrameStatistics"), Verbatim("Frame Statistics..."),
528 FN(OnFrameStatistics),
530 #endif
531 )
532 #ifndef __WXMAC__
533 ),
534
535 Section( "",
536#else
537 ,
538#endif
539#ifdef HAS_AUDIOCOM_UPLOAD
540 Command(
541 wxT("LinkAccount"), XXO("L&ink audio.com account..."),
542 FN(OnLinkAccount), AlwaysEnabledFlag),
543#endif
544 // DA: Does not fully support update checking.
545 #if !defined(EXPERIMENTAL_DA) && defined(HAVE_UPDATES_CHECK)
546 Command( wxT("Updates"), XXO("&Check for Updates..."),
547 FN(OnCheckForUpdates),
549 #endif
550 Command( wxT("About"), XXO("&About Audacity"), FN(OnAbout),
552 )
553 ) ) };
554 return menu;
555}
556
558 wxT(""),
559 Shared( HelpMenu() )
560};
561
562}
563
564#undef FN
wxT("CloseDown"))
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:35
wxEvtHandler CommandHandlerObject
const ReservedCommandFlag & AudioIONotBusyFlag()
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
static CommandHandlerObject & findCommandHandler(AudacityProject &)
Definition: HelpMenus.cpp:451
#define HelpButtonID
Definition: HelpMenus.cpp:81
#define FixButtonID
Definition: HelpMenus.cpp:80
#define FN(X)
Definition: HelpMenus.cpp:460
void ShowDiagnostics(AudacityProject &project, const wxString &info, const TranslatableString &description, const wxString &defaultPath, bool fixedWidth)
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
#define _(s)
Definition: Internat.h:75
#define safenew
Definition: MemoryX.h:10
FileConfig * gPrefs
Definition: Prefs.cpp:71
void DoReloadPreferences(AudacityProject &project)
@ SNAP_OFF
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 ...
@ eIsCreating
Definition: ShuttleGui.h:39
@ eCloseButton
Definition: ShuttleGui.h:607
@ eHelpButton
Definition: ShuttleGui.h:601
THEME_API Theme theTheme
Definition: Theme.cpp:82
#define S(N)
Definition: ToChars.cpp:64
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Declare a class that handles managing of updates.
The AboutDialog shows the program version and developer credits.
Definition: AboutDialog.h:32
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
static AudioIOBase * Get()
Definition: AudioIOBase.cpp:91
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
static void Show(bool show)
Shows the dialog.
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:239
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 void Show(bool show=true)
Show or hide the unique logging window; create it on demand the first time it is shown.
Definition: LogWindow.cpp:61
static void Visit(ToolbarMenuVisitor &visitor)
Definition: Menus.cpp:435
void AS_SetSnapTo(int snap) override
static ProjectSelectionManager & Get(AudacityProject &project)
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
static void DoHelpWelcome(AudacityProject &project)
wxBitmap & Bitmap(int iIndex)
Holds a msgid for the translation catalog; may also bind format arguments.
void GetUpdates(bool ignoreNetworkErrors, bool configurableNotification)
static UpdateManager & GetInstance()
Class which makes a dialog for displaying quick fixes to common issues.
Definition: HelpMenus.cpp:54
std::unique_ptr< MenuItem > Menu(const Identifier &internalName, const TranslatableString &title, Args &&... args)
std::unique_ptr< MenuPart > Section(const Identifier &internalName, Args &&... args)
std::unique_ptr< MenuItems > Items(const Identifier &internalName, Args &&... args)
std::unique_ptr< CommandItem > Command(const CommandID &name, const TranslatableString &label_in, void(Handler::*pmf)(const CommandContext &), CommandFlag flags, const CommandManager::Options &options={}, CommandHandlerFinder finder=FinderScope::DefaultFinder())
std::shared_ptr< BaseItem > BaseItemSharedPtr
Definition: Registry.h:72
filesystem::path Path
void OnMenuTree(const CommandContext &context)
Definition: HelpMenus.cpp:334
void OnFrameStatistics(const CommandContext &)
Definition: HelpMenus.cpp:391
void OnManual(const CommandContext &context)
Definition: HelpMenus.cpp:275
void OnShowLog(const CommandContext &context)
Definition: HelpMenus.cpp:292
void OnQuickHelp(const CommandContext &context)
Definition: HelpMenus.cpp:267
void OnAudioDeviceInfo(const CommandContext &context)
Definition: HelpMenus.cpp:283
void OnAbout(const CommandContext &context)
Definition: HelpMenus.cpp:411
void OnQuickFix(const CommandContext &context)
Definition: HelpMenus.cpp:260
const Identifier name
Definition: Registry.h:67
ToolbarMenuVisitor(AudacityProject &p)