/////////////////////////////////////////////////////////////////////////////// // Name: src/generic/dbgrptg.cpp // Purpose: implementation of wxDebugReportPreviewStd // Author: Vadim Zeitlin, Andrej Putrin // Modified by: // Created: 2005-01-21 // RCS-ID: $Id$ // Copyright: (c) 2005 Vadim Zeitlin // License: wxWindows licence /////////////////////////////////////////////////////////////////////////////// // ============================================================================ // declarations // ============================================================================ // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/sizer.h" #include "wx/checklst.h" #include "wx/textctrl.h" #endif // WX_PRECOMP #if wxUSE_DEBUGREPORT #include "wx/debugrpt.h" #include "wx/intl.h" #include "wx/filename.h" #include "wx/ffile.h" #include "wx/mimetype.h" #include "wx/statline.h" #include "wx/stattext.h" #include "wx/filedlg.h" #include "wx/valtext.h" // ---------------------------------------------------------------------------- // wxDumpPreviewDlg: simple class for showing ASCII preview of dump files // ---------------------------------------------------------------------------- class wxDumpPreviewDlg : public wxDialog { public: wxDumpPreviewDlg(wxWindow *parent, const wxString& title, const wxString& text); private: // the text we show wxTextCtrl *m_text; DECLARE_NO_COPY_CLASS(wxDumpPreviewDlg) }; wxDumpPreviewDlg::wxDumpPreviewDlg(wxWindow *parent, const wxString& title, const wxString& text) : wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { // create controls // --------------- // use wxTE_RICH2 style to avoid 64kB limit under MSW and display big files // faster than with wxTE_RICH m_text = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxPoint(0, 0), wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_NOHIDESEL | wxTE_RICH2); m_text->SetValue(text); // use fixed-width font m_text->SetFont(wxFont(12, wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); wxButton *btnClose = new wxButton(this, wxID_CANCEL, _("Close")); // layout them // ----------- wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL), *sizerBtns = new wxBoxSizer(wxHORIZONTAL); sizerBtns->Add(btnClose, 0, 0, 1); sizerTop->Add(m_text, 1, wxEXPAND); sizerTop->Add(sizerBtns, 0, wxALIGN_RIGHT | wxTOP | wxBOTTOM | wxRIGHT, 1); // set the sizer &c // ---------------- // make the text window bigger to show more contents of the file sizerTop->SetItemMinSize(m_text, 600, 300); SetSizer(sizerTop); Layout(); Fit(); m_text->SetFocus(); } // ---------------------------------------------------------------------------- // wxDumpOpenExternalDlg: choose a command for opening the given file // ---------------------------------------------------------------------------- class wxDumpOpenExternalDlg : public wxDialog { public: wxDumpOpenExternalDlg(wxWindow *parent, const wxFileName& filename); // return the command chosed by user to open this file const wxString& GetCommand() const { return m_command; } wxString m_command; private: void OnBrowse(wxCommandEvent& event); DECLARE_EVENT_TABLE() DECLARE_NO_COPY_CLASS(wxDumpOpenExternalDlg) }; BEGIN_EVENT_TABLE(wxDumpOpenExternalDlg, wxDialog) EVT_BUTTON(wxID_MORE, wxDumpOpenExternalDlg::OnBrowse) END_EVENT_TABLE() wxDumpOpenExternalDlg::wxDumpOpenExternalDlg(wxWindow *parent, const wxFileName& filename) : wxDialog(parent, wxID_ANY, wxString::Format ( _("Open file \"%s\""), filename.GetFullPath().c_str() )) { // create controls // --------------- wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL); sizerTop->Add(new wxStaticText(this, wxID_ANY, wxString::Format ( _("Enter command to open file \"%s\":"), filename.GetFullName().c_str() )), wxSizerFlags().Border()); wxSizer *sizerH = new wxBoxSizer(wxHORIZONTAL); wxTextCtrl *command = new wxTextCtrl ( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(250, -1), 0, wxTextValidator(wxFILTER_NONE, &m_command) ); sizerH->Add(command, wxSizerFlags(1).Align(wxALIGN_CENTER_VERTICAL)); wxButton *browse = new wxButton(this, wxID_MORE, wxT(">>"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT); sizerH->Add(browse, wxSizerFlags(0).Align(wxALIGN_CENTER_VERTICAL). Border(wxLEFT)); sizerTop->Add(sizerH, wxSizerFlags(0).Expand().Border()); sizerTop->Add(new wxStaticLine(this), wxSizerFlags().Expand().Border()); sizerTop->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), wxSizerFlags().Align(wxALIGN_RIGHT).Border()); // set the sizer &c // ---------------- SetSizer(sizerTop); Layout(); Fit(); command->SetFocus(); } void wxDumpOpenExternalDlg::OnBrowse(wxCommandEvent& ) { wxFileName fname(m_command); wxFileDialog dlg(this, wxFileSelectorPromptStr, fname.GetPathWithSep(), fname.GetFullName() #ifdef __WXMSW__ , _("Executable files (*.exe)|*.exe|All files (*.*)|*.*||") #endif // __WXMSW__ ); if ( dlg.ShowModal() == wxID_OK ) { m_command = dlg.GetPath(); TransferDataToWindow(); } } // ---------------------------------------------------------------------------- // wxDebugReportDialog: class showing debug report to the user // ---------------------------------------------------------------------------- class wxDebugReportDialog : public wxDialog { public: wxDebugReportDialog(wxDebugReport& dbgrpt); virtual bool TransferDataToWindow(); virtual bool TransferDataFromWindow(); private: void OnView(wxCommandEvent& ); void OnViewUpdate(wxUpdateUIEvent& ); void OnOpen(wxCommandEvent& ); // small helper: add wxEXPAND and wxALL flags static wxSizerFlags SizerFlags(int proportion) { return wxSizerFlags(proportion).Expand().Border(); } wxDebugReport& m_dbgrpt; wxCheckListBox *m_checklst; wxTextCtrl *m_notes; wxArrayString m_files; DECLARE_EVENT_TABLE() DECLARE_NO_COPY_CLASS(wxDebugReportDialog) }; // ============================================================================ // wxDebugReportDialog implementation // ============================================================================ BEGIN_EVENT_TABLE(wxDebugReportDialog, wxDialog) EVT_BUTTON(wxID_VIEW_DETAILS, wxDebugReportDialog::OnView) EVT_UPDATE_UI(wxID_VIEW_DETAILS, wxDebugReportDialog::OnViewUpdate) EVT_BUTTON(wxID_OPEN, wxDebugReportDialog::OnOpen) EVT_UPDATE_UI(wxID_OPEN, wxDebugReportDialog::OnViewUpdate) END_EVENT_TABLE() // ---------------------------------------------------------------------------- // construction // ---------------------------------------------------------------------------- wxDebugReportDialog::wxDebugReportDialog(wxDebugReport& dbgrpt) : wxDialog(NULL, wxID_ANY, wxString::Format(_("Debug report \"%s\""), dbgrpt.GetReportName().c_str()), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxTHICK_FRAME), m_dbgrpt(dbgrpt) { // upper part of the dialog: explanatory message wxString msg; msg << _("A debug report has been generated in the directory\n") << _T('\n') << _T(" \"") << dbgrpt.GetDirectory() << _T("\"\n") << _T('\n') << _("The report contains the files listed below. If any of these ") << _("files contain private information,\n") << _("please uncheck them and they will be removed from the report.\n") << _T('\n') << _("If you wish to suppress this debug report completely, please ") << _("choose the \"Cancel\" button,\n") << _("but be warned that it may hinder improving the program, so if\n") << _("at all possible please do continue with the report generation.\n") << _T('\n') << _(" Thank you and we're sorry for the inconvenience!\n") << _T("\n\n"); // just some white space to separate from other stuff const wxSizerFlags flagsFixed(SizerFlags(0)); const wxSizerFlags flagsExpand(SizerFlags(1)); const wxSizerFlags flagsExpand2(SizerFlags(2)); wxSizer *sizerPreview = new wxStaticBoxSizer(wxVERTICAL, this, _("&Debug report preview:")); sizerPreview->Add(CreateTextSizer(msg), SizerFlags(0).Centre()); // ... and the list of files in this debug report with buttons to view them wxSizer *sizerFileBtns = new wxBoxSizer(wxVERTICAL); sizerFileBtns->AddStretchSpacer(1); sizerFileBtns->Add(new wxButton(this, wxID_VIEW_DETAILS, _T("&View...")), wxSizerFlags().Border(wxBOTTOM)); sizerFileBtns->Add(new wxButton(this, wxID_OPEN, _T("&Open...")), wxSizerFlags().Border(wxTOP)); sizerFileBtns->AddStretchSpacer(1); m_checklst = new wxCheckListBox(this, wxID_ANY); wxSizer *sizerFiles = new wxBoxSizer(wxHORIZONTAL); sizerFiles->Add(m_checklst, flagsExpand); sizerFiles->Add(sizerFileBtns, flagsFixed); sizerPreview->Add(sizerFiles, flagsExpand2); // lower part of the dialog: notes field wxSizer *sizerNotes = new wxStaticBoxSizer(wxVERTICAL, this, _("&Notes:")); msg = _("If you have any additional information pertaining to this bug\n"); msg << _("report, please enter it here and it will be joined to it:"); m_notes = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE); sizerNotes->Add(CreateTextSizer(msg), flagsFixed); sizerNotes->Add(m_notes, flagsExpand); wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL); sizerTop->Add(sizerPreview, flagsExpand2); sizerTop->AddSpacer(5); sizerTop->Add(sizerNotes, flagsExpand); sizerTop->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), flagsFixed); SetSizerAndFit(sizerTop); Layout(); CentreOnScreen(); } // ---------------------------------------------------------------------------- // data exchange // ---------------------------------------------------------------------------- bool wxDebugReportDialog::TransferDataToWindow() { // all files are included in the report by default const size_t count = m_dbgrpt.GetFilesCount(); for ( size_t n = 0; n < count; n++ ) { wxString name, desc; if ( m_dbgrpt.GetFile(n, &name, &desc) ) { m_checklst->Append(name + _T(" (") + desc + _T(')')); m_checklst->Check(n); m_files.Add(name); } } return true; } bool wxDebugReportDialog::TransferDataFromWindow() { // any unchecked files should be removed from the report const size_t count = m_checklst->GetCount(); for ( size_t n = 0; n < count; n++ ) { if ( !m_checklst->IsChecked(n) ) { m_dbgrpt.RemoveFile(m_files[n]); } } // if the user entered any notes, add them to the report const wxString notes = m_notes->GetValue(); if ( !notes.empty() ) { // for now it's fixed, could make it configurable in the future... const wxChar *NOTES_FILE_NAME = _T("notes.txt"); wxFileName fn(m_dbgrpt.GetDirectory(), NOTES_FILE_NAME); wxFFile file(fn.GetFullPath(), _T("w")); if ( file.IsOpened() && file.Write(notes) ) { m_dbgrpt.AddFile(NOTES_FILE_NAME, _T("user notes")); } } return true; } // ---------------------------------------------------------------------------- // event handlers // ---------------------------------------------------------------------------- void wxDebugReportDialog::OnView(wxCommandEvent& ) { const int sel = m_checklst->GetSelection(); wxCHECK_RET( sel != -1, _T("invalid selection in OnView()") ); wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]); wxString str; wxFFile file(fn.GetFullPath()); if ( file.IsOpened() && file.ReadAll(&str) ) { wxDumpPreviewDlg dlg(this, m_files[sel], str); dlg.ShowModal(); } } void wxDebugReportDialog::OnOpen(wxCommandEvent& ) { const int sel = m_checklst->GetSelection(); wxCHECK_RET( sel != -1, _T("invalid selection in OnOpen()") ); wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]); // try to get the command to open this kind of files ourselves wxString command; wxFileType * ft = wxTheMimeTypesManager->GetFileTypeFromExtension(fn.GetExt()); if ( ft ) { command = ft->GetOpenCommand(fn.GetFullPath()); } // if we couldn't, ask the user if ( command.empty() ) { wxDumpOpenExternalDlg dlg(this, fn); if ( dlg.ShowModal() == wxID_OK ) { // get the command chosen by the user and append file name to it // if we don't have place marker for file name in the command... wxString cmd = dlg.GetCommand(); if ( cmd.find(_T('%')) == wxString::npos ) { // ...add it cmd += _T(" \"%s\""); } command = wxFileType::ExpandCommand(cmd, fn.GetFullPath()); } } if ( !command.empty() ) ::wxExecute(command); } void wxDebugReportDialog::OnViewUpdate(wxUpdateUIEvent& event) { int sel = m_checklst->GetSelection(); if (sel >= 0) { wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]); event.Enable(fn.FileExists()); } else event.Enable(false); } // ============================================================================ // wxDebugReportPreviewStd implementation // ============================================================================ bool wxDebugReportPreviewStd::Show(wxDebugReport& dbgrpt) const { if ( !dbgrpt.GetFilesCount() ) return false; wxDebugReportDialog dlg(dbgrpt); return dlg.ShowModal() == wxID_OK && dbgrpt.GetFilesCount() != 0; } #endif // wxUSE_DEBUGREPORT