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