package net.sf.jabref.external; import java.util.Iterator; import java.util.List; import javax.swing.*; import net.sf.jabref.*; import net.sf.jabref.imports.ParserResult; import net.sf.jabref.imports.PostOpenAction; import net.sf.jabref.undo.NamedCompound; import com.jgoodies.forms.builder.DefaultFormBuilder; import com.jgoodies.forms.layout.FormLayout; /** * This class defines the warning that can be offered when opening a pre-2.3 * JabRef file into a later version. This warning mentions the new external file * link system in this version of JabRef, and offers to: * * * upgrade old-style PDF/PS links into the "file" field * * modify General fields to show "file" instead of "pdf" / "ps" * * modify table column settings to show "file" instead of "pdf" / "ps" */ public class FileLinksUpgradeWarning implements PostOpenAction { private static final String[] FIELDS_TO_LOOK_FOR = new String[] {"pdf", "ps"}; /** * This method should be performed if the major/minor versions recorded in the ParserResult * are less than or equal to 2.2. * @param pr * @return true if the file was written by a jabref version <=2.2 */ public boolean isActionNecessary(ParserResult pr) { // First check if this warning is disabled: if (!Globals.prefs.getBoolean("showFileLinksUpgradeWarning")) return false; if (pr.getJabrefMajorVersion() < 0) return false; // non-JabRef file if (pr.getJabrefMajorVersion() < 2) return true; // old if (pr.getJabrefMajorVersion() > 2) return false; // wow, did we ever reach version 3? return (pr.getJabrefMinorVersion() <= 2); } /** * This method presents a dialog box explaining and offering to make the * changes. If the user confirms, the changes are performed. * @param panel * @param pr */ public void performAction(BasePanel panel, ParserResult pr) { // Find out which actions should be offered: // Only offer to change Preferences if file column is not already visible: boolean offerChangeSettings = !Globals.prefs.getBoolean("fileColumn") || !showsFileInGenFields(); // Only offer to upgrade links if the pdf/ps fields are used: boolean offerChangeDatabase = linksFound(pr.getDatabase(), FIELDS_TO_LOOK_FOR); // If the "file" directory is not set, offer to migrate pdf/ps dir: boolean offerSetFileDir = !Globals.prefs.hasKey(GUIGlobals.FILE_FIELD+"Directory") && (Globals.prefs.hasKey("pdfDirectory") || Globals.prefs.hasKey("psDirectory")); if (!offerChangeDatabase && !offerChangeSettings && !offerSetFileDir) return; // Nothing to do, just return. JCheckBox changeSettings = new JCheckBox(Globals.lang("Change table column and General fields settings to use the new feature"), offerChangeSettings); JCheckBox changeDatabase = new JCheckBox(Globals.lang("Upgrade old external file links to use the new feature"), offerChangeDatabase); JCheckBox setFileDir = new JCheckBox(Globals.lang("Set main external file directory")+":", offerSetFileDir); JTextField fileDir = new JTextField(30); JCheckBox doNotShowDialog = new JCheckBox(Globals.lang("Do not show these options in the future"), false); StringBuilder sb = new StringBuilder("<html>"); sb.append(Globals.lang("This database was written using an older version of JabRef.")); sb.append("<br>"); sb.append(Globals.lang("The current version features a new way of handling links to external files.<br>" +"To take advantage of this, your links must be changed into the new format, and<br>" +"JabRef must be configured to show the new links.")); sb.append("<p>"); sb.append(Globals.lang("Do you want JabRef to do the following operations?")); sb.append("</html>"); JPanel message = new JPanel(); DefaultFormBuilder b = new DefaultFormBuilder(new FormLayout("left:pref", ""), message); b.append(new JLabel(sb.toString())); b.nextLine(); if (offerChangeSettings) { b.append(changeSettings); b.nextLine(); } if (offerChangeDatabase) { b.append(changeDatabase); b.nextLine(); } if (offerSetFileDir) { if (Globals.prefs.hasKey("pdfDirectory")) fileDir.setText(Globals.prefs.get("pdfDirectory")); else fileDir.setText(Globals.prefs.get("psDirectory")); JPanel pan = new JPanel(); pan.add(setFileDir); pan.add(fileDir); JButton browse = new JButton(Globals.lang("Browse")); browse.addActionListener(new BrowseAction(null, fileDir, true)); pan.add(browse); b.append(pan); b.nextLine(); } b.append(""); b.nextLine(); b.append(doNotShowDialog); int answer = JOptionPane.showConfirmDialog(panel.frame(), message, Globals.lang("Upgrade file"), JOptionPane.YES_NO_OPTION); if (doNotShowDialog.isSelected()) Globals.prefs.putBoolean("showFileLinksUpgradeWarning", false); if (answer == JOptionPane.YES_OPTION) makeChanges(panel, pr, changeSettings.isSelected(), changeDatabase.isSelected(), setFileDir.isSelected() ? fileDir.getText() : null); } /** * Check the database to find out whether any of a set of fields are used * for any of the entries. * @param database The bib database. * @param fields The set of fields to look for. * @return true if at least one of the given fields is set in at least one entry, * false otherwise. */ public boolean linksFound(BibtexDatabase database, String[] fields) { for (BibtexEntry entry : database.getEntries()){ for (int i = 0; i < fields.length; i++) { if (entry.getField(fields[i]) != null) return true; } } return false; } /** * This method performs the actual changes. * @param panel * @param pr * @param fileDir The path to the file directory to set, or null if it should not be set. */ public void makeChanges(BasePanel panel, ParserResult pr, boolean upgradePrefs, boolean upgradeDatabase, String fileDir) { if (upgradeDatabase) { // Update file links links in the database: NamedCompound ce = Util.upgradePdfPsToFile(pr.getDatabase(), FIELDS_TO_LOOK_FOR); panel.undoManager.addEdit(ce); panel.markBaseChanged(); } if (fileDir != null) { Globals.prefs.put(GUIGlobals.FILE_FIELD+"Directory", fileDir); } if (upgradePrefs) { // Exchange table columns: Globals.prefs.putBoolean("pdfColumn", Boolean.FALSE); Globals.prefs.putBoolean("fileColumn", Boolean.TRUE); // Modify General fields if necessary: // If we don't find the file field, insert it at the bottom of the first tab: if (!showsFileInGenFields()) { String gfs = Globals.prefs.get(Globals.prefs.CUSTOM_TAB_FIELDS+"0"); //System.out.println(gfs); StringBuffer sb = new StringBuffer(gfs); if (gfs.length() > 0) sb.append(";"); sb.append(GUIGlobals.FILE_FIELD); Globals.prefs.put(Globals.prefs.CUSTOM_TAB_FIELDS+"0", sb.toString()); Globals.prefs.updateEntryEditorTabList(); panel.frame().removeCachedEntryEditors(); } panel.frame().setupAllTables(); } } private boolean showsFileInGenFields() { boolean found = false; EntryEditorTabList tabList = Globals.prefs.getEntryEditorTabList(); outer: for (int i=0; i<tabList.getTabCount(); i++) { List<String> fields = tabList.getTabFields(i); for (Iterator<String> j=fields.iterator(); j.hasNext();) { String field = j.next(); if (field.equals(GUIGlobals.FILE_FIELD)) { found = true; break outer; } } } return found; } }