import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
-import java.nio.charset.Charset;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
+import javax.swing.JRadioButton;
import javax.swing.JTextField;
+import javax.swing.border.EtchedBorder;
import tim.prune.App;
import tim.prune.GenericFunction;
-import tim.prune.GpsPruner;
+import tim.prune.GpsPrune;
import tim.prune.I18nManager;
import tim.prune.UpdateMessageBroker;
import tim.prune.config.Config;
-import tim.prune.data.Altitude;
-import tim.prune.data.AudioFile;
+import tim.prune.data.AudioClip;
import tim.prune.data.Coordinate;
import tim.prune.data.DataPoint;
import tim.prune.data.Field;
-import tim.prune.data.MediaFile;
+import tim.prune.data.MediaObject;
import tim.prune.data.Photo;
+import tim.prune.data.RecentFile;
+import tim.prune.data.SourceInfo;
import tim.prune.data.Timestamp;
import tim.prune.data.TrackInfo;
+import tim.prune.data.UnitSetLibrary;
import tim.prune.gui.DialogCloser;
import tim.prune.load.GenericFileFilter;
import tim.prune.save.xml.GpxCacherList;
+import tim.prune.save.xml.XmlUtils;
/**
private PointTypeSelector _pointTypeSelector = null;
private JCheckBox _timestampsCheckbox = null;
private JCheckBox _copySourceCheckbox = null;
+ private JPanel _encodingsPanel = null;
+ private JRadioButton _useSystemRadio = null, _forceUtf8Radio = null;
private File _exportFile = null;
+ /** Remember the previous sourceInfo object to tell whether it has changed */
+ private SourceInfo _previousSourceInfo = null;
/** this program name */
- private static final String GPX_CREATOR = "Prune v" + GpsPruner.VERSION_NUMBER + " activityworkshop.net";
+ private static final String GPX_CREATOR = "GpsPrune v" + GpsPrune.VERSION_NUMBER + " activityworkshop.net";
/**
_dialog.pack();
}
_pointTypeSelector.init(_app.getTrackInfo());
+ _encodingsPanel.setVisible(!XmlUtils.isSystemUtf8());
+ if (!XmlUtils.isSystemUtf8())
+ {
+ String systemEncoding = XmlUtils.getSystemEncoding();
+ _useSystemRadio.setText(I18nManager.getText("dialog.exportgpx.encoding.system")
+ + " (" + (systemEncoding == null ? "unknown" : systemEncoding) + ")");
+ }
+ setFileTitle();
_dialog.setVisible(true);
}
dialogPanel.setLayout(new BorderLayout());
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
- // Make a central panel with the text boxes
+ // Make a panel for the name/desc text boxes
JPanel descPanel = new JPanel();
descPanel.setLayout(new GridLayout(2, 2));
descPanel.add(new JLabel(I18nManager.getText("dialog.exportgpx.name")));
_copySourceCheckbox.setSelected(true);
checkPanel.add(_copySourceCheckbox);
mainPanel.add(checkPanel);
+ // panel for selecting character encoding
+ _encodingsPanel = new JPanel();
+ if (!XmlUtils.isSystemUtf8())
+ {
+ // only add this panel if system isn't utf8 (or can't be identified yet)
+ _encodingsPanel.setBorder(BorderFactory.createCompoundBorder(
+ BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(4, 4, 4, 4)));
+ _encodingsPanel.setLayout(new BorderLayout());
+ _encodingsPanel.add(new JLabel(I18nManager.getText("dialog.exportgpx.encoding")), BorderLayout.NORTH);
+ JPanel radioPanel = new JPanel();
+ radioPanel.setLayout(new FlowLayout());
+ ButtonGroup radioGroup = new ButtonGroup();
+ _useSystemRadio = new JRadioButton(I18nManager.getText("dialog.exportgpx.encoding.system"));
+ _forceUtf8Radio = new JRadioButton(I18nManager.getText("dialog.exportgpx.encoding.utf8"));
+ radioGroup.add(_useSystemRadio);
+ radioGroup.add(_forceUtf8Radio);
+ radioPanel.add(_useSystemRadio);
+ radioPanel.add(_forceUtf8Radio);
+ _useSystemRadio.setSelected(true);
+ _encodingsPanel.add(radioPanel, BorderLayout.CENTER);
+ mainPanel.add(_encodingsPanel);
+ }
dialogPanel.add(mainPanel, BorderLayout.CENTER);
// close dialog if escape pressed
return dialogPanel;
}
+ /**
+ * Set the suggestion for the name with which to export
+ */
+ private void setFileTitle()
+ {
+ // Get the most recent file info
+ SourceInfo currentSource = _app.getTrackInfo().getFileInfo().getLastFileInfo();
+ if (currentSource != _previousSourceInfo)
+ {
+ String lastTitle = currentSource.getFileTitle();
+ if (lastTitle != null && !lastTitle.equals(""))
+ {
+ // Take the title of the last file loaded
+ _nameField.setText(lastTitle);
+ }
+ }
+ if (_nameField.getText().equals(""))
+ {
+ // no name given in the field already, so try to overwrite it
+ String lastTitle = _app.getTrackInfo().getFileInfo().getLastFileTitle();
+ if (lastTitle != null && !lastTitle.equals(""))
+ {
+ _nameField.setText(lastTitle);
+ }
+ }
+ // Remember this source info so we don't use it again
+ _previousSourceInfo = currentSource;
+ }
/**
* Start the export process based on the input parameters
private void startExport()
{
// OK pressed, so check selections
- if (!_pointTypeSelector.getAnythingSelected()) {
+ if (!_pointTypeSelector.getAnythingSelected())
+ {
JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("dialog.save.notypesselected"),
I18nManager.getText("dialog.saveoptions.title"), JOptionPane.WARNING_MESSAGE);
return;
}
}
+
/**
* Select a GPX file to save to
* @param inParentFrame parent frame for file chooser dialog
return saveFile;
}
+
/**
* Run method for controlling separate thread for exporting
*/
public void run()
{
+ // Instantiate source file cachers in case we want to copy output
+ GpxCacherList gpxCachers = null;
+ if (_copySourceCheckbox.isSelected()) {
+ gpxCachers = new GpxCacherList(_trackInfo.getFileInfo());
+ }
OutputStreamWriter writer = null;
try
{
- // normal writing to file
- writer = new OutputStreamWriter(new FileOutputStream(_exportFile));
- final boolean[] saveFlags = {_pointTypeSelector.getTrackpointsSelected(), _pointTypeSelector.getWaypointsSelected(),
- _pointTypeSelector.getPhotopointsSelected(), _pointTypeSelector.getAudiopointsSelected(),
- _pointTypeSelector.getJustSelection(), _timestampsCheckbox.isSelected()};
+ // normal writing to file - firstly specify UTF8 encoding if requested
+ if (_forceUtf8Radio != null && _forceUtf8Radio.isSelected())
+ writer = new OutputStreamWriter(new FileOutputStream(_exportFile), "UTF-8");
+ else
+ writer = new OutputStreamWriter(new FileOutputStream(_exportFile));
+ // TODO: Move to new method
+ SettingsForExport settings = new SettingsForExport();
+ settings.setExportTrackPoints(_pointTypeSelector.getTrackpointsSelected());
+ settings.setExportWaypoints(_pointTypeSelector.getWaypointsSelected());
+ settings.setExportPhotoPoints(_pointTypeSelector.getPhotopointsSelected());
+ settings.setExportAudiopoints(_pointTypeSelector.getAudiopointsSelected());
+ settings.setExportJustSelection(_pointTypeSelector.getJustSelection());
+ settings.setExportTimestamps(_timestampsCheckbox.isSelected());
// write file
final int numPoints = exportData(writer, _trackInfo, _nameField.getText(),
- _descriptionField.getText(), saveFlags, _copySourceCheckbox.isSelected());
+ _descriptionField.getText(), settings, gpxCachers);
// close file
writer.close();
// Store directory in config for later
Config.setConfigString(Config.KEY_TRACK_DIR, _exportFile.getParentFile().getAbsolutePath());
+ // Add to recent file list
+ Config.getRecentFileList().addFile(new RecentFile(_exportFile, true));
// Show confirmation
+ UpdateMessageBroker.informSubscribers();
UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.save.ok1")
+ " " + numPoints + " " + I18nManager.getText("confirm.save.ok2")
+ " " + _exportFile.getAbsolutePath());
* @param inInfo track info object
* @param inName name of track (optional)
* @param inDesc description of track (optional)
- * @param inSaveFlags array of booleans to export tracks, waypoints, photos, audios, selection, timestamps
- * @param inUseCopy true to copy source if available
+ * @param inExportSettings flags for what to export and how
+ * @param inGpxCachers list of Gpx cachers containing input data
* @return number of points written
* @throws IOException if io errors occur on write
*/
public static int exportData(OutputStreamWriter inWriter, TrackInfo inInfo, String inName,
- String inDesc, boolean[] inSaveFlags, boolean inUseCopy) throws IOException
+ String inDesc, SettingsForExport inSettings, GpxCacherList inGpxCachers) throws IOException
{
- // Instantiate source file cachers in case we want to copy output
- GpxCacherList gpxCachers = null;
- if (inUseCopy) gpxCachers = new GpxCacherList(inInfo.getFileInfo());
// Write or copy headers
inWriter.write(getXmlHeaderString(inWriter));
- inWriter.write(getGpxHeaderString(gpxCachers));
- // Name field
- String trackName = "PruneTrack";
- if (inName != null && !inName.equals(""))
- {
- trackName = inName;
- inWriter.write("\t<name>");
- inWriter.write(trackName);
- inWriter.write("</name>\n");
- }
- // Description field
- inWriter.write("\t<desc>");
- inWriter.write((inDesc != null && !inDesc.equals(""))?inDesc:"Export from Prune");
- inWriter.write("</desc>\n");
+ final String gpxHeader = getGpxHeaderString(inGpxCachers);
+ final boolean isVersion1_1 = (gpxHeader.toUpperCase().indexOf("GPX/1/1") > 0);
+ inWriter.write(gpxHeader);
+ // name and description
+ String trackName = (inName != null && !inName.equals("")) ? XmlUtils.fixCdata(inName) : "GpsPruneTrack";
+ String desc = (inDesc != null && !inDesc.equals("")) ? XmlUtils.fixCdata(inDesc) : "Export from GpsPrune";
+ writeNameAndDescription(inWriter, trackName, desc, isVersion1_1);
- int i = 0;
DataPoint point = null;
- final boolean exportTrackpoints = inSaveFlags[0];
- final boolean exportWaypoints = inSaveFlags[1];
- final boolean exportPhotos = inSaveFlags[2];
- final boolean exportAudios = inSaveFlags[3];
- final boolean exportSelection = inSaveFlags[4];
- final boolean exportTimestamps = inSaveFlags[5];
+ final boolean exportWaypoints = inSettings.getExportWaypoints();
+ final boolean exportSelection = inSettings.getExportJustSelection();
+ final boolean exportTimestamps = inSettings.getExportTimestamps();
// Examine selection
int selStart = -1, selEnd = -1;
if (exportSelection) {
// Loop over waypoints
final int numPoints = inInfo.getTrack().getNumPoints();
int numSaved = 0;
- for (i=0; i<numPoints; i++)
+ for (int i=0; i<numPoints; i++)
{
point = inInfo.getTrack().getPoint(i);
- if (!exportSelection || (i>=selStart && i<=selEnd)) {
+ if (!exportSelection || (i>=selStart && i<=selEnd))
+ {
// Make a wpt element for each waypoint
- if (point.isWaypoint()) {
- if (exportWaypoints)
+ if (point.isWaypoint() && exportWaypoints)
+ {
+ String pointSource = (inGpxCachers == null? null : getPointSource(inGpxCachers, point));
+ if (pointSource != null)
{
- String pointSource = (inUseCopy?getPointSource(gpxCachers, point):null);
- if (pointSource != null) {
- inWriter.write(pointSource);
- inWriter.write('\n');
- }
- else {
- exportWaypoint(point, inWriter, exportTimestamps, exportPhotos, exportAudios);
+ // If timestamp checkbox is off, strip time
+ if (!exportTimestamps) {
+ pointSource = stripTime(pointSource);
}
- numSaved++;
+ inWriter.write('\t');
+ inWriter.write(pointSource);
+ inWriter.write('\n');
+ }
+ else {
+ exportWaypoint(point, inWriter, inSettings);
}
+ numSaved++;
}
}
}
// Export both route points and then track points
- if (exportTrackpoints || exportPhotos || exportAudios)
+ if (inSettings.getExportTrackPoints() || inSettings.getExportPhotoPoints() || inSettings.getExportAudioPoints())
{
// Output all route points (if any)
- numSaved += writeTrackPoints(inWriter, inInfo, exportSelection, exportTrackpoints, exportPhotos,
- exportAudios, exportTimestamps, true, gpxCachers, "<rtept", "\t<rte><number>1</number>\n",
+ numSaved += writeTrackPoints(inWriter, inInfo, inSettings,
+ true, inGpxCachers, "<rtept", "\t<rte><number>1</number>\n",
null, "\t</rte>\n");
// Output all track points, if any
- String trackStart = "\t<trk><name>" + trackName + "</name><number>1</number><trkseg>\n";
- numSaved += writeTrackPoints(inWriter, inInfo, exportSelection, exportTrackpoints, exportPhotos,
- exportAudios, exportTimestamps, false, gpxCachers, "<trkpt", trackStart,
- "\t</trkseg>\n\t<trkseg>\n", "\t</trkseg></trk>\n");
+ String trackStart = "\t<trk>\n\t\t<name>" + trackName + "</name>\n\t\t<number>1</number>\n\t\t<trkseg>\n";
+ numSaved += writeTrackPoints(inWriter, inInfo, inSettings,
+ false, inGpxCachers, "<trkpt", trackStart,
+ "\t</trkseg>\n\t<trkseg>\n", "\t\t</trkseg>\n\t</trk>\n");
}
inWriter.write("</gpx>\n");
return numSaved;
}
+
+ /**
+ * Write the name and description according to the GPX version number
+ * @param inWriter writer object
+ * @param inName name, or null if none supplied
+ * @param inDesc description, or null if none supplied
+ * @param inIsVersion1_1 true if gpx version 1.1, false for version 1.0
+ */
+ private static void writeNameAndDescription(OutputStreamWriter inWriter,
+ String inName, String inDesc, boolean inIsVersion1_1) throws IOException
+ {
+ // Position of name and description fields needs to be different for GPX1.0 and GPX1.1
+ if (inIsVersion1_1)
+ {
+ // GPX 1.1 has the name and description inside a metadata tag
+ inWriter.write("\t<metadata>\n");
+ }
+ if (inName != null && !inName.equals(""))
+ {
+ if (inIsVersion1_1) {inWriter.write('\t');}
+ inWriter.write("\t<name>");
+ inWriter.write(inName);
+ inWriter.write("</name>\n");
+ }
+ if (inIsVersion1_1) {inWriter.write('\t');}
+ inWriter.write("\t<desc>");
+ inWriter.write(inDesc);
+ inWriter.write("</desc>\n");
+ if (inIsVersion1_1)
+ {
+ inWriter.write("\t</metadata>\n");
+ }
+ }
+
/**
* Loop through the track outputting the relevant track points
* @param inWriter writer object for output
* @param inInfo track info object containing track
- * @param inExportSelection true to just output current selection
- * @param inExportTrackpoints true to output track points
- * @param inExportPhotos true to output photo points
- * @param inExportAudios true to output audio points
- * @param inExportTimestamps true to include timestamps in export
+ * @param inSettings export settings defining what should be exported
* @param inOnlyCopies true to only export if source can be copied
* @param inCachers list of GpxCachers
* @param inPointTag tag to match for each point
* @param inEndTag end tag to output
*/
private static int writeTrackPoints(OutputStreamWriter inWriter,
- TrackInfo inInfo, boolean inExportSelection, boolean inExportTrackpoints,
- boolean inExportPhotos, boolean inExportAudios, boolean exportTimestamps,
+ TrackInfo inInfo, SettingsForExport inSettings,
boolean inOnlyCopies, GpxCacherList inCachers, String inPointTag,
String inStartTag, String inSegmentTag, String inEndTag)
throws IOException
{
- // Note: far too many input parameters to this method but avoids duplication
+ // Note: Too many input parameters to this method but avoids duplication
// of output functionality for writing track points and route points
int numPoints = inInfo.getTrack().getNumPoints();
int selStart = inInfo.getSelection().getStart();
int selEnd = inInfo.getSelection().getEnd();
int numSaved = 0;
+ final boolean exportSelection = inSettings.getExportJustSelection();
+ final boolean exportTrackPoints = inSettings.getExportTrackPoints();
+ final boolean exportPhotos = inSettings.getExportPhotoPoints();
+ final boolean exportAudios = inSettings.getExportAudioPoints();
+ final boolean exportTimestamps = inSettings.getExportTimestamps();
// Loop over track points
for (int i=0; i<numPoints; i++)
{
DataPoint point = inInfo.getTrack().getPoint(i);
- if ((!inExportSelection || (i>=selStart && i<=selEnd)) && !point.isWaypoint())
+ if ((!exportSelection || (i>=selStart && i<=selEnd)) && !point.isWaypoint())
{
- if ((point.getPhoto()==null && inExportTrackpoints) || (point.getPhoto()!=null && inExportPhotos)
- || (point.getAudio()!=null && inExportAudios))
+ if ((point.getPhoto()==null && exportTrackPoints) || (point.getPhoto()!=null && exportPhotos)
+ || (point.getAudio()!=null && exportAudios))
{
// get the source from the point (if any)
String pointSource = getPointSource(inCachers, point);
// Clear point source if it's the wrong type of point (eg changed from waypoint or route point)
- if (pointSource != null && !pointSource.toLowerCase().startsWith(inPointTag)) {pointSource = null;}
+ if (pointSource != null && !pointSource.trim().toLowerCase().startsWith(inPointTag)) {
+ pointSource = null;
+ }
if (pointSource != null || !inOnlyCopies)
{
// restart track segment if necessary
inWriter.write(inSegmentTag);
}
if (numSaved == 0) {inWriter.write(inStartTag);}
- if (pointSource != null) {
+ if (pointSource != null)
+ {
+ // If timestamps checkbox is off, strip the time
+ if (!exportTimestamps) {
+ pointSource = stripTime(pointSource);
+ }
inWriter.write(pointSource);
inWriter.write('\n');
}
- else {
- if (!inOnlyCopies) {exportTrackpoint(point, inWriter, exportTimestamps, inExportPhotos, inExportAudios);}
+ else
+ {
+ if (!inOnlyCopies) {
+ exportTrackpoint(point, inWriter, inSettings);
+ }
}
numSaved++;
}
}
}
}
- if (numSaved > 0) {inWriter.write(inEndTag);}
+ if (numSaved > 0) {
+ inWriter.write(inEndTag);
+ }
return numSaved;
}
// Point has been modified - maybe it's possible to modify the source
source = replaceGpxTags(source, "lat=\"", "\"", inPoint.getLatitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
source = replaceGpxTags(source, "lon=\"", "\"", inPoint.getLongitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
- source = replaceGpxTags(source, "<ele>", "</ele>", inPoint.getAltitude().getStringValue(Altitude.Format.METRES));
- source = replaceGpxTags(source, "<time>", "</time>", inPoint.getTimestamp().getText(Timestamp.FORMAT_ISO_8601));
- if (inPoint.isWaypoint()) {source = replaceGpxTags(source, "<name>", "</name>", inPoint.getWaypointName());} // only for waypoints
+ source = replaceGpxTags(source, "<ele>", "</ele>", inPoint.getAltitude().getStringValue(UnitSetLibrary.UNITS_METRES));
+ source = replaceGpxTags(source, "<time>", "</time>", inPoint.getTimestamp().getText(Timestamp.Format.ISO8601, null));
+ if (inPoint.isWaypoint())
+ {
+ source = replaceGpxTags(source, "<name>", "</name>", XmlUtils.fixCdata(inPoint.getWaypointName()));
+ if (source != null)
+ {
+ source = source.replaceAll("<description>", "<desc>").replaceAll("</description>", "</desc>");
+ }
+ source = replaceGpxTags(source, "<desc>", "</desc>",
+ XmlUtils.fixCdata(inPoint.getFieldValue(Field.DESCRIPTION)));
+ }
// photo / audio links
if (source != null && (inPoint.hasMedia() || source.indexOf("</link>") > 0)) {
source = replaceMediaLinks(source, makeMediaLink(inPoint));
return null;
}
+
/**
* Replace the media tags in the given XML string
* @param inSource source XML for point
return null;
}
+
/**
* Get the header string for the xml document including encoding
* @param inWriter writer object
*/
private static String getXmlHeaderString(OutputStreamWriter inWriter)
{
- String encoding = inWriter.getEncoding();
- try {
- encoding = Charset.forName(encoding).name();
- }
- catch (Exception e) {} // ignore failure to find encoding
- return "<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n";
+ return "<?xml version=\"1.0\" encoding=\"" + XmlUtils.getEncoding(inWriter) + "\"?>\n";
}
+
/**
* Get the header string for the gpx tag
* @param inCachers cacher list to ask for headers, if available
if (inCachers != null) {gpxHeader = inCachers.getFirstHeader();}
if (gpxHeader == null || gpxHeader.length() < 5)
{
+ // TODO: Consider changing this to default to GPX 1.1
// Create default (1.0) header
gpxHeader = "<gpx version=\"1.0\" creator=\"" + GPX_CREATOR
+ "\"\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
return gpxHeader + "\n";
}
+
/**
* Export the specified waypoint into the file
* @param inPoint waypoint to export
* @param inWriter writer object
- * @param inTimestamps true to export timestamps too
- * @param inPhoto true to export link to photo
- * @param inAudio true to export link to audio
+ * @param inSettings export settings
* @throws IOException on write failure
*/
- private static void exportWaypoint(DataPoint inPoint, Writer inWriter, boolean inTimestamps,
- boolean inPhoto, boolean inAudio)
+ private static void exportWaypoint(DataPoint inPoint, Writer inWriter,
+ SettingsForExport inSettings)
throws IOException
{
inWriter.write("\t<wpt lat=\"");
inWriter.write(inPoint.getLongitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
inWriter.write("\">\n");
// altitude if available
- if (inPoint.hasAltitude())
+ if (inPoint.hasAltitude() || inSettings.getExportMissingAltitudesAsZero())
{
inWriter.write("\t\t<ele>");
- inWriter.write("" + inPoint.getAltitude().getStringValue(Altitude.Format.METRES));
+ inWriter.write(inPoint.hasAltitude() ? inPoint.getAltitude().getStringValue(UnitSetLibrary.UNITS_METRES) : "0");
inWriter.write("</ele>\n");
}
- // timestamp if available (point might have timestamp and then be turned into a waypoint)
- if (inPoint.hasTimestamp() && inTimestamps)
+ // timestamp if available (some waypoints have timestamps, some not)
+ if (inPoint.hasTimestamp() && inSettings.getExportTimestamps())
{
inWriter.write("\t\t<time>");
- inWriter.write(inPoint.getTimestamp().getText(Timestamp.FORMAT_ISO_8601));
+ inWriter.write(inPoint.getTimestamp().getText(Timestamp.Format.ISO8601, null));
inWriter.write("</time>\n");
}
// write waypoint name after elevation and time
inWriter.write("\t\t<name>");
- inWriter.write(inPoint.getWaypointName().trim());
+ inWriter.write(XmlUtils.fixCdata(inPoint.getWaypointName().trim()));
inWriter.write("</name>\n");
+ // description, if any
+ String desc = XmlUtils.fixCdata(inPoint.getFieldValue(Field.DESCRIPTION));
+ if (desc != null && !desc.equals(""))
+ {
+ inWriter.write("\t\t<desc>");
+ inWriter.write(desc);
+ inWriter.write("</desc>\n");
+ }
// Media links, if any
- if (inPhoto && inPoint.getPhoto() != null)
+ if (inSettings.getExportPhotoPoints() && inPoint.getPhoto() != null)
{
inWriter.write("\t\t");
inWriter.write(makeMediaLink(inPoint.getPhoto()));
inWriter.write('\n');
}
- if (inAudio && inPoint.getAudio() != null)
+ if (inSettings.getExportAudioPoints() && inPoint.getAudio() != null)
{
inWriter.write("\t\t");
inWriter.write(makeMediaLink(inPoint.getAudio()));
* Export the specified trackpoint into the file
* @param inPoint trackpoint to export
* @param inWriter writer object
- * @param inTimestamps true to export timestamps too
- * @param inExportPhoto true to export photo link
- * @param inExportAudio true to export audio link
+ * @param inSettings export settings
*/
- private static void exportTrackpoint(DataPoint inPoint, Writer inWriter, boolean inTimestamps,
- boolean inExportPhoto, boolean inExportAudio)
+ private static void exportTrackpoint(DataPoint inPoint, Writer inWriter, SettingsForExport inSettings)
throws IOException
{
- inWriter.write("\t\t<trkpt lat=\"");
+ inWriter.write("\t\t\t<trkpt lat=\"");
inWriter.write(inPoint.getLatitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
inWriter.write("\" lon=\"");
inWriter.write(inPoint.getLongitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
- inWriter.write("\">");
+ inWriter.write("\">\n");
// altitude
- if (inPoint.hasAltitude())
+ if (inPoint.hasAltitude() || inSettings.getExportMissingAltitudesAsZero())
{
- inWriter.write("<ele>");
- inWriter.write("" + inPoint.getAltitude().getStringValue(Altitude.Format.METRES));
- inWriter.write("</ele>");
+ inWriter.write("\t\t\t\t<ele>");
+ inWriter.write(inPoint.hasAltitude() ? inPoint.getAltitude().getStringValue(UnitSetLibrary.UNITS_METRES) : "0");
+ inWriter.write("</ele>\n");
}
+ // Maybe take timestamp from photo if the point hasn't got one
+ Timestamp pointTimestamp = getPointTimestamp(inPoint, inSettings);
// timestamp if available (and selected)
- if (inPoint.hasTimestamp() && inTimestamps)
+ if (pointTimestamp != null && inSettings.getExportTimestamps())
{
- inWriter.write("<time>");
- inWriter.write(inPoint.getTimestamp().getText(Timestamp.FORMAT_ISO_8601));
- inWriter.write("</time>");
+ inWriter.write("\t\t\t\t<time>");
+ inWriter.write(pointTimestamp.getText(Timestamp.Format.ISO8601, null));
+ inWriter.write("</time>\n");
}
// photo, audio
- if (inPoint.getPhoto() != null && inExportPhoto) {
+ if (inPoint.getPhoto() != null && inSettings.getExportPhotoPoints())
+ {
+ inWriter.write("\t\t\t\t");
inWriter.write(makeMediaLink(inPoint.getPhoto()));
+ inWriter.write("\n");
}
- if (inPoint.getAudio() != null && inExportAudio) {
+ if (inPoint.getAudio() != null && inSettings.getExportAudioPoints()) {
inWriter.write(makeMediaLink(inPoint.getAudio()));
}
- inWriter.write("</trkpt>\n");
+ inWriter.write("\t\t\t</trkpt>\n");
}
+
/**
* Make the xml for the media link(s)
* @param inPoint point to generate text for
private static String makeMediaLink(DataPoint inPoint)
{
Photo photo = inPoint.getPhoto();
- AudioFile audio = inPoint.getAudio();
+ AudioClip audio = inPoint.getAudio();
if (photo == null && audio == null) {
return null;
}
* @param inMedia media item, either photo or audio
* @return link for this media
*/
- private static String makeMediaLink(MediaFile inMedia)
+ private static String makeMediaLink(MediaObject inMedia)
+ {
+ if (inMedia.getFile() != null)
+ // file link
+ return "<link href=\"" + inMedia.getFile().getAbsolutePath() + "\"><text>" + inMedia.getName() + "</text></link>";
+ if (inMedia.getUrl() != null)
+ // url link
+ return "<link href=\"" + inMedia.getUrl() + "\"><text>" + inMedia.getName() + "</text></link>";
+ // No link available, must have been loaded from zip file - no link possible
+ return "";
+ }
+
+
+ /**
+ * Strip the time from a GPX point source string
+ * @param inPointSource point source to copy
+ * @return point source with timestamp removed
+ */
+ private static String stripTime(String inPointSource)
+ {
+ return inPointSource.replaceAll("[ \t]*<time>.*?</time>", "");
+ }
+
+ /**
+ * Get the timestamp from the point or its media
+ * @param inPoint point object
+ * @param inSettings export settings
+ * @return Timestamp object if available, or null
+ */
+ private static Timestamp getPointTimestamp(DataPoint inPoint, SettingsForExport inSettings)
{
- return "<link href=\"" + inMedia.getFile().getAbsolutePath() + "\"><text>" + inMedia.getFile().getName() + "</text></link>";
+ if (inPoint.hasTimestamp())
+ {
+ return inPoint.getTimestamp();
+ }
+ if (inPoint.getPhoto() != null && inSettings.getExportPhotoPoints())
+ {
+ if (inPoint.getPhoto().hasTimestamp())
+ {
+ return inPoint.getPhoto().getTimestamp();
+ }
+ }
+ if (inPoint.getAudio() != null && inSettings.getExportAudioPoints())
+ {
+ if (inPoint.getAudio().hasTimestamp())
+ {
+ return inPoint.getAudio().getTimestamp();
+ }
+ }
+ return null;
}
}