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

Last change on this file since 5299 was 4996, checked in by Don-vip, 12 years ago

fix #2012 - Download from URL dropped on main window

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