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

Last change on this file since 4851 was 4463, checked in by bastiK, 13 years ago

applied #6889 - Only the first matching exporter should save a file (patch by Don-vip)

  • Property svn:eol-style set to native
File size: 8.8 KB
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;
12import javax.swing.JFileChooser;
13import javax.swing.JOptionPane;
14import javax.swing.filechooser.FileFilter;
15
16import org.openstreetmap.josm.Main;
17import org.openstreetmap.josm.data.conflict.ConflictCollection;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.gui.ExtendedDialog;
20import org.openstreetmap.josm.gui.layer.GpxLayer;
21import org.openstreetmap.josm.gui.layer.Layer;
22import org.openstreetmap.josm.gui.layer.OsmDataLayer;
23import org.openstreetmap.josm.io.FileExporter;
24import org.openstreetmap.josm.tools.Shortcut;
25
26public abstract class SaveActionBase extends DiskAccessAction {
27 private File file;
28
29 public SaveActionBase(String name, String iconName, String tooltip, Shortcut shortcut) {
30 super(name, iconName, tooltip, shortcut);
31 }
32
33 @Override
34 public void actionPerformed(ActionEvent e) {
35 if (!isEnabled()) {
36 return;
37 }
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 boolean doSave(Layer layer, File file) {
63 if(!checkSaveConditions(layer))
64 return false;
65 return doInternalSave(layer, file);
66 }
67
68 private 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 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 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 (!confirmOverride(file))
218 return null;
219 return file;
220 }
221
222 public static boolean confirmOverride(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.