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