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