10
11
// The action concerned with opening an existing database.
12
13
public class OpenDatabaseAction extends MnemonicAwareAction {
13
15
boolean showDialog;
15
16
private JabRefFrame frame;
18
// List of actions that may need to be called after opening the file. Such as
19
// upgrade actions etc. that may depend on the JabRef version that wrote the file:
20
private static ArrayList<PostOpenAction> postOpenActions =
21
new ArrayList<PostOpenAction>();
24
// Add the action for checking for new custom entry types loaded from
26
postOpenActions.add(new CheckForNewEntryTypesAction());
27
// Add the action for the new external file handling system in version 2.3:
28
postOpenActions.add(new FileLinksUpgradeWarning());
17
31
public OpenDatabaseAction(JabRefFrame frame, boolean showDialog) {
18
32
super(GUIGlobals.getImage("open"));
19
33
this.frame = frame;
50
64
filesToOpen.add(new File(Util.checkName(e.getActionCommand())));
67
BasePanel toRaise = null;
68
int initialCount = filesToOpen.size(), removed = 0;
70
// Check if any of the files are already open:
71
for (Iterator iterator = filesToOpen.iterator(); iterator.hasNext();) {
72
File file = (File) iterator.next();
73
for (int i=0; i<frame.getTabbedPane().getTabCount(); i++) {
74
BasePanel bp = (BasePanel)frame.baseAt(i);
75
if ((bp.getFile() != null) && bp.getFile().equals(file)) {
78
// See if we removed the final one. If so, we must perhaps
79
// raise the BasePanel in question:
80
if (removed == initialCount) {
53
89
// Run the actual open in a thread to prevent the program
54
90
// locking until the file is loaded.
55
91
if (filesToOpen.size() > 0) {
58
94
public void run() {
59
95
for (Iterator i=theFiles.iterator(); i.hasNext();)
60
96
openIt((File)i.next(), true);
63
100
for (Iterator i=theFiles.iterator(); i.hasNext();)
64
101
frame.getFileHistory().newFile(((File)i.next()).getPath());
103
// If no files are remaining to open, this could mean that a file was
104
// already open. If so, we may have to raise the correct tab:
105
else if (toRaise != null) {
106
frame.output(Globals.lang("File '%0' is already open.", toRaise.getFile().getPath()));
107
frame.getTabbedPane().setSelectedComponent(toRaise);
68
111
class OpenItSwingHelper implements Runnable {
91
134
// Should this be done _after_ we know it was successfully opened?
92
135
String encoding = Globals.prefs.get("defaultEncoding");
93
136
ParserResult pr = loadDatabase(file, encoding);
94
138
if ((pr == null) || (pr == ParserResult.INVALID_FORMAT)) {
95
139
JOptionPane.showMessageDialog(null, Globals.lang("Error opening file" + " '" + fileName + "'"),
96
140
Globals.lang("Error"),
102
addNewDatabase(pr, file, raisePanel);
146
BasePanel panel = addNewDatabase(pr, file, raisePanel);
148
// After adding the database, go through our list and see if
149
// any post open actions need to be done. For instance, checking
150
// if we found new entry types that can be imported, or checking
151
// if the database contents should be modified due to new features
152
// in this version of JabRef:
153
performPostOpenActions(panel, pr, true);
104
155
} catch (Exception ex) {
105
156
//ex.printStackTrace();
106
157
Util.showQuickErrorDialog(frame, Globals.lang("Open database"), ex);
108
JOptionPane.showMessageDialog
109
(frame, ex.getMessage(),
110
Globals.lang("Open database"), JOptionPane.ERROR_MESSAGE);
116
public void addNewDatabase(ParserResult pr, File file,
163
* Go through the list of post open actions, and perform those that need
165
* @param panel The BasePanel where the database is shown.
166
* @param pr The result of the bib file parse operation.
168
public static void performPostOpenActions(BasePanel panel, ParserResult pr,
169
boolean mustRaisePanel) {
170
for (Iterator<PostOpenAction> iterator = postOpenActions.iterator(); iterator.hasNext();) {
171
PostOpenAction action = iterator.next();
172
if (action.isActionNecessary(pr)) {
174
panel.frame().getTabbedPane().setSelectedComponent(panel);
175
action.performAction(panel, pr);
180
public BasePanel addNewDatabase(ParserResult pr, File file,
117
181
boolean raisePanel) {
119
183
String fileName = file.getPath();
144
208
BasePanel bp = new BasePanel(frame, db, file, meta, pr.getEncoding());
146
if (Globals.prefs.getBoolean("autoComplete")) {
147
db.setCompleters(autoCompleters);
151
210
// file is set to null inside the EventDispatcherThread
152
211
SwingUtilities.invokeLater(new OpenItSwingHelper(bp, file, raisePanel));
154
// See if any custom entry types were imported, but disregard those we already know:
155
for (Iterator i = pr.getEntryTypes().keySet().iterator(); i.hasNext();) {
156
String typeName = ((String) i.next()).toLowerCase();
157
if (BibtexEntryType.ALL_TYPES.get(typeName) != null)
160
if (pr.getEntryTypes().size() > 0) {
163
StringBuffer sb = new StringBuffer(Globals.lang("Custom entry types found in file") + ": ");
164
Object[] types = pr.getEntryTypes().keySet().toArray();
166
for (int i = 0; i < types.length; i++) {
167
sb.append(types[i].toString()).append(", ");
169
String s = sb.toString();
170
int answer = JOptionPane.showConfirmDialog(frame,
171
s.substring(0, s.length() - 2) + ".\n"
172
+ Globals.lang("Remember these entry types?"),
173
Globals.lang("Custom entry types"),
174
JOptionPane.YES_NO_OPTION,
175
JOptionPane.QUESTION_MESSAGE);
176
if (answer == JOptionPane.YES_OPTION) {
178
HashMap et = pr.getEntryTypes();
179
for (Iterator i = et.keySet().iterator(); i.hasNext();) {
180
BibtexEntryType typ = (BibtexEntryType) et.get(i.next());
181
//System.out.println(":"+typ.getName()+"\n"+typ.toString());
182
BibtexEntryType.ALL_TYPES.put(typ.getName().toLowerCase(), typ);
188
213
frame.output(Globals.lang("Opened database") + " '" + fileName +
189
214
"' " + Globals.lang("with") + " " +
190
215
db.getEntryCount() + " " + Globals.lang("entries") + ".");
194
220
public static ParserResult loadDatabase(File fileToOpen, String encoding)
246
272
StringBuffer headerText = new StringBuffer();
248
274
boolean keepon = true;
275
int piv = 0, offset = 0;
253
279
c = reader.read();
254
headerText.append((char) c);
255
if (((piv == 0) && Character.isWhitespace((char) c))
256
|| (c == GUIGlobals.SIGNATURE.charAt(piv)))
258
else //if (((char)c) == '@')
280
if ((piv == 0) && ((c == '%') || (Character.isWhitespace((char)c))))
283
headerText.append((char) c);
284
if (c == GUIGlobals.SIGNATURE.charAt(piv))
286
else //if (((char)c) == '@')
260
289
//System.out.println(headerText.toString());
262
291
if (piv == GUIGlobals.SIGNATURE.length()) {
266
295
// System.out.println("'"+headerText.toString().substring(0, headerText.length()-GUIGlobals.SIGNATURE.length())+"'");
267
296
// Found the signature. The rest of the line is unknown, so we skip
269
while (reader.read() != '\n') ;
298
while (reader.read() != '\n');
299
// If the next line starts with something like "% ", handle this:
300
while (((c =reader.read()) == '%') || (Character.isWhitespace((char)c)));
301
// Then we must skip the "Encoding: ". We may already have read the first
303
if ((char)c != GUIGlobals.encPrefix.charAt(0))
271
// Then we must skip the "Encoding: "
272
for (int i = 0; i < GUIGlobals.encPrefix.length(); i++) {
306
for (int i = 1; i < GUIGlobals.encPrefix.length(); i++) {
273
307
if (reader.read() != GUIGlobals.encPrefix.charAt(i))
274
308
break found; // No,
282
316
// If ok, then read the rest of the line, which should contain the
284
318
// of the encoding:
285
319
StringBuffer sb = new StringBuffer();
287
while ((c = reader.read()) != '\n') sb.append((char) c);
321
while ((c = reader.read()) != '\n') {
289
326
suppliedEncoding = sb.toString();