mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-22 07:10:06 +02:00
Move LogWindow to new files
This commit is contained in:
parent
c14e8114ca
commit
4fd6e8a151
@ -19,63 +19,20 @@ Provides thread-safe logging based on the wxWidgets log facility.
|
||||
|
||||
|
||||
|
||||
#include "FileNames.h"
|
||||
#include "Internat.h"
|
||||
#include "SelectFile.h"
|
||||
#include "ShuttleGui.h"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/frame.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wx/weakref.h>
|
||||
|
||||
#include "../images/AudacityLogoAlpha.xpm"
|
||||
#include "widgets/AudacityMessageBox.h"
|
||||
|
||||
//
|
||||
// AudacityLogger class
|
||||
//
|
||||
// Two reasons for this class instead of the wxLogWindow class (or any WX GUI logging class)
|
||||
//
|
||||
// 1) If wxLogWindow is used and initialized before the Mac's "root" window, then
|
||||
// Audacity may crash when terminating. It's not fully understood why this occurs
|
||||
// but it probably has to do with the order of deletion. However, deferring the
|
||||
// creation of the log window until it is actually shown circumvents the problem.
|
||||
// 2) By providing an Audacity specific logging class, it can be made thread-safe and,
|
||||
// By providing an Audacity specific logging class, it can be made thread-safe and,
|
||||
// as such, can be used by the ever growing threading within Audacity.
|
||||
//
|
||||
enum
|
||||
{
|
||||
LoggerID_Save = wxID_HIGHEST + 1,
|
||||
LoggerID_Clear,
|
||||
LoggerID_Close
|
||||
};
|
||||
|
||||
namespace {
|
||||
Destroy_ptr<wxFrame> sFrame;
|
||||
wxWeakRef<wxTextCtrl> sText;
|
||||
|
||||
struct LogWindowUpdater : public PrefsListener
|
||||
{
|
||||
// PrefsListener implementation
|
||||
void UpdatePrefs() override;
|
||||
};
|
||||
// Unique PrefsListener can't be statically constructed before the application
|
||||
// object initializes, so use Optional
|
||||
std::optional<LogWindowUpdater> pUpdater;
|
||||
|
||||
void OnCloseWindow(wxCloseEvent & e);
|
||||
void OnClose(wxCommandEvent & e);
|
||||
void OnClear(wxCommandEvent & e);
|
||||
void OnSave(wxCommandEvent & e);
|
||||
}
|
||||
|
||||
AudacityLogger *AudacityLogger::Get()
|
||||
{
|
||||
@ -161,120 +118,6 @@ bool AudacityLogger::ClearLog()
|
||||
return true;
|
||||
}
|
||||
|
||||
void LogWindow::Show(bool show)
|
||||
{
|
||||
// Hide the frame if created, otherwise do nothing
|
||||
if (!show) {
|
||||
if (sFrame) {
|
||||
sFrame->Show(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If the frame already exists, refresh its contents and show it
|
||||
auto pLogger = AudacityLogger::Get();
|
||||
if (sFrame) {
|
||||
if (!sFrame->IsShown() && sText) {
|
||||
if (pLogger)
|
||||
sText->ChangeValue(pLogger->GetBuffer());
|
||||
sText->SetInsertionPointEnd();
|
||||
sText->ShowPosition(sText->GetLastPosition());
|
||||
}
|
||||
sFrame->Show();
|
||||
sFrame->Raise();
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the first use, so create the frame
|
||||
Destroy_ptr<wxFrame> frame
|
||||
{ safenew wxFrame(NULL, wxID_ANY, _("Audacity Log")) };
|
||||
frame->SetName(frame->GetTitle());
|
||||
frame->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
|
||||
|
||||
// loads either the XPM or the windows resource, depending on the platform
|
||||
{
|
||||
#if !defined(__WXMAC__) && !defined(__WXX11__)
|
||||
#if defined(__WXMSW__)
|
||||
wxIcon ic{wxICON(AudacityLogo)};
|
||||
#elif defined(__WXGTK__)
|
||||
wxIcon ic{wxICON(AudacityLogoAlpha)};
|
||||
#else
|
||||
wxIcon ic{};
|
||||
ic.CopyFromBitmap(theTheme.Bitmap(bmpAudacityLogo48x48));
|
||||
#endif
|
||||
frame->SetIcon(ic);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Log text
|
||||
ShuttleGui S(frame.get(), eIsCreating);
|
||||
|
||||
S.Style(wxNO_BORDER | wxTAB_TRAVERSAL).Prop(true).StartPanel();
|
||||
{
|
||||
S.StartVerticalLay(true);
|
||||
{
|
||||
sText = S.Style(wxTE_MULTILINE | wxHSCROLL | wxTE_READONLY | wxTE_RICH)
|
||||
.AddTextWindow({}); // Populate this text window below
|
||||
|
||||
S.AddSpace(0, 5);
|
||||
S.StartHorizontalLay(wxALIGN_CENTER, 0);
|
||||
{
|
||||
S.AddSpace(10, 0);
|
||||
S.Id(LoggerID_Save).AddButton(XXO("&Save..."));
|
||||
S.Id(LoggerID_Clear).AddButton(XXO("Cl&ear"));
|
||||
S.Id(LoggerID_Close).AddButton(XXO("&Close"));
|
||||
S.AddSpace(10, 0);
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
S.AddSpace(0, 3);
|
||||
}
|
||||
S.EndVerticalLay();
|
||||
}
|
||||
S.EndPanel();
|
||||
|
||||
// Give a place for the menu help text to go
|
||||
// frame->CreateStatusBar();
|
||||
|
||||
frame->Layout();
|
||||
|
||||
// Hook into the frame events
|
||||
frame->Bind(wxEVT_CLOSE_WINDOW, OnCloseWindow );
|
||||
|
||||
frame->Bind( wxEVT_COMMAND_MENU_SELECTED, OnSave, LoggerID_Save);
|
||||
frame->Bind( wxEVT_COMMAND_MENU_SELECTED, OnClear, LoggerID_Clear);
|
||||
frame->Bind( wxEVT_COMMAND_MENU_SELECTED, OnClose, LoggerID_Close);
|
||||
frame->Bind( wxEVT_COMMAND_BUTTON_CLICKED, OnSave, LoggerID_Save);
|
||||
frame->Bind( wxEVT_COMMAND_BUTTON_CLICKED, OnClear, LoggerID_Clear);
|
||||
frame->Bind( wxEVT_COMMAND_BUTTON_CLICKED, OnClose, LoggerID_Close);
|
||||
|
||||
sFrame = std::move( frame );
|
||||
|
||||
sFrame->Show();
|
||||
|
||||
if (pLogger)
|
||||
pLogger->Flush();
|
||||
|
||||
// Also create the listeners
|
||||
if (!pUpdater)
|
||||
pUpdater.emplace();
|
||||
|
||||
if (pLogger) {
|
||||
pLogger->SetListener([]{
|
||||
if (auto pLogger = AudacityLogger::Get()) {
|
||||
if (sFrame && sFrame->IsShown()) {
|
||||
if (sText)
|
||||
sText->ChangeValue(pLogger->GetBuffer());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Initial flush populates sText
|
||||
pLogger->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
wxString AudacityLogger::GetLog(int count)
|
||||
{
|
||||
if (count == 0)
|
||||
@ -292,71 +135,3 @@ wxString AudacityLogger::GetLog(int count)
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
namespace {
|
||||
void OnCloseWindow(wxCloseEvent & WXUNUSED(e))
|
||||
{
|
||||
#if defined(__WXMAC__)
|
||||
// On the Mac, destroy the window rather than hiding it since the
|
||||
// log menu will override the root windows menu if there is no
|
||||
// project window open.
|
||||
sFrame.reset();
|
||||
#else
|
||||
sFrame->Show(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnClose(wxCommandEvent & WXUNUSED(e))
|
||||
{
|
||||
wxCloseEvent dummy;
|
||||
OnCloseWindow(dummy);
|
||||
}
|
||||
|
||||
void OnClear(wxCommandEvent & WXUNUSED(e))
|
||||
{
|
||||
if (auto pLogger = AudacityLogger::Get())
|
||||
pLogger->ClearLog();
|
||||
}
|
||||
|
||||
void OnSave(wxCommandEvent & WXUNUSED(e))
|
||||
{
|
||||
wxString fName = _("log.txt");
|
||||
|
||||
fName = SelectFile(FileNames::Operation::Export,
|
||||
XO("Save log to:"),
|
||||
wxEmptyString,
|
||||
fName,
|
||||
wxT("txt"),
|
||||
{ FileNames::TextFiles },
|
||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
|
||||
sFrame.get());
|
||||
|
||||
if (fName.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(sText && sText->SaveFile(fName))) {
|
||||
AudacityMessageBox(
|
||||
XO("Couldn't save log to file: %s").Format( fName ),
|
||||
XO("Warning"),
|
||||
wxICON_EXCLAMATION,
|
||||
sFrame.get());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void LogWindowUpdater::UpdatePrefs()
|
||||
{
|
||||
//! Re-create the non-modal window in case of change of preferred language
|
||||
if (sFrame) {
|
||||
bool shown = sFrame->IsShown();
|
||||
if (shown) {
|
||||
LogWindow::Show(false);
|
||||
}
|
||||
sFrame.reset();
|
||||
if (shown) {
|
||||
LogWindow::Show(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,6 @@
|
||||
#ifndef __AUDACITY_LOGGER__
|
||||
#define __AUDACITY_LOGGER__
|
||||
|
||||
#include <functional>
|
||||
#include "MemoryX.h"
|
||||
#include "Prefs.h"
|
||||
#include <wx/log.h> // to inherit
|
||||
#include <wx/event.h> // to inherit wxEvtHandler
|
||||
|
||||
@ -61,12 +58,4 @@ protected:
|
||||
bool mUpdated;
|
||||
};
|
||||
|
||||
//! Maintains the unique logging window which displays debug information
|
||||
class AUDACITY_DLL_API LogWindow
|
||||
{
|
||||
public:
|
||||
//! Show or hide the unique logging window; create it on demand the first time it is shown
|
||||
static void Show(bool show = true);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -164,6 +164,8 @@ list( APPEND SOURCES
|
||||
Legacy.cpp
|
||||
Legacy.h
|
||||
LightThemeAsCeeCode.h
|
||||
LogWindow.cpp
|
||||
LogWindow.h
|
||||
Lyrics.cpp
|
||||
Lyrics.h
|
||||
LyricsWindow.cpp
|
||||
|
@ -2,55 +2,36 @@
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
AudacityLogger.cpp
|
||||
LogWindow.cpp
|
||||
|
||||
******************************************************************//**
|
||||
Paul Licameli split from AudacityLogger.cpp
|
||||
|
||||
\class AudacityLogger
|
||||
\brief AudacityLogger is a thread-safe logger class
|
||||
**********************************************************************/
|
||||
#include "LogWindow.h"
|
||||
|
||||
Provides thread-safe logging based on the wxWidgets log facility.
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
|
||||
|
||||
#include "AudacityLogger.h"
|
||||
|
||||
|
||||
|
||||
#include "FileNames.h"
|
||||
#include "Internat.h"
|
||||
#include "SelectFile.h"
|
||||
#include "ShuttleGui.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/log.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/frame.h>
|
||||
#include <wx/icon.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wx/weakref.h>
|
||||
|
||||
#include "../images/AudacityLogoAlpha.xpm"
|
||||
#include "AudacityLogger.h"
|
||||
#include "widgets/AudacityMessageBox.h"
|
||||
#include "FileNames.h"
|
||||
#include "Internat.h"
|
||||
#include "MemoryX.h"
|
||||
#include "Prefs.h"
|
||||
#include "SelectFile.h"
|
||||
#include "ShuttleGui.h"
|
||||
|
||||
//
|
||||
// AudacityLogger class
|
||||
//
|
||||
// Two reasons for this class instead of the wxLogWindow class (or any WX GUI logging class)
|
||||
//
|
||||
// 1) If wxLogWindow is used and initialized before the Mac's "root" window, then
|
||||
#include "../images/AudacityLogoAlpha.xpm"
|
||||
|
||||
// If wxLogWindow is used and initialized before the Mac's "root" window, then
|
||||
// Audacity may crash when terminating. It's not fully understood why this occurs
|
||||
// but it probably has to do with the order of deletion. However, deferring the
|
||||
// creation of the log window until it is actually shown circumvents the problem.
|
||||
// 2) By providing an Audacity specific logging class, it can be made thread-safe and,
|
||||
// as such, can be used by the ever growing threading within Audacity.
|
||||
//
|
||||
enum
|
||||
{
|
||||
LoggerID_Save = wxID_HIGHEST + 1,
|
||||
@ -77,90 +58,6 @@ void OnClear(wxCommandEvent & e);
|
||||
void OnSave(wxCommandEvent & e);
|
||||
}
|
||||
|
||||
AudacityLogger *AudacityLogger::Get()
|
||||
{
|
||||
static std::once_flag flag;
|
||||
std::call_once( flag, []{
|
||||
// wxWidgets will clean up the logger for the main thread, so we can say
|
||||
// safenew. See:
|
||||
// http://docs.wxwidgets.org/3.0/classwx_log.html#a2525bf54fa3f31dc50e6e3cd8651e71d
|
||||
std::unique_ptr < wxLog > // DELETE any previous logger
|
||||
{ wxLog::SetActiveTarget(safenew AudacityLogger) };
|
||||
} );
|
||||
|
||||
// Use dynamic_cast so that we get a NULL ptr in case our logger
|
||||
// is no longer the target.
|
||||
return dynamic_cast<AudacityLogger *>(wxLog::GetActiveTarget());
|
||||
}
|
||||
|
||||
AudacityLogger::AudacityLogger()
|
||||
: wxEvtHandler(),
|
||||
wxLog()
|
||||
{
|
||||
mUpdated = false;
|
||||
}
|
||||
|
||||
AudacityLogger::~AudacityLogger() = default;
|
||||
|
||||
void AudacityLogger::Flush()
|
||||
{
|
||||
if (mUpdated && mListener && mListener())
|
||||
mUpdated = false;
|
||||
}
|
||||
|
||||
auto AudacityLogger::SetListener(Listener listener) -> Listener
|
||||
{
|
||||
auto result = std::move(mListener);
|
||||
mListener = std::move(listener);
|
||||
return result;
|
||||
}
|
||||
|
||||
void AudacityLogger::DoLogText(const wxString & str)
|
||||
{
|
||||
if (!wxIsMainThread()) {
|
||||
wxMutexGuiEnter();
|
||||
}
|
||||
|
||||
if (mBuffer.empty()) {
|
||||
wxString stamp;
|
||||
|
||||
TimeStamp(&stamp);
|
||||
|
||||
mBuffer << stamp << _TS("Audacity ") << AUDACITY_VERSION_STRING << wxT("\n");
|
||||
}
|
||||
|
||||
mBuffer << str << wxT("\n");
|
||||
|
||||
mUpdated = true;
|
||||
|
||||
Flush();
|
||||
|
||||
if (!wxIsMainThread()) {
|
||||
wxMutexGuiLeave();
|
||||
}
|
||||
}
|
||||
|
||||
bool AudacityLogger::SaveLog(const wxString &fileName) const
|
||||
{
|
||||
wxFFile file(fileName, wxT("w"));
|
||||
|
||||
if (file.IsOpened()) {
|
||||
file.Write(mBuffer);
|
||||
file.Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AudacityLogger::ClearLog()
|
||||
{
|
||||
mBuffer = wxEmptyString;
|
||||
DoLogText(wxT("Log Cleared."));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LogWindow::Show(bool show)
|
||||
{
|
||||
// Hide the frame if created, otherwise do nothing
|
||||
@ -275,24 +172,6 @@ void LogWindow::Show(bool show)
|
||||
}
|
||||
}
|
||||
|
||||
wxString AudacityLogger::GetLog(int count)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
wxString buffer;
|
||||
|
||||
auto lines = wxStringTokenize(mBuffer, wxT("\r\n"), wxTOKEN_RET_DELIMS);
|
||||
for (int index = lines.size() - 1; index >= 0 && count > 0; --index, --count)
|
||||
{
|
||||
buffer.Prepend(lines[index]);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
namespace {
|
||||
void OnCloseWindow(wxCloseEvent & WXUNUSED(e))
|
||||
{
|
||||
@ -314,7 +193,8 @@ void OnClose(wxCommandEvent & WXUNUSED(e))
|
||||
|
||||
void OnClear(wxCommandEvent & WXUNUSED(e))
|
||||
{
|
||||
if (auto pLogger = AudacityLogger::Get())
|
||||
auto pLogger = AudacityLogger::Get();
|
||||
if (pLogger)
|
||||
pLogger->ClearLog();
|
||||
}
|
||||
|
||||
|
@ -2,64 +2,14 @@
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
AudacityLogger.h
|
||||
LogWindow.h
|
||||
|
||||
Dominic Mazzoni
|
||||
Paul Licameli split from AudacityLogger.h
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef __AUDACITY_LOGGER__
|
||||
#define __AUDACITY_LOGGER__
|
||||
|
||||
#include <functional>
|
||||
#include "MemoryX.h"
|
||||
#include "Prefs.h"
|
||||
#include <wx/log.h> // to inherit
|
||||
#include <wx/event.h> // to inherit wxEvtHandler
|
||||
|
||||
class wxFrame;
|
||||
class wxTextCtrl;
|
||||
|
||||
class AUDACITY_DLL_API AudacityLogger final : public wxEvtHandler,
|
||||
public wxLog
|
||||
{
|
||||
public:
|
||||
|
||||
~AudacityLogger() override;
|
||||
|
||||
// Get the singleton instance or null
|
||||
static AudacityLogger *Get();
|
||||
|
||||
bool SaveLog(const wxString &fileName) const;
|
||||
bool ClearLog();
|
||||
|
||||
//! Retrieve all or some of the lines since most recent ClearLog or start of program
|
||||
/*! If `count == 0` or is more than the number of lines, return all; else return the last `count` lines */
|
||||
wxString GetLog(int count = 0);
|
||||
|
||||
//! Get all the accumulated text since program start or last ClearLog()
|
||||
const wxString &GetBuffer() const { return mBuffer; }
|
||||
|
||||
void Flush() override;
|
||||
|
||||
//! Type of function called by Flush
|
||||
/*! @return true if flush completed
|
||||
*/
|
||||
using Listener = std::function< bool() >;
|
||||
|
||||
//! Set the unique listener, returning any previous one
|
||||
Listener SetListener(Listener listener);
|
||||
|
||||
protected:
|
||||
void DoLogText(const wxString & msg) override;
|
||||
|
||||
private:
|
||||
AudacityLogger();
|
||||
|
||||
Listener mListener;
|
||||
wxString mBuffer;
|
||||
bool mUpdated;
|
||||
};
|
||||
#ifndef __AUDACITY_LOG_WINDOW__
|
||||
#define __AUDACITY_LOG_WINDOW__
|
||||
|
||||
//! Maintains the unique logging window which displays debug information
|
||||
class AUDACITY_DLL_API LogWindow
|
||||
|
@ -6,12 +6,12 @@
|
||||
|
||||
#include "../AboutDialog.h"
|
||||
#include "../AllThemeResources.h"
|
||||
#include "../AudacityLogger.h"
|
||||
#include "../AudioIOBase.h"
|
||||
#include "../CommonCommandFlags.h"
|
||||
#include "../CrashReport.h" // for HAS_CRASH_REPORT
|
||||
#include "../FileNames.h"
|
||||
#include "../HelpText.h"
|
||||
#include "../LogWindow.h"
|
||||
#include "../Menus.h"
|
||||
#include "Prefs.h"
|
||||
#include "../Project.h"
|
||||
|
@ -36,8 +36,8 @@ for each problem encountered, since there can be many orphans.
|
||||
#include <wx/bmpbuttn.h>
|
||||
|
||||
|
||||
#include "../AudacityLogger.h"
|
||||
#include "wxPanelWrapper.h"
|
||||
#include "../LogWindow.h"
|
||||
#include "../Theme.h"
|
||||
#include "../AllThemeResources.h"
|
||||
#include "../widgets/HelpSystem.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user