Audacity  2.2.2
AudacityLogger.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  AudacityLogger.cpp
6 
7 ******************************************************************//*******************************************************************/
15 
16 
17 #include "Audacity.h" // This should always be included first
18 #include "AudacityLogger.h"
19 #include "FileNames.h"
20 #include "ShuttleGui.h"
21 
22 #include <wx/filedlg.h>
23 #include <wx/log.h>
24 #include <wx/frame.h>
25 #include <wx/icon.h>
26 #include <wx/settings.h>
27 
28 #include "../images/AudacityLogoAlpha.xpm"
29 #include "Experimental.h"
30 #include "widgets/ErrorDialog.h"
31 #include "Internat.h"
32 
33 //
34 // AudacityLogger class
35 //
36 // Two reasons for this class instead of the wxLogWindow class (or any WX GUI logging class)
37 //
38 // 1) If wxLogWindow is used and initialized before the Mac's "root" window, then
39 // Audacity may crash when terminating. It's not fully understood why this occurs
40 // but it probably has to do with the order of deletion. However, deferring the
41 // creation of the log window until it is actually shown circumvents the problem.
42 // 2) By providing an Audacity specific logging class, it can be made thread-safe and,
43 // as such, can be used by the ever growing threading within Audacity.
44 //
45 enum
46 {
47  LoggerID_Save = wxID_HIGHEST + 1,
50 };
51 
53 : wxEvtHandler(),
54  wxLog()
55 {
56  mText = NULL;
57  mUpdated = false;
58 }
59 
61 {
62  if (mUpdated && mFrame && mFrame->IsShown()) {
63  mUpdated = false;
64  mText->ChangeValue(mBuffer);
65  }
66 }
67 
68 void AudacityLogger::DoLogText(const wxString & str)
69 {
70  if (!wxIsMainThread()) {
71  wxMutexGuiEnter();
72  }
73 
74  if (mBuffer.IsEmpty()) {
75  wxString stamp;
76 
77  TimeStamp(&stamp);
78 
79  mBuffer << stamp << _TS("Audacity ") << AUDACITY_VERSION_STRING << wxT("\n");
80  }
81 
82  mBuffer << str << wxT("\n");
83 
84  mUpdated = true;
85 
86  Flush();
87 
88  if (!wxIsMainThread()) {
89  wxMutexGuiLeave();
90  }
91 }
92 
93 void AudacityLogger::Show(bool show)
94 {
95  // Hide the frame if created, otherwise do nothing
96  if (!show) {
97  if (mFrame) {
98  mFrame->Show(false);
99  }
100  return;
101  }
102 
103  // If the frame already exists, refresh its contents and show it
104  if (mFrame) {
105  if (!mFrame->IsShown()) {
106  mText->ChangeValue(mBuffer);
107  mText->SetInsertionPointEnd();
108  mText->ShowPosition(mText->GetLastPosition());
109  }
110  mFrame->Show();
111  mFrame->Raise();
112  return;
113  }
114 
115  // This is the first use, so create the frame
117  { safenew wxFrame(NULL, wxID_ANY, _("Audacity Log")) };
118  frame->SetName(frame->GetTitle());
119  frame->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
120 
121  // loads either the XPM or the windows resource, depending on the platform
122  {
123 #if !defined(__WXMAC__) && !defined(__WXX11__)
124 #if defined(__WXMSW__)
125  wxIcon ic{wxICON(AudacityLogo)};
126 #elif defined(__WXGTK__)
127  wxIcon ic{wxICON(AudacityLogoAlpha)};
128 #else
129  wxIcon ic{};
130  ic.CopyFromBitmap(theTheme.Bitmap(bmpAudacityLogo48x48));
131 #endif
132  frame->SetIcon(ic);
133 #endif
134  }
135 
136  // Log text
137  ShuttleGui S(frame.get(), eIsCreating);
138 
139  S.SetStyle(wxNO_BORDER | wxTAB_TRAVERSAL);
140  S.Prop(true).StartPanel();
141  {
142  S.StartVerticalLay(true);
143  {
144  S.SetStyle(wxTE_MULTILINE | wxHSCROLL | wxTE_READONLY);
145  mText = S.AddTextWindow(mBuffer);
146 
147  S.AddSpace(0, 5);
148  S.StartHorizontalLay(wxALIGN_CENTER, 0);
149  {
150  S.AddSpace(10, 0);
151  S.Id(LoggerID_Save).AddButton(_("&Save..."));
152  S.Id(LoggerID_Clear).AddButton(_("Cl&ear"));
153  S.Id(LoggerID_Close).AddButton(_("&Close"));
154  S.AddSpace(10, 0);
155  }
156  S.EndHorizontalLay();
157  S.AddSpace(0, 3);
158  }
159  S.EndVerticalLay();
160  }
161  S.EndPanel();
162 
163  // Give a place for the menu help text to go
164  // frame->CreateStatusBar();
165 
166  frame->Layout();
167 
168  // Hook into the frame events
169  frame->Bind(wxEVT_CLOSE_WINDOW,
170  wxCloseEventHandler(AudacityLogger::OnCloseWindow),
171  this);
172 
173  frame->Bind( wxEVT_COMMAND_MENU_SELECTED,
175  this, LoggerID_Save);
176  frame->Bind( wxEVT_COMMAND_MENU_SELECTED,
178  this, LoggerID_Clear);
179  frame->Bind( wxEVT_COMMAND_MENU_SELECTED,
181  this, LoggerID_Close);
182  frame->Bind( wxEVT_COMMAND_BUTTON_CLICKED,
184  this, LoggerID_Save);
185  frame->Bind( wxEVT_COMMAND_BUTTON_CLICKED,
187  this, LoggerID_Clear);
188  frame->Bind( wxEVT_COMMAND_BUTTON_CLICKED,
190  this, LoggerID_Close);
191 
192  mFrame = std::move( frame );
193 
194  mFrame->Show();
195 
196  Flush();
197 }
198 
199 #if defined(EXPERIMENTAL_CRASH_REPORT)
200 wxString AudacityLogger::GetLog()
201 {
202  return mBuffer;
203 }
204 #endif
205 
206 void AudacityLogger::OnCloseWindow(wxCloseEvent & WXUNUSED(e))
207 {
208 #if defined(__WXMAC__)
209  // On the Mac, destroy the window rather than hiding it since the
210  // log menu will override the root windows menu if there is no
211  // project window open.
212  mFrame.reset();
213 #else
214  Show(false);
215 #endif
216 }
217 
218 void AudacityLogger::OnClose(wxCommandEvent & WXUNUSED(e))
219 {
220  wxCloseEvent dummy;
221  OnCloseWindow(dummy);
222 }
223 
224 void AudacityLogger::OnClear(wxCommandEvent & WXUNUSED(e))
225 {
226  mBuffer = wxEmptyString;
227  DoLogText(wxT("Log Cleared."));
228 }
229 
230 void AudacityLogger::OnSave(wxCommandEvent & WXUNUSED(e))
231 {
232  wxString fName = _("log.txt");
233 
235  _("Save log to:"),
236  wxEmptyString,
237  fName,
238  wxT("txt"),
239  wxT("*.txt"),
240  wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
241  mFrame.get());
242 
243  if (fName == wxEmptyString) {
244  return;
245  }
246 
247  if (!mText->SaveFile(fName)) {
249  wxString::Format( _("Couldn't save log to file: %s"), fName ),
250  _("Warning"),
251  wxICON_EXCLAMATION,
252  mFrame.get());
253  return;
254  }
255 }
256 
#define AUDACITY_VERSION_STRING
Definition: Audacity.h:81
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
void Show(bool show=true)
#define _TS(s)
Definition: Internat.h:30
void OnCloseWindow(wxCloseEvent &e)
void Flush() override
Destroy_ptr< wxFrame > mFrame
int AudacityMessageBox(const wxString &message, const wxString &caption=AudacityMessageBoxCaptionStr(), long style=wxOK|wxCENTRE, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord)
Definition: ErrorDialog.h:92
#define safenew
Definition: Audacity.h:230
wxString mBuffer
wxBitmap & Bitmap(int iIndex)
Definition: Theme.cpp:1244
void SetStyle(int Style)
Definition: ShuttleGui.h:287
void OnSave(wxCommandEvent &e)
wxTextCtrl * mText
void OnClear(wxCommandEvent &e)
static wxString SelectFile(Operation op, const wxString &message, const wxString &default_path, const wxString &default_filename, const wxString &default_extension, const wxString &wildcard, int flags, wxWindow *parent)
Definition: FileNames.cpp:411
_("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
void OnClose(wxCommandEvent &e)
void DoLogText(const wxString &msg) override
std::unique_ptr< T, Destroyer< T >> Destroy_ptr
Definition: MemoryX.h:433