package com.compomics.util.gui.error_handlers; import com.compomics.util.Util; import com.compomics.util.examples.BareBonesBrowserLaunch; import com.compomics.util.preferences.LastSelectedFolder; import java.io.*; import java.util.Date; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.border.TitledBorder; /** * A simple bug report dialog. * * @author Marc Vaudel * @author Harald Barsnes */ public class BugReport extends javax.swing.JDialog { /** * The folder to open in the file selection dialog. */ private LastSelectedFolder lastSelectedFolder; /** * The specific key for bug reports. */ public static final String lastSelectedFolderKey = "bug_report"; /** * The name of the tool to get the bug report for, e.g., "PeptideShaker". */ private String toolName; /** * The GitHub name of the tool, e.g., "peptide-shaker". */ private String gitHubProjectName; /** * The version number of the tool the log files belongs to. */ private String toolVersion; /** * The name of the Google Group. */ private String googleGroup; /** * The human readable name of the the Google Group. */ private String googleGroupName; /** * The log file to display. */ private File logFile; /** * Creates a new BugReport dialog. * * @param frame the parent frame * @param selectionFolder the folder to open in the file selection dialog * @param toolName the name of the tool to get the bug report for, e.g., * "PeptideShaker" or "SearchGUI" * @param gitHubProjectName the GitHub project name of the tool, e.g., * "peptide-shaker" * @param toolVersion the version number of the tool the log files belongs * to * @param googleGroup the name of the Google Group, e.g., peptide-shaker, * setting to null will refer to the PeptideShaker Google Group * @param googleGroupName the human readable name of the the Google Group, * e.g., PeptideShaker, setting to null will refer to the PeptideShaker * Google Group * @param logFile the log file to display */ public BugReport(JFrame frame, LastSelectedFolder selectionFolder, String toolName, String gitHubProjectName, String toolVersion, String googleGroup, String googleGroupName, File logFile) { super(frame, true); this.lastSelectedFolder = selectionFolder; this.toolName = toolName; this.gitHubProjectName = gitHubProjectName; this.toolVersion = toolVersion; this.googleGroup = googleGroup; this.googleGroupName = googleGroupName; this.logFile = logFile; initComponents(); setUpGui(); setLocationRelativeTo(frame); setVisible(true); } /** * Creates a new BugReport dialog. * * @param dialog the parent frame * @param selectionFolder the folder to open in the file selection dialog * @param toolName the name of the tool to get the bug report for, e.g., * PeptideShaker or SearchGUI * @param gitHubProjectName the GitHub project name of the tool, e.g., * "peptide-shaker" * @param toolVersion the version number of the tool the log files belongs * to * @param googleGroup the name of the Google Group, e.g., peptide-shaker, * setting to null will refer to the PeptideShaker Google Group * @param googleGroupName the human readable name of the the Google Group, * e.g., PeptideShaker, setting to null will refer to the PeptideShaker * Google Group * @param logFile the log file to display */ public BugReport(JDialog dialog, LastSelectedFolder selectionFolder, String toolName, String gitHubProjectName, String toolVersion, String googleGroup, String googleGroupName, File logFile) { super(dialog, true); this.lastSelectedFolder = selectionFolder; this.toolName = toolName; this.gitHubProjectName = gitHubProjectName; this.toolVersion = toolVersion; this.googleGroup = googleGroup; this.googleGroupName = googleGroupName; this.logFile = logFile; initComponents(); setUpGui(); setLocationRelativeTo(dialog); setVisible(true); } /** * Set up the GUI. */ private void setUpGui() { insertLogFileContent(); setTitle(toolName + " Bug Report"); ((TitledBorder) logJPanel.getBorder()).setTitle(toolName + " Log"); if (googleGroup == null) { googleGroup = "peptide-shaker"; } if (googleGroupName == null) { googleGroupName = "PeptideShaker"; } infoJEditorPane.setText("<html><head></head><body>" + "If you encounter any bugs while processing your data, please do one of the following:<br>" + "<ul>" + "<li>Create an issue on the <a href=\"https://github.com/compomics/" + gitHubProjectName + "/issues/\">" + toolName + " web page</a>.</li>" + "<li>Send an e-mail to the <a href=\"http://groups.google.com/group/" + googleGroup + "\">" + googleGroupName + " Google Group</a>.</li>" + "</ul>" + "Please include any relevant information as well as the log message displayed below." + "</body>" + "</html>"); } /** * Displays the content of the log file. */ private void insertLogFileContent() { StringBuilder log = new StringBuilder(); String lineBreak = System.getProperty("line.separator"); try { BufferedReader br = new BufferedReader(new FileReader(logFile)); String line; while ((line = br.readLine()) != null) { log.append(line).append(lineBreak); } br.close(); } catch (FileNotFoundException e) { log.append(toolName).append(".log not found."); e.printStackTrace(); } catch (IOException e) { log.append("An error occurred while reading resources/").append(toolName).append(".log."); e.printStackTrace(); } logTxt.setText(log.toString()); logTxt.setCaretPosition(0); } /** * Returns the last selected folder. * * @return the last selected folder */ private String getLastSelectedFolder() { String result = null; if (lastSelectedFolder != null) { result = lastSelectedFolder.getLastSelectedFolder(lastSelectedFolderKey); if (result == null) { result = lastSelectedFolder.getLastSelectedFolder(); } } return result; } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { backgroundPanel = new javax.swing.JPanel(); logJPanel = new javax.swing.JPanel(); logJScrollPane = new javax.swing.JScrollPane(); logTxt = new javax.swing.JTextArea(); clearJButton = new javax.swing.JButton(); saveJButton = new javax.swing.JButton(); exitButton = new javax.swing.JButton(); infoJPanel = new javax.swing.JPanel(); infoJScrollPane = new javax.swing.JScrollPane(); infoJEditorPane = new javax.swing.JEditorPane(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setTitle("Bug Report"); backgroundPanel.setBackground(new java.awt.Color(230, 230, 230)); logJPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Log")); logJPanel.setOpaque(false); logTxt.setColumns(20); logTxt.setEditable(false); logTxt.setRows(3); logTxt.setTabSize(4); logJScrollPane.setViewportView(logTxt); clearJButton.setText("Clear"); clearJButton.setToolTipText("Clear the log"); clearJButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { clearJButtonActionPerformed(evt); } }); saveJButton.setText("Save"); saveJButton.setToolTipText("Save the log to a text file"); saveJButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { saveJButtonActionPerformed(evt); } }); exitButton.setText("Exit"); exitButton.setMaximumSize(new java.awt.Dimension(57, 23)); exitButton.setMinimumSize(new java.awt.Dimension(57, 23)); exitButton.setPreferredSize(new java.awt.Dimension(57, 23)); exitButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { exitButtonActionPerformed(evt); } }); javax.swing.GroupLayout logJPanelLayout = new javax.swing.GroupLayout(logJPanel); logJPanel.setLayout(logJPanelLayout); logJPanelLayout.setHorizontalGroup( logJPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(logJPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(logJPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(logJScrollPane) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, logJPanelLayout.createSequentialGroup() .addGap(0, 0, Short.MAX_VALUE) .addComponent(saveJButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(clearJButton) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(exitButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) .addContainerGap()) ); logJPanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {clearJButton, exitButton, saveJButton}); logJPanelLayout.setVerticalGroup( logJPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(logJPanelLayout.createSequentialGroup() .addContainerGap() .addComponent(logJScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(logJPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(saveJButton) .addComponent(clearJButton) .addComponent(exitButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGap(6, 6, 6)) ); logJPanelLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {clearJButton, exitButton, saveJButton}); infoJPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Info")); infoJPanel.setOpaque(false); infoJEditorPane.setEditable(false); infoJEditorPane.setBorder(javax.swing.BorderFactory.createEmptyBorder(20, 20, 20, 20)); infoJEditorPane.setContentType("text/html"); // NOI18N infoJEditorPane.setText("<html>\r\n <head>\r\n\r\n </head>\r\n <body>\r\nIf you encounter any bugs while processing your data, please do one of the following:\n<br>\n<ul>\n <li>Create an issue on the <a href=\"https://github.com/compomics/peptide-shaker/issues\">PeptideShaker web page</a>.</li>\n <li>or Send an e-mail to the <a href=\"http://groups.google.com/group/peptide-shaker\">PeptideShaker mailing list</a>.</li>\n</ul>\nPlease include any relevant information as well as the log message displayed below.\n </body>\r\n</html>\r\n"); infoJEditorPane.addHyperlinkListener(new javax.swing.event.HyperlinkListener() { public void hyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) { infoJEditorPaneHyperlinkUpdate(evt); } }); infoJScrollPane.setViewportView(infoJEditorPane); javax.swing.GroupLayout infoJPanelLayout = new javax.swing.GroupLayout(infoJPanel); infoJPanel.setLayout(infoJPanelLayout); infoJPanelLayout.setHorizontalGroup( infoJPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(infoJPanelLayout.createSequentialGroup() .addContainerGap() .addComponent(infoJScrollPane) .addContainerGap()) ); infoJPanelLayout.setVerticalGroup( infoJPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(infoJPanelLayout.createSequentialGroup() .addComponent(infoJScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 131, Short.MAX_VALUE) .addContainerGap()) ); javax.swing.GroupLayout backgroundPanelLayout = new javax.swing.GroupLayout(backgroundPanel); backgroundPanel.setLayout(backgroundPanelLayout); backgroundPanelLayout.setHorizontalGroup( backgroundPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(backgroundPanelLayout.createSequentialGroup() .addContainerGap() .addGroup(backgroundPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(infoJPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(logJPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addContainerGap()) ); backgroundPanelLayout.setVerticalGroup( backgroundPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(backgroundPanelLayout.createSequentialGroup() .addContainerGap() .addComponent(infoJPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(logJPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addContainerGap()) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(backgroundPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(backgroundPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); pack(); }// </editor-fold>//GEN-END:initComponents /** * Makes the links active. * * @param evt */ private void infoJEditorPaneHyperlinkUpdate(javax.swing.event.HyperlinkEvent evt) {//GEN-FIRST:event_infoJEditorPaneHyperlinkUpdate if (evt.getEventType().toString().equalsIgnoreCase( javax.swing.event.HyperlinkEvent.EventType.ENTERED.toString())) { setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR)); } else if (evt.getEventType().toString().equalsIgnoreCase( javax.swing.event.HyperlinkEvent.EventType.EXITED.toString())) { setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); } else if (evt.getEventType().toString().equalsIgnoreCase( javax.swing.event.HyperlinkEvent.EventType.ACTIVATED.toString())) { if (evt.getDescription().startsWith("#")) { infoJEditorPane.scrollToReference(evt.getDescription()); } else { this.setCursor(new java.awt.Cursor(java.awt.Cursor.WAIT_CURSOR)); BareBonesBrowserLaunch.openURL(evt.getDescription()); this.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR)); } } }//GEN-LAST:event_infoJEditorPaneHyperlinkUpdate /** * Clears the log file. * * @param evt */ private void clearJButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearJButtonActionPerformed try { FileWriter w = new FileWriter(logFile); BufferedWriter bw = new BufferedWriter(w); String lineBreak = System.getProperty("line.separator"); bw.write(lineBreak + new Date() + ": " + toolName + " version " + toolVersion + "." + lineBreak); bw.close(); w.close(); } catch (FileNotFoundException e) { JOptionPane.showMessageDialog(this, "Failed to clear the log file.", "File Error", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } catch (IOException e) { JOptionPane.showMessageDialog(this, "Failed to clear the log file.", "File Error", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } insertLogFileContent(); }//GEN-LAST:event_clearJButtonActionPerformed /** * Save the log file to a user specified file. * * @param evt */ private void saveJButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveJButtonActionPerformed File finalOutputFile = Util.getUserSelectedFile(this, ".txt", "Text File (*.txt)", "Select Destination File", getLastSelectedFolder(), toolName + " " + toolVersion + " log.txt", false); if (finalOutputFile != null) { try { if (logFile.exists()) { Util.copyFile(logFile, finalOutputFile); } if (!finalOutputFile.exists()) { JOptionPane.showMessageDialog(this, "An error occurred when saving the log.", "Save Error", JOptionPane.ERROR_MESSAGE); } else { JOptionPane.showMessageDialog(this, "The log has been saved to \'" + finalOutputFile.getPath() + "\'.", "Log Saved", JOptionPane.INFORMATION_MESSAGE); } } catch (IOException e) { JOptionPane.showMessageDialog(this, "An error occurred when saving the log file.", "Save Error", JOptionPane.ERROR_MESSAGE); e.printStackTrace(); } } }//GEN-LAST:event_saveJButtonActionPerformed /** * Closes the dialog. * * @param evt */ private void exitButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitButtonActionPerformed dispose(); }//GEN-LAST:event_exitButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JPanel backgroundPanel; private javax.swing.JButton clearJButton; private javax.swing.JButton exitButton; private javax.swing.JEditorPane infoJEditorPane; private javax.swing.JPanel infoJPanel; private javax.swing.JScrollPane infoJScrollPane; private javax.swing.JPanel logJPanel; private javax.swing.JScrollPane logJScrollPane; private javax.swing.JTextArea logTxt; private javax.swing.JButton saveJButton; // End of variables declaration//GEN-END:variables }