source: josm/trunk/src/org/openstreetmap/josm/actions/OpenFileAction.java@ 3965

Last change on this file since 3965 was 3924, checked in by bastiK, 13 years ago

applied #5757 - Getting rid of not existing files in "Open Recent" (anonymous contribution)

  • Property svn:eol-style set to native
File size: 12.8 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6import static org.openstreetmap.josm.tools.I18n.trn;
7
8import java.awt.event.ActionEvent;
9import java.awt.event.KeyEvent;
10import java.io.File;
11import java.io.IOException;
12import java.util.ArrayList;
13import java.util.Arrays;
14import java.util.Collection;
15import java.util.Collections;
16import java.util.HashSet;
17import java.util.LinkedHashSet;
18import java.util.LinkedList;
19import java.util.List;
20
21import java.util.Set;
22import javax.swing.JFileChooser;
23import javax.swing.JOptionPane;
24import javax.swing.SwingUtilities;
25import javax.swing.filechooser.FileFilter;
26
27import org.openstreetmap.josm.Main;
28import org.openstreetmap.josm.gui.HelpAwareOptionPane;
29import org.openstreetmap.josm.gui.PleaseWaitRunnable;
30import org.openstreetmap.josm.gui.help.HelpUtil;
31import org.openstreetmap.josm.io.AllFormatsImporter;
32import org.openstreetmap.josm.io.FileImporter;
33import org.openstreetmap.josm.io.OsmTransferException;
34import org.openstreetmap.josm.tools.MultiMap;
35import org.openstreetmap.josm.tools.Shortcut;
36import org.xml.sax.SAXException;
37
38/**
39 * Open a file chooser dialog and select an file to import. Then call the gpx-import driver. Finally
40 * open an internal frame into the main window with the gpx data shown.
41 *
42 * @author imi
43 */
44public class OpenFileAction extends DiskAccessAction {
45
46 /**
47 * Create an open action. The name is "Open a file".
48 */
49 public OpenFileAction() {
50 super(tr("Open..."), "open", tr("Open a file."),
51 Shortcut.registerShortcut("system:open", tr("File: {0}", tr("Open...")), KeyEvent.VK_O, Shortcut.GROUP_MENU));
52 putValue("help", ht("/Action/Open"));
53
54 }
55
56 public void actionPerformed(ActionEvent e) {
57 JFileChooser fc = createAndOpenFileChooser(true, true, null);
58 if (fc == null)
59 return;
60 File[] files = fc.getSelectedFiles();
61 OpenFileTask task = new OpenFileTask(Arrays.asList(files), fc.getFileFilter());
62 task.setRecordHistory(true);
63 Main.worker.submit(task);
64 }
65
66 @Override
67 protected void updateEnabledState() {
68 setEnabled(! Main.applet);
69 }
70
71 /**
72 * Open a list of files. The complete list will be passed to batch importers.
73 * @param fileList A list of files
74 */
75 static public void openFiles(List<File> fileList) {
76 openFiles(fileList, false);
77 }
78
79 static public void openFiles(List<File> fileList, boolean recordHistory) {
80 OpenFileTask task = new OpenFileTask(fileList, null);
81 task.setRecordHistory(recordHistory);
82 Main.worker.submit(task);
83 }
84
85 static public class OpenFileTask extends PleaseWaitRunnable {
86 private List<File> files;
87 private List<File> successfullyOpenedFiles = new ArrayList<File>();
88 private FileFilter fileFilter;
89 private boolean cancelled;
90 private boolean recordHistory = false;
91
92 public OpenFileTask(List<File> files, FileFilter fileFilter, String title) {
93 super(title, false /* don't ignore exception */);
94 this.files = new ArrayList<File>(files);
95 this.fileFilter = fileFilter;
96 }
97
98 public OpenFileTask(List<File> files, FileFilter fileFilter) {
99 this(files, fileFilter, tr("Opening files"));
100 }
101
102 /**
103 * save filename in history (for list of recently opened files)
104 * default: false
105 */
106 public void setRecordHistory(boolean recordHistory) {
107 this.recordHistory = recordHistory;
108 }
109
110 public boolean isRecordHistory() {
111 return recordHistory;
112 }
113
114 @Override
115 protected void cancel() {
116 this.cancelled = true;
117 }
118
119 @Override
120 protected void finish() {
121 // do nothing
122 }
123
124 protected void alertFilesNotMatchingWithImporter(Collection<File> files, FileImporter importer) {
125 final StringBuffer msg = new StringBuffer();
126 msg.append("<html>");
127 msg.append(
128 trn(
129 "Cannot open {0} file with the file importer ''{1}''.",
130 "Cannot open {0} files with the file importer ''{1}''.",
131 files.size(),
132 files.size(),
133 importer.filter.getDescription()
134 )
135 ).append("<br>");
136 msg.append("<ul>");
137 for (File f: files) {
138 msg.append("<li>").append(f.getAbsolutePath()).append("</li>");
139 }
140 msg.append("</ul>");
141
142 HelpAwareOptionPane.showMessageDialogInEDT(
143 Main.parent,
144 msg.toString(),
145 tr("Warning"),
146 JOptionPane.WARNING_MESSAGE,
147 HelpUtil.ht("/Action/Open#ImporterCantImportFiles")
148 );
149 }
150
151 protected void alertFilesWithUnknownImporter(Collection<File> files) {
152 final StringBuffer msg = new StringBuffer();
153 msg.append("<html>");
154 msg.append(
155 trn(
156 "Cannot open {0} file because no suitable file importer is available.",
157 "Cannot open {0} files because no suitable file importer is available.",
158 files.size(),
159 files.size()
160 )
161 ).append("<br>");
162 msg.append("<ul>");
163 for (File f: files) {
164 msg.append("<li>").append(f.getAbsolutePath()).append("</li>");
165 }
166 msg.append("</ul>");
167
168 HelpAwareOptionPane.showMessageDialogInEDT(
169 Main.parent,
170 msg.toString(),
171 tr("Warning"),
172 JOptionPane.WARNING_MESSAGE,
173 HelpUtil.ht("/Action/Open#MissingImporterForFiles")
174 );
175 }
176
177 @Override
178 protected void realRun() throws SAXException, IOException, OsmTransferException {
179 if (files == null || files.isEmpty()) return;
180
181 /**
182 * Find the importer with the chosen file filter
183 */
184 FileImporter chosenImporter = null;
185 for (FileImporter importer : ExtensionFileFilter.importers) {
186 if (fileFilter == importer.filter) {
187 chosenImporter = importer;
188 }
189 }
190 /**
191 * If the filter hasn't been changed in the dialog, chosenImporter is null now.
192 * When the filter has been set explicitly to AllFormatsImporter, treat this the same.
193 */
194 if (chosenImporter instanceof AllFormatsImporter) {
195 chosenImporter = null;
196 }
197 getProgressMonitor().setTicksCount(files.size());
198
199 if (chosenImporter != null) {
200 // The importer was expicitely chosen, so use it.
201 List<File> filesNotMatchingWithImporter = new LinkedList<File>();
202 List<File> filesMatchingWithImporter = new LinkedList<File>();
203 for (final File f : files) {
204 if (!chosenImporter.acceptFile(f)) {
205 if (f.isDirectory()) {
206 SwingUtilities.invokeLater(new Runnable() {
207 public void run() {
208 JOptionPane.showMessageDialog(Main.parent, tr(
209 "<html>Cannot open directory ''{0}''.<br>Please select a file.</html>",
210 f.getAbsolutePath()), tr("Open file"), JOptionPane.ERROR_MESSAGE);
211 }
212 });
213 // TODO when changing to Java 6: Don't cancel the
214 // task here but use different modality. (Currently 2 dialogs
215 // would block each other.)
216 return;
217 } else {
218 filesNotMatchingWithImporter.add(f);
219 }
220 } else {
221 filesMatchingWithImporter.add(f);
222 }
223 }
224
225 if (!filesNotMatchingWithImporter.isEmpty()) {
226 alertFilesNotMatchingWithImporter(filesNotMatchingWithImporter, chosenImporter);
227 }
228 if (!filesMatchingWithImporter.isEmpty()) {
229 importData(chosenImporter, filesMatchingWithImporter);
230 }
231 } else {
232 // find appropriate importer
233 MultiMap<FileImporter, File> importerMap = new MultiMap<FileImporter, File>();
234 List<File> filesWithUnknownImporter = new LinkedList<File>();
235 FILES: for (File f : files) {
236 for (FileImporter importer : ExtensionFileFilter.importers) {
237 if (importer.acceptFile(f)) {
238 importerMap.put(importer, f);
239 continue FILES;
240 }
241 }
242 filesWithUnknownImporter.add(f);
243 }
244 if (!filesWithUnknownImporter.isEmpty()) {
245 alertFilesWithUnknownImporter(filesWithUnknownImporter);
246 }
247 List<FileImporter> importers = new ArrayList<FileImporter>(importerMap.keySet());
248 Collections.sort(importers);
249 Collections.reverse(importers);
250
251 Set<String> fileHistory = new LinkedHashSet<String>();
252 Set<String> failedAll = new HashSet<String>();
253
254 for (FileImporter importer : importers) {
255 List<File> files = new ArrayList<File>(importerMap.get(importer));
256 importData(importer, files);
257 // suppose all files will fail to load
258 List<File> failedFiles = new ArrayList<File>(files);
259
260 if (recordHistory && !importer.isBatchImporter()) {
261 // remove the files which didn't fail to load from the failed list
262 failedFiles.removeAll(successfullyOpenedFiles);
263 for (File f : successfullyOpenedFiles) {
264 fileHistory.add(f.getPath());
265 }
266 for (File f : failedFiles) {
267 failedAll.add(f.getPath());
268 }
269 }
270 }
271
272 if (recordHistory) {
273 Collection<String> oldFileHistory = Main.pref.getCollection("file-open.history");
274 fileHistory.addAll(oldFileHistory);
275 // remove the files which failed to load from the list
276 fileHistory.removeAll(failedAll);
277 int maxsize = Math.max(0, Main.pref.getInteger("file-open.history.max-size", 15));
278 Collection<String> trimmedFileHistory = new ArrayList<String>(Math.min(maxsize, fileHistory.size()));
279 int i = 0;
280 for (String s : fileHistory) {
281 if (++i > maxsize) {
282 break;
283 }
284 trimmedFileHistory.add(s);
285 }
286 Main.pref.putCollection("file-open.history", trimmedFileHistory);
287 }
288 }
289 }
290
291 public void importData(FileImporter importer, List<File> files) {
292 if (importer.isBatchImporter()) {
293 if (cancelled) return;
294 String msg;
295 if (files.size() == 1) {
296 msg = tr("Opening 1 file...");
297 } else {
298 msg = trn("Opening {0} file...", "Opening {0} files...", files.size(), files.size());
299 }
300 getProgressMonitor().setCustomText(msg);
301 getProgressMonitor().indeterminateSubTask(msg);
302 if (importer.importDataHandleExceptions(files, getProgressMonitor().createSubTaskMonitor(files.size(), false))) {
303 successfullyOpenedFiles.addAll(files);
304 }
305 } else {
306 for (File f : files) {
307 if (cancelled) return;
308 getProgressMonitor().indeterminateSubTask(tr("Opening file ''{0}'' ...", f.getAbsolutePath()));
309 if (importer.importDataHandleExceptions(f, getProgressMonitor().createSubTaskMonitor(1, false))) {
310 successfullyOpenedFiles.add(f);
311 }
312 }
313 }
314 }
315
316 public List<File> getSuccessfullyOpenedFiles() {
317 return successfullyOpenedFiles;
318 }
319 }
320}
Note: See TracBrowser for help on using the repository browser.