source: josm/trunk/src/org/openstreetmap/josm/gui/io/importexport/GpxImporter.java@ 16869

Last change on this file since 16869 was 16869, checked in by simon04, 4 years ago

see #15441 - Do not create empty GpxRouteLayer

  • Property svn:eol-style set to native
File size: 9.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io.importexport;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.File;
7import java.io.IOException;
8import java.io.InputStream;
9
10import javax.swing.JOptionPane;
11
12import org.openstreetmap.josm.actions.ExtensionFileFilter;
13import org.openstreetmap.josm.data.gpx.GpxData;
14import org.openstreetmap.josm.gui.MainApplication;
15import org.openstreetmap.josm.gui.Notification;
16import org.openstreetmap.josm.gui.layer.GpxLayer;
17import org.openstreetmap.josm.gui.layer.GpxRouteLayer;
18import org.openstreetmap.josm.gui.layer.ImageryLayer;
19import org.openstreetmap.josm.gui.layer.OsmDataLayer;
20import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer;
21import org.openstreetmap.josm.gui.progress.ProgressMonitor;
22import org.openstreetmap.josm.gui.util.GuiHelper;
23import org.openstreetmap.josm.io.Compression;
24import org.openstreetmap.josm.io.GpxReader;
25import org.openstreetmap.josm.spi.preferences.Config;
26import org.openstreetmap.josm.tools.Logging;
27import org.xml.sax.SAXException;
28
29/**
30 * File importer allowing to import GPX files (*.gpx/gpx.gz files).
31 *
32 */
33public class GpxImporter extends FileImporter {
34
35 /**
36 * Utility class containing imported GPX and marker layers, and a task to run after they are added to MapView.
37 */
38 public static class GpxImporterData {
39 /**
40 * The imported GPX layer. May be null if no GPX data.
41 */
42 private final GpxLayer gpxLayer;
43 /**
44 * The imported GPX route layer. May be null if no marker.
45 */
46 private final GpxRouteLayer gpxRouteLayer;
47 /**
48 * The imported marker layer. May be null if no marker.
49 */
50 private final MarkerLayer markerLayer;
51 /**
52 * The task to run after GPX and/or marker layer has been added to MapView.
53 */
54 private final Runnable postLayerTask;
55
56 /**
57 * Constructs a new {@code GpxImporterData}.
58 * @param gpxLayer The imported GPX layer. May be null if no GPX data.
59 * @param markerLayer The imported marker layer. May be null if no marker.
60 * @param postLayerTask The task to run after GPX and/or marker layer has been added to MapView.
61 */
62 public GpxImporterData(GpxLayer gpxLayer, GpxRouteLayer gpxRouteLayer, MarkerLayer markerLayer, Runnable postLayerTask) {
63 this.gpxLayer = gpxLayer;
64 this.gpxRouteLayer = gpxRouteLayer;
65 this.markerLayer = markerLayer;
66 this.postLayerTask = postLayerTask;
67 }
68
69 /**
70 * Returns the imported GPX layer. May be null if no GPX data.
71 * @return the imported GPX layer. May be null if no GPX data.
72 */
73 public GpxLayer getGpxLayer() {
74 return gpxLayer;
75 }
76
77 /**
78 * Returns the imported GPX route layer. May be null if no GPX data.
79 * @return the imported GPX route layer. May be null if no GPX data.
80 */
81 public GpxRouteLayer getGpxRouteLayer() {
82 return gpxRouteLayer;
83 }
84
85 /**
86 * Returns the imported marker layer. May be null if no marker.
87 * @return the imported marker layer. May be null if no marker.
88 */
89 public MarkerLayer getMarkerLayer() {
90 return markerLayer;
91 }
92
93 /**
94 * Returns the task to run after GPX and/or marker layer has been added to MapView.
95 * @return the task to run after GPX and/or marker layer has been added to MapView.
96 */
97 public Runnable getPostLayerTask() {
98 return postLayerTask;
99 }
100 }
101
102 /**
103 * Constructs a new {@code GpxImporter}.
104 */
105 public GpxImporter() {
106 super(getFileFilter());
107 }
108
109 /**
110 * Returns a GPX file filter (*.gpx and *.gpx.gz files).
111 * @return a GPX file filter
112 */
113 public static ExtensionFileFilter getFileFilter() {
114 return ExtensionFileFilter.newFilterWithArchiveExtensions("gpx",
115 Config.getPref().get("save.extension.gpx", "gpx"), tr("GPX Files"), true);
116 }
117
118 @Override
119 public void importData(File file, ProgressMonitor progressMonitor) throws IOException {
120 final String fileName = file.getName();
121
122 try (InputStream is = Compression.getUncompressedFileInputStream(file)) {
123 GpxReader r = new GpxReader(is);
124 boolean parsedProperly = r.parse(true);
125 r.getGpxData().storageFile = file;
126 addLayers(loadLayers(r.getGpxData(), parsedProperly, fileName));
127 } catch (SAXException e) {
128 Logging.error(e);
129 throw new IOException(e.getLocalizedMessage(), e);
130 }
131 }
132
133 /**
134 * Adds the specified GPX and marker layers to Map.main
135 * @param data The layers to add
136 * @see #loadLayers
137 */
138 public static void addLayers(final GpxImporterData data) {
139 // FIXME: remove UI stuff from the IO subsystem
140 GuiHelper.runInEDT(() -> {
141 if (data.markerLayer != null) {
142 MainApplication.getLayerManager().addLayer(data.markerLayer);
143 }
144 if (data.gpxRouteLayer != null) {
145 MainApplication.getLayerManager().addLayer(data.gpxRouteLayer);
146 }
147 if (data.gpxLayer != null) {
148 MainApplication.getLayerManager().addLayer(data.gpxLayer);
149 }
150 data.postLayerTask.run();
151 });
152 }
153
154 /**
155 * Replies the new GPX and marker layers corresponding to the specified GPX data.
156 * @param data The GPX data
157 * @param parsedProperly True if GPX data has been properly parsed by {@link GpxReader#parse}
158 * @param gpxLayerName The GPX layer name
159 * @return the new GPX and marker layers corresponding to the specified GPX data, to be used with {@link #addLayers}
160 * @see #addLayers
161 */
162 public static GpxImporterData loadLayers(final GpxData data, final boolean parsedProperly, final String gpxLayerName) {
163 MarkerLayer markerLayer = null;
164 GpxRouteLayer gpxRouteLayer = null;
165 GpxLayer gpxLayer = new GpxLayer(data, gpxLayerName, data.storageFile != null);
166 if (Config.getPref().getBoolean("marker.makeautomarkers", true) && !data.waypoints.isEmpty()) {
167 markerLayer = new MarkerLayer(data, tr("Markers from {0}", gpxLayerName), data.storageFile, gpxLayer);
168 if (markerLayer.data.isEmpty()) {
169 markerLayer = null;
170 } else {
171 gpxLayer.setLinkedMarkerLayer(markerLayer);
172 }
173 }
174 if (Config.getPref().getBoolean("gpx.makeautoroutes", true) && !data.getRoutes().isEmpty()) {
175 gpxRouteLayer = new GpxRouteLayer(tr("Routes from {0}", gpxLayerName), gpxLayer);
176 }
177
178 final boolean isSameColor = MainApplication.getLayerManager()
179 .getLayersOfType(ImageryLayer.class)
180 .stream().noneMatch(ImageryLayer::isVisible)
181 && data.getTracks().stream().anyMatch(t -> OsmDataLayer.getBackgroundColor().equals(t.getColor()));
182
183 Runnable postLayerTask = () -> {
184 if (!parsedProperly) {
185 String msg;
186 if (data.storageFile == null) {
187 msg = tr("Error occurred while parsing gpx data for layer ''{0}''. Only a part of the file will be available.",
188 gpxLayerName);
189 } else {
190 msg = tr("Error occurred while parsing gpx file ''{0}''. Only a part of the file will be available.",
191 data.storageFile.getPath());
192 }
193 JOptionPane.showMessageDialog(null, msg);
194 }
195 if (isSameColor) {
196 new Notification(tr("The imported track \"{0}\" might not be visible because it has the same color as the background." +
197 "<br>You can change this in the context menu of the imported layer.", gpxLayerName))
198 .setIcon(JOptionPane.WARNING_MESSAGE)
199 .setDuration(Notification.TIME_LONG)
200 .show();
201 }
202 };
203 return new GpxImporterData(gpxLayer, gpxRouteLayer, markerLayer, postLayerTask);
204 }
205
206 /**
207 * Replies the new GPX and marker layers corresponding to the specified GPX file.
208 * @param is input stream to GPX data
209 * @param associatedFile GPX file
210 * @param gpxLayerName The GPX layer name
211 * @param progressMonitor The progress monitor
212 * @return the new GPX and marker layers corresponding to the specified GPX file
213 * @throws IOException if an I/O error occurs
214 */
215 public static GpxImporterData loadLayers(InputStream is, final File associatedFile,
216 final String gpxLayerName, ProgressMonitor progressMonitor) throws IOException {
217 try {
218 final GpxReader r = new GpxReader(is);
219 final boolean parsedProperly = r.parse(true);
220 r.getGpxData().storageFile = associatedFile;
221 return loadLayers(r.getGpxData(), parsedProperly, gpxLayerName);
222 } catch (SAXException e) {
223 Logging.error(e);
224 throw new IOException(tr("Parsing data for layer ''{0}'' failed", gpxLayerName), e);
225 }
226 }
227}
Note: See TracBrowser for help on using the repository browser.