X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/08168cc43d14a68d702253d9926b680729066afb..2439f1d96880ed2fd1551b85795ccee1704dc29c:/samples/debugrpt/debugrpt.cpp diff --git a/samples/debugrpt/debugrpt.cpp b/samples/debugrpt/debugrpt.cpp index f6a0c208b2..152e2664ec 100644 --- a/samples/debugrpt/debugrpt.cpp +++ b/samples/debugrpt/debugrpt.cpp @@ -15,18 +15,30 @@ #include "wx/app.h" #include "wx/log.h" +#include "wx/frame.h" +#include "wx/icon.h" +#include "wx/menu.h" +#include "wx/msgdlg.h" +#include "wx/button.h" +#include "wx/dcclient.h" + #include "wx/datetime.h" #include "wx/ffile.h" #include "wx/filename.h" -#include "wx/dynlib.h" #include "wx/debugrpt.h" -#include "wx/msgdlg.h" - #if !wxUSE_DEBUGREPORT #error "This sample can't be built without wxUSE_DEBUGREPORT" #endif // wxUSE_DEBUGREPORT +#if !wxUSE_ON_FATAL_EXCEPTION + #error "This sample can't be built without wxUSE_ON_FATAL_EXCEPTION" +#endif // wxUSE_ON_FATAL_EXCEPTION + +#if !defined(__WXMSW__) && !defined(__WXPM__) + #include "../sample.xpm" +#endif + // ---------------------------------------------------------------------------- // custom debug reporting class // ---------------------------------------------------------------------------- @@ -39,9 +51,9 @@ class MyDebugReport : public wxDebugReportUpload public: MyDebugReport() : wxDebugReportUpload ( - _T("http://your.url.here/"), - _T("report:file"), - _T("action") + wxT("http://your.url.here/"), + wxT("report:file"), + wxT("action") ) { } @@ -54,19 +66,19 @@ protected: { if ( reply.IsEmpty() ) { - wxLogError(_T("Didn't receive the expected server reply.")); + wxLogError(wxT("Didn't receive the expected server reply.")); return false; } - wxString s(_T("Server replied:\n")); + wxString s(wxT("Server replied:\n")); const size_t count = reply.GetCount(); for ( size_t n = 0; n < count; n++ ) { - s << _T('\t') << reply[n] << _T('\n'); + s << wxT('\t') << reply[n] << wxT('\n'); } - wxLogMessage(_T("%s"), s.c_str()); + wxLogMessage(wxT("%s"), s.c_str()); return true; } @@ -85,12 +97,12 @@ public: { if ( !wxDebugReportCompress::DoProcess() ) return false; - wxMailMessage msg(GetReportName() + _T(" crash report"), - _T("vadim@wxwindows.org"), + wxMailMessage msg(GetReportName() + wxT(" crash report"), + wxT("vadim@wxwindows.org"), wxEmptyString, // mail body wxEmptyString, // from address GetCompressedFileName(), - _T("crashreport.zip")); + wxT("crashreport.zip")); return wxEmail::Send(msg); } @@ -103,7 +115,7 @@ public: // ---------------------------------------------------------------------------- // just some functions to get a slightly deeper stack trace -static void bar(const wxChar *p) +static void bar(const char *p) { char *pc = 0; *pc = *p; @@ -113,17 +125,54 @@ static void bar(const wxChar *p) void baz(const wxString& s) { - printf("baz: %s\n", s.c_str()); + printf("baz: %s\n", (const char*)s.c_str()); } void foo(int n) { if ( n % 2 ) - baz(wxT("odd")); + baz("odd"); else - bar(wxT("even")); + bar("even"); } +// ---------------------------------------------------------------------------- +// main window +// ---------------------------------------------------------------------------- + +enum +{ + DebugRpt_Quit = wxID_EXIT, + DebugRpt_Crash = 100, + DebugRpt_Current, + DebugRpt_Paint, + DebugRpt_Upload, + DebugRpt_About = wxID_ABOUT +}; + +class MyFrame : public wxFrame +{ +public: + MyFrame(); + +private: + void OnQuit(wxCommandEvent& event); + void OnReportForCrash(wxCommandEvent& event); + void OnReportForCurrent(wxCommandEvent& event); + void OnReportPaint(wxCommandEvent& event); + void OnReportUpload(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + + void OnPaint(wxPaintEvent& event); + + + // number of lines drawn in OnPaint() + int m_numLines; + + wxDECLARE_NO_COPY_CLASS(MyFrame); + DECLARE_EVENT_TABLE() +}; + // ---------------------------------------------------------------------------- // application class // ---------------------------------------------------------------------------- @@ -135,94 +184,216 @@ void foo(int n) class MyApp : public wxApp { public: - virtual bool OnInit() - { -#if wxUSE_ON_FATAL_EXCEPTION - wxHandleFatalExceptions(); -#endif + // call wxHandleFatalExceptions here + MyApp(); - if ( !wxApp::OnInit() ) - return false; + // create our main window here + virtual bool OnInit(); - return true; - } + // called when a crash occurs in this application + virtual void OnFatalException(); - virtual int OnRun() - { - // a real program would be presumably be a bit harder to crash than - // just pressing "yes" in a dialog... but this is just an example - switch ( wxMessageBox - ( - _T("Generate report for crash (or just current context)?"), - _T("wxDebugReport Test"), - wxYES_NO | wxCANCEL - ) ) - { - case wxYES: - // this call is going to crash - foo(32); - foo(17); - break; - - case wxNO: - // example of manually generated report, this could be also - // used in wxApp::OnAssert() - GenerateReport(wxDebugReport::Context_Current); - break; - - case wxCANCEL: - break; - } + // this is where we really generate the debug report + void GenerateReport(wxDebugReport::Context ctx); - return 0; - } + // if this function is called, we'll use MyDebugReport which would try to + // upload the (next) generated debug report to its URL, otherwise we just + // generate the debug report and leave it in a local file + void UploadReport(bool doIt) { m_uploadReport = doIt; } - virtual void OnFatalException() - { - GenerateReport(wxDebugReport::Context_Exception); - } +private: + bool m_uploadReport; + + wxDECLARE_NO_COPY_CLASS(MyApp); +}; + +IMPLEMENT_APP(MyApp) + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// MyFrame +// ---------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(DebugRpt_Quit, MyFrame::OnQuit) + EVT_MENU(DebugRpt_Crash, MyFrame::OnReportForCrash) + EVT_MENU(DebugRpt_Current, MyFrame::OnReportForCurrent) + EVT_MENU(DebugRpt_Paint, MyFrame::OnReportPaint) + EVT_MENU(DebugRpt_Upload, MyFrame::OnReportUpload) + EVT_MENU(DebugRpt_About, MyFrame::OnAbout) + + EVT_PAINT(MyFrame::OnPaint) +END_EVENT_TABLE() + +MyFrame::MyFrame() + : wxFrame(NULL, wxID_ANY, wxT("wxWidgets Debug Report Sample"), + wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE|wxDEFAULT_FRAME_STYLE) +{ + m_numLines = 10; + + SetIcon(wxICON(sample)); + + wxMenu *menuFile = new wxMenu; + menuFile->Append(DebugRpt_Quit, wxT("E&xit\tAlt-X")); + + wxMenu *menuReport = new wxMenu; + menuReport->Append(DebugRpt_Crash, wxT("Report for &crash\tCtrl-C"), + wxT("Provoke a crash inside the program and create report for it")); + menuReport->Append(DebugRpt_Current, wxT("Report for c&urrent context\tCtrl-U"), + wxT("Create report for the current program context")); + menuReport->Append(DebugRpt_Paint, wxT("Report for &paint handler\tCtrl-P"), + wxT("Provoke a repeatable crash in wxEVT_PAINT handler")); + menuReport->AppendSeparator(); + menuReport->AppendCheckItem(DebugRpt_Upload, wxT("Up&load debug report"), + wxT("You need to configure a web server accepting debug report uploads to use this function")); + + wxMenu *menuHelp = new wxMenu; + menuHelp->Append(DebugRpt_About, wxT("&About...\tF1")); + + wxMenuBar *mbar = new wxMenuBar(); + mbar->Append(menuFile, wxT("&File")); + mbar->Append(menuReport, wxT("&Report")); + mbar->Append(menuHelp, wxT("&Help")); + SetMenuBar(mbar); - void GenerateReport(wxDebugReport::Context ctx) + CreateStatusBar(); + + Show(); +} + +void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(true); +} + +void MyFrame::OnReportForCrash(wxCommandEvent& WXUNUSED(event)) +{ + // this call is going to crash + foo(32); + foo(17); +} + +void MyFrame::OnReportForCurrent(wxCommandEvent& WXUNUSED(event)) +{ + // example of manually generated report, this could be also + // used in wxApp::OnAssert() + wxGetApp().GenerateReport(wxDebugReport::Context_Current); +} + +void MyFrame::OnReportPaint(wxCommandEvent& WXUNUSED(event)) +{ + // this will result in a crash in OnPaint() + m_numLines = 0; + + // ensure it's called immediately + Refresh(); +} + +void MyFrame::OnReportUpload(wxCommandEvent& event) +{ + wxGetApp().UploadReport(event.IsChecked()); +} + +void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) +{ + wxMessageBox + ( + wxT("wxDebugReport sample\n(c) 2005 Vadim Zeitlin "), + wxT("wxWidgets Debug Report Sample"), + wxOK | wxICON_INFORMATION, + this + ); +} + +void MyFrame::OnPaint(wxPaintEvent& WXUNUSED(event)) +{ + wxPaintDC dc(this); + const wxSize size = GetClientSize(); + for ( wxCoord x = 0; x < size.x; x += size.x/m_numLines ) + dc.DrawLine(x, 0, x, size.y); +} + +// ---------------------------------------------------------------------------- +// MyApp +// ---------------------------------------------------------------------------- + +MyApp::MyApp() +{ + // user needs to explicitely enable this + m_uploadReport = false; + + // call this to tell the library to call our OnFatalException() + wxHandleFatalExceptions(); +} + +bool MyApp::OnInit() +{ + if ( !wxApp::OnInit() ) + return false; + + new MyFrame; + + return true; +} + +void MyApp::OnFatalException() +{ + GenerateReport(wxDebugReport::Context_Exception); +} + +void MyApp::GenerateReport(wxDebugReport::Context ctx) +{ + wxDebugReportCompress *report = m_uploadReport ? new MyDebugReport + : new wxDebugReportCompress; + + // add all standard files: currently this means just a minidump and an + // XML file with system info and stack trace + report->AddAll(ctx); + + // you can also call report->AddFile(...) with your own log files, files + // created using wxRegKey::Export() and so on, here we just add a test + // file containing the date of the crash + wxFileName fn(report->GetDirectory(), wxT("timestamp.my")); + wxFFile file(fn.GetFullPath(), wxT("w")); + if ( file.IsOpened() ) { - MyDebugReport report; - - // add all standard files: currently this means just a minidump and an - // XML file with system info and stack trace - report.AddAll(ctx); - - // you can also call report.AddFile(...) with your own log files, files - // created using wxRegKey::Export() and so on, here we just add a test - // file containing the date of the crash - wxFileName fn(report.GetDirectory(), _T("timestamp.my")); - wxFFile file(fn.GetFullPath(), _T("w")); - if ( file.IsOpened() ) - { - wxDateTime dt = wxDateTime::Now(); - file.Write(dt.FormatISODate() + _T(' ') + dt.FormatISOTime()); - file.Close(); - } + wxDateTime dt = wxDateTime::Now(); + file.Write(dt.FormatISODate() + wxT(' ') + dt.FormatISOTime()); + file.Close(); + } - report.AddFile(fn.GetFullName(), _T("timestamp of this report")); + report->AddFile(fn.GetFullName(), wxT("timestamp of this report")); - // can also add an existing file directly, it will be copied - // automatically + // can also add an existing file directly, it will be copied + // automatically #ifdef __WXMSW__ - report.AddFile(_T("c:\\autoexec.bat"), _T("DOS startup file")); + report->AddFile(wxT("c:\\autoexec.bat"), wxT("DOS startup file")); #else - report.AddFile(_T("/etc/motd"), _T("Message of the day")); + report->AddFile(wxT("/etc/motd"), wxT("Message of the day")); #endif - // calling Show() is not mandatory, but is more polite - if ( wxDebugReportPreviewStd().Show(report) ) + // calling Show() is not mandatory, but is more polite + if ( wxDebugReportPreviewStd().Show(*report) ) + { + if ( report->Process() ) { - if ( report.Process() ) + if ( m_uploadReport ) + { + wxLogMessage(wxT("Report successfully uploaded.")); + } + else { - // report successfully uploaded + wxLogMessage(wxT("Report generated in \"%s\"."), + report->GetCompressedFileName().c_str()); + report->Reset(); } } - //else: user cancelled the report } -}; + //else: user cancelled the report -IMPLEMENT_APP(MyApp) + delete report; +}