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
32#if defined(HAVE_UPDATES_CHECK)
34#endif
35
36// private helper classes and functions
37namespace {
38
47{
48public:
49 using PrefSetter = std::function< void() > ;
50
51 QuickFixDialog(wxWindow * pParent, AudacityProject &project);
52 void Populate();
53 void PopulateOrExchange(ShuttleGui & S);
54 void AddStuck( ShuttleGui & S, bool & bBool,
55 const PrefSetter &prefSetter,
56 const TranslatableString &Prompt, const ManualPageID &Help );
57
58 void OnOk(wxCommandEvent &event);
59 void OnCancel(wxCommandEvent &event);
60 void OnHelp(const ManualPageID &Str);
61 void OnFix(const PrefSetter &setter, wxWindowID id);
62
64
65 int mItem;
69 DECLARE_EVENT_TABLE()
70};
71
72
73#define FixButtonID 7001
74#define HelpButtonID 7011
75
76BEGIN_EVENT_TABLE(QuickFixDialog, wxDialogWrapper)
77 EVT_BUTTON(wxID_OK, QuickFixDialog::OnOk)
78 EVT_BUTTON(wxID_CANCEL, QuickFixDialog::OnCancel)
80
81QuickFixDialog::QuickFixDialog(wxWindow * pParent, AudacityProject &project) :
82 wxDialogWrapper(pParent, wxID_ANY, XO("Do you have these problems?"),
83 wxDefaultPosition, wxDefaultSize,
84 wxDEFAULT_DIALOG_STYLE )
85 , mProject{ project }
86{
87 const long SNAP_OFF = 0;
88
89 gPrefs->Read(wxT("/GUI/SyncLockTracks"), &mbSyncLocked, false);
90 mbInSnapTo = gPrefs->Read(wxT("/SnapTo"), SNAP_OFF) !=0;
91 gPrefs->Read(wxT("/AudioIO/SoundActivatedRecord"), &mbSoundActivated, false);
92
94 PopulateOrExchange(S);
95
96 Fit();
97 auto sz = GetSize();
98 SetMinSize( sz );
99 SetMaxSize( sz );
100
101 // The close button has the cancel id and acts exactly the same as cancel.
102 wxButton * pWin = (wxButton*)FindWindowById( wxID_CANCEL );
103 if( pWin )
104 pWin->SetFocus( );
105 Center();
106}
107
108void QuickFixDialog::AddStuck( ShuttleGui & S, bool & bBool,
109 const PrefSetter &prefSetter,
110 const TranslatableString &Prompt, const ManualPageID &Help )
111{
112 mItem++;
113 wxWindowID id = FixButtonID + mItem;
114 if( !bBool)
115 return;
116
117 S
118 .AddFixedText( Prompt );
119
120 S
121 .Id( id )
122 .AddButton( XXO("Fix") )
123 ->Bind( wxEVT_BUTTON, [this, prefSetter, id](wxCommandEvent&){
124 OnFix( prefSetter, id );
125 } );
126
127 {
128 // Replace standard Help button with smaller icon button.
129 // bs->AddButton(safenew wxButton(parent, wxID_HELP));
130 auto b = safenew wxBitmapButton(S.GetParent(), HelpButtonID+mItem, theTheme.Bitmap( bmpHelpIcon ));
131 b->SetToolTip( _("Help") );
132 b->SetLabel(_("Help")); // for screen readers
133 b->Bind( wxEVT_BUTTON, [this, Help](const wxCommandEvent&){
134 OnHelp( Help );
135 } );
136 S.AddWindow( b );
137 }
138}
139
140void QuickFixDialog::PopulateOrExchange(ShuttleGui & S)
141{
142
143 S.StartVerticalLay(1);
144 S.StartStatic( XO("Quick Fixes"));
145
146 // These aren't all possible modes one can be stuck in, but they are some of them.
147 bool bStuckInMode = mbSyncLocked || mbInSnapTo || mbSoundActivated;
148
149 if( !bStuckInMode ){
150 SetLabel(XO("Nothing to do"));
151 S.AddFixedText(XO("No quick, easily fixed problems were found"));
152 }
153 else {
154 S.StartMultiColumn(3, wxALIGN_CENTER);
155 {
156 mItem = -1;
157
158 auto defaultAction =
159 [](AudacityProject *pProject, const wxString &path){ return
160 [pProject, path]{
161 gPrefs->Write(path, 0);
162 gPrefs->Flush();
163 // This is overkill (aka slow), as all preferences are
164 // reloaded and all
165 // toolbars recreated.
166 // Overkill probably doesn't matter, as this command is
167 // infrequently used.
168 DoReloadPreferences( *pProject );
169 };
170 };
171
172 // Use # in the URLs to ensure we go to the online version of help.
173 // Local help may well not be installed.
174 auto pProject = &mProject;
175 AddStuck( S, mbSyncLocked,
176 defaultAction( pProject, "/GUI/SyncLockTracks" ),
177 XO("Clocks on the Tracks"), "Quick_Fix#sync_lock" );
178 AddStuck( S, mbInSnapTo,
179 [pProject] {
180 gPrefs->Write( "/SnapTo", 0 );
181 gPrefs->Flush();
182 // Sadly SnapTo has to be handled specially,
183 // as it is not part of the standard
184 // preference dialogs.
186 },
187 XO("Can't select precisely"), "Quick_Fix#snap_to" );
188 AddStuck( S, mbSoundActivated,
189 defaultAction( pProject, "/AudioIO/SoundActivatedRecord" ),
190 XO("Recording stops and starts"),
191 "Quick_Fix#sound_activated_recording" );
192 }
193 S.EndMultiColumn();
194 }
195 S.EndStatic();
196
197 S.StartHorizontalLay(wxALIGN_CENTER_HORIZONTAL, 0);
198 S.AddStandardButtons(eCloseButton + (bStuckInMode ? 0 : eHelpButton));
199 S.EndHorizontalLay();
200
201 S.EndVerticalLay();
202
203 wxButton * pBtn = (wxButton*)FindWindowById( wxID_HELP );
204 if( pBtn )
205 pBtn->Bind( wxEVT_BUTTON, [this]( const wxCommandEvent & ){
206 OnHelp( "Quick_Fix#" );
207 } );
208}
209
210void QuickFixDialog::OnOk(wxCommandEvent &event)
211{
212 (void)event;// Compiler food
213 EndModal(wxID_OK);
214}
215
216void QuickFixDialog::OnCancel(wxCommandEvent &event)
217{
218 (void)event;// Compiler food
219 EndModal(wxID_CANCEL);
220}
221
222void QuickFixDialog::OnHelp(const ManualPageID &Str)
223{
224 HelpSystem::ShowHelp(this, Str, true);
225}
226
227void QuickFixDialog::OnFix(const PrefSetter &setter, wxWindowID id)
228{
229 if ( setter )
230 setter();
231
232 // Change the label after doing the fix, as the fix may take a second or two.
233 auto pBtn = FindWindow(id);
234 if( pBtn )
235 pBtn->SetLabel( _("Fixed") );
236
237 // The close button has the cancel id and acts exactly the same as cancel.
238 wxButton * pWin = (wxButton*)FindWindowById( wxID_CANCEL );
239 if( pWin )
240 pWin->SetFocus( );
241}
242
243}
244
245namespace HelpActions {
246
247// exported helper functions
248
249// Menu handler functions
250
252
253void OnQuickFix(const CommandContext &context)
254{
255 auto &project = context.project;
256 QuickFixDialog dlg( &GetProjectFrame( project ), project );
257 dlg.ShowModal();
258}
259
260void OnQuickHelp(const CommandContext &context)
261{
262 auto &project = context.project;
264 &GetProjectFrame( project ),
265 L"Quick_Help");
266}
267
268void OnManual(const CommandContext &context)
269{
270 auto &project = context.project;
272 &GetProjectFrame( project ),
273 L"Main_Page");
274}
275
277{
278 auto &project = context.project;
279 auto gAudioIO = AudioIOBase::Get();
280 wxString info = gAudioIO->GetDeviceInfo();
281 ShowDiagnostics( project, info,
282 XO("Audio Device Info"), wxT("deviceinfo.txt") );
283}
284
285void OnShowLog( const CommandContext &context )
286{
288}
289
290#if defined(HAS_CRASH_REPORT)
291void OnCrashReport(const CommandContext &WXUNUSED(context) )
292{
293// Change to "1" to test a real crash
294#if 0
295 char *p = 0;
296 *p = 1234;
297#endif
298 CrashReport::Generate(wxDebugReport::Context_Current);
299}
300#endif
301
302#ifdef IS_ALPHA
303void OnSegfault(const CommandContext &)
304{
305 unsigned *p = nullptr;
306 *p = 0xDEADBEEF;
307}
308
309void OnException(const CommandContext &)
310{
311 // Throw an exception that can be caught only as (...)
312 // The intent is to exercise detection of unhandled exceptions by the
313 // crash reporter
314 struct Unique{};
315 throw Unique{};
316}
317
318void OnAssertion(const CommandContext &)
319{
320 // We don't use assert() much directly, but Breakpad does detect it
321 // This may crash the program only in debug builds
322 // See also wxSetAssertHandler, and wxApp::OnAssertFailure()
323 assert(false);
324}
325#endif
326
327void OnMenuTree(const CommandContext &context)
328{
329 auto &project = context.project;
330
331 using namespace MenuTable;
332 struct MyVisitor : ToolbarMenuVisitor
333 {
335
336 enum : unsigned { TAB = 3 };
337 void DoBeginGroup( GroupItem &item, const Path& ) override
338 {
339 if ( dynamic_cast<MenuItem*>( &item ) ) {
340 Indent();
341 // using GET for alpha only diagnostic tool
342 info += item.name.GET();
343 Return();
344 indentation = wxString{ ' ', TAB * ++level };
345 }
346 }
347
348 void DoEndGroup( GroupItem &item, const Path& ) override
349 {
350 if ( dynamic_cast<MenuItem*>( &item ) )
351 indentation = wxString{ ' ', TAB * --level };
352 }
353
354 void DoVisit( SingleItem &item, const Path& ) override
355 {
356 // using GET for alpha only diagnostic tool
357 Indent();
358 info += item.name.GET();
359 Return();
360 }
361
362 void DoSeparator() override
363 {
364 static const wxString separatorName{ '=', 20 };
365 Indent();
366 info += separatorName;
367 Return();
368 }
369
370 void Indent() { info += indentation; }
371 void Return() { info += '\n'; }
372
373 unsigned level{};
374 wxString indentation;
375 wxString info;
376 } visitor{ project };
377
378 MenuManager::Visit( visitor );
379
380 ShowDiagnostics( project, visitor.info,
381 Verbatim("Menu Tree"), wxT("menutree.txt"), true );
382}
383
384#if defined(HAVE_UPDATES_CHECK)
385void OnCheckForUpdates(const CommandContext &WXUNUSED(context))
386{
388}
389#endif
390
391void OnAbout(const CommandContext &context)
392{
393#ifdef __WXMAC__
394 // Modeless dialog, consistent with other Mac applications
395 // Simulate the application Exit menu item
396 wxCommandEvent evt{ wxEVT_MENU, wxID_ABOUT };
397 wxTheApp->AddPendingEvent( evt );
398#else
399 auto &project = context.project;
400 auto &window = GetProjectFrame( project );
401
402 // Windows and Linux still modal.
403 AboutDialog dlog( &window );
404 dlog.ShowModal();
405#endif
406}
407
408#if 0
409// Legacy handlers, not used as of version 2.3.0
410
411// Only does the update checks if it's an ALPHA build and not disabled by
412// preferences.
413void MayCheckForUpdates(AudacityProject &project)
414{
415#ifdef IS_ALPHA
416 OnCheckForUpdates(project);
417#endif
418}
419
420void OnHelpWelcome(const CommandContext &context)
421{
423}
424
425#endif
426
427}; // struct Handler
428
429} // namespace
430
432 // Handler is not stateful. Doesn't need a factory registered with
433 // AudacityProject.
434 static HelpActions::Handler instance;
435 return instance;
436};
437
438// Menu definitions
439
440#define FN(X) (& HelpActions::Handler :: X)
441
442namespace {
443using namespace MenuTable;
445{
446 static BaseItemSharedPtr menu{
448 Menu( wxT("Help"), XXO("&Help"),
449 Section( "Basic",
450 // QuickFix menu item not in Audacity 2.3.1 whilst we discuss further.
451 #ifdef EXPERIMENTAL_DA
452 // DA: Has QuickFix menu item.
453 Command( wxT("QuickFix"), XXO("&Quick Fix..."), FN(OnQuickFix),
455 // DA: 'Getting Started' rather than 'Quick Help'.
456 Command( wxT("QuickHelp"), XXO("&Getting Started"), FN(OnQuickHelp),
458 // DA: Emphasise it is the Audacity Manual (No separate DA manual).
459 Command( wxT("Manual"), XXO("Audacity &Manual"), FN(OnManual),
461
462 #else
463 Command( wxT("QuickHelp"), XXO("&Quick Help..."), FN(OnQuickHelp),
465 Command( wxT("Manual"), XXO("&Manual..."), FN(OnManual),
467 #endif
468 ),
469
470 #ifdef __WXMAC__
471 Items
472 #else
473 Section
474 #endif
475 ( "Other",
476 Menu( wxT("Diagnostics"), XXO("&Diagnostics"),
477 Command( wxT("DeviceInfo"), XXO("Au&dio Device Info..."),
478 FN(OnAudioDeviceInfo),
480 Command( wxT("Log"), XXO("Show &Log..."), FN(OnShowLog),
482 #if defined(HAS_CRASH_REPORT)
483 Command( wxT("CrashReport"), XXO("&Generate Support Data..."),
484 FN(OnCrashReport), AlwaysEnabledFlag )
485 #endif
486
487 #ifdef IS_ALPHA
488 ,
489 // alpha-only items don't need to internationalize, so use
490 // Verbatim for labels
491
492 Command( wxT("RaiseSegfault"), Verbatim("Test segfault report"),
493 FN(OnSegfault), AlwaysEnabledFlag ),
494
495 Command( wxT("ThrowException"), Verbatim("Test exception report"),
496 FN(OnException), AlwaysEnabledFlag ),
497
498 Command( wxT("ViolateAssertion"), Verbatim("Test assertion report"),
499 FN(OnAssertion), AlwaysEnabledFlag ),
500
501 // Menu explorer. Perhaps this should become a macro command
502 Command( wxT("MenuTree"), Verbatim("Menu Tree..."),
503 FN(OnMenuTree),
505 #endif
506 )
507 #ifndef __WXMAC__
508 ),
509
510 Section( "",
511#else
512 ,
513#endif
514 // DA: Does not fully support update checking.
515 #if !defined(EXPERIMENTAL_DA) && defined(HAVE_UPDATES_CHECK)
516 Command( wxT("Updates"), XXO("&Check for Updates..."),
517 FN(OnCheckForUpdates),
519 #endif
520 Command( wxT("About"), XXO("&About Audacity..."), FN(OnAbout),
522 )
523 ) ) };
524 return menu;
525}
526
528 wxT(""),
529 Shared( HelpMenu() )
530};
531
532}
533
534#undef FN
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:431
#define HelpButtonID
Definition: HelpMenus.cpp:74
#define FixButtonID
Definition: HelpMenus.cpp:73
#define FN(X)
Definition: HelpMenus.cpp:440
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:610
@ eHelpButton
Definition: ShuttleGui.h:604
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:89
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 ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:237
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:631
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:47
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:327
void OnManual(const CommandContext &context)
Definition: HelpMenus.cpp:268
void OnShowLog(const CommandContext &context)
Definition: HelpMenus.cpp:285
void OnQuickHelp(const CommandContext &context)
Definition: HelpMenus.cpp:260
void OnAudioDeviceInfo(const CommandContext &context)
Definition: HelpMenus.cpp:276
void OnAbout(const CommandContext &context)
Definition: HelpMenus.cpp:391
void OnQuickFix(const CommandContext &context)
Definition: HelpMenus.cpp:253
const Identifier name
Definition: Registry.h:67
ToolbarMenuVisitor(AudacityProject &p)