source: josm/trunk/src/org/openstreetmap/josm/io/GpxExporter.java@ 12646

Last change on this file since 12646 was 12636, checked in by Don-vip, 7 years ago

see #15182 - deprecate Main.getLayerManager(). Replacement: gui.MainApplication.getLayerManager()

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