package com.kenai.redminenb.util; import com.kenai.redminenb.issue.RedmineIssue; import com.taskadapter.redmineapi.bean.Attachment; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileOutputStream; import java.util.concurrent.ExecutionException; import javax.swing.BoxLayout; import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.SwingWorker; import javax.swing.border.EmptyBorder; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; public class AttachmentDisplay extends DelegatingBaseLineJPanel implements ActionListener { private static File lastDirectory; private static final String COMMAND_DELETE = "delete"; private static final String COMMAND_DOWNLOAD = "download"; private final Attachment ad; private final RedmineIssue issue; private final JLabel leadingLabel = new JLabel(); // Delete is only activated if the repository is set to support this // the feature was added to redmine in version 3.3.0 private final LinkButton deleteButton = new LinkButton(); private final LinkButton downloadButton = new LinkButton(); public AttachmentDisplay(RedmineIssue issue, Attachment ad) { super(); setOpaque(false); setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); this.ad = ad; this.issue = issue; leadingLabel.setText(String.format( "%1$s (%2$d bytes) %3$tY-%3$tm-%3$td %3$tH:%3$tM ", ad.getFileName(), ad.getFileSize(), ad.getCreatedOn())); leadingLabel.setToolTipText(ad.getDescription()); this.add(leadingLabel); this.add(downloadButton); if (issue.getRepository().isFeatureDeleteAttachments()) { deleteButton.setBorder(new EmptyBorder(0, 8, 0, 0)); deleteButton.setIcon(new javax.swing.ImageIcon(AttachmentDisplay.class.getResource("/com/kenai/redminenb/resources/user-trash.png"))); deleteButton.setToolTipText("delete"); deleteButton.addActionListener(this); deleteButton.setActionCommand(COMMAND_DELETE); this.add(deleteButton); } downloadButton.setBorder(null); downloadButton.setIcon(new javax.swing.ImageIcon(AttachmentDisplay.class.getResource("/com/kenai/redminenb/resources/document-save.png"))); downloadButton.setToolTipText("download"); downloadButton.addActionListener(this); downloadButton.setActionCommand(COMMAND_DOWNLOAD); } @Override @SuppressFBWarnings( value = "ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD", justification = "Intended behaviour - if there is a race in lastDirectory reading/writing it is ok as it is only help for user") public void actionPerformed(ActionEvent e) { if (COMMAND_DOWNLOAD.equals(e.getActionCommand())) { JFileChooser fileChooser = new JFileChooser(lastDirectory); fileChooser.setDialogTitle("Save attachment"); File preselected; File lastDirectoryBuffer = lastDirectory; if (lastDirectoryBuffer != null && lastDirectoryBuffer.canWrite()) { preselected = new File(lastDirectoryBuffer, ad.getFileName()); } else { preselected = new File(ad.getFileName()); } fileChooser.setSelectedFile(preselected); int result = fileChooser.showSaveDialog(this); if (result == JFileChooser.APPROVE_OPTION) { lastDirectory = fileChooser.getCurrentDirectory(); final File selectedFile = fileChooser.getSelectedFile(); new SwingWorker() { @Override protected Object doInBackground() throws Exception { try (FileOutputStream fos = new FileOutputStream(selectedFile)) { issue.getRepository().getAttachmentManager().downloadAttachmentContent(ad, fos); } return null; } @Override protected void done() { try { get(); } catch (ExecutionException | InterruptedException ex) { NotifyDescriptor nd = new NotifyDescriptor.Message( "Failed to retrieve attachment from issue:\n\n" + ex.getMessage(), NotifyDescriptor.ERROR_MESSAGE ); DialogDisplayer.getDefault().notifyLater(nd); } } }.execute(); } } else if (COMMAND_DELETE.equals(e.getActionCommand())) { NotifyDescriptor nd = new NotifyDescriptor.Confirmation( "Are you sure you want to delete the attachment:\n\n" + ad.getFileName(), "Delete attachment", NotifyDescriptor.OK_CANCEL_OPTION); Object selected = DialogDisplayer.getDefault().notify(nd); if(selected != NotifyDescriptor.OK_OPTION) { return; } new SwingWorker() { @Override protected Object doInBackground() throws Exception { issue.getRepository().getAttachmentManager().delete(ad.getId()); issue.refresh(); return null; } @Override protected void done() { try { get(); } catch (ExecutionException | InterruptedException ex) { NotifyDescriptor nd = new NotifyDescriptor.Message( "Failed to delete attachment:\n\n" + ex.getMessage(), NotifyDescriptor.ERROR_MESSAGE ); DialogDisplayer.getDefault().notifyLater(nd); } } }.execute(); } } }