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