Changed wxLog DoLogXXX() callbacks and introduced wxLogRecordInfo.
The main logging callback is now DoLogRecord() with DoLogTextAtLevel() and DoLogText() provided for convenience. The old DoLog() and DoLogString() are still called but deprecated and their overloads taking wxString which were only added in 2.9.0 are removed. wxLogRecordInfo allows associating more information than just the time stamp with the log record; for now only the logging thread id was added but more fields will make their appearance soon. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@61346 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
5f7c24e2ff
commit
bc73d5aec8
@ -129,9 +129,14 @@ Changes in behaviour not resulting in compilation errors, please read this!
|
||||
manual for more details.
|
||||
|
||||
- wxTreeCtrl::GetSelection now asserts if the tree has the wxTR_MULTIPLE style.
|
||||
Instead use GetSelections() for multiple items; or if you want only the
|
||||
Instead use GetSelections() for multiple items; or if you want only the
|
||||
single item last touched, the new wxTreeCtrl::GetFocusedItem.
|
||||
|
||||
- Custom log targets should be updated to override wxLog::DoLogRecord() method
|
||||
instead of DoLog() or DoLogString() and must be updated if they call the base
|
||||
class versions of these functions as this won't work any more; please see the
|
||||
documentation of wxLog for more information.
|
||||
|
||||
|
||||
Changes in behaviour which may result in compilation errors
|
||||
-----------------------------------------------------------
|
||||
|
@ -34,9 +34,7 @@ public:
|
||||
|
||||
protected:
|
||||
// implement sink function
|
||||
virtual void DoLogString(const wxString& szString, time_t t);
|
||||
|
||||
wxSUPPRESS_DOLOGSTRING_HIDE_WARNING()
|
||||
virtual void DoLogText(const wxString& msg);
|
||||
|
||||
private:
|
||||
// the control we use
|
||||
@ -63,9 +61,9 @@ public:
|
||||
virtual void Flush();
|
||||
|
||||
protected:
|
||||
virtual void DoLog(wxLogLevel level, const wxString& szString, time_t t);
|
||||
|
||||
wxSUPPRESS_DOLOG_HIDE_WARNING()
|
||||
virtual void DoLogRecord(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info);
|
||||
|
||||
// return the title to be used for the log dialog, depending on m_bErrors
|
||||
// and m_bWarnings values
|
||||
@ -142,11 +140,7 @@ public:
|
||||
virtual void OnFrameDelete(wxFrame *frame);
|
||||
|
||||
protected:
|
||||
virtual void DoLog(wxLogLevel level, const wxString& szString, time_t t);
|
||||
virtual void DoLogString(const wxString& szString, time_t t);
|
||||
|
||||
wxSUPPRESS_DOLOG_HIDE_WARNING()
|
||||
wxSUPPRESS_DOLOGSTRING_HIDE_WARNING()
|
||||
virtual void DoLogTextAtLevel(wxLogLevel level, const wxString& msg);
|
||||
|
||||
private:
|
||||
wxLogFrame *m_pLogFrame; // the log frame
|
||||
|
198
include/wx/log.h
198
include/wx/log.h
@ -55,6 +55,10 @@ typedef unsigned long wxLogLevel;
|
||||
|
||||
#include "wx/dynarray.h"
|
||||
|
||||
#if wxUSE_THREADS
|
||||
#include "wx/thread.h"
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
// wxUSE_LOG_DEBUG enables the debug log messages
|
||||
#ifndef wxUSE_LOG_DEBUG
|
||||
#if wxDEBUG_LEVEL
|
||||
@ -116,6 +120,33 @@ enum wxLogLevelValues
|
||||
|
||||
#include "wx/iosfwrap.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// information about a log record, i.e. unit of log output
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct wxLogRecordInfo
|
||||
{
|
||||
wxLogRecordInfo()
|
||||
{
|
||||
timestamp = 0;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
threadId = 0;
|
||||
#endif // wxUSE_THREADS
|
||||
}
|
||||
|
||||
// default copy ctor, assignment operator and dtor are ok
|
||||
|
||||
|
||||
// time of record generation
|
||||
time_t timestamp;
|
||||
|
||||
#if wxUSE_THREADS
|
||||
// id of the thread which logged this record
|
||||
wxThreadIdType threadId;
|
||||
#endif // wxUSE_THREADS
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// derive from this class to redirect (or suppress, or ...) log messages
|
||||
// normally, only a single instance of this class exists but it's not enforced
|
||||
@ -125,7 +156,11 @@ class WXDLLIMPEXP_BASE wxLog
|
||||
{
|
||||
public:
|
||||
// ctor
|
||||
wxLog(){}
|
||||
wxLog() { }
|
||||
|
||||
// make dtor virtual for all derived classes
|
||||
virtual ~wxLog();
|
||||
|
||||
|
||||
// these functions allow to completely disable all log messages
|
||||
|
||||
@ -136,10 +171,6 @@ public:
|
||||
static bool EnableLogging(bool doIt = true)
|
||||
{ bool doLogOld = ms_doLog; ms_doLog = doIt; return doLogOld; }
|
||||
|
||||
// static sink function - see DoLog() for function to overload in the
|
||||
// derived classes
|
||||
static void OnLog(wxLogLevel level, const wxString& szString, time_t t);
|
||||
|
||||
// message buffering
|
||||
|
||||
// flush shows all messages if they're not logged immediately (FILE
|
||||
@ -175,7 +206,7 @@ public:
|
||||
static void Resume() { ms_suspendCount--; }
|
||||
|
||||
// functions controlling the default wxLog behaviour
|
||||
// verbose mode is activated by standard command-line '-verbose'
|
||||
// verbose mode is activated by standard command-line '--verbose'
|
||||
// option
|
||||
static void SetVerbose(bool bVerbose = true) { ms_bVerbose = bVerbose; }
|
||||
|
||||
@ -234,22 +265,50 @@ public:
|
||||
static const wxString& GetTimestamp() { return ms_timestamp; }
|
||||
|
||||
|
||||
// helpers
|
||||
|
||||
// helpers: all functions in this section are mostly for internal use only,
|
||||
// don't call them from your code even if they are not formally deprecated
|
||||
|
||||
// put the time stamp into the string if ms_timestamp != NULL (don't
|
||||
// change it otherwise)
|
||||
static void TimeStamp(wxString *str);
|
||||
|
||||
// this method should only be called from derived classes DoLog()
|
||||
// implementations and shouldn't be called directly, use logging functions
|
||||
// instead
|
||||
void Log(wxLogLevel level, const wxString& msg, time_t t)
|
||||
// these methods should only be called from derived classes DoLogRecord(),
|
||||
// DoLogTextAtLevel() and DoLogText() implementations respectively and
|
||||
// shouldn't be called directly, use logging functions instead
|
||||
void LogRecord(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info)
|
||||
{
|
||||
DoLog(level, msg, t);
|
||||
DoLogRecord(level, msg, info);
|
||||
}
|
||||
|
||||
// make dtor virtual for all derived classes
|
||||
virtual ~wxLog();
|
||||
void LogTextAtLevel(wxLogLevel level, const wxString& msg)
|
||||
{
|
||||
DoLogTextAtLevel(level, msg);
|
||||
}
|
||||
|
||||
void LogText(const wxString& msg)
|
||||
{
|
||||
DoLogText(msg);
|
||||
}
|
||||
|
||||
// this is a helper used by wxLogXXX() functions, don't call it directly
|
||||
// and see DoLog() for function to overload in the derived classes
|
||||
static void OnLog(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info);
|
||||
|
||||
// version called when no information about the location of the log record
|
||||
// generation is available (but the time stamp is), it mainly exists for
|
||||
// backwards compatibility, don't use it in new code
|
||||
static void OnLog(wxLogLevel level, const wxString& msg, time_t t);
|
||||
|
||||
// a helper calling the above overload with current time
|
||||
static void OnLog(wxLogLevel level, const wxString& msg)
|
||||
{
|
||||
OnLog(level, msg, time(NULL));
|
||||
}
|
||||
|
||||
|
||||
// this method exists for backwards compatibility only, don't use
|
||||
@ -257,8 +316,10 @@ public:
|
||||
|
||||
#if WXWIN_COMPATIBILITY_2_6
|
||||
// this function doesn't do anything any more, don't call it
|
||||
wxDEPRECATED( static wxChar *SetLogBuffer(wxChar *buf, size_t size = 0) );
|
||||
#endif
|
||||
wxDEPRECATED_INLINE(
|
||||
static wxChar *SetLogBuffer(wxChar *, size_t = 0), return NULL;
|
||||
);
|
||||
#endif // WXWIN_COMPATIBILITY_2_6
|
||||
|
||||
// don't use integer masks any more, use string trace masks instead
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
@ -269,13 +330,34 @@ public:
|
||||
#endif // WXWIN_COMPATIBILITY_2_8
|
||||
|
||||
protected:
|
||||
// the logging functions that can be overridden
|
||||
// the logging functions that can be overridden: DoLogRecord() is called
|
||||
// for every "record", i.e. a unit of log output, to be logged and by
|
||||
// default formats the message and passes it to DoLogTextAtLevel() which in
|
||||
// turn passes it to DoLogText() by default
|
||||
|
||||
// override this method if you want to change message formatting or do
|
||||
// dynamic filtering
|
||||
virtual void DoLogRecord(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info);
|
||||
|
||||
// default DoLog() prepends the time stamp and a prefix corresponding
|
||||
// to the message to szString and then passes it to DoLogString()
|
||||
virtual void DoLog(wxLogLevel level, const wxString& szString, time_t t);
|
||||
// override this method to redirect output to different channels depending
|
||||
// on its level only; if even the level doesn't matter, override
|
||||
// DoLogText() instead
|
||||
virtual void DoLogTextAtLevel(wxLogLevel level, const wxString& msg);
|
||||
|
||||
// this function is not pure virtual as it might not be needed if you do
|
||||
// the logging in overridden DoLogRecord() or DoLogTextAtLevel() directly
|
||||
// but if you do not override them in your derived class you must override
|
||||
// this one as the default implementation of it simply asserts
|
||||
virtual void DoLogText(const wxString& msg);
|
||||
|
||||
|
||||
// the rest of the functions are for backwards compatibility only, don't
|
||||
// use them in new code; if you're updating your existing code you need to
|
||||
// switch to overriding DoLogRecord/Text() above (although as long as these
|
||||
// functions exist, log classes using them will continue to work)
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
// these shouldn't be used by new code
|
||||
wxDEPRECATED_BUT_USED_INTERNALLY(
|
||||
virtual void DoLog(wxLogLevel level, const char *szString, time_t t)
|
||||
);
|
||||
@ -283,47 +365,28 @@ protected:
|
||||
wxDEPRECATED_BUT_USED_INTERNALLY(
|
||||
virtual void DoLog(wxLogLevel level, const wchar_t *wzString, time_t t)
|
||||
);
|
||||
#endif // WXWIN_COMPATIBILITY_2_8
|
||||
|
||||
void LogString(const wxString& szString, time_t t)
|
||||
{ DoLogString(szString, t); }
|
||||
|
||||
// default DoLogString does nothing but is not pure virtual because if
|
||||
// you override DoLog() you might not need it at all
|
||||
virtual void DoLogString(const wxString& szString, time_t t);
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
// these shouldn't be used by new code
|
||||
virtual void DoLogString(const char *WXUNUSED(szString),
|
||||
time_t WXUNUSED(t)) {}
|
||||
virtual void DoLogString(const wchar_t *WXUNUSED(szString),
|
||||
time_t WXUNUSED(t)) {}
|
||||
wxDEPRECATED_BUT_USED_INTERNALLY_INLINE(
|
||||
virtual void DoLogString(const char *WXUNUSED(szString),
|
||||
time_t WXUNUSED(t)),
|
||||
)
|
||||
|
||||
wxDEPRECATED_BUT_USED_INTERNALLY_INLINE(
|
||||
virtual void DoLogString(const wchar_t *WXUNUSED(wzString),
|
||||
time_t WXUNUSED(t)),
|
||||
)
|
||||
#endif // WXWIN_COMPATIBILITY_2_8
|
||||
|
||||
// this macro should be used in the derived classes to avoid warnings about
|
||||
// hiding the other DoLog() overloads when overriding DoLog(wxString) --
|
||||
// but don't use it with MSVC which doesn't give this warning but does give
|
||||
// warning when a deprecated function is overridden
|
||||
#if WXWIN_COMPATIBILITY_2_8 && !defined(__VISUALC__)
|
||||
#define wxSUPPRESS_DOLOG_HIDE_WARNING() \
|
||||
virtual void DoLog(wxLogLevel, const char *, time_t) { } \
|
||||
virtual void DoLog(wxLogLevel, const wchar_t *, time_t) { }
|
||||
|
||||
#define wxSUPPRESS_DOLOGSTRING_HIDE_WARNING() \
|
||||
virtual void DoLogString(const char *, time_t) { } \
|
||||
virtual void DoLogString(const wchar_t *, time_t) { }
|
||||
#else
|
||||
#define wxSUPPRESS_DOLOG_HIDE_WARNING()
|
||||
#define wxSUPPRESS_DOLOGSTRING_HIDE_WARNING()
|
||||
#endif
|
||||
|
||||
// log a message indicating the number of times the previous message was
|
||||
// repeated if ms_prevCounter > 0, does nothing otherwise; return the old
|
||||
// value of ms_prevCounter
|
||||
// repeated if previous repetition counter is strictly positive, does
|
||||
// nothing otherwise; return the old value of repetition counter
|
||||
unsigned LogLastRepeatIfNeeded();
|
||||
|
||||
private:
|
||||
// implement of LogLastRepeatIfNeeded(): it assumes that the
|
||||
// caller had already locked ms_prevCS
|
||||
// caller had already locked GetPreviousLogCS()
|
||||
unsigned LogLastRepeatIfNeededUnlocked();
|
||||
|
||||
// static variables
|
||||
@ -333,11 +396,6 @@ private:
|
||||
// with the number of times it was repeated
|
||||
static bool ms_bRepetCounting;
|
||||
|
||||
static wxString ms_prevString; // previous message that was logged
|
||||
static unsigned ms_prevCounter; // how many times it was repeated
|
||||
static time_t ms_prevTimeStamp;// timestamp of the previous message
|
||||
static wxLogLevel ms_prevLevel; // level of the previous message
|
||||
|
||||
static wxLog *ms_pLogger; // currently active log sink
|
||||
static bool ms_doLog; // false => all logging disabled
|
||||
static bool ms_bAutoCreate; // create new log targets on demand?
|
||||
@ -378,15 +436,7 @@ public:
|
||||
virtual void Flush();
|
||||
|
||||
protected:
|
||||
#if wxUSE_LOG_DEBUG || wxUSE_LOG_TRACE
|
||||
virtual void DoLog(wxLogLevel level, const wxString& szString, time_t t);
|
||||
|
||||
wxSUPPRESS_DOLOG_HIDE_WARNING()
|
||||
#endif // wxUSE_LOG_DEBUG || wxUSE_LOG_TRACE
|
||||
|
||||
virtual void DoLogString(const wxString& szString, time_t t);
|
||||
|
||||
wxSUPPRESS_DOLOGSTRING_HIDE_WARNING()
|
||||
virtual void DoLogTextAtLevel(wxLogLevel level, const wxString& msg);
|
||||
|
||||
private:
|
||||
wxString m_str;
|
||||
@ -404,9 +454,7 @@ public:
|
||||
|
||||
protected:
|
||||
// implement sink function
|
||||
virtual void DoLogString(const wxString& szString, time_t t);
|
||||
|
||||
wxSUPPRESS_DOLOGSTRING_HIDE_WARNING()
|
||||
virtual void DoLogText(const wxString& msg);
|
||||
|
||||
FILE *m_fp;
|
||||
|
||||
@ -424,9 +472,7 @@ public:
|
||||
|
||||
protected:
|
||||
// implement sink function
|
||||
virtual void DoLogString(const wxString& szString, time_t t);
|
||||
|
||||
wxSUPPRESS_DOLOGSTRING_HIDE_WARNING()
|
||||
virtual void DoLogText(const wxString& msg);
|
||||
|
||||
// using ptr here to avoid including <iostream.h> from this file
|
||||
wxSTD ostream *m_ostr;
|
||||
@ -499,10 +545,10 @@ public:
|
||||
void DetachOldLog() { m_logOld = NULL; }
|
||||
|
||||
protected:
|
||||
// pass the chain to the old logger if needed
|
||||
virtual void DoLog(wxLogLevel level, const wxString& szString, time_t t);
|
||||
|
||||
wxSUPPRESS_DOLOG_HIDE_WARNING()
|
||||
// pass the record to the old logger if needed
|
||||
virtual void DoLogRecord(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info);
|
||||
|
||||
private:
|
||||
// the current log target
|
||||
|
@ -9,8 +9,7 @@
|
||||
|
||||
/**
|
||||
Different standard log levels (you may also define your own) used with
|
||||
wxLog::OnLog() by standard wxLog functions wxLogError(), wxLogWarning(),
|
||||
etc...
|
||||
by standard wxLog functions wxLogError(), wxLogWarning(), etc...
|
||||
*/
|
||||
enum wxLogLevelValues
|
||||
{
|
||||
@ -35,6 +34,24 @@ enum wxLogLevelValues
|
||||
*/
|
||||
typedef unsigned long wxLogLevel;
|
||||
|
||||
/**
|
||||
Information about a log record (unit of the log output).
|
||||
*/
|
||||
struct wxLogRecordInfo
|
||||
{
|
||||
/// Time when the log message was generated.
|
||||
time_t timestamp;
|
||||
|
||||
/**
|
||||
Id of the thread in which the message was generated.
|
||||
|
||||
This field is only available if wxWidgets was built with threads
|
||||
support (<code>wxUSE_THREADS == 1</code>).
|
||||
|
||||
@see wxThread::GetCurrentId()
|
||||
*/
|
||||
wxThreadIdType threadId;
|
||||
};
|
||||
|
||||
/**
|
||||
@class wxLogWindow
|
||||
@ -660,8 +677,7 @@ public:
|
||||
@section log_target Manipulating the log target
|
||||
|
||||
The functions in this section work with and manipulate the active log
|
||||
target. The OnLog() is called by the @e wxLogXXX() functions
|
||||
and invokes the DoLog() of the active log target if any.
|
||||
target.
|
||||
|
||||
Get/Set methods are used to install/query the current active target and,
|
||||
finally, DontCreateOnDemand() disables the automatic creation of a standard
|
||||
@ -670,7 +686,6 @@ public:
|
||||
easily lead to a loss of messages.
|
||||
|
||||
See also:
|
||||
@li OnLog()
|
||||
@li GetActiveTarget()
|
||||
@li SetActiveTarget()
|
||||
@li DontCreateOnDemand()
|
||||
@ -767,12 +782,6 @@ public:
|
||||
*/
|
||||
static bool IsAllowedTraceMask(const wxString& mask);
|
||||
|
||||
/**
|
||||
Forwards the message at specified level to the @e DoLog() function of the
|
||||
active log target if there is any, does nothing otherwise.
|
||||
*/
|
||||
static void OnLog(wxLogLevel level, const wxString& msg, time_t t);
|
||||
|
||||
/**
|
||||
Remove the @a mask from the list of allowed masks for
|
||||
wxLogTrace().
|
||||
@ -854,54 +863,88 @@ public:
|
||||
static void Suspend();
|
||||
|
||||
/**
|
||||
Log the given message.
|
||||
Log the given record.
|
||||
|
||||
This function should only be called from the DoLog() implementations in
|
||||
the derived classes (which can't call wxLog::DoLog() directly as it is
|
||||
protected), it should not be used for logging new messages which can be
|
||||
only sent to the currently active logger using OnLog() which also
|
||||
checks if the logging (for this level) is enabled while this method
|
||||
just directly calls DoLog().
|
||||
the derived classes if they need to call DoLogRecord() on another log
|
||||
object (they can, of course, just use wxLog::DoLogRecord() call syntax
|
||||
to call it on the object itself). It should not be used for logging new
|
||||
messages which can be only sent to the currently active logger using
|
||||
OnLog() which also checks if the logging (for this level) is enabled
|
||||
while this method just directly calls DoLog().
|
||||
|
||||
Example of use of this class from wxLogChain:
|
||||
@code
|
||||
void wxLogChain::DoLog(wxLogLevel level, const wxString& msg, time_t t)
|
||||
void wxLogChain::DoLogRecord(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info)
|
||||
{
|
||||
// let the previous logger show it
|
||||
if ( m_logOld && IsPassingMessages() )
|
||||
m_logOld->Log(level, msg, t);
|
||||
m_logOld->LogRecord(level, msg, info);
|
||||
|
||||
// and also send it to the new one
|
||||
if ( m_logNew && m_logNew != this )
|
||||
m_logNew->Log(level, msg, t);
|
||||
m_logNew->LogRecord(level, msg, info);
|
||||
}
|
||||
@endcode
|
||||
|
||||
@since 2.9.0
|
||||
@since 2.9.1
|
||||
*/
|
||||
void Log(wxLogLevel level, const wxString& msg, time_t timestamp);
|
||||
void LogRecord(wxLogLevel level, const wxString& msg, time_t timestamp);
|
||||
|
||||
protected:
|
||||
/**
|
||||
@name Logging callbacks.
|
||||
|
||||
The functions which should be overridden by custom log targets.
|
||||
|
||||
When defining a new log target, you have a choice between overriding
|
||||
DoLogRecord(), which provides maximal flexibility, DoLogTextAtLevel()
|
||||
which can be used if you don't intend to change the default log
|
||||
messages formatting but want to handle log messages of different levels
|
||||
differently or, in the simplest case, DoLogText().
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
Called to process the message of the specified severity. @a msg is the text
|
||||
of the message as specified in the call of @e wxLogXXX() function which
|
||||
generated it and @a timestamp is the moment when the message was generated.
|
||||
Called to created log a new record.
|
||||
|
||||
The base class version prepends the timestamp to the message, adds a prefix
|
||||
corresponding to the log level and then calls
|
||||
DoLogString() with the resulting string.
|
||||
*/
|
||||
virtual void DoLog(wxLogLevel level, const wxString& msg, time_t timestamp);
|
||||
Any log message created by wxLogXXX() functions is passed to this
|
||||
method of the active log target. The default implementation prepends
|
||||
the timestamp and, for some log levels (e.g. error and warning), the
|
||||
corresponding prefix to @a msg and passes it to DoLogTextAtLevel().
|
||||
|
||||
You may override this method to implement custom formatting of the
|
||||
log messages or to implement custom filtering of log messages (e.g. you
|
||||
could discard all log messages coming from the given source file).
|
||||
*/
|
||||
virtual void DoLogRecord(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info);
|
||||
|
||||
/**
|
||||
Called to log the specified string. The timestamp is already included in the
|
||||
string but still passed to this function.
|
||||
Called to log the specified string at given level.
|
||||
|
||||
A simple implementation may just send the string to @c stdout or, better,
|
||||
@c stderr.
|
||||
The base class versions logs debug and trace messages on the system
|
||||
default debug output channel and passes all the other messages to
|
||||
DoLogText().
|
||||
*/
|
||||
virtual void DoLogString(const wxString& msg, time_t timestamp);
|
||||
virtual void DoLogTextAtLevel(wxLogLevel level, const wxString& msg);
|
||||
|
||||
/**
|
||||
Called to log the specified string.
|
||||
|
||||
A simple implementation might just send the string to @c stdout or
|
||||
@c stderr or save it in a file (of course, the already existing
|
||||
wxLogStderr can be used for this).
|
||||
|
||||
The base class version of this function asserts so it must be
|
||||
overridden if you don't override DoLogRecord() or DoLogTextAtLevel().
|
||||
*/
|
||||
virtual void DoLogText(const wxString& msg);
|
||||
|
||||
//@}
|
||||
};
|
||||
|
||||
|
||||
|
@ -98,6 +98,40 @@ static inline wxCriticalSection& GetPreviousLogCS()
|
||||
static void wxLogWrap(FILE *f, const char *pszPrefix, const char *psz);
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// module globals
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// this struct is used to store information about the previous log message used
|
||||
// by OnLog() to (optionally) avoid logging multiple copies of the same message
|
||||
struct PreviousLogInfo
|
||||
{
|
||||
PreviousLogInfo()
|
||||
{
|
||||
numRepeated = 0;
|
||||
}
|
||||
|
||||
|
||||
// previous message itself
|
||||
wxString msg;
|
||||
|
||||
// its level
|
||||
wxLogLevel level;
|
||||
|
||||
// other information about it
|
||||
wxLogRecordInfo info;
|
||||
|
||||
// the number of times it was already repeated
|
||||
unsigned numRepeated;
|
||||
};
|
||||
|
||||
PreviousLogInfo gs_prevLog;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
@ -112,8 +146,9 @@ static inline wxCriticalSection& GetPreviousLogCS()
|
||||
// generic log function
|
||||
void wxVLogGeneric(wxLogLevel level, const wxString& format, va_list argptr)
|
||||
{
|
||||
if ( wxLog::IsEnabled() ) {
|
||||
wxLog::OnLog(level, wxString::FormatV(format, argptr), time(NULL));
|
||||
if ( wxLog::IsEnabled() )
|
||||
{
|
||||
wxLog::OnLog(level, wxString::FormatV(format, argptr));
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,10 +201,8 @@ void wxDoLogGenericUtf8(wxLogLevel level, const char *format, ...)
|
||||
#define IMPLEMENT_LOG_FUNCTION(level) \
|
||||
void wxVLog##level(const wxString& format, va_list argptr) \
|
||||
{ \
|
||||
if ( wxLog::IsEnabled() ) { \
|
||||
wxLog::OnLog(wxLOG_##level, \
|
||||
wxString::FormatV(format, argptr), time(NULL)); \
|
||||
} \
|
||||
if ( wxLog::IsEnabled() ) \
|
||||
wxLog::OnLog(wxLOG_##level, wxString::FormatV(format, argptr)); \
|
||||
} \
|
||||
IMPLEMENT_LOG_FUNCTION_WCHAR(level) \
|
||||
IMPLEMENT_LOG_FUNCTION_UTF8(level)
|
||||
@ -233,10 +266,8 @@ void wxDoLogFatalErrorUtf8(const char *format, ...)
|
||||
void wxVLogVerbose(const wxString& format, va_list argptr)
|
||||
{
|
||||
if ( wxLog::IsEnabled() ) {
|
||||
if ( wxLog::GetActiveTarget() != NULL && wxLog::GetVerbose() ) {
|
||||
wxLog::OnLog(wxLOG_Info,
|
||||
wxString::FormatV(format, argptr), time(NULL));
|
||||
}
|
||||
if ( wxLog::GetActiveTarget() != NULL && wxLog::GetVerbose() )
|
||||
wxLog::OnLog(wxLOG_Info, wxString::FormatV(format, argptr));
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,8 +300,7 @@ void wxDoLogVerboseUtf8(const char *format, ...)
|
||||
{
|
||||
if ( wxLog::IsEnabled() )
|
||||
{
|
||||
wxLog::OnLog(wxLOG_Debug,
|
||||
wxString::FormatV(format, argptr), time(NULL));
|
||||
wxLog::OnLog(wxLOG_Debug, wxString::FormatV(format, argptr));
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,7 +332,7 @@ void wxDoLogVerboseUtf8(const char *format, ...)
|
||||
wxString msg;
|
||||
msg << wxS("(") << mask << wxS(") ") << wxString::FormatV(format, argptr);
|
||||
|
||||
wxLog::OnLog(wxLOG_Trace, msg, time(NULL));
|
||||
wxLog::OnLog(wxLOG_Trace, msg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,7 +365,7 @@ void wxDoLogVerboseUtf8(const char *format, ...)
|
||||
// that wxLogTrace(wxTraceRefCount | wxTraceOle) will only do something
|
||||
// if both bits are set.
|
||||
if ( wxLog::IsEnabled() && ((wxLog::GetTraceMask() & mask) == mask) ) {
|
||||
wxLog::OnLog(wxLOG_Trace, wxString::FormatV(format, argptr), time(NULL));
|
||||
wxLog::OnLog(wxLOG_Trace, wxString::FormatV(format, argptr));
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,10 +467,10 @@ void WXDLLIMPEXP_BASE wxDoLogSysErrorUtf8(const char *format, ...)
|
||||
|
||||
void WXDLLIMPEXP_BASE wxVLogSysError(long err, const wxString& format, va_list argptr)
|
||||
{
|
||||
if ( wxLog::IsEnabled() ) {
|
||||
if ( wxLog::IsEnabled() )
|
||||
{
|
||||
wxLog::OnLog(wxLOG_Error,
|
||||
wxString::FormatV(format, argptr) + wxLogSysErrorHelper(err),
|
||||
time(NULL));
|
||||
wxString::FormatV(format, argptr) + wxLogSysErrorHelper(err));
|
||||
}
|
||||
}
|
||||
|
||||
@ -491,23 +521,23 @@ unsigned wxLog::LogLastRepeatIfNeeded()
|
||||
|
||||
unsigned wxLog::LogLastRepeatIfNeededUnlocked()
|
||||
{
|
||||
const unsigned count = ms_prevCounter;
|
||||
const unsigned count = gs_prevLog.numRepeated;
|
||||
|
||||
if ( ms_prevCounter )
|
||||
if ( gs_prevLog.numRepeated )
|
||||
{
|
||||
wxString msg;
|
||||
#if wxUSE_INTL
|
||||
msg.Printf(wxPLURAL("The previous message repeated once.",
|
||||
"The previous message repeated %lu times.",
|
||||
ms_prevCounter),
|
||||
ms_prevCounter);
|
||||
gs_prevLog.numRepeated),
|
||||
gs_prevLog.numRepeated);
|
||||
#else
|
||||
msg.Printf(wxS("The previous message was repeated %lu times."),
|
||||
ms_prevCounter);
|
||||
gs_prevLog.numRepeated);
|
||||
#endif
|
||||
ms_prevCounter = 0;
|
||||
ms_prevString.clear();
|
||||
DoLog(ms_prevLevel, msg, ms_prevTimeStamp);
|
||||
gs_prevLog.numRepeated = 0;
|
||||
gs_prevLog.msg.clear();
|
||||
DoLogRecord(gs_prevLog.level, msg, gs_prevLog.info);
|
||||
}
|
||||
|
||||
return count;
|
||||
@ -517,19 +547,39 @@ wxLog::~wxLog()
|
||||
{
|
||||
// Flush() must be called before destroying the object as otherwise some
|
||||
// messages could be lost
|
||||
if ( ms_prevCounter )
|
||||
if ( gs_prevLog.numRepeated )
|
||||
{
|
||||
wxMessageOutputDebug().Printf
|
||||
(
|
||||
wxS("Last repeated message (\"%s\", %lu times) wasn't output"),
|
||||
ms_prevString,
|
||||
ms_prevCounter
|
||||
gs_prevLog.msg,
|
||||
gs_prevLog.numRepeated
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxLog logging functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* static */
|
||||
void wxLog::OnLog(wxLogLevel level, const wxString& szString, time_t t)
|
||||
void
|
||||
wxLog::OnLog(wxLogLevel level, const wxString& msg, time_t t)
|
||||
{
|
||||
wxLogRecordInfo info;
|
||||
info.timestamp = t;
|
||||
#if wxUSE_THREADS
|
||||
info.threadId = wxThread::GetCurrentId();
|
||||
#endif // wxUSE_THREADS
|
||||
|
||||
OnLog(level, msg, info);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
wxLog::OnLog(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info)
|
||||
{
|
||||
if ( IsEnabled() && ms_logLevel >= level )
|
||||
{
|
||||
@ -540,9 +590,9 @@ void wxLog::OnLog(wxLogLevel level, const wxString& szString, time_t t)
|
||||
{
|
||||
wxCRIT_SECT_LOCKER(lock, GetPreviousLogCS());
|
||||
|
||||
if ( szString == ms_prevString )
|
||||
if ( msg == gs_prevLog.msg )
|
||||
{
|
||||
ms_prevCounter++;
|
||||
gs_prevLog.numRepeated++;
|
||||
|
||||
// nothing else to do, in particular, don't log the
|
||||
// repeated message
|
||||
@ -552,42 +602,112 @@ void wxLog::OnLog(wxLogLevel level, const wxString& szString, time_t t)
|
||||
pLogger->LogLastRepeatIfNeededUnlocked();
|
||||
|
||||
// reset repetition counter for a new message
|
||||
ms_prevString = szString;
|
||||
ms_prevLevel = level;
|
||||
ms_prevTimeStamp = t;
|
||||
gs_prevLog.msg = msg;
|
||||
gs_prevLog.level = level;
|
||||
gs_prevLog.info = info;
|
||||
}
|
||||
|
||||
pLogger->DoLog(level, szString, t);
|
||||
pLogger->DoLogRecord(level, msg, info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deprecated function
|
||||
#if WXWIN_COMPATIBILITY_2_6
|
||||
|
||||
wxChar *wxLog::SetLogBuffer(wxChar * WXUNUSED(buf), size_t WXUNUSED(size))
|
||||
void wxLog::DoLogRecord(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // WXWIN_COMPATIBILITY_2_6
|
||||
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
|
||||
void wxLog::DoLog(wxLogLevel WXUNUSED(level),
|
||||
const char *WXUNUSED(szString),
|
||||
time_t WXUNUSED(t))
|
||||
{
|
||||
}
|
||||
|
||||
void wxLog::DoLog(wxLogLevel WXUNUSED(level),
|
||||
const wchar_t *WXUNUSED(wzString),
|
||||
time_t WXUNUSED(t))
|
||||
{
|
||||
}
|
||||
|
||||
// call the old DoLog() to ensure that existing custom log classes still
|
||||
// work
|
||||
//
|
||||
// as the user code could have defined it as either taking "const char *"
|
||||
// (in ANSI build) or "const wxChar *" (in ANSI/Unicode), we have no choice
|
||||
// but to call both of them
|
||||
DoLog(level, (const char*)msg.mb_str(), info.timestamp);
|
||||
DoLog(level, (const wchar_t*)msg.wc_str(), info.timestamp);
|
||||
#endif // WXWIN_COMPATIBILITY_2_8
|
||||
|
||||
|
||||
// TODO: it would be better to extract message formatting in a separate
|
||||
// wxLogFormatter class but for now we hard code formatting here
|
||||
|
||||
wxString prefix;
|
||||
|
||||
// don't time stamp debug messages under MSW as debug viewers usually
|
||||
// already have an option to do it
|
||||
#ifdef __WXMSW__
|
||||
if ( level != wxLOG_Debug && level != wxLOG_Trace )
|
||||
#endif // __WXMSW__
|
||||
TimeStamp(&prefix);
|
||||
|
||||
// TODO: use the other wxLogRecordInfo fields
|
||||
|
||||
switch ( level )
|
||||
{
|
||||
case wxLOG_Error:
|
||||
prefix += _("Error: ");
|
||||
break;
|
||||
|
||||
case wxLOG_Warning:
|
||||
prefix += _("Warning: ");
|
||||
break;
|
||||
|
||||
// don't prepend "debug/trace" prefix under MSW as it goes to the debug
|
||||
// window anyhow and so can't be confused with something else
|
||||
#ifndef __WXMSW__
|
||||
case wxLOG_Debug:
|
||||
// this prefix (as well as the one below) is intentionally not
|
||||
// translated as nobody translates debug messages anyhow
|
||||
prefix += "Debug: ";
|
||||
break;
|
||||
|
||||
case wxLOG_Trace:
|
||||
prefix += "Trace: ";
|
||||
break;
|
||||
#endif // !__WXMSW__
|
||||
}
|
||||
|
||||
DoLogTextAtLevel(level, prefix + msg);
|
||||
}
|
||||
|
||||
void wxLog::DoLogTextAtLevel(wxLogLevel level, const wxString& msg)
|
||||
{
|
||||
// we know about debug messages (because using wxMessageOutputDebug is the
|
||||
// right thing to do in 99% of all cases and also for compatibility) but
|
||||
// anything else needs to be handled in the derived class
|
||||
if ( level == wxLOG_Debug || level == wxLOG_Trace )
|
||||
{
|
||||
wxMessageOutputDebug().Output(msg + wxS('\n'));
|
||||
}
|
||||
else
|
||||
{
|
||||
DoLogText(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void wxLog::DoLogText(const wxString& WXUNUSED(msg))
|
||||
{
|
||||
// in 2.8-compatible build the derived class might override DoLog() or
|
||||
// DoLogString() instead so we can't have this assert there
|
||||
#if !WXWIN_COMPATIBILITY_2_8
|
||||
wxFAIL_MSG( "must be overridden if it is called" );
|
||||
#endif // WXWIN_COMPATIBILITY_2_8
|
||||
}
|
||||
|
||||
void wxLog::DoLog(wxLogLevel WXUNUSED(level), const char *szString, time_t t)
|
||||
{
|
||||
DoLogString(szString, t);
|
||||
}
|
||||
|
||||
void wxLog::DoLog(wxLogLevel WXUNUSED(level), const wchar_t *wzString, time_t t)
|
||||
{
|
||||
DoLogString(wzString, t);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxLog active target management
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxLog *wxLog::GetActiveTarget()
|
||||
{
|
||||
if ( ms_bAutoCreate && ms_pLogger == NULL ) {
|
||||
@ -683,87 +803,6 @@ void wxLog::TimeStamp(wxString *str)
|
||||
#endif // wxUSE_DATETIME
|
||||
}
|
||||
|
||||
void wxLog::DoLog(wxLogLevel level, const wxString& szString, time_t t)
|
||||
{
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
// DoLog() signature changed since 2.8, so we call the old versions here
|
||||
// so that existing custom log classes still work:
|
||||
DoLog(level, (const char*)szString.mb_str(), t);
|
||||
DoLog(level, (const wchar_t*)szString.wc_str(), t);
|
||||
#endif
|
||||
|
||||
switch ( level ) {
|
||||
case wxLOG_FatalError:
|
||||
LogString(_("Fatal error: ") + szString, t);
|
||||
LogString(_("Program aborted."), t);
|
||||
Flush();
|
||||
#ifdef __WXWINCE__
|
||||
ExitThread(3);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case wxLOG_Error:
|
||||
LogString(_("Error: ") + szString, t);
|
||||
break;
|
||||
|
||||
case wxLOG_Warning:
|
||||
LogString(_("Warning: ") + szString, t);
|
||||
break;
|
||||
|
||||
case wxLOG_Info:
|
||||
if ( GetVerbose() )
|
||||
case wxLOG_Message:
|
||||
case wxLOG_Status:
|
||||
default: // log unknown log levels too
|
||||
LogString(szString, t);
|
||||
break;
|
||||
|
||||
#if wxUSE_LOG_DEBUG || wxUSE_LOG_TRACE
|
||||
#if wxUSE_LOG_TRACE
|
||||
case wxLOG_Trace:
|
||||
#endif
|
||||
#if wxUSE_LOG_DEBUG
|
||||
case wxLOG_Debug:
|
||||
#endif
|
||||
{
|
||||
wxString str;
|
||||
|
||||
// don't prepend "debug/trace" prefix under MSW as it goes to
|
||||
// the debug window anyhow and don't add time stamp neither as
|
||||
// debug output viewers under Windows typically add it
|
||||
// themselves anyhow
|
||||
#ifndef __WXMSW__
|
||||
TimeStamp(&str);
|
||||
|
||||
str += level == wxLOG_Trace ? wxT("Trace: ")
|
||||
: wxT("Debug: ");
|
||||
#endif // !__WXMSW__
|
||||
|
||||
str += szString;
|
||||
wxMessageOutputDebug().Output(str);
|
||||
}
|
||||
break;
|
||||
#endif // wxUSE_LOG_DEBUG || wxUSE_LOG_TRACE
|
||||
}
|
||||
}
|
||||
|
||||
void wxLog::DoLogString(const wxString& szString, time_t t)
|
||||
{
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
// DoLogString() signature changed since 2.8, so we call the old versions
|
||||
// here so that existing custom log classes still work; unfortunately this
|
||||
// also means that we can't have the wxFAIL_MSG below in compat mode
|
||||
DoLogString((const char*)szString.mb_str(), t);
|
||||
DoLogString((const wchar_t*)szString.wc_str(), t);
|
||||
#else
|
||||
wxFAIL_MSG(wxS("DoLogString must be overriden if it's called."));
|
||||
wxUnusedVar(szString);
|
||||
wxUnusedVar(t);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wxLog::Flush()
|
||||
{
|
||||
LogLastRepeatIfNeeded();
|
||||
@ -798,42 +837,20 @@ void wxLogBuffer::Flush()
|
||||
}
|
||||
}
|
||||
|
||||
#if wxUSE_LOG_DEBUG || wxUSE_LOG_TRACE
|
||||
|
||||
void wxLogBuffer::DoLog(wxLogLevel level, const wxString& szString, time_t t)
|
||||
void wxLogBuffer::DoLogTextAtLevel(wxLogLevel level, const wxString& msg)
|
||||
{
|
||||
// don't put debug messages in the buffer, we don't want to show
|
||||
// them to the user in a msg box, log them immediately
|
||||
bool showImmediately = false;
|
||||
#if wxUSE_LOG_TRACE
|
||||
if ( level == wxLOG_Trace )
|
||||
showImmediately = true;
|
||||
#endif
|
||||
#if wxUSE_LOG_DEBUG
|
||||
if ( level == wxLOG_Debug )
|
||||
showImmediately = true;
|
||||
#endif
|
||||
|
||||
if ( showImmediately )
|
||||
switch ( level )
|
||||
{
|
||||
wxString str;
|
||||
TimeStamp(&str);
|
||||
str += szString;
|
||||
case wxLOG_Debug:
|
||||
case wxLOG_Trace:
|
||||
wxLog::DoLogTextAtLevel(level, msg);
|
||||
break;
|
||||
|
||||
wxMessageOutputDebug dbgout;
|
||||
dbgout.Printf(wxS("%s\n"), str.c_str());
|
||||
default:
|
||||
m_str << msg << wxS("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
wxLog::DoLog(level, szString, t);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // wxUSE_LOG_DEBUG || wxUSE_LOG_TRACE
|
||||
|
||||
void wxLogBuffer::DoLogString(const wxString& szString, time_t WXUNUSED(t))
|
||||
{
|
||||
m_str << szString << wxS("\n");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -848,14 +865,9 @@ wxLogStderr::wxLogStderr(FILE *fp)
|
||||
m_fp = fp;
|
||||
}
|
||||
|
||||
void wxLogStderr::DoLogString(const wxString& szString, time_t WXUNUSED(t))
|
||||
void wxLogStderr::DoLogText(const wxString& msg)
|
||||
{
|
||||
wxString str;
|
||||
TimeStamp(&str);
|
||||
str << szString;
|
||||
|
||||
wxFputs(str, m_fp);
|
||||
wxFputc(wxS('\n'), m_fp);
|
||||
wxFputs(msg + '\n', m_fp);
|
||||
fflush(m_fp);
|
||||
|
||||
// under GUI systems such as Windows or Mac, programs usually don't have
|
||||
@ -867,8 +879,7 @@ void wxLogStderr::DoLogString(const wxString& szString, time_t WXUNUSED(t))
|
||||
wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
|
||||
if ( traits && !traits->HasStderr() )
|
||||
{
|
||||
wxMessageOutputDebug dbgout;
|
||||
dbgout.Printf(wxS("%s\n"), str.c_str());
|
||||
wxMessageOutputDebug().Output(msg + wxS('\n'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -887,11 +898,9 @@ wxLogStream::wxLogStream(wxSTD ostream *ostr)
|
||||
m_ostr = ostr;
|
||||
}
|
||||
|
||||
void wxLogStream::DoLogString(const wxString& szString, time_t WXUNUSED(t))
|
||||
void wxLogStream::DoLogText(const wxString& msg)
|
||||
{
|
||||
wxString stamp;
|
||||
TimeStamp(&stamp);
|
||||
(*m_ostr) << stamp << szString << wxSTD endl;
|
||||
(*m_ostr) << msg << wxSTD endl;
|
||||
}
|
||||
#endif // wxUSE_STD_IOSTREAM
|
||||
|
||||
@ -933,15 +942,17 @@ void wxLogChain::Flush()
|
||||
m_logNew->Flush();
|
||||
}
|
||||
|
||||
void wxLogChain::DoLog(wxLogLevel level, const wxString& szString, time_t t)
|
||||
void wxLogChain::DoLogRecord(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info)
|
||||
{
|
||||
// let the previous logger show it
|
||||
if ( m_logOld && IsPassingMessages() )
|
||||
m_logOld->Log(level, szString, t);
|
||||
m_logOld->LogRecord(level, msg, info);
|
||||
|
||||
// and also send it to the new one
|
||||
if ( m_logNew && m_logNew != this )
|
||||
m_logNew->Log(level, szString, t);
|
||||
m_logNew->LogRecord(level, msg, info);
|
||||
}
|
||||
|
||||
#ifdef __VISUALC__
|
||||
@ -981,10 +992,6 @@ wxLogInterposerTemp::wxLogInterposerTemp()
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool wxLog::ms_bRepetCounting = false;
|
||||
wxString wxLog::ms_prevString;
|
||||
unsigned int wxLog::ms_prevCounter = 0;
|
||||
time_t wxLog::ms_prevTimeStamp= 0;
|
||||
wxLogLevel wxLog::ms_prevLevel;
|
||||
|
||||
wxLog *wxLog::ms_pLogger = NULL;
|
||||
bool wxLog::ms_doLog = true;
|
||||
|
@ -224,16 +224,13 @@ void wxVLogStatus(wxFrame *pFrame, const wxString& format, va_list argptr)
|
||||
wxString msg;
|
||||
|
||||
wxLog *pLog = wxLog::GetActiveTarget();
|
||||
if ( pLog != NULL ) {
|
||||
if ( pLog != NULL )
|
||||
{
|
||||
msg.PrintfV(format, argptr);
|
||||
|
||||
wxASSERT( gs_pFrame == NULL ); // should be reset!
|
||||
gs_pFrame = pFrame;
|
||||
#ifdef __WXWINCE__
|
||||
wxLog::OnLog(wxLOG_Status, msg, 0);
|
||||
#else
|
||||
wxLog::OnLog(wxLOG_Status, msg, time(NULL));
|
||||
#endif
|
||||
wxLog::OnLog(wxLOG_Status, msg);
|
||||
gs_pFrame = NULL;
|
||||
}
|
||||
}
|
||||
@ -403,16 +400,19 @@ void wxLogGui::Flush()
|
||||
}
|
||||
|
||||
// log all kinds of messages
|
||||
void wxLogGui::DoLog(wxLogLevel level, const wxString& szString, time_t t)
|
||||
void wxLogGui::DoLogRecord(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& info)
|
||||
{
|
||||
switch ( level ) {
|
||||
switch ( level )
|
||||
{
|
||||
case wxLOG_Info:
|
||||
if ( GetVerbose() )
|
||||
case wxLOG_Message:
|
||||
{
|
||||
m_aMessages.Add(szString);
|
||||
m_aMessages.Add(msg);
|
||||
m_aSeverity.Add(wxLOG_Message);
|
||||
m_aTimes.Add((long)t);
|
||||
m_aTimes.Add((long)info.timestamp);
|
||||
m_bHasMessages = true;
|
||||
}
|
||||
break;
|
||||
@ -430,17 +430,11 @@ void wxLogGui::DoLog(wxLogLevel level, const wxString& szString, time_t t)
|
||||
}
|
||||
|
||||
if ( pFrame && pFrame->GetStatusBar() )
|
||||
pFrame->SetStatusText(szString);
|
||||
pFrame->SetStatusText(msg);
|
||||
}
|
||||
#endif // wxUSE_STATUSBAR
|
||||
break;
|
||||
|
||||
case wxLOG_FatalError:
|
||||
// show this one immediately
|
||||
wxMessageBox(szString, _("Fatal error"), wxICON_HAND);
|
||||
wxExit();
|
||||
break;
|
||||
|
||||
case wxLOG_Error:
|
||||
if ( !m_bErrors ) {
|
||||
#if !wxUSE_LOG_DIALOG
|
||||
@ -461,16 +455,16 @@ void wxLogGui::DoLog(wxLogLevel level, const wxString& szString, time_t t)
|
||||
m_bWarnings = true;
|
||||
}
|
||||
|
||||
m_aMessages.Add(szString);
|
||||
m_aMessages.Add(msg);
|
||||
m_aSeverity.Add((int)level);
|
||||
m_aTimes.Add((long)t);
|
||||
m_aTimes.Add((long)info.timestamp);
|
||||
m_bHasMessages = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
// let the base class deal with debug/trace messages as well as any
|
||||
// custom levels
|
||||
wxLog::DoLog(level, szString, t);
|
||||
wxLog::DoLogRecord(level, msg, info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -523,7 +517,7 @@ private:
|
||||
// do show the message in the text control
|
||||
void DoShowLogMessage(const wxString& message)
|
||||
{
|
||||
m_pTextCtrl->AppendText(message);
|
||||
m_pTextCtrl->AppendText(message + wxS('\n'));
|
||||
}
|
||||
|
||||
wxTextCtrl *m_pTextCtrl;
|
||||
@ -713,44 +707,21 @@ void wxLogWindow::Show(bool bShow)
|
||||
m_pLogFrame->Show(bShow);
|
||||
}
|
||||
|
||||
void wxLogWindow::DoLog(wxLogLevel level, const wxString& szString, time_t t)
|
||||
void wxLogWindow::DoLogTextAtLevel(wxLogLevel level, const wxString& msg)
|
||||
{
|
||||
// first let the previous logger show it
|
||||
wxLogPassThrough::DoLog(level, szString, t);
|
||||
wxLogPassThrough::DoLogTextAtLevel(level, msg);
|
||||
|
||||
if ( m_pLogFrame ) {
|
||||
switch ( level ) {
|
||||
case wxLOG_Status:
|
||||
// by default, these messages are ignored by wxLog, so process
|
||||
// them ourselves
|
||||
if ( !szString.empty() )
|
||||
{
|
||||
wxString str;
|
||||
str << _("Status: ") << szString;
|
||||
LogString(str, t);
|
||||
}
|
||||
break;
|
||||
if ( !m_pLogFrame )
|
||||
return;
|
||||
|
||||
// don't put trace messages in the text window for 2 reasons:
|
||||
// 1) there are too many of them
|
||||
// 2) they may provoke other trace messages thus sending a program
|
||||
// into an infinite loop
|
||||
case wxLOG_Trace:
|
||||
break;
|
||||
|
||||
default:
|
||||
// and this will format it nicely and call our DoLogString()
|
||||
wxLog::DoLog(level, szString, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wxLogWindow::DoLogString(const wxString& szString, time_t WXUNUSED(t))
|
||||
{
|
||||
wxString msg;
|
||||
|
||||
TimeStamp(&msg);
|
||||
msg << szString << wxT('\n');
|
||||
// don't put trace messages in the text window for 2 reasons:
|
||||
// 1) there are too many of them
|
||||
// 2) they may provoke other trace messages (e.g. wxMSW code uses
|
||||
// wxLogTrace to log Windows messages and adding text to the control
|
||||
// sends more of them) thus sending a program into an infinite loop
|
||||
if ( level == wxLOG_Trace )
|
||||
return;
|
||||
|
||||
m_pLogFrame->AddLogMessage(msg);
|
||||
}
|
||||
@ -1197,13 +1168,9 @@ wxLogTextCtrl::wxLogTextCtrl(wxTextCtrl *pTextCtrl)
|
||||
m_pTextCtrl = pTextCtrl;
|
||||
}
|
||||
|
||||
void wxLogTextCtrl::DoLogString(const wxString& szString, time_t WXUNUSED(t))
|
||||
void wxLogTextCtrl::DoLogText(const wxString& msg)
|
||||
{
|
||||
wxString msg;
|
||||
TimeStamp(&msg);
|
||||
|
||||
msg << szString << wxT('\n');
|
||||
m_pTextCtrl->AppendText(msg);
|
||||
m_pTextCtrl->AppendText(msg + wxS('\n'));
|
||||
}
|
||||
|
||||
#endif // wxUSE_LOG && wxUSE_TEXTCTRL
|
||||
|
@ -21,15 +21,18 @@
|
||||
#include "wx/log.h"
|
||||
#endif // WX_PRECOMP
|
||||
|
||||
#include "wx/scopeguard.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// test logger
|
||||
// test loggers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// simple log sink which just stores the messages logged for each level
|
||||
class TestLog : public wxLog
|
||||
// base class for all test loggers which simply store all logged messages for
|
||||
// future examination in the test code
|
||||
class TestLogBase : public wxLog
|
||||
{
|
||||
public:
|
||||
TestLog() { }
|
||||
TestLogBase() { }
|
||||
|
||||
wxString GetLog(wxLogLevel level) const
|
||||
{
|
||||
@ -43,19 +46,83 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void DoLog(wxLogLevel level, const wxString& str, time_t WXUNUSED(t))
|
||||
wxString m_logs[wxLOG_Trace + 1];
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(TestLogBase);
|
||||
};
|
||||
|
||||
// simple log sink which just stores the messages logged for each level
|
||||
class TestLog : public TestLogBase
|
||||
{
|
||||
public:
|
||||
TestLog() { }
|
||||
|
||||
protected:
|
||||
virtual void DoLogRecord(wxLogLevel level,
|
||||
const wxString& msg,
|
||||
const wxLogRecordInfo& WXUNUSED(info))
|
||||
{
|
||||
m_logs[level] = msg;
|
||||
}
|
||||
|
||||
private:
|
||||
wxDECLARE_NO_COPY_CLASS(TestLog);
|
||||
};
|
||||
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
|
||||
// log sink overriding the old DoLogXXX() functions should still work too
|
||||
|
||||
// this one overrides DoLog(char*)
|
||||
class CompatTestLog : public TestLogBase
|
||||
{
|
||||
public:
|
||||
CompatTestLog() { }
|
||||
|
||||
protected:
|
||||
virtual void DoLog(wxLogLevel level, const char *str, time_t WXUNUSED(t))
|
||||
{
|
||||
m_logs[level] = str;
|
||||
}
|
||||
|
||||
wxSUPPRESS_DOLOG_HIDE_WARNING()
|
||||
// get rid of the warning about hiding the other overload
|
||||
virtual void DoLog(wxLogLevel WXUNUSED(level),
|
||||
const wchar_t *WXUNUSED(str),
|
||||
time_t WXUNUSED(t))
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
wxString m_logs[wxLOG_Trace + 1];
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(TestLog);
|
||||
wxDECLARE_NO_COPY_CLASS(CompatTestLog);
|
||||
};
|
||||
|
||||
// and this one overload DoLogString(wchar_t*)
|
||||
class CompatTestLog2 : public wxLog
|
||||
{
|
||||
public:
|
||||
CompatTestLog2() { }
|
||||
|
||||
const wxString& Get() const { return m_msg; }
|
||||
|
||||
protected:
|
||||
virtual void DoLogString(const wchar_t *msg, time_t WXUNUSED(t))
|
||||
{
|
||||
m_msg = msg;
|
||||
}
|
||||
|
||||
// get rid of the warning
|
||||
virtual void DoLogString(const char *WXUNUSED(msg), time_t WXUNUSED(t))
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
wxString m_msg;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(CompatTestLog2);
|
||||
};
|
||||
|
||||
#endif // WXWIN_COMPATIBILITY_2_8
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// test class
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -75,6 +142,10 @@ private:
|
||||
#if wxDEBUG_LEVEL
|
||||
CPPUNIT_TEST( Trace );
|
||||
#endif // wxDEBUG_LEVEL
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
CPPUNIT_TEST( CompatLogger );
|
||||
CPPUNIT_TEST( CompatLogger2 );
|
||||
#endif // WXWIN_COMPATIBILITY_2_8
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
void Functions();
|
||||
@ -82,6 +153,10 @@ private:
|
||||
#if wxDEBUG_LEVEL
|
||||
void Trace();
|
||||
#endif // wxDEBUG_LEVEL
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
void CompatLogger();
|
||||
void CompatLogger2();
|
||||
#endif // WXWIN_COMPATIBILITY_2_8
|
||||
|
||||
TestLog *m_log;
|
||||
wxLog *m_logOld;
|
||||
@ -159,3 +234,27 @@ void LogTestCase::Trace()
|
||||
}
|
||||
|
||||
#endif // wxDEBUG_LEVEL
|
||||
|
||||
#if WXWIN_COMPATIBILITY_2_8
|
||||
|
||||
void LogTestCase::CompatLogger()
|
||||
{
|
||||
CompatTestLog log;
|
||||
wxLog * const logOld = wxLog::SetActiveTarget(&log);
|
||||
wxON_BLOCK_EXIT1( wxLog::SetActiveTarget, logOld );
|
||||
|
||||
wxLogError("Old error");
|
||||
CPPUNIT_ASSERT_EQUAL( "Old error", log.GetLog(wxLOG_Error) );
|
||||
}
|
||||
|
||||
void LogTestCase::CompatLogger2()
|
||||
{
|
||||
CompatTestLog2 log;
|
||||
wxLog * const logOld = wxLog::SetActiveTarget(&log);
|
||||
wxON_BLOCK_EXIT1( wxLog::SetActiveTarget, logOld );
|
||||
|
||||
wxLogWarning("Old warning");
|
||||
CPPUNIT_ASSERT_EQUAL( "Old warning", log.Get() );
|
||||
}
|
||||
|
||||
#endif // WXWIN_COMPATIBILITY_2_8
|
||||
|
Loading…
Reference in New Issue
Block a user