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