logg.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,225 行 · 第 1/3 页
CPP
1,225 行
/////////////////////////////////////////////////////////////////////////////
// Name: src/generic/logg.cpp
// Purpose: wxLog-derived classes which need GUI support (the rest is in
// src/common/log.cpp)
// Author: Vadim Zeitlin
// Modified by:
// Created: 20.09.99 (extracted from src/common/log.cpp)
// RCS-ID: $Id: logg.cpp,v 1.94 2005/06/20 00:24:21 VZ Exp $
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
#pragma implementation "logg.h"
#endif
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/button.h"
#include "wx/intl.h"
#include "wx/log.h"
#include "wx/menu.h"
#include "wx/frame.h"
#include "wx/filedlg.h"
#include "wx/msgdlg.h"
#include "wx/textctrl.h"
#include "wx/sizer.h"
#include "wx/statbmp.h"
#include "wx/button.h"
#include "wx/settings.h"
#endif // WX_PRECOMP
#if wxUSE_LOGGUI || wxUSE_LOGWINDOW
#include "wx/file.h"
#include "wx/textfile.h"
#include "wx/statline.h"
#include "wx/artprov.h"
#ifdef __WXMSW__
// for OutputDebugString()
#include "wx/msw/private.h"
#endif // Windows
#ifdef __WXPM__
#include <time.h>
#endif
#if wxUSE_LOG_DIALOG
#include "wx/listctrl.h"
#include "wx/imaglist.h"
#include "wx/image.h"
#else // !wxUSE_LOG_DIALOG
#include "wx/msgdlg.h"
#endif // wxUSE_LOG_DIALOG/!wxUSE_LOG_DIALOG
#if defined(__MWERKS__) && wxUSE_UNICODE
#include <wtime.h>
#endif
#include "wx/datetime.h"
// the suffix we add to the button to show that the dialog can be expanded
#define EXPAND_SUFFIX _T(" >>")
// ----------------------------------------------------------------------------
// private classes
// ----------------------------------------------------------------------------
#if wxUSE_LOG_DIALOG
// this function is a wrapper around strftime(3)
// allows to exclude the usage of wxDateTime
static wxString TimeStamp(const wxChar *format, time_t t)
{
wxChar buf[4096];
if ( !wxStrftime(buf, WXSIZEOF(buf), format, localtime(&t)) )
{
// buffer is too small?
wxFAIL_MSG(_T("strftime() failed"));
}
return wxString(buf);
}
class wxLogDialog : public wxDialog
{
public:
wxLogDialog(wxWindow *parent,
const wxArrayString& messages,
const wxArrayInt& severity,
const wxArrayLong& timess,
const wxString& caption,
long style);
virtual ~wxLogDialog();
// event handlers
void OnOk(wxCommandEvent& event);
void OnDetails(wxCommandEvent& event);
#if wxUSE_FILE
void OnSave(wxCommandEvent& event);
#endif // wxUSE_FILE
void OnListSelect(wxListEvent& event);
private:
// create controls needed for the details display
void CreateDetailsControls();
// the data for the listctrl
wxArrayString m_messages;
wxArrayInt m_severity;
wxArrayLong m_times;
// the "toggle" button and its state
#ifndef __SMARTPHONE__
wxButton *m_btnDetails;
#endif
bool m_showingDetails;
// the controls which are not shown initially (but only when details
// button is pressed)
wxListCtrl *m_listctrl;
#ifndef __SMARTPHONE__
#if wxUSE_STATLINE
wxStaticLine *m_statline;
#endif // wxUSE_STATLINE
#if wxUSE_FILE
wxButton *m_btnSave;
#endif // wxUSE_FILE
#endif // __SMARTPHONE__
// the translated "Details" string
static wxString ms_details;
DECLARE_EVENT_TABLE()
DECLARE_NO_COPY_CLASS(wxLogDialog)
};
BEGIN_EVENT_TABLE(wxLogDialog, wxDialog)
EVT_BUTTON(wxID_OK, wxLogDialog::OnOk)
EVT_BUTTON(wxID_MORE, wxLogDialog::OnDetails)
#if wxUSE_FILE
EVT_BUTTON(wxID_SAVE, wxLogDialog::OnSave)
#endif // wxUSE_FILE
EVT_LIST_ITEM_SELECTED(wxID_ANY, wxLogDialog::OnListSelect)
END_EVENT_TABLE()
#endif // wxUSE_LOG_DIALOG
// ----------------------------------------------------------------------------
// private functions
// ----------------------------------------------------------------------------
#if wxUSE_FILE && wxUSE_FILEDLG
// pass an uninitialized file object, the function will ask the user for the
// filename and try to open it, returns true on success (file was opened),
// false if file couldn't be opened/created and -1 if the file selection
// dialog was cancelled
static int OpenLogFile(wxFile& file, wxString *filename = NULL, wxWindow *parent = NULL);
#endif // wxUSE_FILE
// ----------------------------------------------------------------------------
// global variables
// ----------------------------------------------------------------------------
// we use a global variable to store the frame pointer for wxLogStatus - bad,
// but it's the easiest way
static wxFrame *gs_pFrame = NULL; // FIXME MT-unsafe
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// global functions
// ----------------------------------------------------------------------------
// accepts an additional argument which tells to which frame the output should
// be directed
void wxVLogStatus(wxFrame *pFrame, const wxChar *szFormat, va_list argptr)
{
wxString msg;
wxLog *pLog = wxLog::GetActiveTarget();
if ( pLog != NULL ) {
msg.PrintfV(szFormat, 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
gs_pFrame = (wxFrame *) NULL;
}
}
void wxLogStatus(wxFrame *pFrame, const wxChar *szFormat, ...)
{
va_list argptr;
va_start(argptr, szFormat);
wxVLogStatus(pFrame, szFormat, argptr);
va_end(argptr);
}
// ----------------------------------------------------------------------------
// wxLogGui implementation (FIXME MT-unsafe)
// ----------------------------------------------------------------------------
#if wxUSE_LOGGUI
wxLogGui::wxLogGui()
{
Clear();
}
void wxLogGui::Clear()
{
m_bErrors =
m_bWarnings =
m_bHasMessages = false;
m_aMessages.Empty();
m_aSeverity.Empty();
m_aTimes.Empty();
}
void wxLogGui::Flush()
{
if ( !m_bHasMessages )
return;
// do it right now to block any new calls to Flush() while we're here
m_bHasMessages = false;
wxString appName = wxTheApp->GetAppName();
if ( !appName.empty() )
appName[0u] = (wxChar)wxToupper(appName[0u]);
long style;
wxString titleFormat;
if ( m_bErrors ) {
titleFormat = _("%s Error");
style = wxICON_STOP;
}
else if ( m_bWarnings ) {
titleFormat = _("%s Warning");
style = wxICON_EXCLAMATION;
}
else {
titleFormat = _("%s Information");
style = wxICON_INFORMATION;
}
wxString title;
title.Printf(titleFormat, appName.c_str());
size_t nMsgCount = m_aMessages.Count();
// avoid showing other log dialogs until we're done with the dialog we're
// showing right now: nested modal dialogs make for really bad UI!
Suspend();
wxString str;
if ( nMsgCount == 1 )
{
str = m_aMessages[0];
}
else // more than one message
{
#if wxUSE_LOG_DIALOG
wxLogDialog dlg(NULL,
m_aMessages, m_aSeverity, m_aTimes,
title, style);
// clear the message list before showing the dialog because while it's
// shown some new messages may appear
Clear();
(void)dlg.ShowModal();
#else // !wxUSE_LOG_DIALOG
// concatenate all strings (but not too many to not overfill the msg box)
size_t nLines = 0;
// start from the most recent message
for ( size_t n = nMsgCount; n > 0; n-- ) {
// for Windows strings longer than this value are wrapped (NT 4.0)
const size_t nMsgLineWidth = 156;
nLines += (m_aMessages[n - 1].Len() + nMsgLineWidth - 1) / nMsgLineWidth;
if ( nLines > 25 ) // don't put too many lines in message box
break;
str << m_aMessages[n - 1] << wxT("\n");
}
#endif // wxUSE_LOG_DIALOG/!wxUSE_LOG_DIALOG
}
// this catches both cases of 1 message with wxUSE_LOG_DIALOG and any
// situation without it
if ( !str.empty() )
{
wxMessageBox(str, title, wxOK | style);
// no undisplayed messages whatsoever
Clear();
}
// allow flushing the logs again
Resume();
}
// log all kinds of messages
void wxLogGui::DoLog(wxLogLevel level, const wxChar *szString, time_t t)
{
switch ( level ) {
case wxLOG_Info:
if ( GetVerbose() )
case wxLOG_Message:
{
m_aMessages.Add(szString);
m_aSeverity.Add(wxLOG_Message);
m_aTimes.Add((long)t);
m_bHasMessages = true;
}
break;
case wxLOG_Status:
#if wxUSE_STATUSBAR
{
// find the top window and set it's status text if it has any
wxFrame *pFrame = gs_pFrame;
if ( pFrame == NULL ) {
wxWindow *pWin = wxTheApp->GetTopWindow();
if ( pWin != NULL && pWin->IsKindOf(CLASSINFO(wxFrame)) ) {
pFrame = (wxFrame *)pWin;
}
}
if ( pFrame && pFrame->GetStatusBar() )
pFrame->SetStatusText(szString);
}
#endif // wxUSE_STATUSBAR
break;
case wxLOG_Trace:
case wxLOG_Debug:
#ifdef __WXDEBUG__
{
wxString str;
TimeStamp(&str);
str += szString;
#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
// don't prepend debug/trace here: it goes to the
// debug window anyhow
str += wxT("\r\n");
OutputDebugString(str);
#else
// send them to stderr
wxFprintf(stderr, wxT("[%s] %s\n"),
level == wxLOG_Trace ? wxT("Trace")
: wxT("Debug"),
str.c_str());
fflush(stderr);
#endif
}
#endif // __WXDEBUG__
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
// discard earlier informational messages if this is the 1st
// error because they might not make sense any more and showing
// them in a message box might be confusing
m_aMessages.Empty();
m_aSeverity.Empty();
m_aTimes.Empty();
#endif // wxUSE_LOG_DIALOG
m_bErrors = true;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?