source: josm/trunk/src/org/openstreetmap/josm/gui/io/importexport/GpxExporter.java@ 14950

Last change on this file since 14950 was 14950, checked in by GerdP, 5 years ago

fix #17238 Don't know why I forgot to commit this patch.

  • Property svn:eol-style set to native
File size: 13.2 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.awt.GridBagLayout;
7import java.awt.event.ActionListener;
8import java.awt.event.KeyAdapter;
9import java.awt.event.KeyEvent;
10import java.io.File;
11import java.io.IOException;
12import java.io.OutputStream;
13import java.text.MessageFormat;
14import java.time.Year;
15import java.util.Optional;
16
17import javax.swing.JButton;
18import javax.swing.JCheckBox;
19import javax.swing.JLabel;
20import javax.swing.JList;
21import javax.swing.JOptionPane;
22import javax.swing.JPanel;
23import javax.swing.JScrollPane;
24import javax.swing.ListSelectionModel;
25
26import org.openstreetmap.josm.data.gpx.GpxConstants;
27import org.openstreetmap.josm.data.gpx.GpxData;
28import org.openstreetmap.josm.gui.ExtendedDialog;
29import org.openstreetmap.josm.gui.MainApplication;
30import org.openstreetmap.josm.gui.layer.GpxLayer;
31import org.openstreetmap.josm.gui.layer.Layer;
32import org.openstreetmap.josm.gui.layer.OsmDataLayer;
33import org.openstreetmap.josm.gui.widgets.JosmTextArea;
34import org.openstreetmap.josm.gui.widgets.JosmTextField;
35import org.openstreetmap.josm.io.Compression;
36import org.openstreetmap.josm.io.GpxWriter;
37import org.openstreetmap.josm.spi.preferences.Config;
38import org.openstreetmap.josm.tools.CheckParameterUtil;
39import org.openstreetmap.josm.tools.GBC;
40
41/**
42 * Exports data to a .gpx file. Data may be native GPX or OSM data which will be converted.
43 * @since 1949
44 */
45public class GpxExporter extends FileExporter implements GpxConstants {
46
47 private static final String GPL_WARNING = "<html><font color='red' size='-2'>"
48 + tr("Note: GPL is not compatible with the OSM license. Do not upload GPL licensed tracks.") + "</html>";
49
50 private static final String[] LICENSES = {
51 "Creative Commons By-SA",
52 "Open Database License (ODbL)",
53 "public domain",
54 "GNU Lesser Public License (LGPL)",
55 "BSD License (MIT/X11)"};
56
57 private static final String[] URLS = {
58 "https://creativecommons.org/licenses/by-sa/3.0",
59 "http://opendatacommons.org/licenses/odbl/1.0",
60 "public domain",
61 "https://www.gnu.org/copyleft/lesser.html",
62 "http://www.opensource.org/licenses/bsd-license.php"};
63
64 /**
65 * Constructs a new {@code GpxExporter}.
66 */
67 public GpxExporter() {
68 super(GpxImporter.getFileFilter());
69 }
70
71 @Override
72 public boolean acceptFile(File pathname, Layer layer) {
73 if (!(layer instanceof OsmDataLayer) && !(layer instanceof GpxLayer))
74 return false;
75 return super.acceptFile(pathname, layer);
76 }
77
78 @Override
79 public void exportData(File file, Layer layer) throws IOException {
80 CheckParameterUtil.ensureParameterNotNull(layer, "layer");
81 if (!(layer instanceof OsmDataLayer) && !(layer instanceof GpxLayer))
82 throw new IllegalArgumentException(MessageFormat.format("Expected instance of OsmDataLayer or GpxLayer. Got ''{0}''.", layer
83 .getClass().getName()));
84 CheckParameterUtil.ensureParameterNotNull(file, "file");
85
86 String fn = file.getPath();
87 if (fn.indexOf('.') == -1) {
88 fn += ".gpx";
89 file = new File(fn);
90 }
91
92 // open the dialog asking for options
93 JPanel p = new JPanel(new GridBagLayout());
94
95 GpxData gpxData;
96 // At this moment, we only need to know the attributes of the GpxData,
97 // conversion of OsmDataLayer (if needed) will be done after the dialog is closed.
98 if (layer instanceof GpxLayer) {
99 gpxData = ((GpxLayer) layer).data;
100 } else {
101 gpxData = new GpxData();
102 }
103
104 p.add(new JLabel(tr("GPS track description")), GBC.eol());
105 JosmTextArea desc = new JosmTextArea(3, 40);
106 desc.setWrapStyleWord(true);
107 desc.setLineWrap(true);
108 desc.setText(gpxData.getString(META_DESC));
109 p.add(new JScrollPane(desc), GBC.eop().fill(GBC.BOTH));
110
111 JCheckBox author = new JCheckBox(tr("Add author information"), Config.getPref().getBoolean("lastAddAuthor", true));
112 p.add(author, GBC.eol());
113
114 JLabel nameLabel = new JLabel(tr("Real name"));
115 p.add(nameLabel, GBC.std().insets(10, 0, 5, 0));
116 JosmTextField authorName = new JosmTextField();
117 p.add(authorName, GBC.eol().fill(GBC.HORIZONTAL));
118 nameLabel.setLabelFor(authorName);
119
120 JLabel emailLabel = new JLabel(tr("E-Mail"));
121 p.add(emailLabel, GBC.std().insets(10, 0, 5, 0));
122 JosmTextField email = new JosmTextField();
123 p.add(email, GBC.eol().fill(GBC.HORIZONTAL));
124 emailLabel.setLabelFor(email);
125
126 JLabel copyrightLabel = new JLabel(tr("Copyright (URL)"));
127 p.add(copyrightLabel, GBC.std().insets(10, 0, 5, 0));
128 JosmTextField copyright = new JosmTextField();
129 p.add(copyright, GBC.std().fill(GBC.HORIZONTAL));
130 copyrightLabel.setLabelFor(copyright);
131
132 JButton predefined = new JButton(tr("Predefined"));
133 p.add(predefined, GBC.eol().insets(5, 0, 0, 0));
134
135 JLabel copyrightYearLabel = new JLabel(tr("Copyright year"));
136 p.add(copyrightYearLabel, GBC.std().insets(10, 0, 5, 5));
137 JosmTextField copyrightYear = new JosmTextField("");
138 p.add(copyrightYear, GBC.eol().fill(GBC.HORIZONTAL));
139 copyrightYearLabel.setLabelFor(copyrightYear);
140
141 JLabel warning = new JLabel("<html><font size='-2'>&nbsp;</html");
142 p.add(warning, GBC.eol().fill(GBC.HORIZONTAL).insets(15, 0, 0, 0));
143 addDependencies(gpxData, author, authorName, email, copyright, predefined, copyrightYear, nameLabel, emailLabel,
144 copyrightLabel, copyrightYearLabel, warning);
145
146 p.add(new JLabel(tr("Keywords")), GBC.eol());
147 JosmTextField keywords = new JosmTextField();
148 keywords.setText(gpxData.getString(META_KEYWORDS));
149 p.add(keywords, GBC.eop().fill(GBC.HORIZONTAL));
150
151 ExtendedDialog ed = new ExtendedDialog(MainApplication.getMainFrame(),
152 tr("Export options"),
153 tr("Export and Save"), tr("Cancel"))
154 .setButtonIcons("exportgpx", "cancel")
155 .setContent(p);
156
157 if (ed.showDialog().getValue() != 1) {
158 setCanceled(true);
159 return;
160 }
161 setCanceled(false);
162
163 Config.getPref().putBoolean("lastAddAuthor", author.isSelected());
164 if (!authorName.getText().isEmpty()) {
165 Config.getPref().put("lastAuthorName", authorName.getText());
166 }
167 if (!copyright.getText().isEmpty()) {
168 Config.getPref().put("lastCopyright", copyright.getText());
169 }
170
171 if (layer instanceof OsmDataLayer) {
172 gpxData = ((OsmDataLayer) layer).toGpxData();
173 } else if (layer instanceof GpxLayer) {
174 gpxData = ((GpxLayer) layer).data;
175 } else {
176 gpxData = OsmDataLayer.toGpxData(MainApplication.getLayerManager().getEditDataSet(), file);
177 }
178
179 // add author and copyright details to the gpx data
180 if (author.isSelected()) {
181 if (!authorName.getText().isEmpty()) {
182 gpxData.put(META_AUTHOR_NAME, authorName.getText());
183 gpxData.put(META_COPYRIGHT_AUTHOR, authorName.getText());
184 }
185 if (!email.getText().isEmpty()) {
186 gpxData.put(META_AUTHOR_EMAIL, email.getText());
187 }
188 if (!copyright.getText().isEmpty()) {
189 gpxData.put(META_COPYRIGHT_LICENSE, copyright.getText());
190 }
191 if (!copyrightYear.getText().isEmpty()) {
192 gpxData.put(META_COPYRIGHT_YEAR, copyrightYear.getText());
193 }
194 }
195
196 // add the description to the gpx data
197 if (!desc.getText().isEmpty()) {
198 gpxData.put(META_DESC, desc.getText());
199 }
200
201 // add keywords to the gpx data
202 if (!keywords.getText().isEmpty()) {
203 gpxData.put(META_KEYWORDS, keywords.getText());
204 }
205
206 try (OutputStream fo = Compression.getCompressedFileOutputStream(file); GpxWriter writer = new GpxWriter(fo)) {
207 writer.write(gpxData);
208 }
209 }
210
211 private static void enableCopyright(final GpxData data, final JosmTextField copyright, final JButton predefined,
212 final JosmTextField copyrightYear, final JLabel copyrightLabel, final JLabel copyrightYearLabel,
213 final JLabel warning, boolean enable) {
214 copyright.setEnabled(enable);
215 predefined.setEnabled(enable);
216 copyrightYear.setEnabled(enable);
217 copyrightLabel.setEnabled(enable);
218 copyrightYearLabel.setEnabled(enable);
219 warning.setText(enable ? GPL_WARNING : "<html><font size='-2'>&nbsp;</html");
220
221 if (enable) {
222 if (copyrightYear.getText().isEmpty()) {
223 copyrightYear.setText(Optional.ofNullable(data.getString(META_COPYRIGHT_YEAR)).orElseGet(
224 () -> Year.now().toString()));
225 }
226 if (copyright.getText().isEmpty()) {
227 copyright.setText(Optional.ofNullable(data.getString(META_COPYRIGHT_LICENSE)).orElseGet(
228 () -> Config.getPref().get("lastCopyright", "https://creativecommons.org/licenses/by-sa/2.5")));
229 copyright.setCaretPosition(0);
230 }
231 } else {
232 copyrightYear.setText("");
233 copyright.setText("");
234 }
235 }
236
237 // CHECKSTYLE.OFF: ParameterNumber
238
239 /**
240 * Add all those listeners to handle the enable state of the fields.
241 * @param data GPX data
242 * @param author Author checkbox
243 * @param authorName Author name textfield
244 * @param email E-mail textfield
245 * @param copyright Copyright textfield
246 * @param predefined Predefined button
247 * @param copyrightYear Copyright year textfield
248 * @param nameLabel Name label
249 * @param emailLabel E-mail label
250 * @param copyrightLabel Copyright label
251 * @param copyrightYearLabel Copyright year label
252 * @param warning Warning label
253 */
254 private static void addDependencies(
255 final GpxData data,
256 final JCheckBox author,
257 final JosmTextField authorName,
258 final JosmTextField email,
259 final JosmTextField copyright,
260 final JButton predefined,
261 final JosmTextField copyrightYear,
262 final JLabel nameLabel,
263 final JLabel emailLabel,
264 final JLabel copyrightLabel,
265 final JLabel copyrightYearLabel,
266 final JLabel warning) {
267
268 // CHECKSTYLE.ON: ParameterNumber
269 ActionListener authorActionListener = e -> {
270 boolean b = author.isSelected();
271 authorName.setEnabled(b);
272 email.setEnabled(b);
273 nameLabel.setEnabled(b);
274 emailLabel.setEnabled(b);
275 if (b) {
276 authorName.setText(Optional.ofNullable(data.getString(META_AUTHOR_NAME)).orElseGet(
277 () -> Config.getPref().get("lastAuthorName")));
278 email.setText(Optional.ofNullable(data.getString(META_AUTHOR_EMAIL)).orElseGet(
279 () -> Config.getPref().get("lastAuthorEmail")));
280 } else {
281 authorName.setText("");
282 email.setText("");
283 }
284 boolean isAuthorSet = !authorName.getText().isEmpty();
285 GpxExporter.enableCopyright(data, copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning,
286 b && isAuthorSet);
287 };
288 author.addActionListener(authorActionListener);
289
290 KeyAdapter authorNameListener = new KeyAdapter() {
291 @Override public void keyReleased(KeyEvent e) {
292 boolean b = !authorName.getText().isEmpty() && author.isSelected();
293 GpxExporter.enableCopyright(data, copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b);
294 }
295 };
296 authorName.addKeyListener(authorNameListener);
297
298 predefined.addActionListener(e -> {
299 JList<String> l = new JList<>(LICENSES);
300 l.setVisibleRowCount(LICENSES.length);
301 l.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
302 int answer = JOptionPane.showConfirmDialog(
303 MainApplication.getMainFrame(),
304 new JScrollPane(l),
305 tr("Choose a predefined license"),
306 JOptionPane.OK_CANCEL_OPTION,
307 JOptionPane.QUESTION_MESSAGE
308 );
309 if (answer != JOptionPane.OK_OPTION || l.getSelectedIndex() == -1)
310 return;
311 StringBuilder license = new StringBuilder();
312 for (int i : l.getSelectedIndices()) {
313 if (i == 2) {
314 license = new StringBuilder("public domain");
315 break;
316 }
317 if (license.length() > 0) {
318 license.append(", ");
319 }
320 license.append(URLS[i]);
321 }
322 copyright.setText(license.toString());
323 copyright.setCaretPosition(0);
324 });
325
326 authorActionListener.actionPerformed(null);
327 authorNameListener.keyReleased(null);
328 }
329}
Note: See TracBrowser for help on using the repository browser.