fixed for w/o expat
[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 && wxUSE_XML
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 files contain private information,\nplease uncheck them and they will be removed from the report.\n")
290 << _T('\n')
291 << _("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")
292 << _T('\n')
293 << _(" Thank you and we're sorry for the inconvenience!\n")
294 << _T("\n\n"); // just some white space to separate from other stuff
295
296 const wxSizerFlags flagsFixed(SizerFlags(0));
297 const wxSizerFlags flagsExpand(SizerFlags(1));
298 const wxSizerFlags flagsExpand2(SizerFlags(2));
299
300 wxSizer *sizerPreview =
301 new wxStaticBoxSizer(wxVERTICAL, this, _("&Debug report preview:"));
302 sizerPreview->Add(CreateTextSizer(msg), SizerFlags(0).Centre());
303
304 // ... and the list of files in this debug report with buttons to view them
305 wxSizer *sizerFileBtns = new wxBoxSizer(wxVERTICAL);
306 sizerFileBtns->AddStretchSpacer(1);
307 sizerFileBtns->Add(new wxButton(this, wxID_VIEW_DETAILS, _T("&View...")),
308 wxSizerFlags().Border(wxBOTTOM));
309 sizerFileBtns->Add(new wxButton(this, wxID_OPEN, _T("&Open...")),
310 wxSizerFlags().Border(wxTOP));
311 sizerFileBtns->AddStretchSpacer(1);
312
313 m_checklst = new wxCheckListBox(this, wxID_ANY);
314
315 wxSizer *sizerFiles = new wxBoxSizer(wxHORIZONTAL);
316 sizerFiles->Add(m_checklst, flagsExpand);
317 sizerFiles->Add(sizerFileBtns, flagsFixed);
318
319 sizerPreview->Add(sizerFiles, flagsExpand2);
320
321
322 // lower part of the dialog: notes field
323 wxSizer *sizerNotes = new wxStaticBoxSizer(wxVERTICAL, this, _("&Notes:"));
324
325 msg = _("If you have any additional information pertaining to this bug\nreport, please enter it here and it will be joined to it:");
326
327 m_notes = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
328 wxDefaultPosition, wxDefaultSize,
329 wxTE_MULTILINE);
330
331 sizerNotes->Add(CreateTextSizer(msg), flagsFixed);
332 sizerNotes->Add(m_notes, flagsExpand);
333
334
335 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
336 sizerTop->Add(sizerPreview, flagsExpand2);
337 sizerTop->AddSpacer(5);
338 sizerTop->Add(sizerNotes, flagsExpand);
339 sizerTop->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), flagsFixed);
340
341 SetSizerAndFit(sizerTop);
342 Layout();
343 CentreOnScreen();
344 }
345
346 // ----------------------------------------------------------------------------
347 // data exchange
348 // ----------------------------------------------------------------------------
349
350 bool wxDebugReportDialog::TransferDataToWindow()
351 {
352 // all files are included in the report by default
353 const size_t count = m_dbgrpt.GetFilesCount();
354 for ( size_t n = 0; n < count; n++ )
355 {
356 wxString name,
357 desc;
358 if ( m_dbgrpt.GetFile(n, &name, &desc) )
359 {
360 m_checklst->Append(name + _T(" (") + desc + _T(')'));
361 m_checklst->Check(n);
362
363 m_files.Add(name);
364 }
365 }
366
367 return true;
368 }
369
370 bool wxDebugReportDialog::TransferDataFromWindow()
371 {
372 // any unchecked files should be removed from the report
373 const size_t count = m_checklst->GetCount();
374 for ( size_t n = 0; n < count; n++ )
375 {
376 if ( !m_checklst->IsChecked(n) )
377 {
378 m_dbgrpt.RemoveFile(m_files[n]);
379 }
380 }
381
382 // if the user entered any notes, add them to the report
383 const wxString notes = m_notes->GetValue();
384 if ( !notes.empty() )
385 {
386 // for now filename fixed, could make it configurable in the future...
387 m_dbgrpt.AddText(_T("notes.txt"), notes, _T("user notes"));
388 }
389
390 return true;
391 }
392
393 // ----------------------------------------------------------------------------
394 // event handlers
395 // ----------------------------------------------------------------------------
396
397 void wxDebugReportDialog::OnView(wxCommandEvent& )
398 {
399 const int sel = m_checklst->GetSelection();
400 wxCHECK_RET( sel != -1, _T("invalid selection in OnView()") );
401
402 wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]);
403 wxString str;
404
405 wxFFile file(fn.GetFullPath());
406 if ( file.IsOpened() && file.ReadAll(&str) )
407 {
408 wxDumpPreviewDlg dlg(this, m_files[sel], str);
409 dlg.ShowModal();
410 }
411 }
412
413 void wxDebugReportDialog::OnOpen(wxCommandEvent& )
414 {
415 const int sel = m_checklst->GetSelection();
416 wxCHECK_RET( sel != -1, _T("invalid selection in OnOpen()") );
417
418 wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]);
419
420 // try to get the command to open this kind of files ourselves
421 wxString command;
422 #if wxUSE_MIMETYPE
423 wxFileType *
424 ft = wxTheMimeTypesManager->GetFileTypeFromExtension(fn.GetExt());
425 if ( ft )
426 {
427 command = ft->GetOpenCommand(fn.GetFullPath());
428 delete ft;
429 }
430 #endif // wxUSE_MIMETYPE
431
432 // if we couldn't, ask the user
433 if ( command.empty() )
434 {
435 wxDumpOpenExternalDlg dlg(this, fn);
436 if ( dlg.ShowModal() == wxID_OK )
437 {
438 // get the command chosen by the user and append file name to it
439
440 // if we don't have place marker for file name in the command...
441 wxString cmd = dlg.GetCommand();
442 if ( cmd.find(_T('%')) == wxString::npos )
443 {
444 // ...add it
445 cmd += _T(" \"%s\"");
446 }
447
448 command = wxFileType::ExpandCommand(cmd, fn.GetFullPath());
449 }
450 }
451
452 if ( !command.empty() )
453 ::wxExecute(command);
454 }
455
456 void wxDebugReportDialog::OnViewUpdate(wxUpdateUIEvent& event)
457 {
458 int sel = m_checklst->GetSelection();
459 if (sel >= 0)
460 {
461 wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]);
462 event.Enable(fn.FileExists());
463 }
464 else
465 event.Enable(false);
466 }
467
468
469 // ============================================================================
470 // wxDebugReportPreviewStd implementation
471 // ============================================================================
472
473 bool wxDebugReportPreviewStd::Show(wxDebugReport& dbgrpt) const
474 {
475 if ( !dbgrpt.GetFilesCount() )
476 return false;
477
478 wxDebugReportDialog dlg(dbgrpt);
479
480 return dlg.ShowModal() == wxID_OK && dbgrpt.GetFilesCount() != 0;
481 }
482
483 #endif // wxUSE_DEBUGREPORT
484