Ignore:
Timestamp:
2018-08-07T19:54:24+02:00 (6 years ago)
Author:
Don-vip
Message:

fix #16572 - Conversion options for tags GPX -> OSM (patch by Bjoeni)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/gpx/ConvertToDataLayerAction.java

    r14055 r14103  
    77import java.awt.GridBagLayout;
    88import java.awt.event.ActionEvent;
     9import java.awt.event.ActionListener;
    910import java.io.File;
    1011import java.text.DateFormat;
     
    1920
    2021import javax.swing.AbstractAction;
     22import javax.swing.BorderFactory;
     23import javax.swing.ButtonGroup;
     24import javax.swing.JCheckBox;
    2125import javax.swing.JLabel;
    2226import javax.swing.JOptionPane;
    2327import javax.swing.JPanel;
     28import javax.swing.JRadioButton;
    2429
    2530import org.openstreetmap.josm.Main;
     
    3237import org.openstreetmap.josm.data.osm.Way;
    3338import org.openstreetmap.josm.gui.ConditionalOptionPaneUtil;
     39import org.openstreetmap.josm.gui.ExtendedDialog;
    3440import org.openstreetmap.josm.gui.MainApplication;
    3541import org.openstreetmap.josm.gui.layer.GpxLayer;
     
    7076    public static class FromGpxLayer extends ConvertToDataLayerAction<GpxLayer> {
    7177
     78        private static final String GPX_SETTING = "gpx.convert-tags";
    7279        private final DateFormat timeFormatter = DateUtils.getGpxFormat();
    7380
     
    8390        public DataSet convert() {
    8491            final DataSet ds = new DataSet();
     92
     93            List<String> keys = new ArrayList<>();
     94            String convertTags = Config.getPref().get(GPX_SETTING, "ask");
     95            boolean check = "list".equals(convertTags) || "ask".equals(convertTags);
     96            boolean none = "no".equals(convertTags); // no need to convert tags when no dialog will be shown anyways
     97
    8598            for (GpxTrack trk : layer.data.getTracks()) {
    8699                for (GpxTrackSegment segment : trk.getSegments()) {
     
    90103                        for (Entry<String, Object> entry : p.attr.entrySet()) {
    91104                            String key = entry.getKey();
    92                             String str = p.getString(key);
    93                             if (str != null) {
    94                                 n.put(key, str);
     105                            Object obj = p.get(key);
     106                            if (check && !keys.contains(key) && (obj instanceof String || obj instanceof Date)) {
     107                                keys.add(key);
     108                            }
     109                            if (obj instanceof String) {
     110                                String str = (String) obj;
     111                                if (!none) {
     112                                    // only convert when required
     113                                    n.put(key, str);
     114                                }
    95115                                if (GpxConstants.PT_TIME.equals(key)) {
     116                                    // timestamps should always be converted
    96117                                    try {
    97118                                        n.setTimestamp(DateUtils.fromString(str));
     
    100121                                    }
    101122                                }
    102                             } else {
    103                                 Object obj = p.get(key);
    104                                 if (obj instanceof Date && GpxConstants.PT_TIME.equals(key)) {
    105                                     Date date = (Date) obj;
     123                            } else if (obj instanceof Date && GpxConstants.PT_TIME.equals(key)) {
     124                                // timestamps should always be converted
     125                                Date date = (Date) obj;
     126                                if (!none) { //... but the tag will only be set when required
    106127                                    n.put(key, timeFormatter.format(date));
    107                                     n.setTimestamp(date);
    108128                                }
     129                                n.setTimestamp(date);
    109130                            }
    110131                        }
     
    117138                }
    118139            }
     140            //gpx.convert-tags: all, list, *ask, no
     141            //gpx.convert-tags.last: *all, list, no
     142            //gpx.convert-tags.list.yes
     143            //gpx.convert-tags.list.no
     144            List<String> listPos = Config.getPref().getList(GPX_SETTING + ".list.yes");
     145            List<String> listNeg = Config.getPref().getList(GPX_SETTING + ".list.no");
     146            if (check && !keys.isEmpty()) {
     147                // Either "list" or "ask" was stored in the settings, so the Nodes have to be filtered after all tags have been processed
     148                List<String> allTags = new ArrayList<>(listPos);
     149                allTags.addAll(listNeg);
     150                if (!allTags.containsAll(keys) || "ask".equals(convertTags)) {
     151                    // not all keys are in positive/negative list, so we have to ask the user
     152                    TagConversionDialogResponse res = showTagConversionDialog(keys, listPos, listNeg);
     153                    if (res.sel == null) {
     154                        return null;
     155                    }
     156                    listPos = res.listPos;
     157
     158                    if ("no".equals(res.sel)) {
     159                        // User just chose not to convert any tags, but that was unknown before the initial conversion
     160                        return filterDataSet(ds, null);
     161                    } else if ("all".equals(res.sel)) {
     162                        return ds;
     163                    }
     164                }
     165                if (!listPos.containsAll(keys)) {
     166                    return filterDataSet(ds, listPos);
     167                }
     168            }
    119169            return ds;
     170        }
     171
     172        /**
     173         * Filters the tags of the given {@link DataSet}
     174         * @param ds The {@link DataSet}
     175         * @param listPos A {@code List<String>} containing the tags to be kept, can be {@code null} if all tags are to be removed
     176         * @return The {@link DataSet}
     177         * @since 14103
     178         */
     179        public DataSet filterDataSet(DataSet ds, List<String> listPos) {
     180            Collection<Node> nodes = ds.getNodes();
     181            for (Node n : nodes) {
     182                for (String key : n.keySet()) {
     183                    if (listPos == null || !listPos.contains(key)) {
     184                        n.put(key, null);
     185                    }
     186                }
     187            }
     188            return ds;
     189        }
     190
     191        /**
     192         * Shows the TagConversionDialog asking the user whether to keep all, some or no tags
     193         * @param keys The keys present during the current conversion
     194         * @param listPos The keys that were previously selected
     195         * @param listNeg The keys that were previously unselected
     196         * @return {@link TagConversionDialogResponse} containing the selection
     197         */
     198        private TagConversionDialogResponse showTagConversionDialog(List<String> keys, List<String> listPos, List<String> listNeg) {
     199            TagConversionDialogResponse res = new TagConversionDialogResponse(listPos, listNeg);
     200            String lSel = Config.getPref().get(GPX_SETTING + ".last", "all");
     201
     202            JPanel p = new JPanel(new GridBagLayout());
     203            ButtonGroup r = new ButtonGroup();
     204
     205            p.add(new JLabel(
     206                    tr("The GPX layer contains fields that can be converted to OSM tags. How would you like to proceed?")),
     207                    GBC.eol());
     208            JRadioButton rAll = new JRadioButton(tr("Convert all fields"), "all".equals(lSel));
     209            r.add(rAll);
     210            p.add(rAll, GBC.eol());
     211
     212            JRadioButton rList = new JRadioButton(tr("Only convert the following fields:"), "list".equals(lSel));
     213            r.add(rList);
     214            p.add(rList, GBC.eol());
     215
     216            JPanel q = new JPanel();
     217
     218            List<JCheckBox> checkList = new ArrayList<>();
     219            for (String key : keys) {
     220                JCheckBox cTmp = new JCheckBox(key, !listNeg.contains(key));
     221                checkList.add(cTmp);
     222                q.add(cTmp);
     223            }
     224
     225            q.setBorder(BorderFactory.createEmptyBorder(0, 20, 5, 0));
     226            p.add(q, GBC.eol());
     227
     228            JRadioButton rNone = new JRadioButton(tr("Do not convert any fields"), "no".equals(lSel));
     229            r.add(rNone);
     230            p.add(rNone, GBC.eol());
     231
     232            ActionListener enabler = new TagConversionDialogRadioButtonActionListener(checkList, true);
     233            ActionListener disabler = new TagConversionDialogRadioButtonActionListener(checkList, false);
     234
     235            if (!"list".equals(lSel)) {
     236                disabler.actionPerformed(null);
     237            }
     238
     239            rAll.addActionListener(disabler);
     240            rList.addActionListener(enabler);
     241            rNone.addActionListener(disabler);
     242
     243            ExtendedDialog ed = new ExtendedDialog(Main.parent, tr("Options"),
     244                    tr("Convert"), tr("Convert and remember selection"), tr("Cancel"))
     245                    .setButtonIcons("exportgpx", "exportgpx", "cancel").setContent(p);
     246            int ret = ed.showDialog().getValue();
     247
     248            if (ret == 1 || ret == 2) {
     249                for (JCheckBox cItem : checkList) {
     250                    String key = cItem.getText();
     251                    if (cItem.isSelected()) {
     252                        if (!res.listPos.contains(key)) {
     253                            res.listPos.add(key);
     254                        }
     255                        res.listNeg.remove(key);
     256                    } else {
     257                        if (!res.listNeg.contains(key)) {
     258                            res.listNeg.add(key);
     259                        }
     260                        res.listPos.remove(key);
     261                    }
     262                }
     263                if (rAll.isSelected()) {
     264                    res.sel = "all";
     265                } else if (rNone.isSelected()) {
     266                    res.sel = "no";
     267                }
     268                Config.getPref().put(GPX_SETTING + ".last", res.sel);
     269                if (ret == 2) {
     270                    Config.getPref().put(GPX_SETTING, res.sel);
     271                } else {
     272                    Config.getPref().put(GPX_SETTING, "ask");
     273                }
     274                Config.getPref().putList(GPX_SETTING + ".list.yes", res.listPos);
     275                Config.getPref().putList(GPX_SETTING + ".list.no", res.listNeg);
     276            } else {
     277                res.sel = null;
     278            }
     279            return res;
     280        }
     281
     282        private static class TagConversionDialogResponse {
     283
     284            final List<String> listPos;
     285            final List<String> listNeg;
     286            String sel = "list";
     287
     288            TagConversionDialogResponse(List<String> p, List<String> n) {
     289                listPos = new ArrayList<>(p);
     290                listNeg = new ArrayList<>(n);
     291            }
     292        }
     293
     294        private static class TagConversionDialogRadioButtonActionListener implements ActionListener {
     295
     296            private final boolean enable;
     297            private final List<JCheckBox> checkList;
     298
     299            TagConversionDialogRadioButtonActionListener(List<JCheckBox> chks, boolean en) {
     300                enable = en;
     301                checkList = chks;
     302            }
     303
     304            @Override
     305            public void actionPerformed(ActionEvent arg0) {
     306                for (JCheckBox ch : checkList) {
     307                    ch.setEnabled(enable);
     308                }
     309            }
    120310        }
    121311    }
     
    182372        }
    183373        final DataSet ds = convert();
    184         final OsmDataLayer osmLayer = new OsmDataLayer(ds, tr("Converted from: {0}", layer.getName()), null);
    185         if (layer.getAssociatedFile() != null) {
    186             osmLayer.setAssociatedFile(new File(layer.getAssociatedFile().getParentFile(), layer.getAssociatedFile().getName() + ".osm"));
    187         }
    188         osmLayer.setUploadDiscouraged(true);
    189         MainApplication.getLayerManager().addLayer(osmLayer, false);
    190         MainApplication.getLayerManager().removeLayer(layer);
     374        if (ds != null) {
     375            final OsmDataLayer osmLayer = new OsmDataLayer(ds, tr("Converted from: {0}", layer.getName()), null);
     376            if (layer.getAssociatedFile() != null) {
     377                osmLayer.setAssociatedFile(new File(layer.getAssociatedFile().getParentFile(),
     378                        layer.getAssociatedFile().getName() + ".osm"));
     379            }
     380            osmLayer.setUploadDiscouraged(true);
     381            MainApplication.getLayerManager().addLayer(osmLayer, false);
     382            MainApplication.getLayerManager().removeLayer(layer);
     383        }
    191384    }
    192385}
Note: See TracChangeset for help on using the changeset viewer.