]> git.saurik.com Git - wxWidgets.git/blame - src/generic/dbgrptg.cpp
Added extra hit test style for more accurate reporting
[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>
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
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()
49#endif // __WXMSW__
50
ce4fd7b5
VZ
51// ----------------------------------------------------------------------------
52// wxDumpPreviewDlg: simple class for showing ASCII preview of dump files
53// ----------------------------------------------------------------------------
54
55class wxDumpPreviewDlg : public wxDialog
56{
57public:
58 wxDumpPreviewDlg(wxWindow *parent,
59 const wxString& title,
60 const wxString& text);
61
62private:
63 // the text we show
64 wxTextCtrl *m_text;
65
66 DECLARE_NO_COPY_CLASS(wxDumpPreviewDlg)
67};
68
69wxDumpPreviewDlg::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
124class wxDumpOpenExternalDlg : public wxDialog
125{
126public:
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
134private:
7a893a31
WS
135
136#if wxUSE_FILEDLG
ce4fd7b5 137 void OnBrowse(wxCommandEvent& event);
7a893a31 138#endif // wxUSE_FILEDLG
ce4fd7b5
VZ
139
140 DECLARE_EVENT_TABLE()
141 DECLARE_NO_COPY_CLASS(wxDumpOpenExternalDlg)
142};
143
144BEGIN_EVENT_TABLE(wxDumpOpenExternalDlg, wxDialog)
7a893a31
WS
145
146#if wxUSE_FILEDLG
ce4fd7b5 147 EVT_BUTTON(wxID_MORE, wxDumpOpenExternalDlg::OnBrowse)
7a893a31
WS
148#endif
149
ce4fd7b5
VZ
150END_EVENT_TABLE()
151
152
153wxDumpOpenExternalDlg::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,
f5c479cc
WS
183 wxSize(250, wxDefaultCoord),
184 0
185#if wxUSE_VALIDATORS
186 ,wxTextValidator(wxFILTER_NONE, &m_command)
187#endif
ce4fd7b5
VZ
188 );
189 sizerH->Add(command,
190 wxSizerFlags(1).Align(wxALIGN_CENTER_VERTICAL));
7a893a31
WS
191
192#if wxUSE_FILEDLG
193
ce4fd7b5
VZ
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
7a893a31
WS
200#endif // wxUSE_FILEDLG
201
ce4fd7b5
VZ
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
7a893a31
WS
220#if wxUSE_FILEDLG
221
ce4fd7b5
VZ
222void 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
7a893a31 240#endif // wxUSE_FILEDLG
ce4fd7b5
VZ
241
242// ----------------------------------------------------------------------------
243// wxDebugReportDialog: class showing debug report to the user
244// ----------------------------------------------------------------------------
245
246class wxDebugReportDialog : public wxDialog
247{
248public:
249 wxDebugReportDialog(wxDebugReport& dbgrpt);
250
251 virtual bool TransferDataToWindow();
252 virtual bool TransferDataFromWindow();
253
254private:
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 DECLARE_NO_COPY_CLASS(wxDebugReportDialog)
276};
277
278// ============================================================================
279// wxDebugReportDialog implementation
280// ============================================================================
281
282BEGIN_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)
287END_EVENT_TABLE()
288
289
290// ----------------------------------------------------------------------------
291// construction
292// ----------------------------------------------------------------------------
293
294wxDebugReportDialog::wxDebugReportDialog(wxDebugReport& dbgrpt)
295 : wxDialog(NULL, wxID_ANY,
296 wxString::Format(_("Debug report \"%s\""),
297 dbgrpt.GetReportName().c_str()),
298 wxDefaultPosition,
299 wxDefaultSize,
1c067fe3 300 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
ce4fd7b5
VZ
301 m_dbgrpt(dbgrpt)
302{
303 // upper part of the dialog: explanatory message
304 wxString msg;
305 msg << _("A debug report has been generated in the directory\n")
306 << _T('\n')
307 << _T(" \"") << dbgrpt.GetDirectory() << _T("\"\n")
308 << _T('\n')
67a623de 309 << _("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")
ce4fd7b5 310 << _T('\n')
67a623de 311 << _("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")
ce4fd7b5
VZ
312 << _T('\n')
313 << _(" Thank you and we're sorry for the inconvenience!\n")
314 << _T("\n\n"); // just some white space to separate from other stuff
315
316 const wxSizerFlags flagsFixed(SizerFlags(0));
317 const wxSizerFlags flagsExpand(SizerFlags(1));
318 const wxSizerFlags flagsExpand2(SizerFlags(2));
319
320 wxSizer *sizerPreview =
321 new wxStaticBoxSizer(wxVERTICAL, this, _("&Debug report preview:"));
322 sizerPreview->Add(CreateTextSizer(msg), SizerFlags(0).Centre());
323
324 // ... and the list of files in this debug report with buttons to view them
325 wxSizer *sizerFileBtns = new wxBoxSizer(wxVERTICAL);
326 sizerFileBtns->AddStretchSpacer(1);
327 sizerFileBtns->Add(new wxButton(this, wxID_VIEW_DETAILS, _T("&View...")),
328 wxSizerFlags().Border(wxBOTTOM));
329 sizerFileBtns->Add(new wxButton(this, wxID_OPEN, _T("&Open...")),
330 wxSizerFlags().Border(wxTOP));
331 sizerFileBtns->AddStretchSpacer(1);
332
333 m_checklst = new wxCheckListBox(this, wxID_ANY);
334
335 wxSizer *sizerFiles = new wxBoxSizer(wxHORIZONTAL);
336 sizerFiles->Add(m_checklst, flagsExpand);
337 sizerFiles->Add(sizerFileBtns, flagsFixed);
338
339 sizerPreview->Add(sizerFiles, flagsExpand2);
340
341
342 // lower part of the dialog: notes field
343 wxSizer *sizerNotes = new wxStaticBoxSizer(wxVERTICAL, this, _("&Notes:"));
344
67a623de 345 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
346
347 m_notes = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
348 wxDefaultPosition, wxDefaultSize,
349 wxTE_MULTILINE);
350
351 sizerNotes->Add(CreateTextSizer(msg), flagsFixed);
352 sizerNotes->Add(m_notes, flagsExpand);
353
354
355 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
356 sizerTop->Add(sizerPreview, flagsExpand2);
357 sizerTop->AddSpacer(5);
358 sizerTop->Add(sizerNotes, flagsExpand);
359 sizerTop->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), flagsFixed);
360
361 SetSizerAndFit(sizerTop);
362 Layout();
363 CentreOnScreen();
364}
365
366// ----------------------------------------------------------------------------
367// data exchange
368// ----------------------------------------------------------------------------
369
370bool wxDebugReportDialog::TransferDataToWindow()
371{
372 // all files are included in the report by default
373 const size_t count = m_dbgrpt.GetFilesCount();
374 for ( size_t n = 0; n < count; n++ )
375 {
376 wxString name,
377 desc;
378 if ( m_dbgrpt.GetFile(n, &name, &desc) )
379 {
380 m_checklst->Append(name + _T(" (") + desc + _T(')'));
381 m_checklst->Check(n);
382
383 m_files.Add(name);
384 }
385 }
386
387 return true;
388}
389
390bool wxDebugReportDialog::TransferDataFromWindow()
391{
392 // any unchecked files should be removed from the report
393 const size_t count = m_checklst->GetCount();
394 for ( size_t n = 0; n < count; n++ )
395 {
396 if ( !m_checklst->IsChecked(n) )
397 {
398 m_dbgrpt.RemoveFile(m_files[n]);
399 }
400 }
401
402 // if the user entered any notes, add them to the report
403 const wxString notes = m_notes->GetValue();
404 if ( !notes.empty() )
405 {
e18c3e02
VZ
406 // for now filename fixed, could make it configurable in the future...
407 m_dbgrpt.AddText(_T("notes.txt"), notes, _T("user notes"));
ce4fd7b5
VZ
408 }
409
410 return true;
411}
412
413// ----------------------------------------------------------------------------
414// event handlers
415// ----------------------------------------------------------------------------
416
417void wxDebugReportDialog::OnView(wxCommandEvent& )
418{
419 const int sel = m_checklst->GetSelection();
7a893a31 420 wxCHECK_RET( sel != wxNOT_FOUND, _T("invalid selection in OnView()") );
ce4fd7b5
VZ
421
422 wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]);
423 wxString str;
424
425 wxFFile file(fn.GetFullPath());
426 if ( file.IsOpened() && file.ReadAll(&str) )
427 {
428 wxDumpPreviewDlg dlg(this, m_files[sel], str);
429 dlg.ShowModal();
430 }
431}
432
433void wxDebugReportDialog::OnOpen(wxCommandEvent& )
434{
435 const int sel = m_checklst->GetSelection();
7a893a31 436 wxCHECK_RET( sel != wxNOT_FOUND, _T("invalid selection in OnOpen()") );
ce4fd7b5
VZ
437
438 wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]);
439
440 // try to get the command to open this kind of files ourselves
441 wxString command;
acf094a2 442#if wxUSE_MIMETYPE
ce4fd7b5
VZ
443 wxFileType *
444 ft = wxTheMimeTypesManager->GetFileTypeFromExtension(fn.GetExt());
445 if ( ft )
446 {
447 command = ft->GetOpenCommand(fn.GetFullPath());
acf094a2 448 delete ft;
ce4fd7b5 449 }
acf094a2 450#endif // wxUSE_MIMETYPE
ce4fd7b5
VZ
451
452 // if we couldn't, ask the user
453 if ( command.empty() )
454 {
455 wxDumpOpenExternalDlg dlg(this, fn);
456 if ( dlg.ShowModal() == wxID_OK )
457 {
458 // get the command chosen by the user and append file name to it
459
460 // if we don't have place marker for file name in the command...
461 wxString cmd = dlg.GetCommand();
492b6f0a 462 if ( !cmd.empty() )
ce4fd7b5 463 {
492b6f0a
VZ
464#if wxUSE_MIMETYPE
465 if ( cmd.find(_T('%')) != wxString::npos )
466 {
467 command = wxFileType::ExpandCommand(cmd, fn.GetFullPath());
468 }
469 else // no %s nor %1
470#endif // wxUSE_MIMETYPE
471 {
472 // append the file name to the end
473 command << cmd << _T(" \"") << fn.GetFullPath() << _T('"');
474 }
ce4fd7b5 475 }
ce4fd7b5
VZ
476 }
477 }
478
479 if ( !command.empty() )
480 ::wxExecute(command);
481}
482
483void wxDebugReportDialog::OnViewUpdate(wxUpdateUIEvent& event)
484{
485 int sel = m_checklst->GetSelection();
486 if (sel >= 0)
487 {
488 wxFileName fn(m_dbgrpt.GetDirectory(), m_files[sel]);
489 event.Enable(fn.FileExists());
490 }
491 else
492 event.Enable(false);
493}
494
495
496// ============================================================================
497// wxDebugReportPreviewStd implementation
498// ============================================================================
499
500bool wxDebugReportPreviewStd::Show(wxDebugReport& dbgrpt) const
501{
502 if ( !dbgrpt.GetFilesCount() )
503 return false;
504
505 wxDebugReportDialog dlg(dbgrpt);
506
c707a0d4
VZ
507#ifdef __WXMSW__
508 // before entering the event loop (from ShowModal()), block the event
509 // handling for all other windows as this could result in more crashes
510 wxEventLoop::SetCriticalWindow(&dlg);
511#endif // __WXMSW__
512
ce4fd7b5
VZ
513 return dlg.ShowModal() == wxID_OK && dbgrpt.GetFilesCount() != 0;
514}
515
88a7a4e1 516#endif // wxUSE_DEBUGREPORT && wxUSE_XML