Index: src/org/openstreetmap/josm/actions/DiskAccessAction.java =================================================================== --- src/org/openstreetmap/josm/actions/DiskAccessAction.java (revision 1713) +++ src/org/openstreetmap/josm/actions/DiskAccessAction.java (working copy) @@ -5,7 +5,6 @@ import java.io.File; import javax.swing.JFileChooser; -import javax.swing.filechooser.FileFilter; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.gui.ExtendedDialog; import org.openstreetmap.josm.tools.Shortcut; @@ -56,50 +55,4 @@ return fc; } - public static File createAndOpenSaveFileChooser(String title, - String extension) - { - String curDir = Main.pref.get("lastDirectory"); - if (curDir.equals("")) - curDir = "."; - JFileChooser fc = new JFileChooser(new File(curDir)); - if (title != null) - fc.setDialogTitle(title); - - fc.setMultiSelectionEnabled(false); - for (FileImporter imExporter: ExtensionFileFilter.importers) { - fc.addChoosableFileFilter(imExporter.filter); - } - - fc.setAcceptAllFileFilterUsed(true); - - int answer = fc.showSaveDialog(Main.parent); - if (answer != JFileChooser.APPROVE_OPTION) - return null; - - if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir)) - Main.pref.put("lastDirectory", fc.getCurrentDirectory().getAbsolutePath()); - - File file = fc.getSelectedFile(); - if(extension != null) - { - String fn = file.getPath(); - if(fn.indexOf('.') == -1) - { - FileFilter ff = fc.getFileFilter(); - if (ff instanceof ExtensionFileFilter) - fn += "." + ((ExtensionFileFilter)ff).defaultExtension; - else - fn += extension; - file = new File(fn); - } - } - if(file == null || (file.exists() && 1 != new ExtendedDialog(Main.parent, - tr("Overwrite"), tr("File exists. Overwrite?"), - new String[] {tr("Overwrite"), tr("Cancel")}, - new String[] {"save_as.png", "cancel.png"}).getValue())) - return null; - return file; - } - } Index: src/org/openstreetmap/josm/actions/ExtensionFileFilter.java =================================================================== --- src/org/openstreetmap/josm/actions/ExtensionFileFilter.java (revision 1713) +++ src/org/openstreetmap/josm/actions/ExtensionFileFilter.java (working copy) @@ -1,6 +1,7 @@ // License: GPL. Copyright 2007 by Immanuel Scholz and others package org.openstreetmap.josm.actions; +import static org.openstreetmap.josm.tools.I18n.tr; import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -8,12 +9,18 @@ import javax.swing.filechooser.FileFilter; import org.openstreetmap.josm.io.FileImporter; +import org.openstreetmap.josm.io.GpxExporter; import org.openstreetmap.josm.io.GpxImporter; import org.openstreetmap.josm.io.NMEAImporter; +import org.openstreetmap.josm.io.OsmBzip2Exporter; import org.openstreetmap.josm.io.OsmBzip2Importer; +import org.openstreetmap.josm.io.OsmExporter; +import org.openstreetmap.josm.io.OsmGzipExporter; import org.openstreetmap.josm.io.OsmGzipImporter; import org.openstreetmap.josm.io.OsmImporter; +import org.openstreetmap.josm.io.FileExporter; + /** * A file filter that filters after the extension. Also includes a list of file * filters used in JOSM. @@ -28,6 +35,10 @@ public static ArrayList importers = new ArrayList(Arrays.asList(new OsmImporter(), new OsmGzipImporter(), new OsmBzip2Importer(), new GpxImporter(), new NMEAImporter())); + // list of supported export formats + public static ArrayList exporters = new ArrayList(Arrays.asList(new GpxExporter(), + new OsmExporter(), new OsmGzipExporter(), new OsmBzip2Exporter())); + /** * Construct an extension file filter by giving the extension to check after. * Index: src/org/openstreetmap/josm/actions/GpxExportAction.java =================================================================== --- src/org/openstreetmap/josm/actions/GpxExportAction.java (revision 1713) +++ src/org/openstreetmap/josm/actions/GpxExportAction.java (working copy) @@ -3,263 +3,58 @@ import static org.openstreetmap.josm.tools.I18n.tr; -import java.awt.GridBagLayout; import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.util.Calendar; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JList; import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import javax.swing.ListSelectionModel; import org.openstreetmap.josm.Main; -import org.openstreetmap.josm.data.gpx.GpxData; import org.openstreetmap.josm.gui.ExtendedDialog; import org.openstreetmap.josm.gui.layer.GpxLayer; import org.openstreetmap.josm.gui.layer.Layer; -import org.openstreetmap.josm.gui.layer.OsmDataLayer; -import org.openstreetmap.josm.io.GpxWriter; -import org.openstreetmap.josm.tools.GBC; +import org.openstreetmap.josm.io.FileExporter; +import org.openstreetmap.josm.io.GpxExporter; import org.openstreetmap.josm.tools.Shortcut; /** * Exports data to gpx. */ -public class GpxExportAction extends DiskAccessAction { - - private final static String warningGpl = ""+tr("Note: GPL is not compatible with the OSM license. Do not upload GPL licensed tracks.")+""; +public class GpxExportAction extends SaveActionBase { - private final Layer layer; + public final static String warningGpl = ""+tr("Note: GPL is not compatible with the OSM license. Do not upload GPL licensed tracks.")+""; public GpxExportAction(Layer layer) { super(tr("Export to GPX..."), "exportgpx", tr("Export the data to GPX file."), - Shortcut.registerShortcut("file:exportgpx", tr("Export to GPX..."), KeyEvent.VK_E, Shortcut.GROUP_MENU)); - this.layer = layer; + Shortcut.registerShortcut("file:exportgpx", tr("Export to GPX..."), KeyEvent.VK_E, Shortcut.GROUP_MENU), + layer); } + @Override public void actionPerformed(ActionEvent e) { if (layer == null && Main.map == null) { JOptionPane.showMessageDialog(Main.parent, tr("Nothing to export. Get some data first.")); return; } - JFileChooser fc = createAndOpenFileChooser(false, false, null); - if (fc == null) - return; - File file = fc.getSelectedFile(); + File file = createAndOpenSaveFileChooser(tr("Export GPX file"),".gpx"); if (file == null) return; - exportGpx(file, this.layer == null ? Main.main.editLayer() : this.layer); - } - - public static void exportGpx(File file, Layer layer) { - String fn = file.getPath(); - if (fn.indexOf('.') == -1) { - fn += ".gpx"; - file = new File(fn); - } - - // open the dialog asking for options - JPanel p = new JPanel(new GridBagLayout()); - - p.add(new JLabel(tr("gps track description")), GBC.eol()); - JTextArea desc = new JTextArea(3,40); - desc.setWrapStyleWord(true); - desc.setLineWrap(true); - p.add(new JScrollPane(desc), GBC.eop().fill(GBC.BOTH)); - - JCheckBox author = new JCheckBox(tr("Add author information"), Main.pref.getBoolean("lastAddAuthor", true)); - author.setSelected(true); - p.add(author, GBC.eol()); - JLabel nameLabel = new JLabel(tr("Real name")); - p.add(nameLabel, GBC.std().insets(10,0,5,0)); - JTextField authorName = new JTextField(Main.pref.get("lastAuthorName")); - p.add(authorName, GBC.eol().fill(GBC.HORIZONTAL)); - JLabel emailLabel = new JLabel(tr("E-Mail")); - p.add(emailLabel, GBC.std().insets(10,0,5,0)); - JTextField email = new JTextField(Main.pref.get("osm-server.username")); - p.add(email, GBC.eol().fill(GBC.HORIZONTAL)); - JLabel copyrightLabel = new JLabel(tr("Copyright (URL)")); - p.add(copyrightLabel, GBC.std().insets(10,0,5,0)); - JTextField copyright = new JTextField(); - p.add(copyright, GBC.std().fill(GBC.HORIZONTAL)); - JButton predefined = new JButton(tr("Predefined")); - p.add(predefined, GBC.eol().insets(5,0,0,0)); - JLabel copyrightYearLabel = new JLabel(tr("Copyright year")); - p.add(copyrightYearLabel, GBC.std().insets(10,0,5,5)); - JTextField copyrightYear = new JTextField(""); - p.add(copyrightYear, GBC.eol().fill(GBC.HORIZONTAL)); - JLabel warning = new JLabel("  0) { - gpxData.attr.put(GpxData.META_AUTHOR_NAME, authorName.getText()); - gpxData.attr.put(GpxData.META_COPYRIGHT_AUTHOR, authorName.getText()); - } - if(email.getText().length() > 0) gpxData.attr.put(GpxData.META_AUTHOR_EMAIL, email.getText()); - if(copyright.getText().length() > 0) gpxData.attr.put(GpxData.META_COPYRIGHT_LICENSE, copyright.getText()); - if(copyrightYear.getText().length() > 0) gpxData.attr.put(GpxData.META_COPYRIGHT_YEAR, copyrightYear.getText()); - } - - // add the description to the gpx data - if(desc.getText().length() > 0) gpxData.attr.put(GpxData.META_DESC, desc.getText()); - - // add keywords to the gpx data - if(keywords.getText().length() > 0) gpxData.attr.put(GpxData.META_KEYWORDS, keywords.getText()); - - try { - FileOutputStream fo = new FileOutputStream(file); - new GpxWriter(fo).write(gpxData); - fo.flush(); - fo.close(); - } catch (IOException x) { - x.printStackTrace(); - JOptionPane.showMessageDialog(Main.parent, tr("Error while exporting {0}:\n{1}", fn,x.getMessage()), tr("Error"), JOptionPane.ERROR_MESSAGE); - } - } - - /** - * Add all those listeners to handle the enable state of the fields. - * @param copyrightYearLabel - * @param copyrightLabel - * @param emailLabel - * @param nameLabel - * @param warning - */ - private static void addDependencies( - final JCheckBox author, - final JTextField authorName, - final JTextField email, - final JTextField copyright, - final JButton predefined, - final JTextField copyrightYear, - final JLabel nameLabel, - final JLabel emailLabel, - final JLabel copyrightLabel, - final JLabel copyrightYearLabel, - final JLabel warning) { - - ActionListener authorActionListener = new ActionListener(){ - public void actionPerformed(ActionEvent e) { - boolean b = author.isSelected(); - authorName.setEnabled(b); - email.setEnabled(b); - nameLabel.setEnabled(b); - emailLabel.setEnabled(b); - authorName.setText(b ? Main.pref.get("lastAuthorName") : ""); - email.setText(b ? Main.pref.get("osm-server.username") : ""); - - boolean authorSet = authorName.getText().length() != 0; - enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b && authorSet); - } - }; - author.addActionListener(authorActionListener); - - KeyAdapter authorNameListener = new KeyAdapter(){ - @Override public void keyReleased(KeyEvent e) { - boolean b = authorName.getText().length()!=0 && author.isSelected(); - enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b); - } - }; - authorName.addKeyListener(authorNameListener); - - predefined.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e) { - JList l = new JList(new String[]{"Creative Commons By-SA", "public domain", "GNU Lesser Public License (LGPL)", "BSD License (MIT/X11)"}); - l.setVisibleRowCount(4); - l.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - int answer = JOptionPane.showConfirmDialog(Main.parent, new JScrollPane(l),tr("Choose a predefined license"), JOptionPane.OK_CANCEL_OPTION); - if (answer != JOptionPane.OK_OPTION || l.getSelectedIndex() == -1) - return; - final String[] urls = { - "http://creativecommons.org/licenses/by-sa/2.5", - "public domain", - "http://www.gnu.org/copyleft/lesser.html", - "http://www.opensource.org/licenses/bsd-license.php"}; - String license = ""; - for (int i : l.getSelectedIndices()) { - if (i == 1) { - license = "public domain"; - break; - } - license += license.length()==0 ? urls[i] : ", "+urls[i]; + for (FileExporter exporter : ExtensionFileFilter.exporters) { + if(exporter instanceof GpxExporter) { + try { + exporter.exportData(file, this.layer == null ? Main.main.editLayer() : this.layer); + } catch (IOException e1) { + e1.printStackTrace(); } - copyright.setText(license); - copyright.setCaretPosition(0); } - }); - - authorActionListener.actionPerformed(null); - authorNameListener.keyReleased(null); + } } - private static void enableCopyright(final JTextField copyright, final JButton predefined, final JTextField copyrightYear, final JLabel copyrightLabel, final JLabel copyrightYearLabel, final JLabel warning, boolean enable) { - copyright.setEnabled(enable); - predefined.setEnabled(enable); - copyrightYear.setEnabled(enable); - copyrightLabel.setEnabled(enable); - copyrightYearLabel.setEnabled(enable); - warning.setText(enable ? warningGpl : "    0) { + gpxData.attr.put(GpxData.META_AUTHOR_NAME, authorName.getText()); + gpxData.attr.put(GpxData.META_COPYRIGHT_AUTHOR, authorName.getText()); + } + if(email.getText().length() > 0) { + gpxData.attr.put(GpxData.META_AUTHOR_EMAIL, email.getText()); + } + if(copyright.getText().length() > 0) { + gpxData.attr.put(GpxData.META_COPYRIGHT_LICENSE, copyright.getText()); + } + if(copyrightYear.getText().length() > 0) { + gpxData.attr.put(GpxData.META_COPYRIGHT_YEAR, copyrightYear.getText()); + } + } + + // add the description to the gpx data + if(desc.getText().length() > 0) { + gpxData.attr.put(GpxData.META_DESC, desc.getText()); + } + + // add keywords to the gpx data + if(keywords.getText().length() > 0) { + gpxData.attr.put(GpxData.META_KEYWORDS, keywords.getText()); + } + + try { + FileOutputStream fo = new FileOutputStream(file); + new GpxWriter(fo).write(gpxData); + fo.flush(); + fo.close(); + } catch (IOException x) { + x.printStackTrace(); + JOptionPane.showMessageDialog(Main.parent, tr("Error while exporting {0}:\n{1}", fn,x.getMessage()), tr("Error"), JOptionPane.ERROR_MESSAGE); + } + } +} Index: src/org/openstreetmap/josm/io/OsmBzip2Exporter.java =================================================================== --- src/org/openstreetmap/josm/io/OsmBzip2Exporter.java (revision 0) +++ src/org/openstreetmap/josm/io/OsmBzip2Exporter.java (revision 0) @@ -0,0 +1,30 @@ +// License: GPL. For details, see LICENSE file. +package org.openstreetmap.josm.io; + +import static org.openstreetmap.josm.tools.I18n.tr; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.apache.tools.bzip2.CBZip2OutputStream; +import org.openstreetmap.josm.actions.ExtensionFileFilter; + +public class OsmBzip2Exporter extends OsmExporter { + + public OsmBzip2Exporter() { + super(new ExtensionFileFilter("osm.bz2, osm.bz", "osm.bz2", tr("OSM Server Files bzip2 compressed") + + " (*.osm.bz2 *.osm.bz)")); + } + + @Override + protected OutputStream getOutputStream(File file) throws FileNotFoundException,IOException { + OutputStream out = new FileOutputStream(file); + out.write('B'); + out.write('Z'); + out = new CBZip2OutputStream(out); + return out; + } +} Index: src/org/openstreetmap/josm/io/OsmExporter.java =================================================================== --- src/org/openstreetmap/josm/io/OsmExporter.java (revision 0) +++ src/org/openstreetmap/josm/io/OsmExporter.java (revision 0) @@ -0,0 +1,129 @@ +// License: GPL. For details, see LICENSE file. +package org.openstreetmap.josm.io; + +import static org.openstreetmap.josm.tools.I18n.tr; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Writer; +import javax.swing.JOptionPane; +import org.openstreetmap.josm.Main; +import org.openstreetmap.josm.actions.ExtensionFileFilter; +import org.openstreetmap.josm.actions.SaveActionBase; +import org.openstreetmap.josm.gui.layer.GpxLayer; +import org.openstreetmap.josm.gui.layer.Layer; +import org.openstreetmap.josm.gui.layer.OsmDataLayer; + +public class OsmExporter extends FileExporter { + + public OsmExporter() { + super(new ExtensionFileFilter("osm,xml", "osm", tr("OSM Server Files") + " (*.osm *.xml)")); + } + + public OsmExporter(ExtensionFileFilter filter) { + super(filter); + } + + @Override + public void exportData(File file, Layer layer) throws IOException { + if (layer instanceof GpxLayer) { + save(file, (GpxLayer)layer); + ((GpxLayer)layer).data.storageFile = file; + } else if (layer instanceof OsmDataLayer) { + save(file, (OsmDataLayer)layer); + } + } + + private void save(File file, OsmDataLayer layer) { + File tmpFile = null; + try { + // use a tmp file because if something errors out in the + // process of writing the file, we might just end up with + // a truncated file. That can destroy lots of work. + if (file.exists()) { + tmpFile = new File(file.getPath() + "~"); + SaveActionBase.copy(file, tmpFile); + } + + // create outputstream and wrap it with gzip or bzip, if necessary + OutputStream out = getOutputStream(file); + Writer writer = new OutputStreamWriter(out, "UTF-8"); + + OsmWriter w = new OsmWriter(new PrintWriter(writer), false, layer.data.version); + w.header(); + w.writeDataSources(layer.data); + w.writeContent(layer.data); + w.footer(); + w.close(); + // FIXME - how to close? + if (!Main.pref.getBoolean("save.keepbackup") && (tmpFile != null)) { + tmpFile.delete(); + } + layer.cleanData(null, false); + } catch (IOException e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while saving.")+"\n"+e.getMessage()); + + try { + // if the file save failed, then the tempfile will not + // be deleted. So, restore the backup if we made one. + if (tmpFile != null && tmpFile.exists()) { + SaveActionBase.copy(tmpFile, file); + } + } catch (IOException e2) { + e2.printStackTrace(); + JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while restoring backup file.")+"\n"+e2.getMessage()); + } + } + } + + protected OutputStream getOutputStream(File file) throws FileNotFoundException,IOException { + return new FileOutputStream(file); + } + + private void save(File file, GpxLayer layer) { + File tmpFile = null; + try { + GpxImporter gpxImExporter = new GpxImporter(); + if (gpxImExporter.acceptFile(file)) { + + // use a tmp file because if something errors out in the + // process of writing the file, we might just end up with + // a truncated file. That can destroy lots of work. + if (file.exists()) { + tmpFile = new File(file.getPath() + "~"); + SaveActionBase.copy(file, tmpFile); + } + FileOutputStream fo = (FileOutputStream) getOutputStream(file); + new GpxWriter(fo).write(layer.data); + fo.flush(); + fo.close(); + + if (!Main.pref.getBoolean("save.keepbackup") && (tmpFile != null)) { + tmpFile.delete(); + } + } else { + JOptionPane.showMessageDialog(Main.parent, tr("Unknown file extension.")); + return; + } + } catch (IOException e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while saving.")+"\n"+e.getMessage()); + } + try { + // if the file save failed, then the tempfile will not + // be deleted. So, restore the backup if we made one. + if (tmpFile != null && tmpFile.exists()) { + SaveActionBase.copy(tmpFile, file); + } + } catch (IOException e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while restoring backup file.")+"\n"+e.getMessage()); + } + } +} Index: src/org/openstreetmap/josm/io/OsmGzipExporter.java =================================================================== --- src/org/openstreetmap/josm/io/OsmGzipExporter.java (revision 0) +++ src/org/openstreetmap/josm/io/OsmGzipExporter.java (revision 0) @@ -0,0 +1,26 @@ +// License: GPL. For details, see LICENSE file. +package org.openstreetmap.josm.io; + +import static org.openstreetmap.josm.tools.I18n.tr; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.zip.GZIPOutputStream; + +import org.openstreetmap.josm.actions.ExtensionFileFilter; + +public class OsmGzipExporter extends OsmExporter { + + public OsmGzipExporter() { + super(new ExtensionFileFilter("osm.gz", "osm.gz", tr("OSM Server Files gzip compressed") + " (*.osm.gz)")); + } + + @Override + protected OutputStream getOutputStream(File file) throws FileNotFoundException, IOException { + OutputStream out = new FileOutputStream(file); + return new GZIPOutputStream(out); + } +}