1 package net.sf.jabref.external;
3 import net.sf.jabref.*;
4 import net.sf.jabref.gui.AttachFileDialog;
5 import net.sf.jabref.undo.NamedCompound;
6 import net.sf.jabref.undo.UndoableFieldChange;
11 import java.awt.event.ActionListener;
12 import java.awt.event.ActionEvent;
13 import java.util.Collection;
15 import com.jgoodies.forms.layout.FormLayout;
16 import com.jgoodies.forms.builder.DefaultFormBuilder;
17 import com.jgoodies.forms.builder.ButtonBarBuilder;
20 * This action goes through all selected entries in the BasePanel, and attempts to autoset the
21 * given external file (pdf, ps, ...) based on the same algorithm used for the "Auto" button in
24 public class AutoSetExternalFileForEntries extends AbstractWorker {
26 private String fieldName;
27 private BasePanel panel;
28 private BibtexEntry[] sel = null;
29 private OptionsDialog optDiag = null;
31 Object[] brokenLinkOptions =
32 {Globals.lang("Ignore"), Globals.lang("Assign new file"), Globals.lang("Clear field"),
33 Globals.lang("Quit synchronization")};
35 private boolean goOn = true, autoSet = true, overWriteAllowed = true, checkExisting = true;
37 private int skipped = 0, entriesChanged = 0, brokenLinks = 0;
40 public AutoSetExternalFileForEntries(BasePanel panel, String fieldName) {
41 this.fieldName = fieldName;
46 /*// Get all entries, and make sure there are selected entries:
47 sel = panel.getSelectedEntries();
49 // No entries selected. Assume all entries should be treated:
51 Collection col = panel.database().getEntries();
52 sel = new BibtexEntry[col.size()];
53 sel = (BibtexEntry[]) col.toArray(sel);
58 // Ask about rules for the operation:
60 optDiag = new OptionsDialog(panel.frame(), fieldName);
61 Util.placeDialog(optDiag, panel.frame());
62 optDiag.setVisible(true);
63 if (optDiag.canceled()) {
67 autoSet = !optDiag.autoSetNone.isSelected();
68 overWriteAllowed = optDiag.autoSetAll.isSelected();
69 checkExisting = optDiag.checkLinks.isSelected();
71 panel.output(Globals.lang("Synchronizing %0 links...", fieldName.toUpperCase()));
76 panel.output(Globals.lang("No entries selected."));
79 panel.frame().setProgressBarValue(0);
80 panel.frame().setProgressBarVisible(true);
81 int weightAutoSet = 10; // autoSet takes 10 (?) times longer than checkExisting
82 int progressBarMax = (autoSet ? weightAutoSet * sel.length : 0)
83 + (checkExisting ? sel.length : 0);
84 panel.frame().setProgressBarMaximum(progressBarMax);
89 NamedCompound ce = new NamedCompound(Globals.lang("Autoset %0 field", fieldName));
91 final OpenFileFilter off = Util.getFileFilterForField(fieldName);
93 ExternalFilePanel extPan = new ExternalFilePanel(fieldName, panel.metaData(), null, null, off);
94 FieldTextField editor = new FieldTextField(fieldName, "", false);
96 // Find the default directory for this field type:
97 String dir = panel.metaData().getFileDirectory(fieldName);
99 // First we try to autoset fields
101 for (int i = 0; i < sel.length; i++) {
102 progress += weightAutoSet;
103 panel.frame().setProgressBarValue(progress);
105 final Object old = sel[i].getField(fieldName);
106 // Check if a extension is already set, and if so, if we are allowed to overwrite it:
107 if ((old != null) && !old.equals("") && !overWriteAllowed)
109 extPan.setEntry(sel[i], panel.getDatabase());
110 editor.setText((old != null) ? (String) old : "");
111 Thread t = extPan.autoSetFile(fieldName, editor);
112 // Wait for the autoset process to finish:
116 } catch (InterruptedException e) {
119 // If something was found, entriesChanged it:
120 if (!editor.getText().equals("") && !editor.getText().equals(old)) {
121 // Store an undo edit:
122 //System.out.println("Setting: "+sel[i].getCiteKey()+" "+editor.getText());
123 ce.addEdit(new UndoableFieldChange(sel[i], fieldName, old, editor.getText()));
124 sel[i].setField(fieldName, editor.getText());
129 //System.out.println("Done setting");
130 // The following loop checks all external links that are already set.
133 for (int i = 0; i < sel.length; i++) {
134 panel.frame().setProgressBarValue(progress++);
135 final Object old = sel[i].getField(fieldName);
136 // Check if a extension is set:
137 if ((old != null) && !((String) old).equals("")) {
138 // Get an absolute path representation:
139 File file = Util.expandFilename((String) old, new String[]{dir, "."});
141 if ((file == null) || !file.exists()) {
144 JOptionPane.showOptionDialog(panel.frame(),
145 Globals.lang("<HTML>Could not find file '%0'<BR>linked from entry '%1'</HTML>",
146 new String[]{(String) old, sel[i].getCiteKey()}),
147 Globals.lang("Broken link"),
148 JOptionPane.YES_NO_CANCEL_OPTION,
149 JOptionPane.QUESTION_MESSAGE, null, brokenLinkOptions, brokenLinkOptions[0]);
153 AttachFileDialog afd = new AttachFileDialog(panel.frame(),
154 panel.metaData(), sel[i], fieldName);
155 Util.placeDialog(afd, panel.frame());
156 afd.setVisible(true);
157 if (!afd.cancelled()) {
158 ce.addEdit(new UndoableFieldChange(sel[i], fieldName, old, afd.getValue()));
159 sel[i].setField(fieldName, afd.getValue());
165 ce.addEdit(new UndoableFieldChange(sel[i], fieldName, old, null));
166 sel[i].setField(fieldName, null);
181 if (entriesChanged > 0) {
182 // Add the undo edit:
184 panel.undoManager.addEdit(ce);
189 public void update() {
193 panel.output(Globals.lang("Finished synchronizing %0 links. Entries changed%c %1.",
194 new String[]{fieldName.toUpperCase(), String.valueOf(entriesChanged)}));
195 panel.frame().setProgressBarVisible(false);
196 if (entriesChanged > 0) {
197 panel.markBaseChanged();
201 static class OptionsDialog extends JDialog {
202 JRadioButton autoSetUnset, autoSetAll, autoSetNone;
203 JCheckBox checkLinks;
204 JButton ok = new JButton(Globals.lang("Ok")),
205 cancel = new JButton(Globals.lang("Cancel"));
207 private boolean canceled = true;
208 private String fieldName;
210 public OptionsDialog(JFrame parent, String fieldName) {
211 super(parent, Globals.lang("Synchronize %0 links", fieldName.toUpperCase()), true);
212 final String fn = fieldName.toUpperCase();
213 this.fieldName = fieldName;
214 ok.addActionListener(new ActionListener() {
215 public void actionPerformed(ActionEvent e) {
221 Action closeAction = new AbstractAction() {
222 public void actionPerformed(ActionEvent e) {
228 cancel.addActionListener(closeAction);
230 InputMap im = cancel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
231 ActionMap am = cancel.getActionMap();
232 im.put(Globals.prefs.getKey("Close dialog"), "close");
233 am.put("close", closeAction);
235 fieldName = fieldName.toUpperCase();
236 autoSetUnset = new JRadioButton(Globals.lang("Autoset %0 links. Do not overwrite existing links.", fn), true);
237 autoSetAll = new JRadioButton(Globals.lang("Autoset %0 links. Allow overwriting existing links.", fn), false);
238 autoSetNone = new JRadioButton(Globals.lang("Do not autoset"), false);
239 checkLinks = new JCheckBox(Globals.lang("Check existing %0 links", fn), true);
240 ButtonGroup bg = new ButtonGroup();
241 bg.add(autoSetUnset);
244 FormLayout layout = new FormLayout("fill:pref", "");
245 DefaultFormBuilder builder = new DefaultFormBuilder(layout);
246 description = new JLabel("<HTML>" +
247 Globals.lang(//"This function helps you keep your external %0 links up-to-date." +
248 "Attempt to autoset %0 links for your entries. Autoset works if "
249 + "a %0 file in your %0 directory or a subdirectory<BR>is named identically to an entry's BibTeX key, plus extension.", fn)
251 // name.setVerticalAlignment(JLabel.TOP);
252 builder.appendSeparator(Globals.lang("Autoset"));
253 builder.append(description);
255 builder.append(autoSetUnset);
257 builder.append(autoSetAll);
259 builder.append(autoSetNone);
261 builder.appendSeparator(Globals.lang("Check links"));
263 description = new JLabel("<HTML>" +
264 Globals.lang("This makes JabRef look up each %0 extension and check if the file exists. If not, you will "
265 + "be given options<BR>to resolve the problem.", fn)
267 builder.append(description);
269 builder.append(checkLinks);
271 builder.appendSeparator();
274 JPanel main = builder.getPanel();
275 main.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
277 ButtonBarBuilder bb = new ButtonBarBuilder();
280 bb.addGridded(cancel);
282 getContentPane().add(main, BorderLayout.CENTER);
283 getContentPane().add(bb.getPanel(), BorderLayout.SOUTH);
288 public void setVisible(boolean visible) {
292 String dir = Globals.prefs.get(fieldName + "Directory");
293 if ((dir == null) || (dir.trim().length() == 0)) {
295 autoSetNone.setSelected(true);
296 autoSetNone.setEnabled(false);
297 autoSetAll.setEnabled(false);
298 autoSetUnset.setEnabled(false);
300 autoSetNone.setEnabled(true);
301 autoSetAll.setEnabled(true);
302 autoSetUnset.setEnabled(true);
305 new FocusRequester(ok);
306 super.setVisible(visible);
310 public boolean canceled() {