added svn:ignores
[debian/openrocket] / src / net / sf / openrocket / gui / dialogs / BugReportDialog.java
1 package net.sf.openrocket.gui.dialogs;
2
3 import java.awt.Desktop;
4 import java.awt.Dialog;
5 import java.awt.Dimension;
6 import java.awt.Window;
7 import java.awt.event.ActionEvent;
8 import java.awt.event.ActionListener;
9 import java.io.IOException;
10 import java.io.PrintWriter;
11 import java.io.StringWriter;
12 import java.io.UnsupportedEncodingException;
13 import java.net.URI;
14 import java.net.URISyntaxException;
15 import java.net.URLEncoder;
16 import java.util.List;
17 import java.util.Locale;
18 import java.util.SortedSet;
19 import java.util.TreeSet;
20
21 import javax.swing.JButton;
22 import javax.swing.JDialog;
23 import javax.swing.JLabel;
24 import javax.swing.JOptionPane;
25 import javax.swing.JPanel;
26 import javax.swing.JScrollPane;
27 import javax.swing.JTextArea;
28
29 import net.miginfocom.swing.MigLayout;
30 import net.sf.openrocket.communication.BugReporter;
31 import net.sf.openrocket.gui.components.SelectableLabel;
32 import net.sf.openrocket.gui.components.StyledLabel;
33 import net.sf.openrocket.logging.LogLevelBufferLogger;
34 import net.sf.openrocket.logging.LogLine;
35 import net.sf.openrocket.startup.Application;
36 import net.sf.openrocket.util.BugException;
37 import net.sf.openrocket.util.GUIUtil;
38 import net.sf.openrocket.util.JarUtil;
39 import net.sf.openrocket.util.Prefs;
40
41 public class BugReportDialog extends JDialog {
42         
43         private static final String REPORT_EMAIL = "openrocket-bugs@lists.sourceforge.net";
44         
45         
46         public BugReportDialog(Window parent, String labelText, String message) {
47                 super(parent, "Bug report", Dialog.ModalityType.APPLICATION_MODAL);
48                 
49                 JPanel panel = new JPanel(new MigLayout("fill"));
50                 
51                 // Some fscking Swing bug that makes html labels initially way too high
52                 JLabel label = new JLabel(labelText);
53                 Dimension d = label.getPreferredSize();
54                 d.width = 100000;
55                 label.setMaximumSize(d);
56                 panel.add(label, "gapleft para, wrap para");
57                 
58                 label = new JLabel("<html>If connected to the Internet, you can simply click " +
59                                 "<em>Send bug report</em>.");
60                 d = label.getPreferredSize();
61                 d.width = 100000;
62                 label.setMaximumSize(d);
63                 panel.add(label, "gapleft para, wrap");
64                 
65                 panel.add(new JLabel("Otherwise, send the text below to the address: "),
66                                 "gapleft para, split 2, gapright rel");
67                 panel.add(new SelectableLabel(REPORT_EMAIL), "growx, wrap para");
68                 
69
70                 final JTextArea textArea = new JTextArea(message, 20, 70);
71                 textArea.setEditable(true);
72                 panel.add(new JScrollPane(textArea), "grow, wrap");
73                 
74
75                 panel.add(new StyledLabel("The information above may be included in a public " +
76                                 "bug report.  Make sure it does not contain any sensitive information you " +
77                                 "do not want to be made public.", -1), "wrap para");
78                 
79
80
81                 ////  Close button
82                 JButton close = new JButton("Close");
83                 close.addActionListener(new ActionListener() {
84                         @Override
85                         public void actionPerformed(ActionEvent e) {
86                                 BugReportDialog.this.dispose();
87                         }
88                 });
89                 panel.add(close, "right, sizegroup buttons, split");
90                 
91
92                 ////  Mail button
93                 //              if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Action.MAIL)) {
94                 //                      JButton mail = new JButton("Open email");
95                 //                      mail.setToolTipText("Open email client with the suitable email ready.");
96                 //                      mail.addActionListener(new ActionListener() {
97                 //                              @Override
98                 //                              public void actionPerformed(ActionEvent e) {
99                 //                                      String text = textArea.getText();
100                 //                                      openEmail(text);
101                 //                              }
102                 //                      });
103                 //                      panel.add(mail, "right, sizegroup buttons");
104                 //              }
105                 
106
107                 ////  Send button
108                 JButton send = new JButton("Send bug report");
109                 send.setToolTipText("Automatically send the bug report to the OpenRocket developers.");
110                 send.addActionListener(new ActionListener() {
111                         @Override
112                         public void actionPerformed(ActionEvent e) {
113                                 String text = textArea.getText();
114                                 try {
115                                         
116                                         BugReporter.sendBugReport(text);
117                                         
118                                         // Success if we came here
119                                         JOptionPane.showMessageDialog(BugReportDialog.this,
120                                                         new Object[] { "Bug report successfully sent.",
121                                                                         "Thank you for helping make OpenRocket better!" },
122                                                         "Bug report sent", JOptionPane.INFORMATION_MESSAGE);
123                                         
124                                 } catch (Exception ex) {
125                                         // Sending the message failed.
126                                         JOptionPane.showMessageDialog(BugReportDialog.this,
127                                                         new Object[] { "OpenRocket was unable to send the bug report:",
128                                                                         ex.getClass().getSimpleName() + ": " + ex.getMessage(), " ",
129                                                                         "Please send the report manually to " + REPORT_EMAIL },
130                                                         "Error sending report", JOptionPane.ERROR_MESSAGE);
131                                 }
132                         }
133                 });
134                 panel.add(send, "right, sizegroup buttons");
135                 
136                 this.add(panel);
137                 
138                 this.validate();
139                 this.pack();
140                 this.pack();
141                 this.setLocationRelativeTo(parent);
142                 
143                 GUIUtil.setDisposableDialogOptions(this, send);
144         }
145         
146         
147
148         /**
149          * Show a general bug report dialog allowing the user to input information about
150          * the bug they encountered.
151          * 
152          * @param parent        the parent window (may be null).
153          */
154         public static void showBugReportDialog(Window parent) {
155                 
156                 StringBuilder sb = new StringBuilder();
157                 
158                 sb.append("---------- Bug report ----------\n");
159                 sb.append('\n');
160                 sb.append("Include detailed steps on how to trigger the bug:\n");
161                 sb.append('\n');
162                 sb.append("1. \n");
163                 sb.append("2. \n");
164                 sb.append("3. \n");
165                 sb.append('\n');
166                 
167                 sb.append("What does the software do and what in your opinion should it do in the " +
168                                 "case described above:\n");
169                 sb.append('\n');
170                 sb.append('\n');
171                 sb.append('\n');
172                 
173                 sb.append("Include your email address (optional; it helps if we can " +
174                                 "contact you in case we need additional information):\n");
175                 sb.append('\n');
176                 sb.append('\n');
177                 sb.append('\n');
178                 
179
180                 sb.append("(Do not modify anything below this line.)\n");
181                 sb.append("---------- System information ----------\n");
182                 addSystemInformation(sb);
183                 sb.append("---------- Error log ----------\n");
184                 addErrorLog(sb);
185                 sb.append("---------- End of bug report ----------\n");
186                 sb.append('\n');
187                 
188                 BugReportDialog reportDialog =
189                                 new BugReportDialog(parent,
190                                                 "<html><b>You can report a bug in OpenRocket by filling in and submitting " +
191                                                                 "the form below.</b><br>" +
192                                                                 "You can also report bugs and include attachments on the project " +
193                                                                 "web site.", sb.toString());
194                 reportDialog.setVisible(true);
195         }
196         
197         
198         /**
199          * Show a dialog presented when an uncaught exception occurs.
200          * 
201          * @param parent        the parent window (may be null).
202          * @param t                     the thread that encountered the exception (may be null).
203          * @param e                     the exception.
204          */
205         public static void showExceptionDialog(Window parent, Thread t, Throwable e) {
206                 StringBuilder sb = new StringBuilder();
207                 
208                 sb.append("---------- Bug report ----------\n");
209                 sb.append('\n');
210                 sb.append("Please include a description about what actions you were " +
211                                 "performing when the exception occurred:\n");
212                 sb.append('\n');
213                 sb.append('\n');
214                 sb.append('\n');
215                 sb.append('\n');
216                 
217
218                 sb.append("Include your email address (optional; it helps if we can " +
219                                 "contact you in case we need additional information):\n");
220                 sb.append('\n');
221                 sb.append('\n');
222                 sb.append('\n');
223                 sb.append('\n');
224                 
225                 sb.append("(Do not modify anything below this line.)\n");
226                 sb.append("---------- Exception stack trace ----------\n");
227                 StringWriter sw = new StringWriter();
228                 PrintWriter pw = new PrintWriter(sw);
229                 e.printStackTrace(pw);
230                 sb.append(sw.getBuffer());
231                 sb.append('\n');
232                 
233
234                 sb.append("---------- Thread information ----------\n");
235                 if (t == null) {
236                         sb.append("Thread is not specified.");
237                 } else {
238                         sb.append(t + "\n");
239                 }
240                 sb.append('\n');
241                 
242
243                 sb.append("---------- System information ----------\n");
244                 addSystemInformation(sb);
245                 sb.append("---------- Error log ----------\n");
246                 addErrorLog(sb);
247                 sb.append("---------- End of bug report ----------\n");
248                 sb.append('\n');
249                 
250                 BugReportDialog reportDialog =
251                                 new BugReportDialog(parent, "<html><b>Please include a short description about " +
252                                                 "what you were doing when the exception occurred.</b>", sb.toString());
253                 reportDialog.setVisible(true);
254         }
255         
256         
257         private static void addSystemInformation(StringBuilder sb) {
258                 sb.append("OpenRocket version: " + Prefs.getVersion() + "\n");
259                 sb.append("OpenRocket source: " + Prefs.getBuildSource() + "\n");
260                 sb.append("OpenRocket location: " + JarUtil.getCurrentJarFile() + "\n");
261                 sb.append("Current default locale: " + Locale.getDefault() + "\n");
262                 sb.append("System properties:\n");
263                 
264                 // Sort the keys
265                 SortedSet<String> keys = new TreeSet<String>();
266                 for (Object key : System.getProperties().keySet()) {
267                         keys.add((String) key);
268                 }
269                 
270                 for (String key : keys) {
271                         String value = System.getProperty(key);
272                         sb.append("  " + key + "=");
273                         if (key.equals("line.separator")) {
274                                 for (char c : value.toCharArray()) {
275                                         sb.append(String.format("\\u%04x", (int) c));
276                                 }
277                         } else {
278                                 sb.append(value);
279                         }
280                         sb.append('\n');
281                 }
282         }
283         
284         
285         private static void addErrorLog(StringBuilder sb) {
286                 LogLevelBufferLogger buffer = Application.getLogBuffer();
287                 List<LogLine> logs = buffer.getLogs();
288                 for (LogLine l : logs) {
289                         sb.append(l.toString()).append('\n');
290                 }
291         }
292         
293         
294
295         /**
296          * Open the default email client with the suitable bug report.
297          * Note that this does not work on some systems even if Desktop.isSupported()
298          * claims so.
299          * 
300          * @param text  the bug report text.
301          * @return              whether opening the client succeeded.
302          */
303         private boolean openEmail(String text) {
304                 String version;
305                 
306                 try {
307                         text = URLEncoder.encode(text, "UTF-8");
308                         version = URLEncoder.encode(Prefs.getVersion(), "UTF-8");
309                 } catch (UnsupportedEncodingException e) {
310                         throw new BugException(e);
311                 }
312                 
313
314
315                 String mailto = "mailto:" + REPORT_EMAIL
316                                 + "?subject=Bug%20report%20for%20OpenRocket%20" + version
317                                 + "?body=" + text;
318                 URI uri;
319                 try {
320                         uri = new URI(mailto);
321                 } catch (URISyntaxException e) {
322                         e.printStackTrace();
323                         return false;
324                 }
325                 
326                 Desktop desktop = Desktop.getDesktop();
327                 try {
328                         desktop.mail(uri);
329                 } catch (IOException e) {
330                         e.printStackTrace();
331                         return false;
332                 }
333                 
334                 return true;
335         }
336         
337 }