source: josm/trunk/src/org/openstreetmap/josm/actions/SaveActionBase.java @ 5241

Revision 5014, 8.9 KB checked in by xeen, 3 months ago (diff)

fix #7429

  • Property svn:eol-style set to native
Line 
1//License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.io.File;
8import java.io.IOException;
9import java.util.Collection;
10import java.util.LinkedList;
11import java.util.List;
12
13import javax.swing.JFileChooser;
14import javax.swing.JOptionPane;
15import javax.swing.filechooser.FileFilter;
16
17import org.openstreetmap.josm.Main;
18import org.openstreetmap.josm.data.conflict.ConflictCollection;
19import org.openstreetmap.josm.data.osm.OsmPrimitive;
20import org.openstreetmap.josm.gui.ExtendedDialog;
21import org.openstreetmap.josm.gui.layer.GpxLayer;
22import org.openstreetmap.josm.gui.layer.Layer;
23import org.openstreetmap.josm.gui.layer.OsmDataLayer;
24import org.openstreetmap.josm.io.FileExporter;
25import org.openstreetmap.josm.tools.Shortcut;
26
27public abstract class SaveActionBase extends DiskAccessAction {
28    private File file;
29
30    public SaveActionBase(String name, String iconName, String tooltip, Shortcut shortcut) {
31        super(name, iconName, tooltip, shortcut);
32    }
33
34    @Override
35    public void actionPerformed(ActionEvent e) {
36        if (!isEnabled())
37            return;
38        boolean saved = doSave();
39        if (saved) {
40            addToFileOpenHistory();
41        }
42    }
43
44    public boolean doSave() {
45        Layer layer = null;
46        if (Main.isDisplayingMapView() && (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
47                || Main.map.mapView.getActiveLayer() instanceof GpxLayer)) {
48            layer = Main.map.mapView.getActiveLayer();
49        }
50        if (layer == null)
51            return false;
52        return doSave(layer);
53    }
54
55    public boolean doSave(Layer layer) {
56        if(!checkSaveConditions(layer))
57            return false;
58        file = getFile(layer);
59        return doInternalSave(layer, file);
60    }
61
62    public static boolean doSave(Layer layer, File file) {
63        if(!checkSaveConditions(layer))
64            return false;
65        return doInternalSave(layer, file);
66    }
67
68    private static boolean doInternalSave(Layer layer, File file) {
69        if (file == null)
70            return false;
71
72        try {
73            boolean exported = false;
74            for (FileExporter exporter : ExtensionFileFilter.exporters) {
75                if (exporter.acceptFile(file, layer)) {
76                    exporter.exportData(file, layer);
77                    exported = true;
78                    break;
79                }
80            }
81            if (!exported) {
82                JOptionPane.showMessageDialog(Main.parent, tr("No Exporter found! Nothing saved."), tr("Warning"),
83                        JOptionPane.WARNING_MESSAGE);
84                return false;
85            }
86            layer.setName(file.getName());
87            layer.setAssociatedFile(file);
88            if (layer instanceof OsmDataLayer) {
89                ((OsmDataLayer) layer).onPostSaveToFile();
90            }
91            Main.parent.repaint();
92        } catch (IOException e) {
93            e.printStackTrace();
94            return false;
95        }
96        return true;
97    }
98
99    protected abstract File getFile(Layer layer);
100
101    /**
102     * Checks whether it is ok to launch a save (whether we have data,
103     * there is no conflict etc.)
104     * @return <code>true</code>, if it is safe to save.
105     */
106    public static boolean checkSaveConditions(Layer layer) {
107        if (layer instanceof GpxLayer)
108            return ((GpxLayer)layer).data != null;
109        else if (layer instanceof OsmDataLayer)  {
110            if (isDataSetEmpty((OsmDataLayer)layer)) {
111                ExtendedDialog dialog = new ExtendedDialog(
112                        Main.parent,
113                        tr("Empty document"),
114                        new String[] {tr("Save anyway"), tr("Cancel")}
115                );
116                dialog.setContent(tr("The document contains no data."));
117                dialog.setButtonIcons(new String[] {"save.png", "cancel.png"});
118                dialog.showDialog();
119                if (dialog.getValue() != 1) return false;
120            }
121
122            ConflictCollection conflicts = ((OsmDataLayer)layer).getConflicts();
123            if (conflicts != null && !conflicts.isEmpty()) {
124                ExtendedDialog dialog = new ExtendedDialog(
125                        Main.parent,
126                        /* I18N: Display title of the window showing conflicts */
127                        tr("Conflicts"),
128                        new String[] {tr("Reject Conflicts and Save"), tr("Cancel")}
129                );
130                dialog.setContent(tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"));
131                dialog.setButtonIcons(new String[] {"save.png", "cancel.png"});
132                dialog.showDialog();
133                if (dialog.getValue() != 1) return false;
134            }
135            return true;
136        }
137        return false;
138    }
139
140    public static File openFileDialog(Layer layer) {
141        if (layer instanceof OsmDataLayer)
142            return createAndOpenSaveFileChooser(tr("Save OSM file"), "osm");
143        else if (layer instanceof GpxLayer)
144            return createAndOpenSaveFileChooser(tr("Save GPX file"), "gpx");
145        return createAndOpenSaveFileChooser(tr("Save Layer"), "lay");
146    }
147
148    /**
149     * Check the data set if it would be empty on save. It is empty, if it contains
150     * no objects (after all objects that are created and deleted without being
151     * transferred to the server have been removed).
152     *
153     * @return <code>true</code>, if a save result in an empty data set.
154     */
155    private static boolean isDataSetEmpty(OsmDataLayer layer) {
156        for (OsmPrimitive osm : layer.data.allNonDeletedPrimitives())
157            if (!osm.isDeleted() || !osm.isNewOrUndeleted())
158                return false;
159        return true;
160    }
161
162    /**
163     * Refreshes the enabled state
164     *
165     */
166    @Override
167    protected void updateEnabledState() {
168        if (Main.applet) {
169            setEnabled(false);
170            return;
171        }
172        boolean check =  Main.map != null
173        && Main.map.mapView !=null
174        && Main.map.mapView.getActiveLayer() != null;
175        if(!check) {
176            setEnabled(false);
177            return;
178        }
179        Layer layer = Main.map.mapView.getActiveLayer();
180        setEnabled(layer instanceof OsmDataLayer || layer instanceof GpxLayer);
181    }
182
183    public static File createAndOpenSaveFileChooser(String title, String extension) {
184        String curDir = Main.pref.get("lastDirectory");
185        if (curDir.equals("")) {
186            curDir = ".";
187        }
188        JFileChooser fc = new JFileChooser(new File(curDir));
189        if (title != null) {
190            fc.setDialogTitle(title);
191        }
192
193        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
194        fc.setMultiSelectionEnabled(false);
195        fc.setAcceptAllFileFilterUsed(false);
196        ExtensionFileFilter.applyChoosableExportFileFilters(fc, extension);
197        int answer = fc.showSaveDialog(Main.parent);
198        if (answer != JFileChooser.APPROVE_OPTION)
199            return null;
200
201        if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir)) {
202            Main.pref.put("lastDirectory", fc.getCurrentDirectory().getAbsolutePath());
203        }
204
205        File file = fc.getSelectedFile();
206        String fn = file.getPath();
207        if(fn.indexOf('.') == -1)
208        {
209            FileFilter ff = fc.getFileFilter();
210            if (ff instanceof ExtensionFileFilter) {
211                fn += "." + ((ExtensionFileFilter)ff).getDefaultExtension();
212            } else if(extension != null) {
213                fn += "." + extension;
214            }
215            file = new File(fn);
216        }
217        if (!confirmOverwrite(file))
218            return null;
219        return file;
220    }
221
222    public static boolean confirmOverwrite(File file) {
223        if (file == null || (file.exists())) {
224            ExtendedDialog dialog = new ExtendedDialog(
225                    Main.parent,
226                    tr("Overwrite"),
227                    new String[] {tr("Overwrite"), tr("Cancel")}
228            );
229            dialog.setContent(tr("File exists. Overwrite?"));
230            dialog.setButtonIcons(new String[] {"save_as.png", "cancel.png"});
231            dialog.showDialog();
232            return (dialog.getValue() == 1);
233        }
234        return true;
235    }
236
237    protected void addToFileOpenHistory() {
238        String filepath;
239        try {
240            filepath = file.getCanonicalPath();
241        } catch (IOException ign) {
242            return;
243        }
244
245        int maxsize = Math.max(0, Main.pref.getInteger("file-open.history.max-size", 15));
246        Collection<String> oldHistory = Main.pref.getCollection("file-open.history");
247        List<String> history = new LinkedList<String>(oldHistory);
248        history.remove(filepath);
249        history.add(0, filepath);
250        Main.pref.putCollectionBounded("file-open.history", maxsize, history);
251    }
252}
Note: See TracBrowser for help on using the repository browser.