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