Audacity  2.2.2
HelpSystem.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  HelpSystem.cpp
6 
7  Jimmy Johnson
8  Leland Lucius
9  Richard Ash
10 
11 *//********************************************************************/
12 
13 #include "../Audacity.h"
14 
15 #include <wx/button.h>
16 #include <wx/icon.h>
17 #include <wx/dialog.h>
18 #include <wx/intl.h>
19 #include <wx/sizer.h>
20 #include <wx/stattext.h>
21 #include <wx/utils.h>
22 #include <wx/html/htmlwin.h>
23 #include <wx/settings.h>
24 #include <wx/statusbr.h>
25 #include <wx/regex.h>
26 
27 #include "../FileNames.h"
28 #include "LinkingHtmlWindow.h"
29 #include "../Theme.h"
30 #include "../AllThemeResources.h"
31 #include "../ShuttleGui.h"
32 #include "../HelpText.h"
33 #include "../Project.h"
34 #include "../Prefs.h"
35 
36 #include "ErrorDialog.h"
37 #include "HelpSystem.h"
38 
39 #ifdef USE_ALPHA_MANUAL
40 const wxString HelpSystem::HelpHostname = wxT("alphamanual.audacityteam.org");
41 const wxString HelpSystem::HelpServerHomeDir = wxT("/man/");
42 const wxString HelpSystem::HelpServerManDir = wxT("/man/");
43 #else
44 const wxString HelpSystem::HelpHostname = wxT("manual.audacityteam.org");
45 const wxString HelpSystem::HelpServerHomeDir = wxT("/");
46 const wxString HelpSystem::HelpServerManDir = wxT("/man/");
47 #endif
48 const wxString HelpSystem::LocalHelpManDir = wxT("/man/");
49 const wxString HelpSystem::ReleaseSuffix = wxT(".html");
50 
54 void HelpSystem::ShowInfoDialog( wxWindow *parent,
55  const wxString &dlogTitle,
56  const wxString &shortMsg,
57  const wxString &message,
58  const int xSize, const int ySize)
59 {
60  wxDialogWrapper dlog(parent, wxID_ANY,
61  dlogTitle,
62  wxDefaultPosition, wxDefaultSize,
63  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX /*| wxDEFAULT_FRAME_STYLE */);
64 
65  dlog.SetName(dlog.GetTitle());
66  ShuttleGui S(&dlog, eIsCreating);
67 
68  S.StartVerticalLay(1);
69  {
70  S.AddTitle( shortMsg);
71  S.SetStyle( wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH | wxTE_RICH2 |
72  wxTE_AUTO_URL | wxTE_NOHIDESEL | wxHSCROLL );
73  S.AddTextWindow(message);
74 
75  S.SetBorder( 0 );
76  S.StartHorizontalLay(wxALIGN_CENTER_HORIZONTAL, 0);
78  S.EndHorizontalLay();
79  }
80  S.EndVerticalLay();
81 
82  // Smallest size is half default size. Seems reasonable.
83  dlog.SetMinSize( wxSize(xSize/2, ySize/2) );
84  dlog.SetSize( wxSize(xSize, ySize) );
85  dlog.Center();
86  dlog.ShowModal();
87 }
88 
89 void HelpSystem::ShowHtmlText(wxWindow *pParent,
90  const wxString &Title,
91  const wxString &HtmlText,
92  bool bIsFile,
93  bool bModal)
94 {
95  LinkingHtmlWindow *html;
96 
97  wxASSERT(pParent); // to justify safenew
98  // JKC: ANSWER-ME: Why do we create a fake 'frame' and then put a BrowserDialog
99  // inside it, rather than have a variant of the BrowserDialog that is a
100  // frame??
101  // Bug 1412 seems to be related to the extra frame.
102  auto pFrame = safenew wxFrame {
103  pParent, wxID_ANY, Title, wxDefaultPosition, wxDefaultSize,
104 #if defined(__WXMAC__)
105  // On OSX, the html frame can go behind the help dialog and if the help
106  // html frame is modal, you can't get back to it. Pressing escape gets
107  // you out of this, but it's just easier to add the wxSTAY_ON_TOP flag
108  // to prevent it from falling behind the dialog. Not the perfect solution
109  // but acceptable in this case.
110  wxSTAY_ON_TOP |
111 #endif
112  wxDEFAULT_FRAME_STYLE
113  };
114 
115  BrowserDialog * pWnd;
116  if( bModal )
117  pWnd = safenew HtmlTextHelpDialog{ pFrame, Title };
118  else
119  pWnd = safenew BrowserDialog{ pFrame, Title };
120 
121  // Bug 1412 workaround for 'extra window'. Hide the 'fake' window.
122  pFrame->SetTransparent(0);
123  ShuttleGui S( pWnd, eIsCreating );
124 
125  S.SetStyle( wxNO_BORDER | wxTAB_TRAVERSAL );
126  wxPanel *pPan = S.Prop(true).StartPanel();
127  {
128  S.StartHorizontalLay( wxEXPAND, false );
129  {
130  wxButton * pWndBackwards = S.Id( wxID_BACKWARD ).AddButton( _("<") );
131  wxButton * pWndForwards = S.Id( wxID_FORWARD ).AddButton( _(">") );
132  pWndForwards->Enable( false );
133  pWndBackwards->Enable( false );
134  #if wxUSE_TOOLTIPS
135  pWndForwards->SetToolTip( _("Forwards" ));
136  pWndBackwards->SetToolTip( _("Backwards" ));
137  #endif
138  }
139  S.EndHorizontalLay();
140 
141  html = safenew LinkingHtmlWindow(pPan, wxID_ANY,
142  wxDefaultPosition,
143  bIsFile ? wxSize(500, 400) : wxSize(480, 240),
144  wxHW_SCROLLBAR_AUTO | wxSUNKEN_BORDER);
145 
146  html->SetRelatedFrame( pFrame, wxT("Help: %s") );
147  if( bIsFile )
148  html->LoadFile( HtmlText );
149  else
150  html->SetPage( HtmlText);
151 
152  S.Prop(1).AddWindow( html, wxEXPAND );
153 
154  S.Id( wxID_CANCEL ).AddButton( _("Close") )->SetDefault();
155  }
156  S.EndPanel();
157 
158  // -- START of ICON stuff -----
159  // If this section (providing an icon) causes compilation errors on linux, comment it out for now.
160  // it will just mean that the icon is missing. Works OK on Windows.
161  #ifdef __WXMSW__
162  wxIcon ic{ wxICON(AudacityLogo) };
163  #else
164  wxIcon ic{};
165  ic.CopyFromBitmap(theTheme.Bitmap(bmpAudacityLogo48x48));
166  #endif
167  pFrame->SetIcon( ic );
168  // -- END of ICON stuff -----
169 
170 
171  pWnd->mpHtml = html;
172  pWnd->SetBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
173 
174  pFrame->CreateStatusBar();
175  pFrame->Centre();
176  pFrame->Layout();
177  pFrame->SetSizeHints(pWnd->GetSize());
178 
179  pFrame->SetName(Title);
180  if (bModal)
181  pWnd->ShowModal();
182  else {
183  pWnd->Show(true);
184  pFrame->Show(true);
185  }
186 
187  html->SetRelatedStatusBar( 0 );
188  html->SetFocus();
189 
190  return;
191 }
192 
193 // Shows help in browser, or possibly in own dialog.
194 void HelpSystem::ShowHelp(wxWindow *parent,
195  const wxString &localFileName,
196  const wxString &remoteURL,
197  bool bModal,
198  bool alwaysDefaultBrowser)
199 {
200  wxASSERT(parent); // to justify safenew
201  AudacityProject * pProj = GetActiveProject();
202  wxString HelpMode = wxT("Local");
203 
204  if( pProj )
205  {
206  HelpMode = pProj->mHelpPref;
207  // these next lines are for legacy cfg files (pre 2.0) where we had different modes
208  if( (HelpMode == wxT("Standard")) || (HelpMode == wxT("InBrowser")) )
209  {
210  HelpMode = wxT("Local");
211  pProj->mHelpPref = HelpMode;
212  gPrefs->Write(wxT("/GUI/Help"), HelpMode);
213  gPrefs->Flush();
214  }
215  }
216 
217  // Anchors (URLs with a '#' in them) are not supported by many OSs for local file names
218  // See, for example, https://groups.google.com/forum/#!topic/wx-users/pC0uOZJalRQ
219  // Problems have been reported on Win, Mac and some versions of Linux.
220  // So we set HelpMode to use the internet if an anchor is found.
221  if (localFileName.Find('#', true) != wxNOT_FOUND)
222  HelpMode = wxT("FromInternet");
223  // Until a solution is found for this, the next few lines are irrelevant.
224 
225  // Obtain the local file system file name, without the anchor if present.
226  wxString localfile;
227  if (localFileName.Find('#', true) != wxNOT_FOUND)
228  localfile = localFileName.BeforeLast('#');
229  else
230  localfile = localFileName;
231 
232  if( (HelpMode == wxT("FromInternet")) && !remoteURL.IsEmpty() )
233  {
234  // Always go to remote URL. Use External browser.
235  OpenInDefaultBrowser( remoteURL );
236  }
237  else if( localfile.IsEmpty() || !wxFileExists( localfile ))
238  {
239  // If you give an empty remote URL, you should have already ensured
240  // that the file exists!
241  wxASSERT( !remoteURL.IsEmpty() );
242  // I can't find it'.
243  // Use Built-in browser to suggest you use the remote url.
244  wxString Text = HelpText( wxT("remotehelp") );
245  Text.Replace( wxT("*URL*"), remoteURL );
246  ShowHtmlText( parent, _("Help on the Internet"), Text, false, bModal );
247  }
248  else if( HelpMode == wxT("Local") || alwaysDefaultBrowser)
249  {
250  // Local file, External browser
251  OpenInDefaultBrowser( wxString(wxT("file:"))+localFileName );
252  }
253  else
254  {
255  // Local file, Built-in browser
256  ShowHtmlText( parent, wxT(""), localFileName, true, bModal );
257  }
258 }
259 
260 void HelpSystem::ShowHelp(wxWindow *parent,
261  const wxString &PageName,
262  bool bModal)
263 {
264  wxString localHelpPage;
265  wxString webHelpPath;
266  wxString webHelpPage;
267  wxString releasePageName;
268  wxString anchor; // optional part of URL after (and including) the '#'
269  if (PageName.Find('#', true) != wxNOT_FOUND)
270  { // need to split anchor off into separate variable
271  releasePageName= PageName.BeforeLast('#');
272  anchor = wxT("#") + PageName.AfterLast('#');
273  }
274  else
275  {
276  releasePageName = PageName;
277  anchor = wxT("");
278  }
279  // The wiki pages are transformed to static HTML by
280  // scripts/mw2html_audacity/mw2html.py
281  // The name is first transformed to lower case, then all
282  // 'special characters' are replaced by underscores. Spaces are
283  // transformed to "+".
284  //
285  // The transformations are handled in mw2html by first applying
286  // 'urllib.parse.quote_plus' (escape chars that are not in "always safe" list)
287  // then replacing escape characters (%xx) with underscores,
288  // and finally removing duplicate / redundant underscores.
289  //
290  // The front page and 'quick_help' are treated as special cases and placed in
291  // the root of the help directory rather than the "/man/" sub-directory.
292  if (releasePageName == wxT("Main_Page"))
293  {
294  releasePageName = wxT("index") + HelpSystem::ReleaseSuffix + anchor;
295  localHelpPage = wxFileName(FileNames::HtmlHelpDir(), releasePageName).GetFullPath();
296  webHelpPath = wxT("https://")+HelpSystem::HelpHostname+HelpSystem::HelpServerHomeDir;
297  }
298  else if (releasePageName == wxT("Quick_Help"))
299  {
300 // DA: No bundled help, by default, and different quick-help URL.
301 #ifdef EXPERIMENTAL_DA
302  releasePageName = wxT("video") + HelpSystem::ReleaseSuffix + anchor;
303  localHelpPage = wxFileName(FileNames::HtmlHelpDir(), releasePageName).GetFullPath();
304  webHelpPath = wxT("http://www.darkaudacity.com/");
305 #else
306  releasePageName = wxT("quick_help") + HelpSystem::ReleaseSuffix + anchor;
307  localHelpPage = wxFileName(FileNames::HtmlHelpDir(), releasePageName).GetFullPath();
308  webHelpPath = wxT("https://")+HelpSystem::HelpHostname+HelpSystem::HelpServerHomeDir;
309 #endif
310  }
311  // not a page name, but rather a full path (e.g. to wiki)
312  // in which case do not do any substitutions.
313  else if (releasePageName.StartsWith( "http" ) )
314  {
315  localHelpPage = "";
316  webHelpPage = releasePageName + anchor;
317  }
318  else
319  {
320  // Handle all other pages.
321  // Change to lower case.
322  releasePageName = releasePageName.Lower();
323  wxRegEx re;
324  // replace 'special characters' with underscores.
325  // RFC 2396 defines the characters a-z, A-Z, 0-9 and ".-_" as "always safe"
326  // mw2html also replaces "-" with "_" so replace that too.
327 
328  // If PageName contains a %xx code, mw2html will transform it:
329  // '%xx' => '%25xx' => '_'
330  re.Compile(wxT("%.."));
331  re.ReplaceAll(&releasePageName, (wxT("_")));
332  // Now replace all other 'not-safe' characters.
333  re.Compile(wxT("[^[:alnum:] . [:space:]]"));
334  re.ReplaceAll(&releasePageName, (wxT("_")));
335  // Replace spaces with "+"
336  releasePageName.Replace(wxT(" "), wxT("+"), true);
337  // Reduce multiple underscores to single underscores
338  re.Compile(wxT("__+"));
339  re.ReplaceAll(&releasePageName, (wxT("_")));
340  // Replace "_." with "."
341  releasePageName.Replace(wxT("_."), wxT("."), true);
342  // Concatenate file name with file extension and anchor.
343  releasePageName = releasePageName + HelpSystem::ReleaseSuffix + anchor;
344  // Other than index and quick_help, all local pages are in subdirectory 'LocalHelpManDir'.
345  localHelpPage = wxFileName(FileNames::HtmlHelpDir() + LocalHelpManDir, releasePageName).GetFullPath();
346  // Other than index and quick_help, all on-line pages are in subdirectory 'HelpServerManDir'.
347  webHelpPath = wxT("https://")+HelpSystem::HelpHostname+HelpSystem::HelpServerManDir;
348  }
349 
350 #ifdef USE_ALPHA_MANUAL
351  webHelpPage = webHelpPath + PageName;
352 #else
353  webHelpPage = webHelpPath + releasePageName;
354 #endif
355 
356  wxLogMessage(wxT("Help button pressed: PageName %s, releasePageName %s"),
357  PageName, releasePageName);
358  wxLogMessage(wxT("webHelpPage %s, localHelpPage %s"),
359  webHelpPage, localHelpPage);
360 
361  wxASSERT(parent); // to justify safenew
362 
364  parent,
365  localHelpPage,
366  webHelpPage,
367  bModal
368  );
369 }
static void ShowInfoDialog(wxWindow *parent, const wxString &dlogTitle, const wxString &shortMsg, const wxString &message, const int xSize, const int ySize)
Displays cutable information in a text ctrl, with an OK button.
Definition: HelpSystem.cpp:54
AudacityPrefs * gPrefs
Definition: Prefs.cpp:73
AUDACITY_DLL_API Theme theTheme
Definition: Theme.cpp:209
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI...
Definition: ShuttleGui.h:409
wxWindow * AddWindow(wxWindow *pWindow, int Flags=wxALIGN_CENTRE|wxALL)
Definition: ShuttleGui.cpp:288
static const wxString LocalHelpManDir
Definition: HelpSystem.h:96
wxPanel * StartPanel(int iStyle=0)
Definition: ShuttleGui.cpp:847
static const wxString HelpServerHomeDir
Definition: HelpSystem.h:86
static const wxString HelpHostname
Definition: HelpSystem.h:81
#define safenew
Definition: Audacity.h:230
void EndHorizontalLay()
static void ShowHtmlText(wxWindow *pParent, const wxString &Title, const wxString &HtmlText, bool bIsFile=false, bool bModal=false)
Definition: HelpSystem.cpp:89
wxBitmap & Bitmap(int iIndex)
Definition: Theme.cpp:1244
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:176
void EndVerticalLay()
static wxString HtmlHelpDir()
Definition: FileNames.cpp:173
wxString HelpText(const wxString &Key)
Definition: HelpText.cpp:298
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
ShuttleGui & Id(int id)
void SetStyle(int Style)
Definition: ShuttleGui.h:287
static void ShowHelp(wxWindow *parent, const wxString &localFileName, const wxString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:194
void AddTitle(const wxString &Prompt)
Centred text string.
Definition: ShuttleGui.cpp:274
static const wxString ReleaseSuffix
Definition: HelpSystem.h:100
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop")).Raw()), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom")).Raw()), OnMoveTrack)#define SET_TRACK_NAME_PLUGIN_SYMBOLclass SetTrackNameCommand:public AudacityCommand
wxTextCtrl * AddTextWindow(const wxString &Value)
Multiline text box that grows.
Definition: ShuttleGui.cpp:608
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:308
static const wxString HelpServerManDir
Definition: HelpSystem.h:91
wxString mHelpPref
Definition: Project.h:706
ShuttleGui & Prop(int iProp)
Definition: ShuttleGui.h:418
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxButton *extra=NULL)
void SetBorder(int Border)
Definition: ShuttleGui.h:286
HtmlWindow * mpHtml
void OpenInDefaultBrowser(const wxHtmlLinkInfo &link)
wxButton * AddButton(const wxString &Text, int PositionFlags=wxALIGN_CENTRE)
Definition: ShuttleGui.cpp:341
void StartVerticalLay(int iProp=1)