package net.sf.jabref.external; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.util.List; import java.util.ArrayList; import javax.swing.*; import net.sf.jabref.*; import net.sf.jabref.gui.FileListTableModel; import net.sf.jabref.gui.FileListEntry; import net.sf.jabref.util.XMPUtil; import com.jgoodies.forms.builder.ButtonBarBuilder; /** * * This action goes through all selected entries in the BasePanel, and attempts * to write the XMP data to the external pdf. * * @author $Author: coezbek $ * @version $Revision: 2488 $ ($Date: 2007-11-14 01:25:31 +0100 (Mi, 14 Nov 2007) $) * */ public class WriteXMPAction extends AbstractWorker { BasePanel panel; BibtexEntry[] entries; BibtexDatabase database; OptionsDialog optDiag; boolean goOn = true; int skipped, entriesChanged, errors; public WriteXMPAction(BasePanel panel) { this.panel = panel; } public void init() { // Get entries and check if it makes sense to perform this operation entries = panel.getSelectedEntries(); if (entries.length == 0) { database = panel.getDatabase(); entries = database.getEntries().toArray(new BibtexEntry[]{}); if (entries.length == 0) { JOptionPane.showMessageDialog(panel, Globals .lang("This operation requires at least one entry."), Globals .lang("Write XMP-metadata"), JOptionPane.ERROR_MESSAGE); goOn = false; return; } else { int response = JOptionPane.showConfirmDialog(panel, Globals .lang("Write XMP-metadata for all PDFs in current database?"), Globals .lang("Write XMP-metadata"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); if (response != JOptionPane.YES_OPTION) { goOn = false; return; } } } errors = entriesChanged = skipped = 0; if (optDiag == null) { optDiag = new OptionsDialog(panel.frame().getFrame()); } optDiag.open(); panel.output(Globals.lang("Writing XMP metadata...")); } public void run() { if (!goOn) return; for (int i = 0; i < entries.length; i++) { BibtexEntry entry = entries[i]; // Make a list of all PDFs linked from this entry: List<File> files = new ArrayList<File>(); // First check the (legacy) "pdf" field: String pdf = entry.getField("pdf"); String dir = panel.metaData().getFileDirectory("pdf"); File f = Util.expandFilename(pdf, new String[]{dir,"."}); if (f != null) files.add(f); // Then check the "file" field: dir = panel.metaData().getFileDirectory(GUIGlobals.FILE_FIELD); String field = entry.getField(GUIGlobals.FILE_FIELD); if (field != null) { FileListTableModel tm = new FileListTableModel(); tm.setContent(field); for (int j=0; j<tm.getRowCount(); j++) { FileListEntry flEntry = tm.getEntry(j); if ((flEntry.getType()!=null) && (flEntry.getType().getName().toLowerCase().equals("pdf"))) { f = Util.expandFilename(flEntry.getLink(), new String[]{dir,"."}); if (f != null) files.add(f); } } } optDiag.progressArea.append(entry.getCiteKey() + "\n"); if (files.size() == 0) { skipped++; optDiag.progressArea.append(" " + Globals.lang("Skipped - No PDF linked") + ".\n"); } else for (File file : files) { if (!file.exists()) { skipped++; optDiag.progressArea.append(" " + Globals.lang("Skipped - PDF does not exist") + ":\n"); optDiag.progressArea.append(" " + file.getPath() + "\n"); } else { try { XMPUtil.writeXMP(file, entry, database); optDiag.progressArea.append(" " + Globals.lang("Ok") + ".\n"); entriesChanged++; } catch (Exception e) { optDiag.progressArea.append(" " + Globals.lang("Error while writing") + " '" + file.getPath() + "':\n"); optDiag.progressArea.append(" " + e.getLocalizedMessage() + "\n"); errors++; } } } if (optDiag.canceled){ optDiag.progressArea.append("\n" + Globals.lang("Operation canceled.\n")); break; } } optDiag.progressArea.append("\n" + Globals.lang("Finished writing XMP for %0 file (%1 skipped, %2 errors).", String .valueOf(entriesChanged), String.valueOf(skipped), String.valueOf(errors))); optDiag.done(); } public void update() { if (!goOn) return; panel.output(Globals.lang("Finished writing XMP for %0 file (%1 skipped, %2 errors).", String.valueOf(entriesChanged), String.valueOf(skipped), String.valueOf(errors))); } class OptionsDialog extends JDialog { private static final long serialVersionUID = 7459164400811785958L; JButton okButton = new JButton(Globals.lang("Ok")), cancelButton = new JButton(Globals .lang("Cancel")); boolean canceled; JTextArea progressArea; public OptionsDialog(JFrame parent) { super(parent, Globals.lang("Writing XMP metadata for selected entries..."), false); okButton.setEnabled(false); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); AbstractAction cancel = new AbstractAction() { private static final long serialVersionUID = -338601477652815366L; public void actionPerformed(ActionEvent e) { canceled = true; } }; cancelButton.addActionListener(cancel); InputMap im = cancelButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); ActionMap am = cancelButton.getActionMap(); im.put(Globals.prefs.getKey("Close dialog"), "close"); am.put("close", cancel); progressArea = new JTextArea(15, 60); JScrollPane scrollPane = new JScrollPane(progressArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); Dimension d = progressArea.getPreferredSize(); d.height += scrollPane.getHorizontalScrollBar().getHeight() + 15; d.width += scrollPane.getVerticalScrollBar().getWidth() + 15; panel.setSize(d); progressArea.setBackground(Color.WHITE); progressArea.setEditable(false); progressArea.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); progressArea.setText(""); JPanel panel = new JPanel(); panel.setBorder(BorderFactory.createEmptyBorder(3, 2, 3, 2)); panel.add(scrollPane); // progressArea.setPreferredSize(new Dimension(300, 300)); ButtonBarBuilder bb = new ButtonBarBuilder(); bb.addGlue(); bb.addGridded(okButton); bb.addRelatedGap(); bb.addGridded(cancelButton); bb.addGlue(); JPanel bbPanel = bb.getPanel(); bbPanel.setBorder(BorderFactory.createEmptyBorder(0, 3, 3, 3)); getContentPane().add(panel, BorderLayout.CENTER); getContentPane().add(bbPanel, BorderLayout.SOUTH); pack(); this.setResizable(false); } public void done() { okButton.setEnabled(true); cancelButton.setEnabled(false); } public void open() { progressArea.setText(""); canceled = false; Util.placeDialog(optDiag, panel.frame()); okButton.setEnabled(false); cancelButton.setEnabled(true); new FocusRequester(okButton); optDiag.setVisible(true); } } }