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

Revision 4996, 13.7 KB checked in by Don-vip, 3 months ago (diff)

fix #2012 - Download from URL dropped on main window

  • Property svn:eol-style set to native
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.