added AddText() function (trivial wrapper around AddFile()), use it in debug rpt...
[wxWidgets.git] / src / generic / dbgrptg.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/dbgrptg.cpp
3 // Purpose: implementation of wxDebugReportPreviewStd
4 // Author: Vadim Zeitlin, Andrej Putrin
5 // Modified by:
6 // Created: 2005-01-21
7 // RCS-ID: $Id$
8 // Copyright: (c) 2005 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #ifndef WX_PRECOMP
27 #include "wx/sizer.h"
28 #include "wx/checklst.h"
29 #include "wx/textctrl.h"
30 #endif // WX_PRECOMP
31
32 #if wxUSE_DEBUGREPORT
33
34 #include "wx/debugrpt.h"
35
36 #include "wx/intl.h"
37 #include "wx/filename.h"
38 #include "wx/ffile.h"
39 #include "wx/mimetype.h"
40
41 #include "wx/statline.h"
42 #include "wx/stattext.h"
43 #include "wx/filedlg.h"
44 #include "wx/valtext.h"
45
46 // ----------------------------------------------------------------------------
47 // wxDumpPreviewDlg: simple class for showing ASCII preview of dump files
48 // ----------------------------------------------------------------------------
49
50 class wxDumpPreviewDlg : public wxDialog
51 {
52 public:
53 wxDumpPreviewDlg(wxWindow *parent,
54 const wxString& title,
55 const wxString& text);
56
57 private:
58 // the text we show
59 wxTextCtrl *m_text;
60
61 DECLARE_NO_COPY_CLASS(wxDumpPreviewDlg)
62 };
63
64 wxDumpPreviewDlg::wxDumpPreviewDlg(wxWindow *parent,
65 const wxString& title,
66 const wxString& text)
67 : wxDialog(parent, wxID_ANY, title,
68 wxDefaultPosition, wxDefaultSize,
69 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
70 {
71 // create controls
72 // ---------------
73
74 // use wxTE_RICH2 style to avoid 64kB limit under MSW and display big files
75 // faster than with wxTE_RICH
76 m_text = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
77 wxPoint(0, 0), wxDefaultSize,
78 wxTE_MULTILINE |
79 wxTE_READONLY |
80 wxTE_NOHIDESEL |
81 wxTE_RICH2);
82 m_text->SetValue(text);
83
84 // use fixed-width font
85 m_text->SetFont(wxFont(12, wxFONTFAMILY_TELETYPE,
86 wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
87
88 wxButton *btnClose = new wxButton(this, wxID_CANCEL, _("Close"));
89
90
91 // layout them
92 // -----------
93
94 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL),
95 *sizerBtns = new wxBoxSizer(wxHORIZONTAL);
96
97 sizerBtns->Add(btnClose, 0, 0, 1);
98
99 sizerTop->Add(m_text, 1, wxEXPAND);
100 sizerTop->Add(sizerBtns, 0, wxALIGN_RIGHT | wxTOP | wxBOTTOM | wxRIGHT, 1);
101
102 // set the sizer &c
103 // ----------------
104
105 // make the text window bigger to show more contents of the file
106 sizerTop->SetItemMinSize(m_text, 600, 300);
107 SetSizer(sizerTop);
108
109 Layout();
110 Fit();
111
112 m_text->SetFocus();
113 }
114
115 // ----------------------------------------------------------------------------
116 // wxDumpOpenExternalDlg: choose a command for opening the given file
117 // ----------------------------------------------------------------------------
118
119 class wxDumpOpenExternalDlg : public wxDialog
120 {
121 public:
122 wxDumpOpenExternalDlg(wxWindow *parent, const wxFileName& filename);
123
124 // return the command chosed by user to open this file
125 const wxString& GetCommand() const { return m_command; }
126
127 wxString m_command;
128
129 private:
130 void OnBrowse(wxCommandEvent& event);
131
132 DECLARE_EVENT_TABLE()
133 DECLARE_NO_COPY_CLASS(wxDumpOpenExternalDlg)
134 };
135
136 BEGIN_EVENT_TABLE(wxDumpOpenExternalDlg, wxDialog)
137 EVT_BUTTON(wxID_MORE, wxDumpOpenExternalDlg::OnBrowse)
138 END_EVENT_TABLE()
139
140
141 wxDumpOpenExternalDlg::wxDumpOpenExternalDlg(wxWindow *parent,
142 const wxFileName& filename)
143 : wxDialog(parent,
144 wxID_ANY,
145 wxString::Format
146 (
147 _("Open file \"%s\""),
148 filename.GetFullPath().c_str()
149 ))
150 {
151 // create controls
152 // ---------------
153
154 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
155 sizerTop->Add(new wxStaticText(this, wxID_ANY,
156 wxString::Format
157 (
158 _("Enter command to open file \"%s\":"),
159 filename.GetFullName().c_str()
160 )),
161 wxSizerFlags().Border());
162
163 wxSizer *sizerH = new wxBoxSizer(wxHORIZONTAL);
164
165 wxTextCtrl *command = new wxTextCtrl
166 (
167 this,
168 wxID_ANY,
169 wxEmptyString,
170 wxDefaultPosition,
171 wxSize(250, wxDefaultCoord),
172 0
173 #if wxUSE_VALIDATORS
174 ,wxTextValidator(wxFILTER_NONE, &m_command)
175 #endif
176 );
177 sizerH->Add(command,
178 wxSizerFlags(1).Align(wxALIGN_CENTER_VERTICAL));
179 wxButton *browse = new wxButton(this, wxID_MORE, wxT(">>"),
180 wxDefaultPosition, wxDefaultSize,
181 wxBU_EXACTFIT);
182 sizerH->Add(browse,
183 wxSizerFlags(0).Align(wxALIGN_CENTER_VERTICAL). Border(wxLEFT));
184
185 sizerTop->Add(sizerH, wxSizerFlags(0).Expand().Border());
186
187 sizerTop->Add(new wxStaticLine(this), wxSizerFlags().Expand().Border());
188
189 sizerTop->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL),
190 wxSizerFlags().Align(wxALIGN_RIGHT).Border());
191
192 // set the sizer &c
193 // ----------------
194
195 SetSizer(sizerTop);
196
197 Layout();
198 Fit();
199
200 command->SetFocus();
201 }
202
203 void wxDumpOpenExternalDlg::OnBrowse(wxCommandEvent& )
204 {
205 wxFileName fname(m_command);
206 wxFileDialog dlg(this,
207 wxFileSelectorPromptStr,
208 fname.GetPathWithSep(),
209 fname.GetFullName()
210 #ifdef __WXMSW__
211 , _("Executable files (*.exe)|*.exe|All files (*.*)|*.*||")
212 #endif // __WXMSW__
213 );
214 if ( dlg.ShowModal() == wxID_OK )
215 {
216 m_command = dlg.GetPath();
217 TransferDataToWindow();
218 }
219 }
220
221
222 // ----------------------------------------------------------------------------
223 // wxDebugReportDialog: class showing debug report to the user
224 // ----------------------------------------------------------------------------
225
226 class wxDebugReportDialog : public wxDialog
227 {
228 public:
229 wxDebugReportDialog(wxDebugReport& dbgrpt);
230
231 virtual bool TransferDataToWindow();
232 virtual bool TransferDataFromWindow();
233
234 private:
235 void OnView(wxCommandEvent& );
236 void OnViewUpdate(wxUpdateUIEvent& );
237 void OnOpen(wxCommandEvent& );
238
239
240 // small helper: add wxEXPAND and wxALL flags
241 static wxSizerFlags SizerFlags(int proportion)
242 {
243 return wxSizerFlags(proportion).Expand().Border();
244 }
245
246
247 wxDebugReport& m_dbgrpt;
248
249 wxCheckListBox *m_checklst;
250 wxTextCtrl *m_notes;
251
252 wxArrayString m_files;
253
254 DECLARE_EVENT_TABLE()
255 DECLARE_NO_COPY_CLASS(wxDebugReportDialog)
256 };
257
258 // ============================================================================
259 // wxDebugReportDialog implementation
260 // ============================================================================
261
262 BEGIN_EVENT_TABLE(wxDebugReportDialog, wxDialog)
263 EVT_BUTTON(wxID_VIEW_DETAILS, wxDebugReportDialog::OnView)
264 EVT_UPDATE_UI(wxID_VIEW_DETAILS, wxDebugReportDialog::OnViewUpdate)
265 EVT_BUTTON(wxID_OPEN, wxDebugReportDialog::OnOpen)
266 EVT_UPDATE_UI(wxID_OPEN, wxDebugReportDialog::OnViewUpdate)
267 END_EVENT_TABLE()
268
269
270 // ----------------------------------------------------------------------------
271 // construction
272 // ----------------------------------------------------------------------------
273
274 wxDebugReportDialog::wxDebugReportDialog(wxDebugReport& dbgrpt)
275 : wxDialog(NULL, wxID_ANY,
276 wxString::Format(_("Debug report \"%s\""),
277 dbgrpt.GetReportName().c_str()),
278 wxDefaultPosition,
279 wxDefaultSize,
280 wxDEFAULT_DIALOG_STYLE | wxTHICK_FRAME),
281 m_dbgrpt(dbgrpt)
282 {
283 // upper part of the dialog: explanatory message
284 wxString msg;
285 msg << _("A debug report has been generated in the directory\n")
286 << _T('\n')
287 << _T(" \"") << dbgrpt.GetDirectory() << _T("\"\n")
288 << _T('\n')
289 << _("The report contains the files listed below. If any of these ")
290 << _("files contain private information,\n")
291 << _("please uncheck them and they will be removed from the report.\n")
292 << _T('\n')
293 << _("If you wish to suppress this debug report completely, please ")
294 << _("choose the \"Cancel\" button,\n")
295 << _("but be warned that it may hinder improving the program, so if\n")
296 << _("at all possible please do continue with the report generation.\n")
297 << _T('\n')
298 << _(" Thank you and we're sorry for the inconvenience!\n")
299 << _T("\n\n"); // just some white space to separate from other stuff
300
301 const wxSizerFlags flagsFixed(SizerFlags(0));
302 const wxSizerFlags flagsExpand(SizerFlags(1));
303 const wxSizerFlags flagsExpand2(SizerFlags(2));
304
305 wxSizer *sizerPreview =
306 new wxStaticBoxSizer(wxVERTICAL, this, _("&Debug report preview:"));
307 sizerPreview->Add(CreateTextSizer(msg), SizerFlags(0).Centre());
308
309 // ... and the list of files in this debug report with buttons to view them
310 wxSizer *sizerFileBtns = new wxBoxSizer(wxVERTICAL);
311 sizerFileBtns->AddStretchSpacer(1);
312 sizerFileBtns->Add(new wxButton(this, wxID_VIEW_DETAILS, _T("&View...")),
313 wxSizerFlags().Border(wxBOTTOM));
314 sizerFileBtns->Add(new wxButton(this, wxID_OPEN, _T("&Open...")),
315 wxSizerFlags().Border(wxTOP));
316 sizerFileBtns->AddStretchSpacer(1);
317
318 m_checklst = new wxCheckListBox(this, wxID_ANY);
319
320 wxSizer *sizerFiles = new wxBoxSizer(wxHORIZONTAL);
321 sizerFiles->Add(m_checklst, flagsExpand);
322 sizerFiles->Add(sizerFileBtns, flagsFixed);
323
324 sizerPreview->Add(sizerFiles, flagsExpand2);
325
326
327 // lower part of the dialog: notes field
328 wxSizer *sizerNotes = new wxStaticBoxSizer(wxVERTICAL, this, _("&Notes:"));
329
330 msg = _("If you have any additional information pertaining to this bug\n");
331 msg << _("report, please enter it here and it will be joined to it:");
332
333 m_notes = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
334 wxDefaultPosition, wxDefaultSize,
335 wxTE_MULTILINE);
336
337 sizerNotes->Add(CreateTextSizer(msg), flagsFixed);
338 sizerNotes->Add(m_notes, flagsExpand);
339
340
341 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
342 sizerTop->Add(sizerPreview, flagsExpand2);
343 sizerTop->AddSpacer(5);
344 sizerTop->Add(sizerNotes, flagsExpand);
345 sizerTop->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), flagsFixed);
346
347 SetSizerAndFit(sizerTop);
348 Layout();
349 CentreOnScreen();
350 }
351
352 // ----------------------------------------------------------------------------
353 // data exchange
354 // ----------------------------------------------------------------------------
355
356 bool wxDebugReportDialog::TransferDataToWindow()
357 {
358 // all files are included in the report by default
359 const size_t count = m_dbgrpt.GetFilesCount();
360 for ( size_t n = 0; n < count; n++ )
361 {
362 wxString name,
363 desc;
364 if ( m_dbgrpt.GetFile(n, &name, &desc) )
365 {
366 m_checklst->Append(name + _T(" (") + desc + _T(')'));
367 m_checklst->Check(n);
368
369 m_files.Add(name);
370 }
371 }
372
373 return true;
374 }
375
376 bool wxDebugReportDialog::TransferDataFromWindow()
377 {
378 // any unchecked files should be removed from the report
379 const size_t count = m_checklst->GetCount();
380 for ( size_t n = 0; n < count; n++ )
381 {
382 if ( !m_checklst->IsChecked(n) )
383 {
384 m_dbgrpt.RemoveFile(m_files[n]);
385 }
386 }
387
388 // if the user entered any notes, add them to the report
389 const wxString notes = m_notes->GetValue();
390 if ( !notes.empty() )
391 {
392 // for now filename fixed, could make it configurable in the future...
393 m_dbgrpt.AddText(_T("notes.txt"), notes, _T("user notes"));
394 }
395
396 return true;
397 }
398
399 // ----------------------------------------------------------------------------
400 // event handlers
401 // ----------------------------------------------------------------------------
402
403 void wxDebugReportDialog::OnView(wxCommandEvent& )
404 {
405 const int sel = m_checklst->GetSelection();
406 wxCHECK_RET( sel != -1, _T("invalid selection in OnView()") );
407
408 wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]);
409 wxString str;
410
411 wxFFile file(fn.GetFullPath());
412 if ( file.IsOpened() && file.ReadAll(&str) )
413 {
414 wxDumpPreviewDlg dlg(this, m_files[sel], str);
415 dlg.ShowModal();
416 }
417 }
418
419 void wxDebugReportDialog::OnOpen(wxCommandEvent& )
420 {
421 const int sel = m_checklst->GetSelection();
422 wxCHECK_RET( sel != -1, _T("invalid selection in OnOpen()") );
423
424 wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]);
425
426 // try to get the command to open this kind of files ourselves
427 wxString command;
428 #if wxUSE_MIMETYPE
429 wxFileType *
430 ft = wxTheMimeTypesManager->GetFileTypeFromExtension(fn.GetExt());
431 if ( ft )
432 {
433 command = ft->GetOpenCommand(fn.GetFullPath());
434 delete ft;
435 }
436 #endif // wxUSE_MIMETYPE
437
438 // if we couldn't, ask the user
439 if ( command.empty() )
440 {
441 wxDumpOpenExternalDlg dlg(this, fn);
442 if ( dlg.ShowModal() == wxID_OK )
443 {
444 // get the command chosen by the user and append file name to it
445
446 // if we don't have place marker for file name in the command...
447 wxString cmd = dlg.GetCommand();
448 if ( cmd.find(_T('%')) == wxString::npos )
449 {
450 // ...add it
451 cmd += _T(" \"%s\"");
452 }
453
454 command = wxFileType::ExpandCommand(cmd, fn.GetFullPath());
455 }
456 }
457
458 if ( !command.empty() )
459 ::wxExecute(command);
460 }
461
462 void wxDebugReportDialog::OnViewUpdate(wxUpdateUIEvent& event)
463 {
464 int sel = m_checklst->GetSelection();
465 if (sel >= 0)
466 {
467 wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]);
468 event.Enable(fn.FileExists());
469 }
470 else
471 event.Enable(false);
472 }
473
474
475 // ============================================================================
476 // wxDebugReportPreviewStd implementation
477 // ============================================================================
478
479 bool wxDebugReportPreviewStd::Show(wxDebugReport& dbgrpt) const
480 {
481 if ( !dbgrpt.GetFilesCount() )
482 return false;
483
484 wxDebugReportDialog dlg(dbgrpt);
485
486 return dlg.ShowModal() == wxID_OK && dbgrpt.GetFilesCount() != 0;
487 }
488
489 #endif // wxUSE_DEBUGREPORT
490