Index: src/org/openstreetmap/josm/gui/layer/gpx/ConvertToDataLayerAction.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/gpx/ConvertToDataLayerAction.java	(revision 14085)
+++ src/org/openstreetmap/josm/gui/layer/gpx/ConvertToDataLayerAction.java	(working copy)
@@ -6,6 +6,7 @@
 
 import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.io.File;
 import java.text.DateFormat;
 import java.util.ArrayList;
@@ -18,9 +19,13 @@
 import java.util.Optional;
 
 import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.JCheckBox;
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
+import javax.swing.JRadioButton;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.gpx.GpxConstants;
@@ -31,6 +36,7 @@
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
+import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
@@ -81,7 +87,13 @@
 
         @Override
         public DataSet convert() {
-            final DataSet ds = new DataSet();
+            DataSet ds = new DataSet();
+
+            List<String> keys = new ArrayList<>();
+            String convertTags = Config.getPref().get("gpx.convert-tags", "ask");
+            boolean check = convertTags.equals("list") || convertTags.equals("ask");
+            boolean none = convertTags.equals("no"); // no need to convert tags when no dialog will be shown anyways
+
             for (GpxTrack trk : layer.data.getTracks()) {
                 for (GpxTrackSegment segment : trk.getSegments()) {
                     List<Node> nodes = new ArrayList<>();
@@ -89,10 +101,18 @@
                         Node n = new Node(p.getCoor());
                         for (Entry<String, Object> entry : p.attr.entrySet()) {
                             String key = entry.getKey();
-                            String str = p.getString(key);
-                            if (str != null) {
-                                n.put(key, str);
+                            Object obj = p.get(key);
+                            if (check && !keys.contains(key) && (obj instanceof String || obj instanceof Date)) {
+                                keys.add(key);
+                            }
+                            if (obj instanceof String) {
+                                String str = (String) obj;
+                                if (!none) {
+                                    // only convert when required
+                                    n.put(key, str);
+                                }
                                 if (GpxConstants.PT_TIME.equals(key)) {
+                                    // timestamps should always be converted
                                     try {
                                         n.setTimestamp(DateUtils.fromString(str));
                                     } catch (UncheckedParseException e) {
@@ -99,13 +119,13 @@
                                         Logging.log(Logging.LEVEL_WARN, e);
                                     }
                                 }
-                            } else {
-                                Object obj = p.get(key);
-                                if (obj instanceof Date && GpxConstants.PT_TIME.equals(key)) {
-                                    Date date = (Date) obj;
+                            } else if (obj instanceof Date && GpxConstants.PT_TIME.equals(key)) {
+                                // timestamps should always be converted
+                                Date date = (Date) obj;
+                                if (!none) { //... but the tag will only be set when required
                                     n.put(key, timeFormatter.format(date));
-                                    n.setTimestamp(date);
                                 }
+                                n.setTimestamp(date);
                             }
                         }
                         ds.addPrimitive(n);
@@ -116,8 +136,177 @@
                     ds.addPrimitive(w);
                 }
             }
+            //gpx.convert-tags: all, list, *ask, no
+            //gpx.convert-tags.last: *all, list, no
+            //gpx.convert-tags.list.yes
+            //gpx.convert-tags.list.no
+            List<String> listPos = Config.getPref().getList("gpx.convert-tags.list.yes");
+            List<String> listNeg = Config.getPref().getList("gpx.convert-tags.list.no");
+            if (check && !keys.isEmpty()) {
+                // Either "list" or "ask" was stored in the settings, so the nodes have to be filtered after all tags have been processed
+                List<String> allTags = new ArrayList<>(listPos);
+                allTags.addAll(listNeg);
+                if (!allTags.containsAll(keys) || convertTags.equals("ask")) {
+                    // not all keys are in positive/negative list, so we have to ask the user
+                    TagConversionDialogResponse res = showTagConversionDialog(keys, listPos, listNeg);
+                    if (res.sel == null) {
+                        return null;
+                    }
+                    listPos = res.listPos;
+
+                    if (res.sel.equals("no")) {
+                        // User just chose not to convert any tags, but that was unknown before the initial conversion
+                        return filterDataSet(ds, null);
+                    } else if (res.sel.equals("all")) {
+                        return ds;
+                    }
+                }
+                if (!listPos.containsAll(keys)) {
+                    ds = filterDataSet(ds, listPos);
+                }
+            }
             return ds;
         }
+
+        /**
+         * Filters the tags of the given {@link DataSet}
+         * @param ds The {@link DataSet}
+         * @param listPos A {@code List<String>} containing the tags to be kept, can be {@code null} if all tags are to be removed
+         * @return The {@link DataSet}
+         * @since xxx
+         */
+        public DataSet filterDataSet(DataSet ds, List<String> listPos) {
+            Collection<Node> nodes = ds.getNodes();
+            for (Node n : nodes) {
+                for (String key : n.keySet()) {
+                    if (listPos == null || !listPos.contains(key)) {
+                        n.put(key, null);
+                    }
+                }
+            }
+            return ds;
+        }
+
+        /**
+         * Shows the TagConversionDialog asking the user whether to keep all, some or no tags
+         * @param keys The keys present during the current conversion
+         * @param listPos The keys that were previously selected
+         * @param listNeg The keys that were previously unselected
+         * @return {@link TagConversionDialogResponse} containing the selection
+         */
+        private TagConversionDialogResponse showTagConversionDialog(List<String> keys, List<String> listPos,
+                List<String> listNeg) {
+            TagConversionDialogResponse res = new TagConversionDialogResponse(listPos, listNeg);
+            String lSel = Config.getPref().get("gpx.convert-tags.last", "all");
+
+            JPanel p = new JPanel(new GridBagLayout());
+            ButtonGroup r = new ButtonGroup();
+
+            p.add(new JLabel(tr(
+                    "The GPX layer contains fields that can be converted to OSM tags. How would you like to proceed?")),
+                    GBC.eol());
+            JRadioButton rAll = new JRadioButton(tr("Convert all fields"), lSel.equals("all"));
+            r.add(rAll);
+            p.add(rAll, GBC.eol());
+
+            JRadioButton rList = new JRadioButton(tr("Only convert the following fields:"), lSel.equals("list"));
+            r.add(rList);
+            p.add(rList, GBC.eol());
+
+            JPanel q = new JPanel();
+
+            List<JCheckBox> checkList = new ArrayList<>();
+            for (String key : keys) {
+                JCheckBox cTmp = new JCheckBox(key, !listNeg.contains(key));
+                checkList.add(cTmp);
+                q.add(cTmp);
+            }
+
+            q.setBorder(BorderFactory.createEmptyBorder(0, 20, 5, 0));
+            p.add(q, GBC.eol());
+
+            JRadioButton rNone = new JRadioButton(tr("Do not convert any fields"), lSel.equals("no"));
+            r.add(rNone);
+            p.add(rNone, GBC.eol());
+
+            ActionListener enabler = new TagConversionDialogRadioButtonActionListener(checkList, true);
+            ActionListener disabler = new TagConversionDialogRadioButtonActionListener(checkList, false);
+
+            if (!lSel.equals("list")) {
+                disabler.actionPerformed(null);
+            }
+
+            rAll.addActionListener(disabler);
+            rList.addActionListener(enabler);
+            rNone.addActionListener(disabler);
+
+            ExtendedDialog ed = new ExtendedDialog(Main.parent, tr("Options"), tr("Convert"),
+                    tr("Convert and remember selection"), tr("Cancel"))
+                            .setButtonIcons("exportgpx", "exportgpx", "cancel").setContent(p);
+            int ret = ed.showDialog().getValue();
+
+            if (ret == 1 || ret == 2) {
+                for (JCheckBox cItem : checkList) {
+                    String key = cItem.getText();
+                    if (cItem.isSelected()) {
+                        if (!listPos.contains(key)) {
+                            res.listPos.add(key);
+                        }
+                        res.listNeg.remove(key);
+                    } else {
+                        if (!listNeg.contains(key)) {
+                            res.listNeg.add(key);
+                        }
+                        res.listPos.remove(key);
+                    }
+                }
+                if (rAll.isSelected()) {
+                    res.sel = "all";
+                } else if (rNone.isSelected()) {
+                    res.sel = "no";
+                }
+                Config.getPref().put("gpx.convert-tags.last", res.sel);
+                if (ret == 2) {
+                    Config.getPref().put("gpx.convert-tags", res.sel);
+                } else {
+                    Config.getPref().put("gpx.convert-tags", "ask");
+                }
+                Config.getPref().putList("gpx.convert-tags.list.yes", res.listPos);
+                Config.getPref().putList("gpx.convert-tags.list.no", res.listNeg);
+            } else {
+                res.sel = null;
+            }
+            return res;
+        }
+
+        private class TagConversionDialogResponse {
+            public TagConversionDialogResponse(List<String> p, List<String> n) {
+                listPos = new ArrayList<>(p);
+                listNeg = new ArrayList<>(n);
+            }
+
+            List<String> listPos;
+            List<String> listNeg;
+            String sel = "list";
+        }
+
+        private class TagConversionDialogRadioButtonActionListener implements ActionListener {
+
+            private boolean enable;
+            private List<JCheckBox> checkList;
+
+            public TagConversionDialogRadioButtonActionListener(List<JCheckBox> chks, boolean en) {
+                enable = en;
+                checkList = chks;
+            }
+
+            @Override
+            public void actionPerformed(ActionEvent arg0) {
+                for (JCheckBox ch : checkList) {
+                    ch.setEnabled(enable);
+                }
+            }
+        }
     }
 
     /**
@@ -181,12 +370,15 @@
             return;
         }
         final DataSet ds = convert();
-        final OsmDataLayer osmLayer = new OsmDataLayer(ds, tr("Converted from: {0}", layer.getName()), null);
-        if (layer.getAssociatedFile() != null) {
-            osmLayer.setAssociatedFile(new File(layer.getAssociatedFile().getParentFile(), layer.getAssociatedFile().getName() + ".osm"));
+        if (ds != null) {
+            final OsmDataLayer osmLayer = new OsmDataLayer(ds, tr("Converted from: {0}", layer.getName()), null);
+            if (layer.getAssociatedFile() != null) {
+                osmLayer.setAssociatedFile(new File(layer.getAssociatedFile().getParentFile(),
+                        layer.getAssociatedFile().getName() + ".osm"));
+            }
+            osmLayer.setUploadDiscouraged(true);
+            MainApplication.getLayerManager().addLayer(osmLayer, false);
+            MainApplication.getLayerManager().removeLayer(layer);
         }
-        osmLayer.setUploadDiscouraged(true);
-        MainApplication.getLayerManager().addLayer(osmLayer, false);
-        MainApplication.getLayerManager().removeLayer(layer);
     }
 }

