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

Last change on this file since 6320 was 6248, checked in by Don-vip, 11 years ago

Rework console output:

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