5724ddebed2a9ae9fb0befdb5123aa91fc5bff8d
[debian/jabref.git] / src / java / net / sf / jabref / external / FileLinksUpgradeWarning.java
1 package net.sf.jabref.external;
2
3 import net.sf.jabref.imports.ParserResult;
4 import net.sf.jabref.imports.PostOpenAction;
5 import net.sf.jabref.*;
6 import net.sf.jabref.undo.NamedCompound;
7
8 import javax.swing.*;
9 import java.awt.event.ActionListener;
10 import java.awt.event.ActionEvent;
11 import java.util.regex.Pattern;
12 import java.util.Iterator;
13 import java.util.List;
14
15 import com.jgoodies.forms.builder.DefaultFormBuilder;
16 import com.jgoodies.forms.layout.FormLayout;
17
18 /**
19  * This class defines the warning that can be offered when opening a pre-2.3
20  * JabRef file into a later version. This warning mentions the new external file
21  * link system in this version of JabRef, and offers to:
22  *
23  * * upgrade old-style PDF/PS links into the "file" field
24  * * modify General fields to show "file" instead of "pdf" / "ps"
25  * * modify table column settings to show "file" instead of "pdf" / "ps"
26  */
27 public class FileLinksUpgradeWarning implements PostOpenAction {
28
29     private static final String[] FIELDS_TO_LOOK_FOR = new String[] {"pdf", "ps"};
30
31     /**
32      * This method should be performed if the major/minor versions recorded in the ParserResult
33      * are less than or equal to 2.2.
34      * @param pr
35      * @return true if the file was written by a jabref version <=2.2
36      */
37     public boolean isActionNecessary(ParserResult pr) {
38         // First check if this warning is disabled:
39         if (!Globals.prefs.getBoolean("showFileLinksUpgradeWarning"))
40             return false;
41         if (pr.getJabrefMajorVersion() < 0)
42             return false; // non-JabRef file
43         if (pr.getJabrefMajorVersion() < 2)
44             return true; // old
45         if (pr.getJabrefMajorVersion() > 2)
46             return false; // wow, did we ever reach version 3?
47         return (pr.getJabrefMinorVersion() <= 2);
48     }
49
50     /**
51      * This method presents a dialog box explaining and offering to make the
52      * changes. If the user confirms, the changes are performed.
53      * @param panel
54      * @param pr
55      */
56     public void performAction(BasePanel panel, ParserResult pr) {
57         // Find out which actions should be offered:
58         // Only offer to change Preferences if file column is not already visible:
59         boolean offerChangeSettings = !Globals.prefs.getBoolean("fileColumn") || !showsFileInGenFields();
60         // Only offer to upgrade links if the pdf/ps fields are used:
61         boolean offerChangeDatabase = linksFound(pr.getDatabase(), FIELDS_TO_LOOK_FOR);
62         // If the "file" directory is not set, offer to migrate pdf/ps dir:
63         boolean offerSetFileDir = !Globals.prefs.hasKey(GUIGlobals.FILE_FIELD+"Directory")
64                 && (Globals.prefs.hasKey("pdfDirectory") || Globals.prefs.hasKey("psDirectory"));
65
66         if (!offerChangeDatabase && !offerChangeSettings && !offerSetFileDir)
67                     return; // Nothing to do, just return.
68                 
69         JCheckBox changeSettings = new JCheckBox(Globals.lang("Change table column and General fields settings to use the new feature"),
70                 offerChangeSettings);
71         JCheckBox changeDatabase = new JCheckBox(Globals.lang("Upgrade old external file links to use the new feature"),
72                 offerChangeDatabase);
73         JCheckBox setFileDir = new JCheckBox(Globals.lang("Set main external file directory")+":", offerSetFileDir);
74         JTextField fileDir = new JTextField(30);
75         JCheckBox doNotShowDialog = new JCheckBox(Globals.lang("Do not show these options in the future"),
76                 false);
77
78         StringBuilder sb = new StringBuilder("<html>");
79         sb.append(Globals.lang("This database was written using an older version of JabRef."));
80         sb.append("<br>");
81         sb.append(Globals.lang("The current version features a new way of handling links to external files.<br>"
82             +"To take advantage of this, your links must be changed into the new format, and<br>"
83             +"JabRef must be configured to show the new links."));
84         sb.append("<p>");
85         sb.append(Globals.lang("Do you want JabRef to do the following operations?"));
86         sb.append("</html>");
87
88         JPanel message = new JPanel();
89         DefaultFormBuilder b = new DefaultFormBuilder(message,
90                 new FormLayout("left:pref", ""));
91         b.append(new JLabel(sb.toString()));
92         b.nextLine();
93         if (offerChangeSettings) {
94             b.append(changeSettings);
95             b.nextLine();
96         }
97         if (offerChangeDatabase) {
98             b.append(changeDatabase);
99             b.nextLine();
100         }
101         if (offerSetFileDir) {
102             if (Globals.prefs.hasKey("pdfDirectory"))
103                 fileDir.setText(Globals.prefs.get("pdfDirectory"));
104             else
105                 fileDir.setText(Globals.prefs.get("psDirectory"));
106             JPanel pan = new JPanel();
107             pan.add(setFileDir);
108             pan.add(fileDir);
109             JButton browse = new JButton(Globals.lang("Browse"));
110             browse.addActionListener(new BrowseAction(null, fileDir, true));
111             pan.add(browse);
112             b.append(pan);
113             b.nextLine();
114         }
115         b.append("");
116         b.nextLine();
117         b.append(doNotShowDialog);
118
119         int answer = JOptionPane.showConfirmDialog(panel.frame(),
120                 message, Globals.lang("Upgrade file"), JOptionPane.YES_NO_OPTION);
121         if (doNotShowDialog.isSelected())
122             Globals.prefs.putBoolean("showFileLinksUpgradeWarning", false);
123
124         if (answer == JOptionPane.YES_OPTION)
125             makeChanges(panel, pr, changeSettings.isSelected(), changeDatabase.isSelected(),
126                     setFileDir.isSelected() ? fileDir.getText() : null);
127     }
128
129     /**
130      * Check the database to find out whether any of a set of fields are used
131      * for any of the entries.
132      * @param database The bib database.
133      * @param fields The set of fields to look for.
134      * @return true if at least one of the given fields is set in at least one entry,
135      *  false otherwise.
136      */
137     public boolean linksFound(BibtexDatabase database, String[] fields) {
138         for (Iterator iterator = database.getEntries().iterator(); iterator.hasNext();) {
139             BibtexEntry entry = (BibtexEntry)iterator.next();
140             for (int i = 0; i < fields.length; i++) {
141                 if (entry.getField(fields[i]) != null)
142                     return true;
143             }
144         }
145         return false;
146     }
147
148     /**
149      * This method performs the actual changes.
150      * @param panel
151      * @param pr
152      * @param fileDir The path to the file directory to set, or null if it should not be set.
153      */
154     public void makeChanges(BasePanel panel, ParserResult pr, boolean upgradePrefs,
155                             boolean upgradeDatabase, String fileDir) {
156
157         if (upgradeDatabase) {
158             // Update file links links in the database:
159             NamedCompound ce = Util.upgradePdfPsToFile(pr.getDatabase(), FIELDS_TO_LOOK_FOR);
160             panel.undoManager.addEdit(ce);
161             panel.markBaseChanged();
162         }
163
164         if (fileDir != null) {
165             Globals.prefs.put(GUIGlobals.FILE_FIELD+"Directory", fileDir);
166         }
167
168         if (upgradePrefs) {
169             // Exchange table columns:
170             Globals.prefs.putBoolean("pdfColumn", Boolean.FALSE);
171             Globals.prefs.putBoolean("fileColumn", Boolean.TRUE);
172
173             // Modify General fields if necessary:
174             // If we don't find the file field, insert it at the bottom of the first tab:
175             if (!showsFileInGenFields()) {
176                 String gfs = Globals.prefs.get(Globals.prefs.CUSTOM_TAB_FIELDS+"0");
177                 //System.out.println(gfs);
178                 StringBuffer sb = new StringBuffer(gfs);
179                 if (gfs.length() > 0)
180                     sb.append(";");
181                 sb.append(GUIGlobals.FILE_FIELD);
182                 Globals.prefs.put(Globals.prefs.CUSTOM_TAB_FIELDS+"0", sb.toString());
183                 Globals.prefs.updateEntryEditorTabList();
184                 panel.frame().removeCachedEntryEditors();
185             }
186             panel.frame().setupAllTables();
187         }
188     }
189
190     private boolean showsFileInGenFields() {
191         boolean found = false;
192         EntryEditorTabList tabList = Globals.prefs.getEntryEditorTabList();
193         outer: for (int i=0; i<tabList.getTabCount(); i++) {
194             List fields = tabList.getTabFields(i);
195             for (Iterator j=fields.iterator(); j.hasNext();) {
196                 String field = (String)j.next();
197                 if (field.equals(GUIGlobals.FILE_FIELD)) {
198                     found = true;
199                     break outer;
200                 }
201             }
202         }
203         return found;
204     }
205
206 }