import tim.prune.data.SourceInfo;
import tim.prune.data.Track;
import tim.prune.data.TrackInfo;
+import tim.prune.function.SelectTracksFunction;
import tim.prune.function.browser.BrowserLauncher;
import tim.prune.function.browser.UrlGenerator;
import tim.prune.function.edit.FieldEditList;
import tim.prune.function.edit.PointEditor;
+import tim.prune.gui.SidebarController;
import tim.prune.gui.MenuManager;
import tim.prune.gui.UndoManager;
import tim.prune.gui.Viewport;
import tim.prune.load.FileLoader;
import tim.prune.load.JpegLoader;
+import tim.prune.load.TrackNameList;
import tim.prune.save.ExifSaver;
import tim.prune.save.FileSaver;
-import tim.prune.undo.UndoAddAltitudeOffset;
-import tim.prune.undo.UndoAddTimeOffset;
-import tim.prune.undo.UndoCompress;
-import tim.prune.undo.UndoConnectPhoto;
-import tim.prune.undo.UndoCreatePoint;
-import tim.prune.undo.UndoCutAndMove;
-import tim.prune.undo.UndoDeletePhoto;
-import tim.prune.undo.UndoDeletePoint;
-import tim.prune.undo.UndoDeleteRange;
-import tim.prune.undo.UndoDisconnectPhoto;
-import tim.prune.undo.UndoEditPoint;
-import tim.prune.undo.UndoException;
-import tim.prune.undo.UndoInsert;
-import tim.prune.undo.UndoLoad;
-import tim.prune.undo.UndoLoadPhotos;
-import tim.prune.undo.UndoMergeTrackSegments;
-import tim.prune.undo.UndoOperation;
-import tim.prune.undo.UndoReverseSection;
+import tim.prune.undo.*;
/**
private TrackInfo _trackInfo = null;
private int _lastSavePosition = 0;
private MenuManager _menuManager = null;
+ private SidebarController __sidebarController = null;
private FileLoader _fileLoader = null;
private JpegLoader _jpegLoader = null;
private FileSaver _fileSaver = null;
int selStart = _trackInfo.getSelection().getStart();
int selEnd = _trackInfo.getSelection().getEnd();
UndoAddTimeOffset undo = new UndoAddTimeOffset(selStart, selEnd, inTimeOffset);
- if (_trackInfo.getTrack().addTimeOffset(selStart, selEnd, inTimeOffset))
+ if (_trackInfo.getTrack().addTimeOffset(selStart, selEnd, inTimeOffset, false))
{
_undoStack.add(undo);
UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_EDITED);
if (success)
{
_undoStack.add(undo);
+ _trackInfo.getSelection().markInvalid();
UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_EDITED);
UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.addaltitudeoffset"));
}
}
/**
- * Receive loaded data and optionally merge with current Track
+ * Receive loaded data and start load
* @param inFieldArray array of fields
* @param inDataArray array of data
* @param inAltFormat altitude format
*/
public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray,
Altitude.Format inAltFormat, SourceInfo inSourceInfo)
+ {
+ informDataLoaded(inFieldArray, inDataArray, inAltFormat, inSourceInfo, null);
+ }
+
+ /**
+ * Receive loaded data and determine whether to filter on tracks or not
+ * @param inFieldArray array of fields
+ * @param inDataArray array of data
+ * @param inAltFormat altitude format
+ * @param inSourceInfo information about the source of the data
+ * @param inTrackNameList information about the track names
+ */
+ public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray,
+ Altitude.Format inAltFormat, SourceInfo inSourceInfo, TrackNameList inTrackNameList)
{
// Check whether loaded array can be properly parsed into a Track
Track loadedTrack = new Track();
JOptionPane.showMessageDialog(_frame, I18nManager.getText("dialog.open.contentsdoubled"),
I18nManager.getText("function.open"), JOptionPane.WARNING_MESSAGE);
}
+ // Look at TrackNameList, decide whether to filter or not
+ if (inTrackNameList != null && inTrackNameList.getNumTracks() > 1)
+ {
+ // Launch a dialog to let the user choose which tracks to load, then continue
+ new SelectTracksFunction(this, inFieldArray, inDataArray, inAltFormat, inSourceInfo,
+ inTrackNameList).begin();
+ }
+ else {
+ // go directly to load
+ informDataLoaded(loadedTrack, inSourceInfo);
+ }
+ }
+
+ /**
+ * Receive loaded data and optionally merge with current Track
+ * @param inLoadedTrack loaded track
+ * @param inSourceInfo information about the source of the data
+ */
+ public void informDataLoaded(Track inLoadedTrack, SourceInfo inSourceInfo)
+ {
// Decide whether to load or append
if (_track.getNumPoints() > 0)
{
if (answer == JOptionPane.YES_OPTION)
{
// append data to current Track
- _undoStack.add(new UndoLoad(_track.getNumPoints(), loadedTrack.getNumPoints()));
- _track.combine(loadedTrack);
+ _undoStack.add(new UndoLoad(_track.getNumPoints(), inLoadedTrack.getNumPoints()));
+ _track.combine(inLoadedTrack);
// set source information
- inSourceInfo.populatePointObjects(_track, loadedTrack.getNumPoints());
+ inSourceInfo.populatePointObjects(_track, inLoadedTrack.getNumPoints());
_trackInfo.getFileInfo().addSource(inSourceInfo);
}
else if (answer == JOptionPane.NO_OPTION)
{
// Don't append, replace data
PhotoList photos = null;
- if (_trackInfo.getPhotoList().hasCorrelatedPhotos())
- {
+ if (_trackInfo.getPhotoList().hasCorrelatedPhotos()) {
photos = _trackInfo.getPhotoList().cloneList();
}
- _undoStack.add(new UndoLoad(_trackInfo, inDataArray.length, photos));
+ _undoStack.add(new UndoLoad(_trackInfo, inLoadedTrack.getNumPoints(), photos));
_lastSavePosition = _undoStack.size();
_trackInfo.getSelection().clearAll();
- _track.load(loadedTrack);
+ _track.load(inLoadedTrack);
inSourceInfo.populatePointObjects(_track, _track.getNumPoints());
_trackInfo.getFileInfo().replaceSource(inSourceInfo);
- if (photos != null)
- {
+ if (photos != null) {
_trackInfo.getPhotoList().removeCorrelatedPhotos();
}
}
else
{
// Currently no data held, so transfer received data
- _undoStack.add(new UndoLoad(_trackInfo, inDataArray.length, null));
+ _undoStack.add(new UndoLoad(_trackInfo, inLoadedTrack.getNumPoints(), null));
_lastSavePosition = _undoStack.size();
_trackInfo.getSelection().clearAll();
- _track.load(loadedTrack);
+ _track.load(inLoadedTrack);
inSourceInfo.populatePointObjects(_track, _track.getNumPoints());
_trackInfo.getFileInfo().addSource(inSourceInfo);
}
// Save numbers so load can be undone
_undoStack.add(new UndoLoadPhotos(numPhotosAdded, numPointsAdded));
}
- if (numPhotosAdded == 1)
- {
+ if (numPhotosAdded == 1) {
UpdateMessageBroker.informSubscribers("" + numPhotosAdded + " " + I18nManager.getText("confirm.jpegload.single"));
}
- else
- {
+ else {
UpdateMessageBroker.informSubscribers("" + numPhotosAdded + " " + I18nManager.getText("confirm.jpegload.multi"));
}
// MAYBE: Improve message when photo(s) fail to load (eg already added)
{
return _viewport;
}
+
+ /**
+ * Set the controller for the full screen mode
+ * @param inController controller object
+ */
+ public void setSidebarController(SidebarController inController)
+ {
+ __sidebarController = inController;
+ }
+
+ /**
+ * Toggle sidebars on and off
+ */
+ public void toggleSidebars()
+ {
+ __sidebarController.toggle();
+ }
}
import tim.prune.function.distance.DistanceFunction;
import tim.prune.function.edit.PointNameEditor;
import tim.prune.function.gpsies.GetGpsiesFunction;
+import tim.prune.function.gpsies.UploadGpsiesFunction;
import tim.prune.function.srtm.LookupSrtmFunction;
import tim.prune.load.GpsLoader;
import tim.prune.save.GpsSaver;
import tim.prune.save.GpxExporter;
import tim.prune.save.KmlExporter;
import tim.prune.save.PovExporter;
+import tim.prune.save.SvgExporter;
/**
* Class to provide access to functions
public static GenericFunction FUNCTION_GPXEXPORT = null;
public static GenericFunction FUNCTION_KMLEXPORT = null;
public static PovExporter FUNCTION_POVEXPORT = null;
+ public static SvgExporter FUNCTION_SVGEXPORT = null;
public static GenericFunction FUNCTION_GPSLOAD = null;
public static GenericFunction FUNCTION_GPSSAVE = null;
public static GenericFunction FUNCTION_SAVECONFIG = null;
public static GenericFunction FUNCTION_ADD_TIME_OFFSET = null;
public static GenericFunction FUNCTION_ADD_ALTITUDE_OFFSET = null;
public static GenericFunction FUNCTION_CONVERT_NAMES_TO_TIMES = null;
+ public static GenericFunction FUNCTION_DELETE_FIELD_VALUES = null;
public static GenericFunction FUNCTION_PASTE_COORDINATES = null;
public static GenericFunction FUNCTION_FIND_WAYPOINT = null;
public static GenericFunction FUNCTION_DUPLICATE_POINT = null;
public static GenericFunction FUNCTION_DISTANCES = null;
public static GenericFunction FUNCTION_FULL_RANGE_DETAILS = null;
public static GenericFunction FUNCTION_GET_GPSIES = null;
+ public static GenericFunction FUNCTION_UPLOAD_GPSIES = null;
public static GenericFunction FUNCTION_SET_MAP_BG = null;
public static GenericFunction FUNCTION_SET_DISK_CACHE = null;
public static GenericFunction FUNCTION_SET_PATHS = null;
FUNCTION_GPXEXPORT = new GpxExporter(inApp);
FUNCTION_KMLEXPORT = new KmlExporter(inApp);
FUNCTION_POVEXPORT = new PovExporter(inApp);
+ FUNCTION_SVGEXPORT = new SvgExporter(inApp);
FUNCTION_GPSLOAD = new GpsLoader(inApp);
FUNCTION_GPSSAVE = new GpsSaver(inApp);
FUNCTION_SAVECONFIG = new SaveConfig(inApp);
FUNCTION_ADD_TIME_OFFSET = new AddTimeOffset(inApp);
FUNCTION_ADD_ALTITUDE_OFFSET = new AddAltitudeOffset(inApp);
FUNCTION_CONVERT_NAMES_TO_TIMES = new ConvertNamesToTimes(inApp);
+ FUNCTION_DELETE_FIELD_VALUES = new DeleteFieldValues(inApp);
FUNCTION_PASTE_COORDINATES = new PasteCoordinates(inApp);
FUNCTION_FIND_WAYPOINT = new FindWaypoint(inApp);
FUNCTION_DUPLICATE_POINT = new DuplicatePoint(inApp);
FUNCTION_DISTANCES = new DistanceFunction(inApp);
FUNCTION_FULL_RANGE_DETAILS = new FullRangeDetails(inApp);
FUNCTION_GET_GPSIES = new GetGpsiesFunction(inApp);
+ FUNCTION_UPLOAD_GPSIES = new UploadGpsiesFunction(inApp);
FUNCTION_SET_MAP_BG = new SetMapBgFunction(inApp);
FUNCTION_SET_DISK_CACHE = new DiskCacheConfig(inApp);
FUNCTION_SET_PATHS = new SetPathsFunction(inApp);
import java.awt.event.WindowAdapter;
import java.awt.BorderLayout;
+import java.awt.Component;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileNotFoundException;
import tim.prune.config.Config;
import tim.prune.config.ConfigException;
import tim.prune.gui.DetailsDisplay;
+import tim.prune.gui.SidebarController;
import tim.prune.gui.IconManager;
import tim.prune.gui.MenuManager;
import tim.prune.gui.SelectorDisplay;
public class GpsPruner
{
/** Version number of application, used in about screen and for version check */
- public static final String VERSION_NUMBER = "10";
+ public static final String VERSION_NUMBER = "11";
/** Build number, just used for about screen */
- public static final String BUILD_NUMBER = "189";
+ public static final String BUILD_NUMBER = "204";
/** Static reference to App object */
private static App APP = null;
UpdateMessageBroker.informSubscribers("Prune v" + VERSION_NUMBER);
// Arrange in the frame using split panes
- JSplitPane midPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, mapDisp, profileDisp);
- midPane.setResizeWeight(1.0); // allocate as much space as poss to map
- JSplitPane triplePane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, midPane, rightPanel);
- triplePane.setResizeWeight(1.0); // allocate as much space as poss to map
+ JSplitPane midSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, mapDisp, profileDisp);
+ midSplit.setResizeWeight(1.0); // allocate as much space as poss to map
+ JSplitPane rightSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, midSplit, rightPanel);
+ rightSplit.setResizeWeight(1.0); // allocate as much space as poss to map
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(toolbar, BorderLayout.NORTH);
- frame.getContentPane().add(new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel,
- triplePane), BorderLayout.CENTER);
+ JSplitPane leftSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightSplit);
+ frame.getContentPane().add(leftSplit, BorderLayout.CENTER);
frame.getContentPane().add(statusBar, BorderLayout.SOUTH);
// add closing listener
frame.setSize(650, 450);
frame.setVisible(true);
// Set position of map/profile splitter
- midPane.setDividerLocation(0.75);
+ midSplit.setDividerLocation(0.75);
+ // Make a full screen toggler
+ SidebarController fsc = new SidebarController(new Component[] {leftPanel, profileDisp, rightPanel},
+ new JSplitPane[] {leftSplit, midSplit, rightSplit});
+ APP.setSidebarController(fsc);
// Finally, give the files to load to the App
APP.loadDataFiles(inDataFiles);
}
*/
public static void informSubscribers(byte inChange)
{
+ // TODO: Launch separate thread so that whatever caused the inform can finish
for (int i=0; i<_subscribers.length; i++)
{
if (_subscribers[i] != null)
JPanel card2Top = new JPanel();
card2Top.setLayout(new BoxLayout(card2Top, BoxLayout.Y_AXIS));
_tipLabel = new JLabel(I18nManager.getText("dialog.correlate.options.tip"));
+ _tipLabel.setBorder(BorderFactory.createEmptyBorder(8, 6, 5, 6));
card2Top.add(_tipLabel);
- card2Top.add(new JLabel(I18nManager.getText("dialog.correlate.options.intro")));
+ JLabel introLabel = new JLabel(I18nManager.getText("dialog.correlate.options.intro"));
+ introLabel.setBorder(BorderFactory.createEmptyBorder(8, 6, 5, 6));
+ card2Top.add(introLabel);
// time offset section
JPanel offsetPanel = new JPanel();
offsetPanel.setBorder(BorderFactory.createTitledBorder(I18nManager.getText("dialog.correlate.options.offsetpanel")));
card2Top.add(previewButton);
card2.add(card2Top, BorderLayout.NORTH);
// preview
- _previewTable = new JTable();
+ _previewTable = new JTable(new PhotoPreviewTableModel());
JScrollPane previewScrollPane = new JScrollPane(_previewTable);
previewScrollPane.setPreferredSize(new Dimension(300, 100));
card2.add(previewScrollPane, BorderLayout.CENTER);
for (int i=0; i<numPhotos; i++)
{
Photo photo = inTrackInfo.getPhotoList().getPhoto(i);
- if (photo.getDataPoint() != null && photo.getDataPoint().hasTimestamp())
+ // For working out time differences, can't use photos which already had point information
+ if (photo.getDataPoint() != null && photo.getDataPoint().hasTimestamp()
+ && photo.getOriginalStatus() == Photo.Status.NOT_CONNECTED)
{
// Calculate time difference, add to table model
long timeDiff = photo.getTimestamp().getSecondsSince(photo.getDataPoint().getTimestamp());
PhotoPreviewTableRow row = new PhotoPreviewTableRow(pair);
// Don't try to correlate photos which don't have points either side
boolean correlatePhoto = pair.isValid();
+ // Don't select photos which already have a point
+ if (photo.getCurrentStatus() != Photo.Status.NOT_CONNECTED) {correlatePhoto = false;}
// Check time limits, distance limits
if (timeLimit != null && correlatePhoto) {
long numSecs = pair.getMinSeconds();
correlatePhoto = (angDistPhoto < angDistLimit);
}
// Don't select photos which are already correlated to the same point
- if (pair.getSecondsBefore() == 0L && pair.getPointBefore().getPhoto() != null
- && pair.getPointBefore().getPhoto().equals(photo)) {
+ if (pair.getSecondsBefore() == 0L && pair.getPointBefore().isDuplicate(photo.getDataPoint())) {
correlatePhoto = false;
}
row.setCorrelateFlag(correlatePhoto);
for (int i=0; i<numPoints; i++)
{
DataPoint point = inTrack.getPoint(i);
- Timestamp pointStamp = point.getTimestamp();
- if (pointStamp != null && pointStamp.isValid())
+ if (point.getPhoto() == null || point.getPhoto().getCurrentStatus() != Photo.Status.TAGGED)
{
- long numSeconds = pointStamp.getSecondsSince(photoStamp);
- pair.addPoint(point, numSeconds);
+ Timestamp pointStamp = point.getTimestamp();
+ if (pointStamp != null && pointStamp.isValid())
+ {
+ long numSeconds = pointStamp.getSecondsSince(photoStamp);
+ pair.addPoint(point, numSeconds);
+ }
}
}
return pair;
pair.getPointBefore().setPhoto(pair.getPhoto());
pair.getPhoto().setDataPoint(pair.getPointBefore());
}
- else if (pointPhoto.equals(pair.getPhoto()))
- {
+ else if (pointPhoto.equals(pair.getPhoto())) {
// photo is already connected, nothing to do
}
- else
- {
+ else {
// point is already connected to a different photo, so need to clone point
numPointsToCreate++;
}
*/
public int compareTo(TimeIndexPair inOther)
{
- return (int) (_time - inOther._time);
+ int compare = (int) (_time - inOther._time);
+ if (compare == 0) {compare = _index - inOther._index;}
+ return compare;
}
/**
/**
- * Constructor with int vaue
+ * Constructor with int value
* @param inValue int value of altitude
* @param inFormat format of altitude, either metres or feet
*/
*/
public boolean equals(Coordinate inOther)
{
- return (inOther != null && _cardinal == inOther._cardinal
- && _degrees == inOther._degrees
- && _minutes == inOther._minutes
- && _seconds == inOther._seconds
- && _fracs == inOther._fracs);
+ return (_asDouble == inOther._asDouble);
}
}
case FORMAT_DEG_WHOLE_MIN:
{
- answer = "" + PRINTABLE_CARDINALS[_cardinal] + threeDigitString(_degrees) + "\u00B0"
- + (int) Math.floor(_minutes + _seconds / 60.0 + _fracs / 60.0 / _fracDenom + 0.5) + "'";
+ int deg = _degrees;
+ int min = (int) Math.floor(_minutes + _seconds / 60.0 + _fracs / 60.0 / _fracDenom + 0.5);
+ if (min == 60) {
+ min = 0; deg++;
+ }
+ answer = "" + PRINTABLE_CARDINALS[_cardinal] + threeDigitString(deg) + "\u00B0" + min + "'";
break;
}
case FORMAT_DEG:
_fieldValues[fieldIndex] = inValue;
// Increment edit count on all field edits except segment
if (inField != Field.NEW_SEGMENT) {
- if (!inUndo) {
- _modifyCount++;
- }
- else {
- _modifyCount--;
- }
+ setModified(inUndo);
}
// Change Coordinate, Altitude, Name or Timestamp fields after edit
if (_altitude != null && _altitude.getFormat() != Altitude.Format.NO_FORMAT) {
}
}
+ /**
+ * Either increment or decrement the modify count, depending on whether it's an undo or not
+ * @param inUndo true for undo, false otherwise
+ */
+ public void setModified(boolean inUndo)
+ {
+ if (!inUndo) {
+ _modifyCount++;
+ }
+ else {
+ _modifyCount--;
+ }
+ }
+
/**
* @return field list for this point
*/
{
_dataPoint = inPoint;
// set status according to point
- if (inPoint == null)
- {
+ if (inPoint == null) {
setCurrentStatus(Status.NOT_CONNECTED);
}
- else
- {
+ else {
setCurrentStatus(Status.CONNECTED);
}
}
// Original data
private Track _track = null;
// Range information
- private AltitudeRange _altRange = null;
- private DoubleRange _latRange = null;
- private DoubleRange _lonRange = null;
private double _latMedian = 0.0;
private double _lonMedian = 0.0;
private int _minAltitude = 0;
- private int _maxAltitude = 0;
// Scaling information
private double _longFactor = 0.0;
+ private double _altFactor = 0.0;
// Scaled points
private double[] _xValues = null;
private double[] _yValues = null;
- private int[] _altValues = null;
+ private double[] _altValues = null;
+ // max values
private double _maxX = 0.0;
private double _maxY = 0.0;
+ private double _maxScaledAlt = 0.0;
// lat/long lines
private double[] _latLinesDegs = null;
private double[] _lonLinesDegs = null;
public PointScaler(Track inTrack)
{
_track = inTrack;
- _altRange = new AltitudeRange();
- _latRange = new DoubleRange();
- _lonRange = new DoubleRange();
}
public void scale()
{
// Clear data
- _altRange.clear();
- _latRange.clear();
- _lonRange.clear();
+ DoubleRange latRange = new DoubleRange();
+ DoubleRange lonRange = new DoubleRange();
+ DoubleRange altRange = new DoubleRange();
int numPoints = 0;
int p = 0;
DataPoint point = null;
point = _track.getPoint(p);
if (point != null)
{
- _latRange.addValue(point.getLatitude().getDouble());
- _lonRange.addValue(point.getLongitude().getDouble());
- _altRange.addValue(point.getAltitude());
+ latRange.addValue(point.getLatitude().getDouble());
+ lonRange.addValue(point.getLongitude().getDouble());
+ altRange.addValue(point.getAltitude().getValue(Altitude.Format.METRES));
}
}
// Find median latitude and calculate factor
- _latMedian = (_latRange.getMinimum() + _latRange.getMaximum()) / 2;
- _lonMedian = (_lonRange.getMinimum() + _lonRange.getMaximum()) / 2;
- _minAltitude = _altRange.getMinimum();
+ _latMedian = (latRange.getMinimum() + latRange.getMaximum()) / 2;
+ _lonMedian = (lonRange.getMinimum() + lonRange.getMaximum()) / 2;
+ _minAltitude = (int) altRange.getMinimum();
_longFactor = Math.cos(_latMedian / 180.0 * Math.PI); // quite rough
+ // Find altitude scale factor using distance
+ DataPoint p1 = new DataPoint(new Latitude(latRange.getMinimum(), Coordinate.FORMAT_DEG),
+ new Longitude(_lonMedian, Coordinate.FORMAT_DEG), null);
+ DataPoint p2 = new DataPoint(new Latitude(latRange.getMaximum(), Coordinate.FORMAT_DEG),
+ new Longitude(_lonMedian, Coordinate.FORMAT_DEG), null);
+ double horizDist = Distance.convertRadiansToDistance(
+ DataPoint.calculateRadiansBetween(p1, p2), Distance.Units.METRES);
+ _altFactor = 1.0 / horizDist;
// create new arrays for scaled values
if (_xValues == null || _xValues.length != numPoints)
{
_xValues = new double[numPoints];
_yValues = new double[numPoints];
- _altValues = new int[numPoints];
+ _altValues = new double[numPoints];
}
// Calculate scaled values
for (p=0; p<numPoints; p++)
_xValues[p] = getScaledLongitude(point.getLongitude().getDouble());
_yValues[p] = getScaledLatitude(point.getLatitude().getDouble());
_altValues[p] = getScaledAltitude(point.getAltitude());
+ if (_altValues[p] > _maxScaledAlt) {_maxScaledAlt = _altValues[p];}
}
}
// Calculate x and y range
- _maxX = getScaledLongitude(_lonRange.getMaximum());
- _maxY = getScaledLatitude(_latRange.getMaximum());
- _maxAltitude = _altRange.getMaximum() - _altRange.getMinimum();
+ _maxX = getScaledLongitude(lonRange.getMaximum());
+ _maxY = getScaledLatitude(latRange.getMaximum());
}
}
* @return maximum vert value
*/
public double getMaximumVert() { return _maxY; }
- /**
- * @return maximum alt value
- */
- public int getMaximumAlt() { return _maxAltitude; }
+
+ /** @return maximum scaled altitude value */
+ public double getMaxScaledAlt() { return _maxScaledAlt; }
/**
* Get the horizontal value for the specified point
* @param inIndex index of point, starting at 0
* @return scaled altitude value
*/
- public int getAltValue(int inIndex)
+ public double getAltValue(int inIndex)
{
return _altValues[inIndex];
}
* @param inLatitude latitude in degrees
* @return scaled latitude
*/
- public double getScaledLatitude(double inLatitude)
+ private double getScaledLatitude(double inLatitude)
{
return inLatitude - _latMedian;
}
* @param inLongitude longitude in degrees
* @return scaled longitude
*/
- public double getScaledLongitude(double inLongitude)
+ private double getScaledLongitude(double inLongitude)
{
return (inLongitude - _lonMedian) * _longFactor;
}
* @param inAltitude Altitude object
* @return scaled altitude
*/
- public int getScaledAltitude(Altitude inAltitude)
+ private double getScaledAltitude(Altitude inAltitude)
{
if (inAltitude == null) return -1;
- return inAltitude.getValue(_altRange.getFormat()) - _minAltitude;
+ return (inAltitude.getValue(Altitude.Format.METRES) - _minAltitude) * _altFactor;
}
/**
* @param inScaledLatitude scaled latitude
* @return latitude in degrees
*/
- public double getUnscaledLatitude(double inScaledLatitude)
+ private double getUnscaledLatitude(double inScaledLatitude)
{
return inScaledLatitude + _latMedian;
}
* @param inScaledLongitude scaled longitude
* @return longitude in degrees
*/
- public double getUnscaledLongitude(double inScaledLongitude)
+ private double getUnscaledLongitude(double inScaledLongitude)
{
return inScaledLongitude / _longFactor + _lonMedian;
}
import java.io.File;
/**
- * Class to hold the source of the point data,
- * including original file and file type, and
- * also file offsets for source copying
+ * Class to hold the source of the point data, including the original file
+ * and file type, and references to each of the point objects
*/
public class SourceInfo
{
/** Array of datapoints */
private DataPoint[] _points = null;
+ /** Number of points */
+ private int _numPoints = 0;
+ /** Array of point indices (if necessary) */
+ private int[] _pointIndices = null;
/**
*/
public int getNumPoints()
{
- return _points.length;
+ return _numPoints;
+ }
+
+ /**
+ * Set the indices of the points selected out of a loaded track
+ * @param inSelectedFlags array of booleans showing whether each point in the original data was loaded or not
+ */
+ public void setPointIndices(boolean[] inSelectedFlags)
+ {
+ _numPoints = inSelectedFlags.length;
+ _pointIndices = new int[_numPoints];
+ int p=0;
+ for (int i=0; i<_numPoints; i++) {
+ if (inSelectedFlags[i]) {_pointIndices[p++] = i;}
+ }
+ // Now the point indices array holds the index of each of the selected points
}
/**
*/
public void populatePointObjects(Track inTrack, int inNumPoints)
{
+ if (_numPoints == 0) {_numPoints = inNumPoints;}
if (inNumPoints > 0)
{
_points = new DataPoint[inNumPoints];
for (int i=0; i<_points.length && (idx < 0); i++) {
if (_points[i] == inPoint) {idx = i;}
}
- return idx;
+ if (_pointIndices == null) {return idx;} // All points loaded
+ return _pointIndices[idx]; // use point index mapping
}
}
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* Class to hold the timestamp of a track point
private static final DateFormat ISO_8601_FORMAT_NOZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
private static DateFormat[] ALL_DATE_FORMATS = null;
private static Calendar CALENDAR = null;
+ private static final Pattern GENERAL_TIMESTAMP_PATTERN
+ = Pattern.compile("(\\d{4})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})");
+ private static Matcher GENERAL_TIMESTAMP_MATCHER = null;
private static long SECS_SINCE_1970 = 0L;
private static long SECS_SINCE_GARTRIP = 0L;
private static long MSECS_SINCE_1970 = 0L;
try
{
long rawValue = Long.parseLong(inString.trim());
- // check for each format possibility and pick nearest
- long diff1 = Math.abs(SECS_SINCE_1970 - rawValue);
- long diff2 = Math.abs(MSECS_SINCE_1970 - rawValue);
- long diff3 = Math.abs(MSECS_SINCE_1990 - rawValue);
- long diff4 = Math.abs(SECS_SINCE_GARTRIP - rawValue);
-
- // Start off with "seconds since 1970" format
- long smallestDiff = diff1;
- _seconds = rawValue;
- // Now check millis since 1970
- if (diff2 < smallestDiff)
- {
- // milliseconds since 1970
- _seconds = rawValue / 1000L;
- smallestDiff = diff2;
- }
- // Now millis since 1990
- if (diff3 < smallestDiff)
- {
- // milliseconds since 1990
- _seconds = rawValue / 1000L + TWENTY_YEARS_IN_SECS;
- smallestDiff = diff3;
- }
- // Lastly, check gartrip offset
- if (diff4 < smallestDiff)
- {
- // seconds since gartrip offset
- _seconds = rawValue + GARTRIP_OFFSET;
- }
+ _seconds = getSeconds(rawValue);
_valid = true;
}
catch (NumberFormatException nfe)
}
catch (ParseException e) {}
}
+ if (!_valid && inString.length() == 19) {
+ GENERAL_TIMESTAMP_MATCHER = GENERAL_TIMESTAMP_PATTERN.matcher(inString);
+ if (GENERAL_TIMESTAMP_MATCHER.matches()) {
+ try {
+ _seconds = getSeconds(Integer.parseInt(GENERAL_TIMESTAMP_MATCHER.group(1)),
+ Integer.parseInt(GENERAL_TIMESTAMP_MATCHER.group(2)),
+ Integer.parseInt(GENERAL_TIMESTAMP_MATCHER.group(3)),
+ Integer.parseInt(GENERAL_TIMESTAMP_MATCHER.group(4)),
+ Integer.parseInt(GENERAL_TIMESTAMP_MATCHER.group(5)),
+ Integer.parseInt(GENERAL_TIMESTAMP_MATCHER.group(6)));
+ _valid = true;
+ }
+ catch (NumberFormatException nfe2) {} // parse shouldn't fail if matcher matched
+ }
+ }
}
}
}
*/
public Timestamp(int inYear, int inMonth, int inDay, int inHour, int inMinute, int inSecond)
{
- Calendar cal = Calendar.getInstance();
- cal.set(Calendar.YEAR, inYear);
- cal.set(Calendar.MONTH, inMonth - 1);
- cal.set(Calendar.DAY_OF_MONTH, inDay);
- cal.set(Calendar.HOUR_OF_DAY, inHour);
- cal.set(Calendar.MINUTE, inMinute);
- cal.set(Calendar.SECOND, inSecond);
- cal.set(Calendar.MILLISECOND, 0);
- _seconds = cal.getTimeInMillis() / 1000;
+ _seconds = getSeconds(inYear, inMonth, inDay, inHour, inMinute, inSecond);
_valid = true;
}
}
+ /**
+ * Convert the given timestamp parameters into a number of seconds
+ * @param inYear year
+ * @param inMonth month, beginning with 1
+ * @param inDay day of month, beginning with 1
+ * @param inHour hour of day, 0-24
+ * @param inMinute minute
+ * @param inSecond seconds
+ * @return number of seconds
+ */
+ private static long getSeconds(int inYear, int inMonth, int inDay, int inHour, int inMinute, int inSecond)
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.YEAR, inYear);
+ cal.set(Calendar.MONTH, inMonth - 1);
+ cal.set(Calendar.DAY_OF_MONTH, inDay);
+ cal.set(Calendar.HOUR_OF_DAY, inHour);
+ cal.set(Calendar.MINUTE, inMinute);
+ cal.set(Calendar.SECOND, inSecond);
+ cal.set(Calendar.MILLISECOND, 0);
+ return cal.getTimeInMillis() / 1000;
+ }
+
+ /**
+ * Convert the given long parameters into a number of seconds
+ * @param inRawValue long value representing seconds / milliseconds
+ * @return number of seconds
+ */
+ private static long getSeconds(long inRawValue)
+ {
+ // check for each format possibility and pick nearest
+ long diff1 = Math.abs(SECS_SINCE_1970 - inRawValue);
+ long diff2 = Math.abs(MSECS_SINCE_1970 - inRawValue);
+ long diff3 = Math.abs(MSECS_SINCE_1990 - inRawValue);
+ long diff4 = Math.abs(SECS_SINCE_GARTRIP - inRawValue);
+
+ // Start off with "seconds since 1970" format
+ long smallestDiff = diff1;
+ long seconds = inRawValue;
+ // Now check millis since 1970
+ if (diff2 < smallestDiff)
+ {
+ // milliseconds since 1970
+ seconds = inRawValue / 1000L;
+ smallestDiff = diff2;
+ }
+ // Now millis since 1990
+ if (diff3 < smallestDiff)
+ {
+ // milliseconds since 1990
+ seconds = inRawValue / 1000L + TWENTY_YEARS_IN_SECS;
+ smallestDiff = diff3;
+ }
+ // Lastly, check gartrip offset
+ if (diff4 < smallestDiff)
+ {
+ // seconds since gartrip offset
+ seconds = inRawValue + GARTRIP_OFFSET;
+ }
+ return seconds;
+ }
+
/**
* @return true if timestamp is valid
*/
*/
public String getText(int inFormat)
{
+ if (!_valid) {return "";}
if (inFormat == FORMAT_ISO_8601) {
return format(ISO_8601_FORMAT);
}
- if (_text == null)
- {
- if (_valid) {
- _text = format(DEFAULT_DATE_FORMAT);
- }
- else _text = "";
+ if (_text == null) {
+ _text = (_valid?format(DEFAULT_DATE_FORMAT):"");
}
return _text;
}
* @param inStart start of range
* @param inEnd end of range
* @param inOffset offset to add (-ve to subtract)
+ * @param inUndo true for undo operation
* @return true on success
*/
- public boolean addTimeOffset(int inStart, int inEnd, long inOffset)
+ public boolean addTimeOffset(int inStart, int inEnd, long inOffset, boolean inUndo)
{
// sanity check
if (inStart < 0 || inEnd < 0 || inStart >= inEnd || inEnd >= _numPoints) {
// This point has a timestamp so add the offset to it
foundTimestamp = true;
timestamp.addOffset(inOffset);
+ _dataPoints[i].setModified(inUndo);
}
}
return foundTimestamp;
// This point has an altitude so add the offset to it
foundAlt = true;
alt.addOffset(inOffset, inFormat, inDecimals);
+ _dataPoints[i].setModified(false);
}
}
// needs to be scaled again
private JDialog _dialog = null;
private JTabbedPane _tabs = null;
private JButton _okButton = null;
+ private JTextArea _aboutTextArea = null;
/** Labels for whether tools installed or not */
private JLabel[] _installedLabels = null;
descBuffer.append("<p>").append(I18nManager.getText("dialog.about.summarytext2")).append("</p>");
descBuffer.append("<p>").append(I18nManager.getText("dialog.about.summarytext3")).append("</p>");
descBuffer.append("<p>").append(I18nManager.getText("dialog.about.languages")).append(" : ")
- .append("deutsch, english, espa\u00F1ol, fran\u00E7ais, italiano, polski, \u4e2d\u6587; (chinese)<br>" +
- "schwiizerd\u00FC\u00FCtsch, \u65E5\u672C\u8A9E (japanese), t\u00FCrk\u00E7e, portugu\u00EAs, " +
- "bahasa indonesia, rom\u00E2n\u0103").append("</p>");
+ .append("deutsch, english, espa\u00F1ol, fran\u00E7ais, italiano, nederlands,<br>" +
+ " polski, portugu\u00EAs, \u4e2d\u6587 (chinese), \u65E5\u672C\u8A9E (japanese), schwiizerd\u00FC\u00FCtsch, t\u00FCrk\u00E7e, " +
+ "<br> \u010de\u0161tina, rom\u00E2n\u0103, afrikaans, bahasa indonesia, farsi").append("</p>");
descBuffer.append("<p>").append(I18nManager.getText("dialog.about.translatedby")).append("</p>");
JEditorPane descPane = new JEditorPane("text/html", descBuffer.toString());
descPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
new JLabel(" theYinYeti, Rothermographer, Sam, Rudolph, nazotoko,"),
1, 4);
addToGridBagPanel(creditsPanel, gridBag, constraints,
- new JLabel(" katpatuka, R\u00E9mi"),
+ new JLabel(" katpatuka, R\u00E9mi, Marcus, Ali, Javier, Jeroen, prot_d"),
1, 5);
addToGridBagPanel(creditsPanel, gridBag, constraints,
new JLabel(I18nManager.getText("dialog.about.credits.translations") + " : "),
// Read me
JPanel readmePanel = new JPanel();
readmePanel.setLayout(new BorderLayout());
- JTextArea textArea = new JTextArea(getReadmeText());
- textArea.setEditable(false);
- textArea.setLineWrap(true); textArea.setWrapStyleWord(true);
- JScrollPane scrollPane = new JScrollPane(textArea);
+ _aboutTextArea = new JTextArea(I18nManager.getText("details.photo.loading"));
+ // Set readme text in separate thread so that about screen pops up sooner
+ new Thread(new Runnable() {
+ public void run() {
+ _aboutTextArea.setText(getReadmeText());
+ }
+ }).start();
+ _aboutTextArea.setEditable(false);
+ _aboutTextArea.setLineWrap(true); _aboutTextArea.setWrapStyleWord(true);
+ JScrollPane scrollPane = new JScrollPane(_aboutTextArea);
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setPreferredSize(new Dimension(600, 130));
readmePanel.add(scrollPane, BorderLayout.CENTER);
--- /dev/null
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import tim.prune.App;
+import tim.prune.DataSubscriber;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
+import tim.prune.data.Field;
+import tim.prune.data.FieldList;
+import tim.prune.data.Track;
+import tim.prune.undo.UndoDeleteFieldValues;
+
+/**
+ * Class to provide the function to delete the values of a single field
+ * for all points in the current range
+ */
+public class DeleteFieldValues extends GenericFunction
+{
+ private JDialog _dialog = null;
+ private JList _fieldList = null;
+ private FieldListModel _listModel = null;
+ private JButton _okButton = null;
+
+
+ /**
+ * Constructor
+ * @param inApp application object for callback
+ */
+ public DeleteFieldValues(App inApp)
+ {
+ super(inApp);
+ }
+
+ /** Get the name key */
+ public String getNameKey() {
+ return "function.deletefieldvalues";
+ }
+
+ /**
+ * Begin the function
+ */
+ public void begin()
+ {
+ // Make dialog window
+ if (_dialog == null)
+ {
+ _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+ _dialog.setLocationRelativeTo(_parentFrame);
+ _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ _dialog.getContentPane().add(makeDialogComponents());
+ _dialog.pack();
+ }
+ // refresh the dialog
+ initDialog();
+ // Check whether any fields left
+ if (_listModel.getSize() < 1) {
+ _app.showErrorMessage(getNameKey(), "dialog.deletefieldvalues.nofields");
+ }
+ else {
+ _dialog.setVisible(true);
+ }
+ }
+
+
+ /**
+ * Create dialog components
+ * @return Panel containing all gui elements in dialog
+ */
+ private JPanel makeDialogComponents()
+ {
+ JPanel dialogPanel = new JPanel();
+ dialogPanel.setLayout(new BorderLayout());
+ dialogPanel.add(new JLabel(I18nManager.getText("dialog.deletefieldvalues.intro")), BorderLayout.NORTH);
+ // List in centre
+ _fieldList = new JList(new String[] {"First field", "Second field"});
+ // These entries will be replaced by the initDialog method
+ _fieldList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ _fieldList.addListSelectionListener(new ListSelectionListener() {
+ public void valueChanged(ListSelectionEvent e) {
+ _okButton.setEnabled(_fieldList.getSelectedIndex() >= 0);
+ }
+ });
+ dialogPanel.add(new JScrollPane(_fieldList), BorderLayout.CENTER);
+ // button panel at bottom
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ _okButton = new JButton(I18nManager.getText("button.ok"));
+ ActionListener okListener = new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ finish();
+ }
+ };
+ _okButton.addActionListener(okListener);
+ _okButton.setEnabled(false);
+ buttonPanel.add(_okButton);
+ JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _dialog.dispose();
+ }
+ });
+ buttonPanel.add(cancelButton);
+ dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+ dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+ return dialogPanel;
+ }
+
+ /**
+ * Initialise the dialog with the field list
+ */
+ private void initDialog()
+ {
+ _listModel = new FieldListModel();
+ int selStart = _app.getTrackInfo().getSelection().getStart();
+ int selEnd = _app.getTrackInfo().getSelection().getEnd();
+ // Loop over fields in track
+ final Track track = _app.getTrackInfo().getTrack();
+ FieldList fieldsInTrack = track.getFieldList();
+ for (int i=0; i<fieldsInTrack.getNumFields(); i++) {
+ Field field = fieldsInTrack.getField(i);
+ if (field != Field.LATITUDE && field != Field.LONGITUDE
+ && track.hasData(field, selStart, selEnd))
+ {
+ _listModel.addField(field);
+ }
+ }
+ _fieldList.setModel(_listModel);
+ _fieldList.clearSelection();
+ _okButton.setEnabled(false);
+ }
+
+ /**
+ * Finish the dialog when OK pressed
+ */
+ private void finish()
+ {
+ // Complete function
+ Field field = _listModel.getField(_fieldList.getSelectedIndex());
+ if (field != null)
+ {
+ UndoDeleteFieldValues undo = new UndoDeleteFieldValues(_app.getTrackInfo(), field);
+ final int selStart = _app.getTrackInfo().getSelection().getStart();
+ final int selEnd = _app.getTrackInfo().getSelection().getEnd();
+ final Track track = _app.getTrackInfo().getTrack();
+ for (int i=selStart; i<= selEnd; i++) {
+ track.getPoint(i).setFieldValue(field, null, false);
+ }
+ _dialog.dispose();
+ _app.getTrackInfo().getSelection().markInvalid();
+ UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_EDITED);
+ _app.completeFunction(undo, I18nManager.getText("confirm.deletefieldvalues"));
+ }
+ }
+}
--- /dev/null
+package tim.prune.function;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+
+/**
+ * Abstract superclass for pov and svg export functions
+ */
+public abstract class Export3dFunction extends GenericFunction
+{
+ /** altitude exaggeration factor */
+ protected double _altFactor = 50.0;
+
+ /**
+ * Required constructor
+ * @param inApp App object
+ */
+ public Export3dFunction(App inApp) {
+ super(inApp);
+ }
+
+ /**
+ * Set the coordinates for the camera
+ * @param inX X coordinate of camera
+ * @param inY Y coordinate of camera
+ * @param inZ Z coordinate of camera
+ */
+ public abstract void setCameraCoordinates(double inX, double inY, double inZ);
+
+ /**
+ * @param inFactor exaggeration factor
+ */
+ public void setAltitudeExaggeration(double inFactor)
+ {
+ if (inFactor >= 1.0) {
+ _altFactor = inFactor;
+ }
+ }
+}
--- /dev/null
+package tim.prune.function;
+
+import java.util.ArrayList;
+import javax.swing.AbstractListModel;
+import tim.prune.data.Field;
+
+/**
+ * Class to act as a list model for the delete field values function
+ */
+public class FieldListModel extends AbstractListModel
+{
+ /** ArrayList containing fields */
+ private ArrayList<Field> _fields = new ArrayList<Field>();
+
+
+ /**
+ * Add a field to the list
+ * @param inField field object to add
+ */
+ public void addField(Field inField)
+ {
+ if (inField != null) {_fields.add(inField);}
+ }
+
+ /**
+ * @return number of elements in list
+ */
+ public int getSize()
+ {
+ return _fields.size();
+ }
+
+ /**
+ * @param inRow row number
+ * @return String for specified row
+ */
+ public Object getElementAt(int inRow)
+ {
+ if (inRow < 0 || inRow >= getSize()) {return null;}
+ return _fields.get(inRow).getName();
+ }
+
+ /**
+ * @param inRow row number
+ * @return specified Field object
+ */
+ public Field getField(int inRow)
+ {
+ if (inRow < 0 || inRow >= getSize()) {return null;}
+ return _fields.get(inRow);
+ }
+}
--- /dev/null
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.data.Altitude;
+import tim.prune.data.Field;
+import tim.prune.data.SourceInfo;
+import tim.prune.data.Track;
+import tim.prune.load.TrackNameList;
+
+/**
+ * Function to allow the selection of which tracks to load from the file / stream
+ */
+public class SelectTracksFunction extends GenericFunction
+{
+ private Field[] _fieldArray = null;
+ private Object[][] _dataArray = null;
+ private Altitude.Format _altFormat = Altitude.Format.NO_FORMAT;
+ private SourceInfo _sourceInfo = null;
+ private TrackNameList _trackNameList = null;
+ private JDialog _dialog = null;
+ private JList _trackList = null;
+
+ /**
+ * Constructor
+ * @param inApp app object to use for load
+ * @param inFieldArray field array
+ * @param inDataArray data array
+ * @param inAltFormat altitude format
+ * @param inSourceInfo source information
+ * @param inTrackNameList track name list
+ */
+ public SelectTracksFunction(App inApp, Field[] inFieldArray, Object[][] inDataArray,
+ Altitude.Format inAltFormat, SourceInfo inSourceInfo, TrackNameList inTrackNameList)
+ {
+ super(inApp);
+ _fieldArray = inFieldArray;
+ _dataArray = inDataArray;
+ _altFormat = inAltFormat;
+ _sourceInfo = inSourceInfo;
+ _trackNameList = inTrackNameList;
+ }
+
+ /**
+ * Start the function
+ */
+ public void begin()
+ {
+ _dialog = new JDialog(_parentFrame, I18nManager.getText("function.open"));
+ _dialog.setLocationRelativeTo(_parentFrame);
+ _dialog.getContentPane().add(makeContents());
+ _dialog.pack();
+ _dialog.setVisible(true);
+ selectAll();
+ }
+
+ /**
+ * @return the contents of the window as a Component
+ */
+ private Component makeContents()
+ {
+ JPanel mainPanel = new JPanel();
+ mainPanel.setLayout(new BorderLayout());
+ mainPanel.add(new JLabel(I18nManager.getText("dialog.selecttracks.intro")), BorderLayout.NORTH);
+ // track list
+ final int numTracks = _trackNameList.getNumTracks();
+ String[] names = new String[numTracks];
+ for (int i=0; i<numTracks; i++)
+ {
+ String name = _trackNameList.getTrackName(i);
+ if (name == null || name.equals("")) {
+ name = I18nManager.getText("dialog.selecttracks.noname");
+ }
+ names[i] = name + " (" + _trackNameList.getNumPointsInTrack(i) + ")";
+ }
+ _trackList = new JList(names);
+ _trackList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ mainPanel.add(new JScrollPane(_trackList), BorderLayout.CENTER);
+ // select all button
+ JButton selectAllButton = new JButton(I18nManager.getText("button.selectall"));
+ selectAllButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ selectAll();
+ }
+ });
+ JPanel eastPanel = new JPanel();
+ eastPanel.add(selectAllButton);
+ mainPanel.add(eastPanel, BorderLayout.EAST);
+
+ // button panel at bottom
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ JButton okButton = new JButton(I18nManager.getText("button.ok"));
+ okButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ finish();
+ }
+ });
+ buttonPanel.add(okButton);
+ JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _dialog.dispose();
+ _app.informNoDataLoaded();
+ }
+ });
+ buttonPanel.add(cancelButton);
+ mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+ mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+ return mainPanel;
+ }
+
+ /** @return name key */
+ public String getNameKey() {
+ return "dialog.selecttracks";
+ }
+
+ /**
+ * Select all the tracks in the list
+ */
+ private void selectAll()
+ {
+ _trackList.setSelectionInterval(0, _trackNameList.getNumTracks()-1);
+ }
+
+ /**
+ * OK pressed, so finish the load
+ */
+ private void finish()
+ {
+ _dialog.dispose();
+ // Load track as it is, which is expensive but makes interrogating waypoints easier
+ Track loadedTrack = new Track();
+ loadedTrack.load(_fieldArray, _dataArray, _altFormat);
+ int[] tracks = _trackList.getSelectedIndices();
+ // Check if all tracks are selected, then don't have to filter at all
+ if (tracks.length == _trackNameList.getNumTracks()) {
+ _app.informDataLoaded(loadedTrack, _sourceInfo);
+ }
+ else
+ {
+ // build array of which tracks have been selected
+ boolean[] selectedTracks = new boolean[_trackNameList.getNumTracks()];
+ for (int i=0; i<tracks.length; i++) {
+ selectedTracks[tracks[i]] = true;
+ }
+ // Loop over all points, counting points which survive filter and making flag array
+ int numPointsSelected = 0;
+ int currentTrack = -1;
+ final int totalPoints = loadedTrack.getNumPoints();
+ boolean[] selectedPoints = new boolean[totalPoints];
+ for (int i=0; i<totalPoints; i++)
+ {
+ final int startOfNextTrack = _trackNameList.getStartIndex(currentTrack+1);
+ if (i == startOfNextTrack) {currentTrack++;}
+ if (currentTrack < 0 || selectedTracks[currentTrack] || loadedTrack.getPoint(i).isWaypoint()) {
+ selectedPoints[i] = true;
+ numPointsSelected++;
+ }
+ }
+ // If none of the points have been selected, then load nothing
+ if (numPointsSelected <= 0) {
+ _app.informNoDataLoaded();
+ }
+ else {
+ // Create new data array of required length
+ Object[][] newDataArray = new String[numPointsSelected][];
+ // Loop over all points again, copying surviving points
+ int currPoint = 0;
+ for (int i=0; i<totalPoints; i++)
+ {
+ if (selectedPoints[i]) {
+ newDataArray[currPoint] = _dataArray[i];
+ currPoint++;
+ }
+ }
+ // Construct Track and call informDataLoaded
+ Track filteredTrack = new Track();
+ filteredTrack.load(_fieldArray, newDataArray, _altFormat);
+ // Tell source info object which points were selected (pass selectedPoints array)
+ _sourceInfo.setPointIndices(selectedPoints);
+ _app.informDataLoaded(filteredTrack, _sourceInfo);
+ }
+ }
+ }
+}
private int _startIndex = 0;
/** Names of languages for display in dropdown (not translated) */
- private static final String[] LANGUAGE_NAMES = {"deutsch", "english", "espa\u00F1ol", "fran\u00E7ais",
- "italiano", "polski", "\u4e2d\u6587 (chinese)", "\u65E5\u672C\u8A9E (japanese)",
- "schwiizerd\u00FC\u00FCtsch", "t\u00FCrk\u00E7e", "portugu\u00EAs",
- "afrikaans", "bahasa indonesia", "rom\u00E2n\u0103"
+ private static final String[] LANGUAGE_NAMES = {"\u010de\u0161tina", "deutsch", "english", "espa\u00F1ol",
+ "fran\u00E7ais", "italiano", "nederlands", "polski", "portugu\u00EAs", "\u4e2d\u6587 (chinese)",
+ "\u65E5\u672C\u8A9E (japanese)", "schwiizerd\u00FC\u00FCtsch", "t\u00FCrk\u00E7e", "rom\u00E2n\u0103",
+ "afrikaans", "bahasa indonesia", "farsi"
};
/** Associated language codes (must be in same order as names!) */
- private static final String[] LANGUAGE_CODES = {"de", "en", "es", "fr", "it", "pl", "zh", "ja",
- "de_ch", "tr", "pt", "af", "in", "ro"
+ private static final String[] LANGUAGE_CODES = {"cz", "de", "en", "es", "fr", "it", "nl", "pl", "pt", "zh",
+ "ja", "de_ch", "tr", "ro", "af", "in", "fa"
};
introLabel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
mainPanel.add(introLabel, BorderLayout.NORTH);
- JEditorPane kp = new JEditorPane("text/html", I18nManager.getText("dialog.keys.keylist"));
+ String keyText = I18nManager.getText("dialog.keys.keylist");
+ // If running on Mac, do global replace on "Ctrl" (or "Strg") for "Command" (or lang-specific text)
+ if (System.getProperty("mrj.version") != null) {
+ String mod = I18nManager.getText("dialog.keys.normalmodifier");
+ String macmod = I18nManager.getText("dialog.keys.macmodifier");
+ if (mod != null && macmod != null && mod.length() > 1 && macmod.length() > 1) {
+ keyText = keyText.replaceAll(mod, macmod);
+ }
+ }
+ JEditorPane kp = new JEditorPane("text/html", keyText);
kp.setEditable(false);
kp.setOpaque(false);
kp.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
package tim.prune.function.browser;
+import java.net.URI;
import javax.swing.JOptionPane;
/**
* Class to launch a browser window to show an external map
+ * Some code and ideas taken from BareBonesBrowserLaunch at centerkey.com
*/
public abstract class BrowserLauncher
{
*/
private static void init()
{
+ _browserCommand = null;
// First check if "which" command is available
if (commandExists("which"))
{
// which exists, so try browsers in turn
- String[] browsersToTry = {"firefox", "iceweasel", "konqueror", "opera", "epiphany", "mozilla", "safari", "lynx"};
+ String[] browsersToTry = {"firefox", "iceweasel", "konqueror", "opera", "epiphany",
+ "mozilla", "safari", "google-chrome", "lynx"};
String browserFound = null;
for (int i=0; i<browsersToTry.length && browserFound == null; i++)
{
_browserCommand = new String[] {browserFound, null};
}
}
- else
+
+ if (_browserCommand == null)
{
- // no which command, so check if os name looks like a mac
+ // no which command (or none of the browsers found), so check if os name looks like a mac
String osName = System.getProperty("os.name").toLowerCase();
- boolean isMacOsx = osName.indexOf("mac os") >= 0
- || osName.indexOf("darwin") >= 0;
+ boolean isMacOsx = osName.indexOf("mac os") >= 0 || osName.indexOf("darwin") >= 0;
if (isMacOsx) {
// for Mac Osx just use "open" command
_browserCommand = new String[] {"open", null};
*/
public static void launchBrowser(String inUrl)
{
- if (!_initialised) {init();}
- if (_browserCommand == null) {
- JOptionPane.showMessageDialog(null, "Cannot show url: " + inUrl);
+ // First choice is to try the Desktop library from java 6, if available
+ try {
+ Class<?> d = Class.forName("java.awt.Desktop");
+ d.getDeclaredMethod("browse", new Class[] {URI.class}).invoke(
+ d.getDeclaredMethod("getDesktop").invoke(null), new Object[] {URI.create(inUrl)});
+ //above code mimics: Desktop.getDesktop().browse(URI.create(inUrl));
}
- else
+ catch (Exception ignore)
{
- try
- {
- // enclose url in quotes if necessary
- String url = inUrl;
- if (_urlNeedsQuotes) {url = "\"" + url + "\"";}
- // Fill in url in last element of coommand array
- _browserCommand[_browserCommand.length - 1] = url;
- // execute command to launch browser
- Runtime.getRuntime().exec(_browserCommand);
+ // The Desktop call failed, need to try backup methods
+ if (!_initialised) {init();}
+ if (_browserCommand == null) {
+ JOptionPane.showMessageDialog(null, "Cannot show url: " + inUrl);
}
- catch (Exception e) {
- JOptionPane.showMessageDialog(null, "Failed to show url: " + inUrl);
+ else
+ {
+ try
+ {
+ // enclose url in quotes if necessary
+ String url = inUrl;
+ if (_urlNeedsQuotes) {url = "\"" + url + "\"";}
+ // Fill in url in last element of command array
+ _browserCommand[_browserCommand.length - 1] = url;
+ // execute command to launch browser
+ Runtime.getRuntime().exec(_browserCommand);
+ }
+ catch (Exception e) {
+ JOptionPane.showMessageDialog(null, "Failed to show url: " + inUrl);
+ }
}
}
}
for (int j=i-NUM_POINTS_TO_BACKTRACK; j<i; j++)
{
if (j<0) {j=0;} // only look at last few points, but not before 0
- if (currPoint.isDuplicate(_track.getPoint(j)))
+ if (!inFlags[j] && currPoint.isDuplicate(_track.getPoint(j)))
{
inFlags[i] = true;
numDeleted++;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
});
_table.setPreferredScrollableViewportSize(new Dimension(_table.getWidth(), _table.getRowHeight() * 6));
panel.add(new JScrollPane(_table), BorderLayout.CENTER);
- panel.add(new JLabel(I18nManager.getText("dialog.pointedit.text")), BorderLayout.NORTH);
+ // Label at top
+ JLabel topLabel = new JLabel(I18nManager.getText("dialog.pointedit.text"));
+ topLabel.setBorder(BorderFactory.createEmptyBorder(8, 6, 3, 6));
+ panel.add(topLabel, BorderLayout.NORTH);
_editButton = new JButton(I18nManager.getText("button.edit"));
_editButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
package tim.prune.function.gpsies;\r
\r
+import java.net.HttpURLConnection;\r
import java.net.URLConnection;\r
import java.net.URL;\r
import java.io.IOException;\r
-import java.io.File;\r
import java.io.InputStream;\r
import java.util.Random;\r
import java.io.OutputStream;\r
-import java.io.FileInputStream;\r
\r
/**\r
- * Taken from Client HTTP Request class\r
+ * Taken from the Client HTTP Request class at com.myjavatools.web\r
+ * and subsequently simplified and modified\r
* @author Vlad Patryshev\r
*/\r
public class FormPoster\r
{\r
- private URLConnection _connection;\r
+ private URLConnection _connection = null;\r
private OutputStream _os = null;\r
- private static final Random random = new Random();\r
- private static final String boundary = "---------------------------"\r
+ private static final Random RANDOM_GEN = new Random();\r
+ private static final String BOUNDARY = "---------------------------"\r
+ randomString() + randomString() + randomString();\r
\r
\r
+ /** Connect (if not already connected) */\r
protected void connect() throws IOException {\r
if (_os == null) _os = _connection.getOutputStream();\r
}\r
\r
+ /** Write a single character */\r
protected void write(char c) throws IOException {\r
connect();\r
_os.write(c);\r
}\r
\r
+ /** Write a string */\r
protected void write(String s) throws IOException {\r
connect();\r
_os.write(s.getBytes());\r
}\r
\r
+ /** Write a -r-n newline sequence */\r
protected void newline() throws IOException {\r
- connect();\r
write("\r\n");\r
}\r
\r
+ /** Write a string followed by a newline */\r
protected void writeln(String s) throws IOException {\r
- connect();\r
write(s);\r
newline();\r
}\r
\r
- protected static String randomString() {\r
- return Long.toString(random.nextLong(), 36);\r
+ /** Generate a random alphanumeric string */\r
+ private static String randomString() {\r
+ return Long.toString(RANDOM_GEN.nextLong(), 36);\r
}\r
\r
+ /** Write a boundary marker */\r
private void boundary() throws IOException {\r
write("--");\r
- write(boundary);\r
+ write(BOUNDARY);\r
}\r
\r
- /**\r
- * Creates a new multipart POST HTTP request on a freshly opened URLConnection\r
- *\r
- * @param inConnection an already open URL connection\r
- * @throws IOException\r
- */\r
- public FormPoster(URLConnection inConnection) throws IOException\r
- {\r
- _connection = inConnection;\r
- _connection.setDoOutput(true);\r
- _connection.setRequestProperty("Content-Type",\r
- "multipart/form-data; boundary=" + boundary);\r
- }\r
\r
/**\r
* Creates a new multipart POST HTTP request for a specified URL\r
- *\r
* @param url the URL to send request to\r
* @throws IOException\r
*/\r
- public FormPoster(URL url) throws IOException {\r
- this(url.openConnection());\r
- }\r
-\r
- /**\r
- * Creates a new multipart POST HTTP request for a specified URL string\r
- *\r
- * @param urlString the string representation of the URL to send request to\r
- * @throws IOException\r
- */\r
- public FormPoster(String urlString) throws IOException {\r
- this(new URL(urlString));\r
+ public FormPoster(URL inUrl) throws IOException\r
+ {\r
+ _connection = inUrl.openConnection();\r
+ _connection.setDoOutput(true);\r
+ _connection.setRequestProperty("Content-Type",\r
+ "multipart/form-data; boundary=" + BOUNDARY);\r
}\r
\r
-\r
- private void writeName(String name) throws IOException\r
+ /** Write a header with the given name */\r
+ private void writeName(String inName) throws IOException\r
{\r
newline();\r
write("Content-Disposition: form-data; name=\"");\r
- write(name);\r
+ write(inName);\r
write('"');\r
}\r
\r
* @param value parameter value\r
* @throws IOException\r
*/\r
- public void setParameter(String name, String value) throws IOException\r
+ public void setParameter(String inName, String inValue) throws IOException\r
{\r
boundary();\r
- writeName(name);\r
+ writeName(inName);\r
newline(); newline();\r
- writeln(value);\r
+ writeln(inValue);\r
}\r
\r
+ /** Pipe the contents of the input stream to the output stream */\r
private static void pipe(InputStream in, OutputStream out) throws IOException\r
{\r
byte[] buf = new byte[500000];\r
int nread;\r
- int total = 0;\r
synchronized (in) {\r
while((nread = in.read(buf, 0, buf.length)) >= 0) {\r
out.write(buf, 0, nread);\r
- total += nread;\r
}\r
}\r
out.flush();\r
\r
/**\r
* adds a file parameter to the request\r
- * @param name parameter name\r
- * @param filename the name of the file\r
- * @param is input stream to read the contents of the file from\r
+ * @param inName parameter name\r
+ * @param inFilename the name of the file\r
+ * @param inStream input stream to read the contents of the file from\r
* @throws IOException\r
*/\r
- public void setParameter(String name, String filename, InputStream is) throws IOException\r
+ public void setParameter(String inName, String inFilename, InputStream inStream) throws IOException\r
{\r
boundary();\r
- writeName(name);\r
+ writeName(inName);\r
write("; filename=\"");\r
- write(filename);\r
+ write(inFilename);\r
write('"');\r
newline();\r
write("Content-Type: ");\r
- String type = URLConnection.guessContentTypeFromName(filename);\r
- if (type == null) type = "application/octet-stream";\r
+ String type = URLConnection.guessContentTypeFromName(inFilename);\r
+ if (type == null) {type = "application/octet-stream";}\r
writeln(type);\r
newline();\r
- pipe(is, _os);\r
+ pipe(inStream, _os);\r
newline();\r
}\r
\r
- /**\r
- * adds a file parameter to the request\r
- * @param name parameter name\r
- * @param file the file to upload\r
- * @throws IOException\r
- */\r
- public void setParameter(String name, File file) throws IOException {\r
- setParameter(name, file.getPath(), new FileInputStream(file));\r
- }\r
-\r
- /**\r
- * adds a parameter to the request; if the parameter is a File, the file is uploaded,\r
- * otherwise the string value of the parameter is passed in the request\r
- * @param name parameter name\r
- * @param object parameter value, a File or anything else that can be stringified\r
- * @throws IOException\r
- */\r
- public void setParameter(String name, Object object) throws IOException\r
- {\r
- if (object instanceof File) {\r
- setParameter(name, (File) object);\r
- } else {\r
- setParameter(name, object.toString());\r
- }\r
- }\r
-\r
/**\r
* posts the requests to the server\r
* @return input stream with the server response\r
* @throws IOException\r
*/\r
- public InputStream post() throws IOException {\r
+ public InputStream post() throws IOException\r
+ {\r
boundary();\r
writeln("--");\r
_os.close();\r
}\r
\r
/**\r
- * post the POST request to the server, with the specified parameter\r
- * @param name parameter name\r
- * @param value parameter value\r
- * @return input stream with the server response\r
- * @throws IOException\r
- * @see setParameter\r
- */\r
- public InputStream post(String name, Object value) throws IOException {\r
- setParameter(name, value);\r
- return post();\r
- }\r
-\r
- /**\r
- * post the POST request to the server, with the specified parameters\r
- * @param name1 first parameter name\r
- * @param value1 first parameter value\r
- * @param name2 second parameter name\r
- * @param value2 second parameter value\r
- * @return input stream with the server response\r
- * @throws IOException\r
- * @see setParameter\r
- */\r
- public InputStream post(String name1, Object value1, String name2, Object value2) throws IOException {\r
- setParameter(name1, value1);\r
- return post(name2, value2);\r
- }\r
-\r
- /**\r
- * post the POST request to the server, with the specified parameters\r
- * @param name1 first parameter name\r
- * @param value1 first parameter value\r
- * @param name2 second parameter name\r
- * @param value2 second parameter value\r
- * @param name3 third parameter name\r
- * @param value3 third parameter value\r
- * @return input stream with the server response\r
- * @throws IOException\r
- * @see setParameter\r
- */\r
- public InputStream post(String name1, Object value1, String name2, Object value2,\r
- String name3, Object value3) throws IOException\r
- {\r
- setParameter(name1, value1);\r
- return post(name2, value2, name3, value3);\r
- }\r
-\r
- /**\r
- * post the POST request to the server, with the specified parameters\r
- * @param name1 first parameter name\r
- * @param value1 first parameter value\r
- * @param name2 second parameter name\r
- * @param value2 second parameter value\r
- * @param name3 third parameter name\r
- * @param value3 third parameter value\r
- * @param name4 fourth parameter name\r
- * @param value4 fourth parameter value\r
- * @return input stream with the server response\r
- * @throws IOException\r
- * @see setParameter\r
- */\r
- public InputStream post(String name1, Object value1, String name2, Object value2,\r
- String name3, Object value3, String name4, Object value4) throws IOException\r
- {\r
- setParameter(name1, value1);\r
- return post(name2, value2, name3, value3, name4, value4);\r
- }\r
-\r
- /**\r
- * post the POST request specified URL, with the specified parameter\r
- * @param name parameter name\r
- * @param value parameter value\r
- * @return input stream with the server response\r
- * @throws IOException\r
- * @see setParameter\r
- */\r
- public static InputStream post(URL url, String name1, Object value1) throws IOException {\r
- return new FormPoster(url).post(name1, value1);\r
- }\r
-\r
- /**\r
- * post the POST request to specified URL, with the specified parameters\r
- * @param name1 first parameter name\r
- * @param value1 first parameter value\r
- * @param name2 second parameter name\r
- * @param value2 second parameter value\r
- * @return input stream with the server response\r
- * @throws IOException\r
- * @see setParameter\r
- */\r
- public static InputStream post(URL url, String name1, Object value1,\r
- String name2, Object value2) throws IOException\r
- {\r
- return new FormPoster(url).post(name1, value1, name2, value2);\r
- }\r
-\r
- /**\r
- * post the POST request to specified URL, with the specified parameters\r
- * @param name1 first parameter name\r
- * @param value1 first parameter value\r
- * @param name2 second parameter name\r
- * @param value2 second parameter value\r
- * @param name3 third parameter name\r
- * @param value3 third parameter value\r
- * @return input stream with the server response\r
- * @throws IOException\r
- * @see setParameter\r
+ * @return the HTTP response code, 200 for success or -1 if not available\r
*/\r
- public static InputStream post(URL url, String name1, Object value1, String name2, Object value2,\r
- String name3, Object value3) throws IOException\r
+ public int getResponseCode() throws IOException\r
{\r
- return new FormPoster(url).post(name1, value1, name2, value2, name3, value3);\r
- }\r
-\r
- /**\r
- * post the POST request to specified URL, with the specified parameters\r
- * @param name1 first parameter name\r
- * @param value1 first parameter value\r
- * @param name2 second parameter name\r
- * @param value2 second parameter value\r
- * @param name3 third parameter name\r
- * @param value3 third parameter value\r
- * @param name4 fourth parameter name\r
- * @param value4 fourth parameter value\r
- * @return input stream with the server response\r
- * @throws IOException\r
- * @see setParameter\r
- */\r
- public static InputStream post(URL url, String name1, Object value1, String name2, Object value2,\r
- String name3, Object value3, String name4, Object value4) throws IOException\r
- {\r
- return new FormPoster(url).post(name1, value1, name2, value2, name3, value3, name4, value4);\r
+ if (_connection != null && _connection instanceof HttpURLConnection) {\r
+ return ((HttpURLConnection) _connection).getResponseCode();\r
+ }\r
+ return -1;\r
}\r
}\r
--- /dev/null
+package tim.prune.function.gpsies;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+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.JPasswordField;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.border.EtchedBorder;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.function.browser.BrowserLauncher;
+import tim.prune.gui.GuiGridLayout;
+import tim.prune.save.GpxExporter;
+
+/**
+ * Function to upload track information up to Gpsies.com
+ */
+public class UploadGpsiesFunction extends GenericFunction
+{
+ /** Dialog object */
+ private JDialog _dialog = null;
+ /** Edit box for user name */
+ private JTextField _usernameField = null;
+ /** Edit box for password */
+ private JPasswordField _passwordField = null;
+ /** Name of track */
+ private JTextField _nameField = null;
+ /** Description */
+ private JTextArea _descField = null;
+ /** Private checkbox */
+ private JCheckBox _privateCheckbox = null;
+ /** Activity checkboxes */
+ private JCheckBox[] _activityCheckboxes = null;
+ /** Writer object for GPX export */
+ private OutputStreamWriter _writer = null;
+ /** upload button */
+ private JButton _uploadButton = null;
+
+ /** URL to post form to */
+ private static final String GPSIES_URL = "http://www.gpsies.com/upload.do";
+ /** Keys for describing activities */
+ private static final String[] ACTIVITY_KEYS = {"trekking", "walking", "jogging",
+ "biking", "motorbiking", "snowshoe", "sailing", "skating"};
+
+ /**
+ * Constructor
+ * @param inApp App object
+ */
+ public UploadGpsiesFunction(App inApp) {
+ super(inApp);
+ }
+
+ /**
+ * @return name key
+ */
+ public String getNameKey() {
+ return "function.uploadgpsies";
+ }
+
+ /**
+ * Begin the function
+ */
+ public void begin()
+ {
+ // Initialise dialog, show empty list
+ if (_dialog == null)
+ {
+ _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+ _dialog.setLocationRelativeTo(_parentFrame);
+ _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ _dialog.getContentPane().add(makeDialogComponents());
+ _dialog.pack();
+ }
+ // Show dialog
+ _dialog.setVisible(true);
+ }
+
+
+ /**
+ * Create dialog components
+ * @return Panel containing all gui elements in dialog
+ */
+ private Component makeDialogComponents()
+ {
+ JPanel dialogPanel = new JPanel();
+ dialogPanel.setLayout(new BorderLayout());
+
+ JPanel gridPanel = new JPanel();
+ GuiGridLayout grid = new GuiGridLayout(gridPanel);
+ grid.add(new JLabel(I18nManager.getText("dialog.gpsies.username")));
+ _usernameField = new JTextField(15);
+ grid.add(_usernameField);
+ grid.add(new JLabel(I18nManager.getText("dialog.gpsies.password")));
+ _passwordField = new JPasswordField(15);
+ grid.add(_passwordField);
+ // Track name and description
+ grid.add(new JLabel(I18nManager.getText("dialog.gpsies.column.name")));
+ _nameField = new JTextField(15);
+ grid.add(_nameField);
+ grid.add(new JLabel(I18nManager.getText("dialog.gpsies.description")));
+ _descField = new JTextArea(5, 15);
+ _descField.setLineWrap(true);
+ _descField.setWrapStyleWord(true);
+ grid.add(new JScrollPane(_descField));
+ // Listener on all these text fields to enable/disable the ok button
+ KeyAdapter keyListener = new KeyAdapter() {
+ /** Key released */
+ public void keyReleased(KeyEvent inE) {
+ enableOK();
+ if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ _dialog.dispose();
+ }
+ }
+ };
+ _usernameField.addKeyListener(keyListener);
+ _passwordField.addKeyListener(keyListener);
+ _nameField.addKeyListener(keyListener);
+ // Listen for tabs on description field, to change focus not enter tabs
+ _descField.addKeyListener(new KeyAdapter() {
+ /** Key pressed */
+ public void keyPressed(KeyEvent inE) {
+ if (inE.getKeyCode() == KeyEvent.VK_TAB) {
+ inE.consume();
+ if (inE.isShiftDown()) {
+ _nameField.requestFocusInWindow();
+ }
+ else {
+ _privateCheckbox.requestFocusInWindow();
+ }
+ }
+ }
+ });
+ // Listen for Ctrl-backspace on password field (delete contents)
+ _passwordField.addKeyListener(new KeyAdapter() {
+ /** Key released */
+ public void keyReleased(KeyEvent inE) {
+ if (inE.isControlDown() && (inE.getKeyCode() == KeyEvent.VK_BACK_SPACE
+ || inE.getKeyCode() == KeyEvent.VK_DELETE)) {
+ _passwordField.setText("");
+ }
+ }
+ });
+ // Checkbox for private / public
+ grid.add(new JLabel(I18nManager.getText("dialog.gpsies.keepprivate")));
+ _privateCheckbox = new JCheckBox();
+ _privateCheckbox.setSelected(true);
+ grid.add(_privateCheckbox);
+
+ // panel for activity type checkboxes
+ JPanel activityPanel = new JPanel();
+ activityPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
+ ChangeListener checkListener = new ChangeListener() {
+ public void stateChanged(ChangeEvent arg0) {
+ enableOK();
+ }
+ };
+ GuiGridLayout actGrid = new GuiGridLayout(activityPanel, true);
+ final int numActivities = ACTIVITY_KEYS.length;
+ _activityCheckboxes = new JCheckBox[numActivities];
+ for (int i=0; i<numActivities; i++)
+ {
+ _activityCheckboxes[i] = new JCheckBox(I18nManager.getText("dialog.gpsies.activity." + ACTIVITY_KEYS[i]));
+ _activityCheckboxes[i].addChangeListener(checkListener);
+ actGrid.add(_activityCheckboxes[i]);
+ }
+ grid.add(new JLabel(I18nManager.getText("dialog.gpsies.activities")));
+ grid.add(activityPanel);
+ JPanel midPanel = new JPanel();
+ midPanel.setLayout(new BoxLayout(midPanel, BoxLayout.Y_AXIS));
+ midPanel.add(gridPanel);
+ dialogPanel.add(midPanel, BorderLayout.CENTER);
+
+ // button panel at bottom
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ _uploadButton = new JButton(I18nManager.getText("button.upload"));
+ _uploadButton.setEnabled(false);
+ _uploadButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ startUpload();
+ }
+ });
+ buttonPanel.add(_uploadButton);
+ JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ _dialog.dispose();
+ }
+ });
+ buttonPanel.add(cancelButton);
+ dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+ dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+ return dialogPanel;
+ }
+
+
+ /**
+ * Check the inputs and enable or disable the upload button
+ */
+ private void enableOK()
+ {
+ // Check for lengths of input fields - only username, password and filename are required
+ boolean ok = (_usernameField.getText().length() > 0 && _nameField.getText().length() > 0);
+ if (ok) {
+ // also check password field
+ char[] pass = _passwordField.getPassword();
+ ok = pass.length > 0;
+ for (int i=0; i<pass.length; i++) {pass[i] = '0';} // recommended by javadoc
+ if (ok) {
+ ok = false;
+ for (int i=0; i<_activityCheckboxes.length; i++) {
+ ok = ok || _activityCheckboxes[i].isSelected();
+ }
+ }
+ }
+ _uploadButton.setEnabled(ok);
+ }
+
+
+ /**
+ * Start the upload process (require separate thread?)
+ */
+ private void startUpload()
+ {
+ try
+ {
+ FormPoster poster = new FormPoster(new URL(GPSIES_URL));
+ poster.setParameter("device", "Prune");
+ poster.setParameter("username", _usernameField.getText());
+ poster.setParameter("password", new String(_passwordField.getPassword()));
+ boolean hasActivity = false;
+ for (int i=0; i<ACTIVITY_KEYS.length; i++)
+ {
+ if (_activityCheckboxes[i].isSelected()) {
+ hasActivity = true;
+ poster.setParameter("trackTypes", ACTIVITY_KEYS[i]);
+ }
+ }
+ if (!hasActivity) {poster.setParameter("trackTypes", "walking");} // default if none given
+ poster.setParameter("filename", _nameField.getText());
+ poster.setParameter("fileDescription", _descField.getText());
+ poster.setParameter("startpointCountry", "DE");
+ poster.setParameter("endpointCountry", "DE"); // both those will be corrected by gpsies
+ poster.setParameter("status", (_privateCheckbox.isSelected()?"3":"1"));
+ poster.setParameter("submit", "speichern"); // required
+ // Use Pipes to connect the GpxExporter's output with the FormPoster's input
+ PipedInputStream iStream = new PipedInputStream();
+ PipedOutputStream oStream = new PipedOutputStream(iStream);
+ _writer = new OutputStreamWriter(oStream);
+ new Thread(new Runnable() {
+ public void run() {
+ boolean[] saveFlags = {true, true, true, false, true}; // export everything
+ try {
+ GpxExporter.exportData(_writer, _app.getTrackInfo(), _nameField.getText(), null, saveFlags, false);
+ _writer.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }).start();
+ poster.setParameter("formFile", "filename.gpx", iStream);
+
+ BufferedInputStream answer = new BufferedInputStream(poster.post());
+ int response = poster.getResponseCode();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(answer));
+ String line = reader.readLine();
+ // Try to extract gpsies page url from the returned message
+ String pageUrl = null;
+ if (response == 200 && line.substring(0, 2).toUpperCase().equals("OK"))
+ {
+ final int bracketPos = line.indexOf('[');
+ if (bracketPos > 0 && line.endsWith("]")) {
+ pageUrl = line.substring(bracketPos + 1, line.length()-1);
+ }
+ }
+ if (pageUrl != null)
+ {
+ // OK received and managed to extract a Url from the return message.
+ int userChoice = JOptionPane.showConfirmDialog(_app.getFrame(),
+ I18nManager.getText("dialog.gpsies.confirmopenpage"),
+ I18nManager.getText(getNameKey()), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
+ if (userChoice == JOptionPane.OK_OPTION) {
+ BrowserLauncher.launchBrowser(pageUrl);
+ }
+ }
+ else {
+ _app.showErrorMessageNoLookup(getNameKey(), I18nManager.getText("error.gpsies.uploadnotok")
+ + ": " + line);
+ }
+ }
+ catch (MalformedURLException e) {}
+ catch (IOException ioe) {
+ _app.showErrorMessageNoLookup(getNameKey(), I18nManager.getText("error.gpsies.uploadfailed") + ": "
+ + ioe.getClass().getName() + " : " + ioe.getMessage());
+ }
+ _dialog.dispose();
+ }
+}
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
+import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
/** Altitude below which is considered void */
private static final int VOID_VAL = -32768;
+
/**
* Constructor
* @param inApp App object
*/
public void run()
{
- _dialog.setVisible(true);
// Compile list of tiles to get
Track track = _app.getTrackInfo().getTrack();
ArrayList<SrtmTile> tileList = new ArrayList<SrtmTile>();
+ boolean hasZeroAltitudePoints = false;
+ boolean hasNonZeroAltitudePoints = false;
+ // First, loop to see what kind of points we have
+ for (int i=0; i<track.getNumPoints(); i++)
+ {
+ if (track.getPoint(i).hasAltitude())
+ {
+ if (track.getPoint(i).getAltitude().getValue() == 0) {
+ hasZeroAltitudePoints = true;
+ }
+ else {
+ hasNonZeroAltitudePoints = true;
+ }
+ }
+ }
+ // Should we overwrite the zero altitude values?
+ boolean overwriteZeros = hasZeroAltitudePoints && !hasNonZeroAltitudePoints;
+ // If non-zero values present as well, ask user whether to overwrite the zeros or not
+ if (hasNonZeroAltitudePoints && hasZeroAltitudePoints && JOptionPane.showConfirmDialog(_parentFrame,
+ I18nManager.getText("dialog.lookupsrtm.overwritezeros"), I18nManager.getText(getNameKey()),
+ JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)
+ {
+ overwriteZeros = true;
+ }
+
+ _dialog.setVisible(true);
+ // Now loop again to extract the required tiles
for (int i=0; i<track.getNumPoints(); i++)
{
- // Only consider points which don't have altitudes already
- if (!track.getPoint(i).hasAltitude())
+ // Consider points which don't have altitudes or have zero values
+ if (!track.getPoint(i).hasAltitude() || (overwriteZeros && track.getPoint(i).getAltitude().getValue() == 0))
{
SrtmTile tile = new SrtmTile(track.getPoint(i));
boolean alreadyGot = false;
if (!alreadyGot) {tileList.add(tile);}
}
}
+ lookupValues(tileList, overwriteZeros);
+ }
+
+ /**
+ * Lookup the values from SRTM data
+ * @param inTileList list of tiles to get
+ * @param inOverwriteZeros true to overwrite zero altitude values
+ */
+ private void lookupValues(ArrayList<SrtmTile> inTileList, boolean inOverwriteZeros)
+ {
+ Track track = _app.getTrackInfo().getTrack();
UndoLookupSrtm undo = new UndoLookupSrtm(_app.getTrackInfo());
int numAltitudesFound = 0;
// Update progress bar
- _progressBar.setMaximum(tileList.size());
- _progressBar.setIndeterminate(tileList.size() <= 1);
+ _progressBar.setMaximum(inTileList.size());
+ _progressBar.setIndeterminate(inTileList.size() <= 1);
_progressBar.setValue(0);
// Get urls for each tile
- URL[] urls = TileFinder.getUrls(tileList);
- for (int t=0; t<tileList.size() && !_cancelled; t++)
+ URL[] urls = TileFinder.getUrls(inTileList);
+ for (int t=0; t<inTileList.size() && !_cancelled; t++)
{
if (urls[t] != null)
{
- SrtmTile tile = tileList.get(t);
+ SrtmTile tile = inTileList.get(t);
// System.out.println("tile " + t + " of " + tileList.size() + " = " + urls[t].toString());
try {
_progressBar.setValue(t);
for (int p=0; p<track.getNumPoints(); p++)
{
DataPoint point = track.getPoint(p);
- if (!point.hasAltitude() || point.getAltitude().getValue() == 0) {
+ if (!point.hasAltitude() || (inOverwriteZeros && point.getAltitude().getValue() == 0)) {
if (new SrtmTile(point).equals(tile))
{
double x = (point.getLongitude().getDouble() - tile.getLongitude()) * 1200;
_app.completeFunction(undo, I18nManager.getText("confirm.lookupsrtm1") + " " + numAltitudesFound
+ " " + I18nManager.getText("confirm.lookupsrtm2"));
}
+ else if (inTileList.size() > 0) {
+ _app.showErrorMessage(getNameKey(), "error.lookupsrtm.nonefound");
+ }
else {
- _app.showErrorMessage(getNameKey(), "error.lookupsrtm.none");
+ _app.showErrorMessage(getNameKey(), "error.lookupsrtm.nonerequired");
}
}
private GridBagLayout _layout = null;
private GridBagConstraints _constraints = null;
private JPanel _panel = null;
+ private boolean _allLeft = false;
private int _x = 0;
private int _y = 0;
* @param inPanel panel using layout
*/
public GuiGridLayout(JPanel inPanel)
+ {
+ this(inPanel, false);
+ }
+
+ /**
+ * Constructor
+ * @param inPanel panel using layout
+ * @param inAllLeft true to align all elements to left
+ */
+ public GuiGridLayout(JPanel inPanel, boolean inAllLeft)
{
_panel = inPanel;
+ _allLeft = inAllLeft;
_layout = new GridBagLayout();
_constraints = new GridBagConstraints();
_constraints.weightx = 1.0;
_constraints.gridy = _y;
_constraints.weightx = (_x==0?0.5:1.0);
// set anchor
- _constraints.anchor = (_x == 0?GridBagConstraints.LINE_END:GridBagConstraints.LINE_START);
+ _constraints.anchor = ((_x == 0 && !_allLeft)?GridBagConstraints.LINE_END:GridBagConstraints.LINE_START);
_layout.setConstraints(inComponent, _constraints);
// add to panel
_panel.add(inComponent);
private JMenuItem _exportKmlItem = null;
private JMenuItem _exportGpxItem = null;
private JMenuItem _exportPovItem = null;
+ private JMenuItem _exportSvgItem = null;
private JMenuItem _undoItem = null;
private JMenuItem _clearUndoItem = null;
private JMenuItem _editPointItem = null;
private JMenu _rearrangeMenu = null;
private JMenuItem _cutAndMoveItem = null;
private JMenuItem _convertNamesToTimesItem = null;
+ private JMenuItem _deleteFieldValuesItem = null;
private JCheckBoxMenuItem _mapCheckbox = null;
private JMenuItem _show3dItem = null;
private JMenu _browserMapMenu = null;
private JMenuItem _chartItem = null;
private JMenuItem _getGpsiesItem = null;
+ private JMenuItem _uploadGpsiesItem = null;
private JMenuItem _lookupSrtmItem = null;
private JMenuItem _distanceItem = null;
private JMenuItem _fullRangeDetailsItem = null;
_exportPovItem = makeMenuItem(FunctionLibrary.FUNCTION_POVEXPORT);
_exportPovItem.setEnabled(false);
fileMenu.add(_exportPovItem);
+ // Svg
+ _exportSvgItem = makeMenuItem(FunctionLibrary.FUNCTION_SVGEXPORT);
+ _exportSvgItem.setEnabled(false);
+ fileMenu.add(_exportSvgItem);
fileMenu.addSeparator();
JMenuItem exitMenuItem = new JMenuItem(I18nManager.getText("menu.file.exit"));
exitMenuItem.addActionListener(new ActionListener() {
_getGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_GET_GPSIES);
_getGpsiesItem.setEnabled(false);
trackMenu.add(_getGpsiesItem);
+ // Upload to gpsies
+ _uploadGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_UPLOAD_GPSIES);
+ _uploadGpsiesItem.setEnabled(false);
+ trackMenu.add(_uploadGpsiesItem);
_lookupSrtmItem = makeMenuItem(FunctionLibrary.FUNCTION_LOOKUP_SRTM);
_lookupSrtmItem.setEnabled(false);
trackMenu.add(_lookupSrtmItem);
});
_mergeSegmentsItem.setEnabled(false);
rangeMenu.add(_mergeSegmentsItem);
+ _deleteFieldValuesItem = makeMenuItem(FunctionLibrary.FUNCTION_DELETE_FIELD_VALUES);
+ _deleteFieldValuesItem.setEnabled(false);
+ rangeMenu.add(_deleteFieldValuesItem);
rangeMenu.addSeparator();
_interpolateItem = new JMenuItem(I18nManager.getText("menu.range.interpolate"));
_interpolateItem.addActionListener(new ActionListener() {
}
});
viewMenu.add(_mapCheckbox);
+ // Turn off the sidebars
+ JCheckBoxMenuItem sidebarsCheckbox = new JCheckBoxMenuItem(I18nManager.getText("menu.view.showsidebars"));
+ sidebarsCheckbox.setSelected(true);
+ sidebarsCheckbox.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ _app.toggleSidebars();
+ }
+ });
+ viewMenu.add(sidebarsCheckbox);
+ // 3d
_show3dItem = makeMenuItem(FunctionLibrary.FUNCTION_3D);
_show3dItem.setEnabled(false);
viewMenu.add(_show3dItem);
_exportKmlItem.setEnabled(hasData);
_exportGpxItem.setEnabled(hasData);
_exportPovItem.setEnabled(hasData);
+ _exportSvgItem.setEnabled(hasData);
_compressItem.setEnabled(hasData);
_deleteMarkedPointsItem.setEnabled(hasData && _track.hasMarkedPoints());
_rearrangeMenu.setEnabled(hasData && _track.hasTrackPoints() && _track.hasWaypoints());
_browserMapMenu.setEnabled(hasData);
_distanceItem.setEnabled(hasData);
_getGpsiesItem.setEnabled(hasData);
+ _uploadGpsiesItem.setEnabled(hasData && _track.hasTrackPoints());
_lookupSrtmItem.setEnabled(hasData);
_findWaypointItem.setEnabled(hasData && _track.hasWaypoints());
// is undo available?
_addTimeOffsetItem.setEnabled(hasRange);
_addAltitudeOffsetItem.setEnabled(hasRange);
_convertNamesToTimesItem.setEnabled(hasRange && _track.hasWaypoints());
+ _deleteFieldValuesItem.setEnabled(hasRange);
_fullRangeDetailsItem.setEnabled(hasRange);
// Is the currently selected point outside the current range?
_cutAndMoveItem.setEnabled(hasRange && hasPoint &&
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
_waypointListModel = new WaypointListModel(_trackInfo.getTrack());
_waypointList = new JList(_waypointListModel);
_waypointList.setVisibleRowCount(NUM_LIST_ENTRIES);
+ _waypointList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
_waypointList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e)
{
_photoListModel = new PhotoListModel(_trackInfo.getPhotoList());
_photoList = new JList(_photoListModel);
_photoList.setVisibleRowCount(NUM_LIST_ENTRIES);
+ _photoList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
_photoList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e)
{
--- /dev/null
+package tim.prune.gui;
+
+import java.awt.Component;
+
+import javax.swing.JSplitPane;
+import javax.swing.SwingUtilities;
+
+/**
+ * Class to control the showing and hiding of the sidebars
+ * (left panel, right panel and profile display)
+ */
+public class SidebarController
+{
+ /** array of hideable components */
+ private Component[] _components = null;
+ /** array of splitter panes */
+ private JSplitPane[] _splitters = null;
+ /** array of splitter positions */
+ private int[] _positions = null;
+
+
+ /**
+ * Constructor
+ * @param inComponents array of components to hide/show
+ * @param inSplitters array of splitter panes
+ */
+ public SidebarController(Component[] inComponents, JSplitPane[] inSplitters)
+ {
+ _components = inComponents;
+ _splitters = inSplitters;
+ _positions = new int[inSplitters.length];
+ }
+
+ /**
+ * Toggle full screen mode on or off
+ */
+ public void toggle()
+ {
+ if (_components != null && _components.length > 0)
+ {
+ boolean visible = _components[0].isVisible();
+ if (visible) {
+ // Store divider locations
+ for (int i=0; i<_components.length; i++) {
+ _positions[i] = _splitters[i].getDividerLocation();
+ }
+ }
+ // Set visibility of components
+ for (int i=0; i<_components.length; i++) {
+ _components[i].setVisible(!visible);
+ }
+ // Restore divider locations
+ for (int i=0; i<_components.length; i++) {
+ if (!visible) {
+ _splitters[i].setDividerLocation(_positions[i]);
+ }
+ }
+ // Hiding of panels has to occur in separate thread to update properly
+ if (visible) SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ for (int i=0; i<_components.length; i++) {
+ _splitters[i].setDividerLocation(i==0?0.0:1.0);
+ _splitters[i].invalidate();
+ }
+ }
+ });
+ }
+ }
+}
package tim.prune.gui.map;
+import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.FontMetrics;
import java.awt.Graphics;
+import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
if ((_mapImage == null || _recalculate))
{
paintMapContents();
- _scaleBar.updateScale(_mapPosition.getZoom(), _mapPosition.getCentreTileY());
+ _scaleBar.updateScale(_mapPosition.getZoom(), _mapPosition.getYFromPixels(0, 0));
}
// Draw the prepared image onto the panel
if (_mapImage != null) {
}
// Make maps brighter / fainter
- float[] scaleFactors = {1.0f, 1.05f, 1.1f, 1.2f, 1.6f, 2.0f};
- float scaleFactor = scaleFactors[_transparencySlider.getValue()];
+ final float[] scaleFactors = {1.0f, 1.05f, 1.1f, 1.2f, 1.6f, 2.2f};
+ final float scaleFactor = scaleFactors[_transparencySlider.getValue()];
if (scaleFactor > 1.0f)
{
RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
final Color secondColour = Config.getColourScheme().getColour(ColourScheme.IDX_SECONDARY);
final Color textColour = Config.getColourScheme().getColour(ColourScheme.IDX_TEXT);
+ // try to set double line width for painting
+ if (inG instanceof Graphics2D) {
+ ((Graphics2D) inG).setStroke(new BasicStroke(2.0f));
+ }
int pointsPainted = 0;
// draw track points
inG.setColor(pointColour);
// select point if it's a left-click
if (!inE.isMetaDown())
{
- int pointIndex = _track.getNearestPointIndex(
- _mapPosition.getXFromPixels(inE.getX(), getWidth()),
- _mapPosition.getYFromPixels(inE.getY(), getHeight()),
- _mapPosition.getBoundsFromPixels(CLICK_SENSITIVITY), false);
- // Extend selection for shift-click
- if (inE.isShiftDown()) {
- _trackInfo.extendSelection(pointIndex);
+ if (inE.getClickCount() == 1)
+ {
+ // single click
+ int pointIndex = _track.getNearestPointIndex(
+ _mapPosition.getXFromPixels(inE.getX(), getWidth()),
+ _mapPosition.getYFromPixels(inE.getY(), getHeight()),
+ _mapPosition.getBoundsFromPixels(CLICK_SENSITIVITY), false);
+ // Extend selection for shift-click
+ if (inE.isShiftDown()) {
+ _trackInfo.extendSelection(pointIndex);
+ }
+ else {
+ _trackInfo.selectPoint(pointIndex);
+ }
}
- else {
- _trackInfo.selectPoint(pointIndex);
+ else if (inE.getClickCount() == 2) {
+ // double click
+ panMap(inE.getX() - getWidth()/2, inE.getY() - getHeight()/2);
+ zoomIn();
}
}
else
{
/** zoom level */
private int _zoomLevel = -1;
- /** y tile number */
- private int _yTile = -1;
+ /** y position */
+ private double _yPos = 0.0;
// Dimensions
/** Offset from left side in pixels */
/** Margin between bar and end text in pixels */
private static final int MARGIN_WIDTH = 8;
- /** metric scales for each zoom level */
- private static final int[] _metricScales = {10000, 5000, 2000, 2000, 1000, 500, 200, 100,
- 50, 20, 10, 5, 2, 2, 1, -2, -5, -10, -20, -50, -100, -200};
+ /** scales for each zoom level */
+ private static final int[] _scales = {10000, 5000, 2000, 2000, 1000, 500, 200, 100,
+ 50, 20, 10, 5, 2, 2, 1,
+ -2, -5, -10, -20, -50, -100, -200};
/** pixel counts for each zoom level (metric) */
- private static final int[] _metricPixels = {64, 64, 51, 102, 102, 102, 81, 81,
- 81, 65, 65, 65, 52, 105, 105, 105, 83, 83, 83, 67, 67, 67};
- /** imperial scales for each zoom level (num miles) */
- private static final int[] _mileScales = {10000, 10000, 5000, 2000, 2000, 1000, 500, 200,
- 100, 50, 20, 10, 5, 2, 1, -2, -2, -5, -10, -20, -50, -100};
- /** pixel counts for each zoom level (miles) */
- private static final int[] _milePixels = {79, 79, 79, 64, 127, 127, 127, 102,
- 102, 102, 81, 81, 81, 65, 65, 65, 130, 104, 104, 104, 104, 83, 83};
+ private static final double[] _metricPixels = {64, 64, 51, 102, 102, 102, 81, 81,
+ 81, 65, 65, 65, 52, 105, 105,
+ 105, 83, 83, 83, 67, 67, 67};
/**
{
try {
boolean useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
- int rightSide = LEFT_OFFSET + (useMetric?_metricPixels[_zoomLevel]:_milePixels[_zoomLevel]);
- int scale = (useMetric?_metricScales[_zoomLevel]:_mileScales[_zoomLevel]);
+ double drightSide = LEFT_OFFSET + _metricPixels[_zoomLevel] * (useMetric?1:1.609);
+ int scale = _scales[_zoomLevel];
- // work out cos(latitude) from y tile and zoom, and apply to scale
- final double n = Math.pow(2, _zoomLevel);
- final double angle = Math.PI * (1 - 2.0*_yTile/n);
+ // work out cos(latitude) from y position, and apply to scale
+ final double angle = Math.PI * (1 - 2*_yPos);
final double lat = Math.atan(Math.sinh(angle));
final double cosLat = Math.cos(lat);
- rightSide = (int) (rightSide / cosLat);
+ int rightSide = (int) (drightSide / cosLat);
// Adjust if scale is too large
while (rightSide > 300)
{
// Abort if scale is now less than 1 unit (shouldn't ever be)
if (scale < 1) {return;}
}
+ // Abort if scale is negative (around poles)
+ if (rightSide < 1) {return;}
// Determine colours to use
Color barColour = Config.getColourScheme().getColour(ColourScheme.IDX_TEXT);
inG.drawLine(rightSide, Y_OFFSET+1, rightSide, Y_OFFSET-TICK_HEIGHT);
inG.drawLine(rightSide+1, Y_OFFSET+1, rightSide+1, Y_OFFSET-TICK_HEIGHT);
// text
- String text = (scale>0?(""+scale):("1/"+(-scale))) + " "
- + I18nManager.getText(useMetric?"units.kilometres.short":"units.miles.short");
+ String text = getScaleText(scale, useMetric);
inG.setColor(blankColour);
inG.drawString(text, rightSide+MARGIN_WIDTH-1, Y_OFFSET);
inG.drawString(text, rightSide+MARGIN_WIDTH+1, Y_OFFSET);
}
}
+ /**
+ * Get the scale text for the given scale
+ * @param inScale scale number
+ * @param inUseMetric true to use km/m, false for miles/ft
+ * @return scale text as string
+ */
+ private static String getScaleText(int inScale, boolean inUseMetric)
+ {
+ if (inScale > 0) {
+ // Positive scale means km or miles
+ return "" + inScale + " " +
+ I18nManager.getText(inUseMetric?"units.kilometres.short":"units.miles.short");
+ }
+ if (inUseMetric) {
+ // negative scale means m
+ return "" + (-1000 / inScale) + " " + I18nManager.getText("units.metres.short");
+ }
+ // fallen through to feet
+ return "" + (-5280 / inScale) + " " + I18nManager.getText("units.feet.short");
+ }
+
/**
* Update the scale level
* @param inZoom new zoom level
+ * @param inYPos y position, where 0 is north pole, 1 is south pole
*/
- public void updateScale(int inZoom, int inYtile)
+ public void updateScale(int inZoom, double inYPos)
{
_zoomLevel = inZoom;
- _yTile = inYtile;
+ _yPos = inYPos;
}
}
_hasData = true;
_pointHasData[i] = true;
}
+ else _pointHasData[i] = false;
}
}
}
// Find minimum and maximum values to plot
double minValue = _data.getMinValue();
double maxValue = _data.getMaxValue();
- if (maxValue <= minValue) {maxValue = minValue + 1;}
+ if (maxValue <= minValue) {maxValue = minValue + 1; minValue--;}
final int numPoints = _track.getNumPoints();
_xScaleFactor = 1.0 * (width - 2 * BORDER_WIDTH - 1) / numPoints;
}
}
// current point (make sure it's drawn last)
- if (_data.hasData(selectedPoint))
+ if (selectedPoint >= 0)
{
x = (int) (_xScaleFactor * selectedPoint) + 1;
g.setColor(secondColour);
g.fillRect(BORDER_WIDTH + x, height-usableHeight-BORDER_WIDTH+1, barWidth, usableHeight-2);
- g.setColor(currentColour);
- value = _data.getData(selectedPoint);
- y = (int) (yScaleFactor * (value - minValue));
- g.fillRect(BORDER_WIDTH + x, height-BORDER_WIDTH - y, barWidth, y);
+ if (_data.hasData(selectedPoint))
+ {
+ g.setColor(currentColour);
+ value = _data.getData(selectedPoint);
+ y = (int) (yScaleFactor * (value - minValue));
+ g.fillRect(BORDER_WIDTH + x, height-BORDER_WIDTH - y, barWidth, y);
+ }
}
}
catch (NullPointerException npe) { // ignore, probably due to data being changed
public abstract String getNoDataKey();
/**
- * Initialise the data arrays
+ * Initialise the data arrays to the correct size
*/
protected void initArrays()
{
*/
public abstract class ExifGateway
{
- // *********************************************************
- // TODO: Check this exif library flag before releasing!
- /** Flag to specify internal or external library */
- private static final boolean USE_INTERNAL_LIBRARY = true;
- // *********************************************************
-
/** Library object to call */
private static ExifLibrary _exifLibrary = null;
/** Flag to set whether failure warning has already been shown */
/** Static block to initialise library */
static
{
- String libraryClass = USE_INTERNAL_LIBRARY?"InternalExifLibrary":"ExternalExifLibrary";
+ String libraryClass = ExifLibrarySwitch.USE_INTERNAL_LIBRARY?"InternalExifLibrary":"ExternalExifLibrary";
try
{
_exifLibrary = (ExifLibrary) Class.forName("tim.prune.jpeg." + libraryClass).newInstance();
*/
public static String getDescriptionKey()
{
- String key = USE_INTERNAL_LIBRARY?"internal":"external";
+ String key = ExifLibrarySwitch.USE_INTERNAL_LIBRARY?"internal":"external";
if (_exifLibrary == null || !_exifLibrary.looksOK()) {key = key + ".failed";}
return key;
}
--- /dev/null
+package tim.prune.jpeg;
+
+/**
+ * Empty class just to provide a switch between internal and external libraries
+ */
+public abstract class ExifLibrarySwitch
+{
+ /** Flag to specify internal or external library */
+ static final boolean USE_INTERNAL_LIBRARY = true;
+}
data.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(),
times[2].intValue()});
Rational[] dates = gpsdir.getRationalArray(TAG_GPS_DATESTAMP);
- data.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});
+ if (dates != null) {
+ data.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});
+ }
}
}
{
Directory exifdir = metadata.getDirectory(ExifDirectory.class);
- // Take time and date from exif tags if haven't got it already from GPS
- if (data.getGpsDatestamp() == null && exifdir.containsTag(ExifDirectory.TAG_DATETIME_ORIGINAL)) {
+ // Take time and date from exif tags
+ if (exifdir.containsTag(ExifDirectory.TAG_DATETIME_ORIGINAL)) {
data.setOriginalTimestamp(exifdir.getString(ExifDirectory.TAG_DATETIME_ORIGINAL));
}
+ // Also take "digitized" timestamp
+ if (exifdir.containsTag(ExifDirectory.TAG_DATETIME_DIGITIZED)) {
+ data.setDigitizedTimestamp(exifdir.getString(ExifDirectory.TAG_DATETIME_DIGITIZED));
+ }
// Photo rotation code
if (exifdir.containsTag(ExifDirectory.TAG_ORIENTATION)) {
private int[] _gpsTimestamp = null;
private int[] _gpsDatestamp = null;
private String _originalTimestamp = null;
+ private String _digitizedTimestamp = null;
private int _orientationCode = -1;
private byte[] _thumbnail = null;
private ArrayList<String> _errors = null;
_originalTimestamp = inStamp;
}
+ /**
+ * Set the digitized timestamp
+ * @param inStamp digitized (creation) timestamp of photo
+ */
+ public void setDigitizedTimestamp(String inStamp)
+ {
+ _digitizedTimestamp = inStamp;
+ }
+
/**
* Set the orientation code
* @param inCode code from exif (1 to 8)
public int getOrientationCode() { return _orientationCode; }
/** @return original timestamp as string */
public String getOriginalTimestamp() { return _originalTimestamp; }
+ /** @return digitized timestamp as string */
+ public String getDigitizedTimestamp() { return _digitizedTimestamp; }
/**
* Set the thumbnail
public static final int TAG_GPS_TIMESTAMP = 0x0007;\r
/** GPS date (atomic clock) GPSDateStamp 23 1d RATIONAL 3 */\r
public static final int TAG_GPS_DATESTAMP = 0x001d;\r
- /** Exif timestamp */\r
+ /** "Original" Exif timestamp */\r
public static final int TAG_DATETIME_ORIGINAL = 0x9003;\r
+ /** "Creation" or "Digitized" timestamp */\r
+ public static final int TAG_DATETIME_DIGITIZED = 0x9004;\r
/** Thumbnail offset */\r
private static final int TAG_THUMBNAIL_OFFSET = 0x0201;\r
/** Thumbnail length */\r
private void processGpsTag(JpegData inMetadata, int inTagType, int inTagValueOffset,\r
int inComponentCount, int inFormatCode)\r
{\r
- // Only interested in tags latref, lat, longref, lon, altref, alt and gps timestamp\r
- switch (inTagType)\r
+ try\r
{\r
- case TAG_GPS_LATITUDE_REF:\r
- inMetadata.setLatitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
- break;\r
- case TAG_GPS_LATITUDE:\r
- Rational[] latitudes = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
- inMetadata.setLatitude(new double[] {latitudes[0].doubleValue(), latitudes[1].doubleValue(), latitudes[2].doubleValue()});\r
- break;\r
- case TAG_GPS_LONGITUDE_REF:\r
- inMetadata.setLongitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
- break;\r
- case TAG_GPS_LONGITUDE:\r
- Rational[] longitudes = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
- inMetadata.setLongitude(new double[] {longitudes[0].doubleValue(), longitudes[1].doubleValue(), longitudes[2].doubleValue()});\r
- break;\r
- case TAG_GPS_ALTITUDE_REF:\r
- inMetadata.setAltitudeRef(_data[inTagValueOffset]);\r
- break;\r
- case TAG_GPS_ALTITUDE:\r
- inMetadata.setAltitude(readRational(inTagValueOffset, inFormatCode, inComponentCount).intValue());\r
- break;\r
- case TAG_GPS_TIMESTAMP:\r
- Rational[] times = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
- inMetadata.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(), times[2].intValue()});\r
- break;\r
- case TAG_GPS_DATESTAMP:\r
- Rational[] dates = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
- inMetadata.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});\r
- break;\r
- default: // ignore all other tags\r
+ // Only interested in tags latref, lat, longref, lon, altref, alt and gps timestamp\r
+ switch (inTagType)\r
+ {\r
+ case TAG_GPS_LATITUDE_REF:\r
+ inMetadata.setLatitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
+ break;\r
+ case TAG_GPS_LATITUDE:\r
+ Rational[] latitudes = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+ inMetadata.setLatitude(new double[] {latitudes[0].doubleValue(), latitudes[1].doubleValue(), latitudes[2].doubleValue()});\r
+ break;\r
+ case TAG_GPS_LONGITUDE_REF:\r
+ inMetadata.setLongitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
+ break;\r
+ case TAG_GPS_LONGITUDE:\r
+ Rational[] longitudes = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+ inMetadata.setLongitude(new double[] {longitudes[0].doubleValue(), longitudes[1].doubleValue(), longitudes[2].doubleValue()});\r
+ break;\r
+ case TAG_GPS_ALTITUDE_REF:\r
+ inMetadata.setAltitudeRef(_data[inTagValueOffset]);\r
+ break;\r
+ case TAG_GPS_ALTITUDE:\r
+ inMetadata.setAltitude(readRational(inTagValueOffset, inFormatCode, inComponentCount).intValue());\r
+ break;\r
+ case TAG_GPS_TIMESTAMP:\r
+ Rational[] times = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+ inMetadata.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(), times[2].intValue()});\r
+ break;\r
+ case TAG_GPS_DATESTAMP:\r
+ Rational[] dates = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+ if (dates != null) {\r
+ inMetadata.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});\r
+ }\r
+ else {\r
+ // Not in rational array format, but maybe as String?\r
+ String date = readString(inTagValueOffset, inFormatCode, inComponentCount);\r
+ if (date != null && date.length() == 10) {\r
+ inMetadata.setGpsDatestamp(new int[] {Integer.parseInt(date.substring(0, 4)),\r
+ Integer.parseInt(date.substring(5, 7)), Integer.parseInt(date.substring(8))});\r
+ }\r
+ }\r
+ break;\r
+ default: // ignore all other tags\r
+ }\r
}\r
+ catch (Exception e) {} // ignore and continue\r
}\r
\r
\r
int inComponentCount, int inFormatCode)\r
{\r
// Only interested in original timestamp, thumbnail offset and thumbnail length\r
- if (inTagType == TAG_DATETIME_ORIGINAL)\r
- {\r
+ if (inTagType == TAG_DATETIME_ORIGINAL) {\r
inMetadata.setOriginalTimestamp(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
}\r
+ else if (inTagType == TAG_DATETIME_DIGITIZED) {\r
+ inMetadata.setDigitizedTimestamp(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
+ }\r
else if (inTagType == TAG_THUMBNAIL_OFFSET) {\r
_thumbnailOffset = TIFF_HEADER_START_OFFSET + get16Bits(inTagValueOffset);\r
extractThumbnail(inMetadata);\r
--- /dev/null
+# Text entries for the Prune application
+# Czech entries as extra
+
+# Menu entries
+menu.file=Soubor
+menu.file.addphotos=P\u0159idat fotografie
+menu.file.save=Ulo\u017eit jako text
+menu.file.exit=Konec
+menu.track=Trasa
+menu.track.undo=Undo
+menu.track.clearundo=Vypr\u00e1zdnit pam\u011b\u0165 undo
+menu.track.deletemarked=Smazat ozna\u010den\u00e9 body
+menu.track.rearrange=P\u0159euspo\u0159\u00e1dat body
+menu.track.rearrange.start=V\u0161e na po\u010d\u00e1tek
+menu.track.rearrange.end=V\u0161e na konec
+menu.track.rearrange.nearest=Zarovnat body na trasu
+menu.range=Rozmez\u00ed
+menu.range.all=Vybrat v\u0161e
+menu.range.none=Zru\u0161it v\u00fdb\u011br
+menu.range.start=Nastavit za\u010d\u00e1tek rozmez\u00ed
+menu.range.end=Nastavit konec rozmez\u00ed
+menu.range.deleterange=Smazat rozmez\u00ed
+menu.range.interpolate=Interpolovat
+menu.range.average=St\u0159ed z v\u00fdb\u011bru
+menu.range.reverse=Obr\u00e1tit rozmez\u00ed
+menu.range.mergetracksegments=Slou\u010dit \u010d\u00e1sti trasy
+menu.range.cutandmove=P\u0159en\u00e9st v\u00fdb\u011br
+menu.point=Bod
+menu.point.editpoint=Upravit bod
+menu.point.deletepoint=Smazat bod
+menu.photo=Fotografie
+menu.photo.saveexif=Ulo\u017eit do Exif
+menu.photo.connect=P\u0159ipojit do bodu
+menu.photo.disconnect=Odpojit od bodu
+menu.photo.delete=Odebrat fotografii
+menu.view=Zobrazen\u00ed
+menu.view.showsidebars=Zobrazit panely
+menu.view.browser=Mapa v internetov\u00e9m prohl\u00ed\u017ee\u010di
+menu.view.browser.google=Mapy Google
+menu.view.browser.openstreetmap=Openstreetmap
+menu.view.browser.mapquest=Mapquest
+menu.view.browser.yahoo=Mapy Yahoo
+menu.view.browser.bing=Mapy Bing
+menu.settings=Nastaven\u00ed
+menu.settings.onlinemode=Na\u010d\u00edtat mapy z internetu
+menu.help=Pomoc
+# Popup menu for map
+menu.map.zoomin=P\u0159ibl\u00ed\u017eit
+menu.map.zoomout=Odd\u00e1lit
+menu.map.zoomfull=\u00dapln\u011b odd\u00e1lit
+menu.map.newpoint=Vytvo\u0159it nov\u00fd bod
+menu.map.connect=Propojit body
+menu.map.autopan=Automatika zorn\u00e9ho pole
+menu.map.showmap=Zobrazit mapu
+menu.map.showscalebar=Zobrazit m\u011b\u0159\u00edtko
+
+# Alt keys for menus
+altkey.menu.file=S
+altkey.menu.track=T
+altkey.menu.range=R
+altkey.menu.point=B
+altkey.menu.view=Z
+altkey.menu.photo=F
+altkey.menu.settings=N
+altkey.menu.help=P
+
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=O
+shortcut.menu.file.load=N
+shortcut.menu.file.save=U
+shortcut.menu.track.undo=U
+shortcut.menu.edit.compress=K
+shortcut.menu.range.all=V
+shortcut.menu.help.help=P
+
+# Functions
+function.open=Otev\u0159\u00edt soubor
+function.loadfromgps=Na\u010d\u00edst data z GPS
+function.sendtogps=Poslat data do GPS
+function.exportkml=Export KML
+function.exportgpx=Export GPX
+function.exportpov=Export POV
+function.exportsvg=Export SVG
+function.editwaypointname=Nastavit n\u00e1zev bodu
+function.compress=Komprimovat trasu
+function.addtimeoffset=P\u0159idat \u010dasov\u00fd posun
+function.addaltitudeoffset=P\u0159idat v\u00fd\u0161kov\u00fd posun
+function.convertnamestotimes=P\u0159ev\u00e9st n\u00e1zvy bod\u016f na \u010dasov\u00e9 zna\u010dky
+function.deletefieldvalues=Smazat hodnoty pole
+function.findwaypoint=Hledat bod
+function.pastecoordinates=Zadat sou\u0159adnice
+function.charts=Grafy
+function.show3d=Trojrozm\u011brn\u011b
+function.distances=Vzd\u00e1lenosti
+function.fullrangedetails=Detaily rozmez\u00ed
+function.setmapbg=Nastavit pozad\u00ed
+function.setkmzimagesize=Nastavit velikost exportu KMZ
+function.setpaths=Nastavit cestu k program\u016fm
+function.getgpsies=St\u00e1hnout trasy z Gpsies
+function.uploadgpsies=Nahr\u00e1t trasu na Gpsies
+function.lookupsrtm=Na\u010d\u00edst nadm. v\u00fd\u0161ku ze SRTM
+function.duplicatepoint=Zdvojit bod
+function.setcolours=Nastavit barvy
+function.setlanguage=Nastavit jazyk
+function.correlatephotos=Sladit fotografie podle \u010dasu
+function.rearrangephotos=Uspo\u0159\u00e1dat fotografie
+function.rotatephotoleft=Oto\u010dit fotografii doleva
+function.rotatephotoright=Oto\u010dit fotografii doprava
+function.ignoreexifthumb=Ignorovat n\u00e1hled v Exif
+function.help=Pomoc
+function.showkeys=Zobrazit kl\u00e1vesov\u00e9 zkratky
+function.about=O programu
+function.checkversion=Zkontrolovat existenci nov\u00e9 verze
+function.saveconfig=Ulo\u017eit nastaven\u00ed
+function.diskcache=Ulo\u017eit mapy na disk
+
+# Dialogs
+dialog.exit.confirm.title=Ukon\u010dit Prune
+dialog.exit.confirm.text=Data nejsou ulo\u017eena. Opravdu chcete ukon\u010dit program?
+dialog.openappend.title=P\u0159ipojit k na\u010dten\u00fdm dat\u016fm
+dialog.openappend.text=P\u0159ipojit tato data k ji\u017e na\u010dten\u00fdm dat\u016fm?
+dialog.deletepoint.title=Smazat bod
+dialog.deletepoint.deletephoto=Odebrat fotografii p\u0159ipojenou k tomuto bodu?
+dialog.deletephoto.title=Odebrat fotografii
+dialog.deletephoto.deletepoint=Smazat bod p\u0159ipojen\u00fd k t\u00e9to fotografii?
+dialog.openoptions.title=Volby p\u0159i na\u010dten\u00ed
+dialog.openoptions.filesnippet=N\u00e1hled souboru
+dialog.load.table.field=Pole
+dialog.load.table.datatype=Typ dat
+dialog.load.table.description=Popis
+dialog.delimiter.label=Odd\u011blova\u010d pol\u00ed
+dialog.delimiter.comma=\u010c\u00e1rka ,
+dialog.delimiter.tab=Tabul\u00e1tor
+dialog.delimiter.space=Mezera
+dialog.delimiter.semicolon=St\u0159edn\u00edk ;
+dialog.delimiter.other=Jin\u00e9
+dialog.openoptions.deliminfo.records=z\u00e1znam\u016f, s
+dialog.openoptions.deliminfo.fields=poli
+dialog.openoptions.deliminfo.norecords=\u017d\u00e1dn\u00e9 z\u00e1znamy
+dialog.openoptions.altitudeunits=Jednotky v\u00fd\u0161ky
+dialog.open.contentsdoubled=Tento soubor obsahuje dv\u011b kopie ka\u017ed\u00e9ho bodu,\nv\u017edy jednou jako body trasy a jednou jako v\u00fdzna\u010dn\u00e9 body.
+dialog.selecttracks.intro=Vyberte trasu nebo trasy k na\u010dten\u00ed
+dialog.selecttracks.noname=Bez n\u00e1zvu
+dialog.jpegload.subdirectories=V\u010detn\u011b podadres\u00e1\u0159\u016f
+dialog.jpegload.loadjpegswithoutcoords=V\u010detn\u011b fotografi\u00ed bez sou\u0159adnic
+dialog.jpegload.loadjpegsoutsidearea=V\u010detn\u011b fotografi\u00ed mimo aktu\u00e1ln\u00ed oblast
+dialog.jpegload.progress.title=Na\u010d\u00edt\u00e1m fotografie
+dialog.jpegload.progress=Pros\u00edm chvilku strpen\u00ed p\u0159i vyhled\u00e1v\u00e1n\u00ed fotografi\u00ed
+dialog.gpsload.nogpsbabel=Nenalezen program gpsbabel. Pokra\u010dovat?
+dialog.gpsload.device=Ozna\u010den\u00ed za\u0159\u00edzen\u00ed
+dialog.gpsload.format=Form\u00e1t
+dialog.gpsload.getwaypoints=Na\u010d\u00edst body
+dialog.gpsload.gettracks=Na\u010d\u00edst trasy
+dialog.gpsload.save=Ulo\u017eit do souboru
+dialog.gpssend.sendwaypoints=Poslat bod
+dialog.gpssend.sendtracks=Poslat trasy
+dialog.gpssend.trackname=N\u00e1zev trasy
+dialog.saveoptions.title=Ulo\u017eit soubor
+dialog.save.fieldstosave=Ulo\u017eit pole
+dialog.save.table.field=Pole
+dialog.save.table.hasdata=Nepr\u00e1zdn\u00e9
+dialog.save.table.save=Ulo\u017eit
+dialog.save.headerrow=Ulo\u017eit i z\u00e1hlav\u00ed
+dialog.save.coordinateunits=Jednotky sou\u0159adnic
+dialog.save.altitudeunits=Jednotky v\u00fd\u0161ky
+dialog.save.timestampformat=Form\u00e1t \u010dasov\u00e9 zna\u010dky
+dialog.save.overwrite.title=Soubor u\u017e existuje
+dialog.save.overwrite.text=Tento soubor u\u017e existuje. Opravdu chcete soubor p\u0159epsat?
+dialog.save.notypesselected=Nebyl vybr\u00e1n ani jeden typ bod\u016f
+dialog.exportkml.text=Nadpis dat
+dialog.exportkml.altitude=V\u00fd\u0161ka nad hladinou mo\u0159e (pro l\u00e9t\u00e1n\u00ed)
+dialog.exportkml.kmz=Komprimovat do souboru kmz
+dialog.exportkml.exportimages=Vlo\u017eit n\u00e1hledy fotografi\u00ed
+dialog.exportkml.trackcolour=Barva trasy
+dialog.exportgpx.name=N\u00e1zev
+dialog.exportgpx.desc=Popis
+dialog.exportgpx.includetimestamps=Ulo\u017eit \u010dasov\u00e9 zna\u010dky
+dialog.exportgpx.copysource=Zkop\u00edrovat zdrojov\u00e9 xml
+dialog.exportpov.text=Pros\u00edm vlo\u017ete paramerty exportu do POV
+dialog.exportpov.font=Font
+dialog.exportpov.camerax=Kamera X
+dialog.exportpov.cameray=Kamera Y
+dialog.exportpov.cameraz=Kamera Z
+dialog.exportpov.modelstyle=Model
+dialog.exportpov.ballsandsticks=Koule a ty\u010dky
+dialog.exportpov.tubesandwalls=Roury a st\u011bny
+dialog.exportpov.warningtracksize=Tato trasa sest\u00e1v\u00e1 z mnoha bod\u016f, kter\u00e9 mo\u017en\u00e1 Java3D nebude um\u011bt zobrazit.\nOpravdu chcete pokra\u010dovat?
+dialog.exportsvg.text=Zvolte parametry exportu do SVG
+dialog.exportsvg.phi=Azimut \u03d5
+dialog.exportsvg.theta=V\u00fd\u0161kov\u00fd \u00fahel \u03b8
+dialog.exportsvg.gradients=Vypl\u0148ovat body barevn\u00fdm p\u0159echodem
+dialog.pointtype.desc=Ulo\u017eit body n\u00e1sleduj\u00edc\u00edch typ\u016f:
+dialog.pointtype.track=Body trasy
+dialog.pointtype.waypoint=V\u00fdzna\u010dn\u00e9 body
+dialog.pointtype.photo=M\u00edsta s fotografiemi
+dialog.pointtype.selection=Jen v\u00fdb\u011br
+dialog.confirmreversetrack.title=Potvr\u010fte obr\u00e1cen\u00ed
+dialog.confirmreversetrack.text=Tato trasa obsahuje \u010dasov\u00e9 zna\u010dky, jejich\u017e po\u0159ad\u00ed se obr\u00e1cen\u00edm zm\u011bn\u00ed.\nOpravdu chcete obr\u00e1tit v\u00fdb\u011br?
+dialog.confirmcutandmove.title=Potvr\u010fte p\u0159esun
+dialog.confirmcutandmove.text=Tato trasa obsahuje \u010dasov\u00e9 zna\u010dky, jejich\u017e po\u0159ad\u00ed se p\u0159esunem zm\u011bn\u00ed.\nOpravdu chcete v\u00fdb\u011br p\u0159esunout?
+dialog.interpolate.title=Interpolovat body
+dialog.interpolate.parameter.text=Po\u010det bod\u016f, kter\u00e9 se maj\u00ed p\u0159idat mezi vybran\u00e9 body
+dialog.undo.title=Vr\u00e1tit akci (akce)
+dialog.undo.pretext=Pros\u00edm vyberte akci (akce) k vr\u00e1cen\u00ed
+dialog.undo.none.title=Nelze vr\u00e1tit
+dialog.undo.none.text=Nenalezeny \u017e\u00e1dn\u00e9 akce k vr\u00e1cen\u00ed
+dialog.clearundo.title=Vypr\u00e1zdnit pam\u011b\u0165 undo
+dialog.clearundo.text=Opravdu chcete vypr\u00e1zdnit pam\u011b\u0165 undo?\nNebude u\u017e mo\u017en\u00e9 akce vracet do p\u016fvodn\u00edho stavu!
+dialog.pointedit.title=Upravit bod
+dialog.pointedit.text=Vyberte pole k editaci a stiskn\u011bte 'Upravit'
+dialog.pointedit.table.field=Pole
+dialog.pointedit.table.value=Hodnota
+dialog.pointedit.table.changed=Zm\u011bn\u011bno
+dialog.pointedit.changevalue.text=Zadejte novou hodnotu pole
+dialog.pointedit.changevalue.title=Upravit pole
+dialog.pointnameedit.name=N\u00e1zev v\u00fdzna\u010dn\u00e9ho bodu
+dialog.pointnameedit.uppercase=VELKÁ p\u00edsmena
+dialog.pointnameedit.lowercase=mal\u00e1 p\u00edsmena
+dialog.pointnameedit.sentencecase=Po\u010d\u00e1te\u010dn\u00ed P\u00edsmena Velk\u00e1
+dialog.addtimeoffset.add=P\u0159idat \u010das
+dialog.addtimeoffset.subtract=Odebrat \u010das
+dialog.addtimeoffset.days=Dny
+dialog.addtimeoffset.hours=Hodiny
+dialog.addtimeoffset.minutes=Minuty
+dialog.addtimeoffset.notimestamps=Nelze p\u0159idat \u010das, proto\u017ee v\u00fdb\u011br neobsahuje \u017e\u00e1dn\u00e9 \u010dasov\u00e9 zna\u010dky
+dialog.findwaypoint.intro=Vlo\u017ete \u010d\u00e1st n\u00e1zvu v\u00fdzna\u010dn\u00e9ho bodu
+dialog.findwaypoint.search=Hledat
+dialog.saveexif.title=Ulo\u017eit Exif
+dialog.saveexif.intro=Vyberte fotografie k ulo\u017een\u00ed
+dialog.saveexif.nothingtosave=Hodnoty sou\u0159adnic nebyly zm\u011bn\u011bny, nen\u00ed t\u0159eba nic ukl\u00e1dat
+dialog.saveexif.noexiftool=Nebyl nalezen program exiftool. Pokra\u010dovat?
+dialog.saveexif.table.photoname=N\u00e1zev fotografie
+dialog.saveexif.table.status=Status
+dialog.saveexif.table.save=Ulo\u017eit
+dialog.saveexif.photostatus.connected=P\u0159ipojeno
+dialog.saveexif.photostatus.disconnected=Odpojeno
+dialog.saveexif.photostatus.modified=Zm\u011bn\u011bno
+dialog.saveexif.overwrite=P\u0159epsat soubory
+dialog.saveexif.force=P\u0159epsat i p\u0159i nepodstatn\u00fdch chyb\u00e1ch
+dialog.charts.xaxis=Osa X
+dialog.charts.yaxis=Osa Y
+dialog.charts.output=V\u00fdstup
+dialog.charts.screen=V\u00fdstup na obrazovku
+dialog.charts.svg=V\u00fdstup do souboru SVG
+dialog.charts.svgwidth=\u0160\u00ed\u0159ka SVG
+dialog.charts.svgheight=V\u00fd\u0161ka SVG
+dialog.charts.needaltitudeortimes=Trasa mus\u00ed obsahovat bu\u010f informaci o nadmo\u0159sk\u00e9 v\u00fd\u0161ce nebo o \u010dase, aby bylo mo\u017en\u00e9 vytv\u00e1\u0159et grafy
+dialog.charts.gnuplotnotfound=Nepoda\u0159ilo se nal\u00e9zt gnuplot na dan\u00e9m um\u00edst\u011bn\u00ed
+dialog.distances.intro=P\u0159\u00edm\u00e9 vzd\u00e1lenosti mezi body
+dialog.distances.column.from=Z bodu
+dialog.distances.column.to=Do bodu
+dialog.distances.currentpoint=Aktu\u00e1ln\u00ed bod
+dialog.distances.toofewpoints=Je t\u0159eba zadat v\u00edce bod\u016f, aby bylo mo\u017en\u00e9 vypo\u010d\u00edst jejich vzd\u00e1lenost
+dialog.fullrangedetails.intro=Zobrazuji detaily vybran\u00e9ho rozmez\u00ed
+dialog.setmapbg.intro=Vyberte jeden ze zdroj\u016f map nebo p\u0159idejte nov\u00fd
+dialog.addmapsource.title=P\u0159idat nov\u00fd zdroj map
+dialog.addmapsource.sourcename=N\u00e1zev zdroje
+dialog.addmapsource.layer1url=URL prvn\u00ed vrstvy
+dialog.addmapsource.layer2url=Voliteln\u011b URL druh\u00e9 vrstvy
+dialog.addmapsource.maxzoom=Maxim\u00e1ln\u00ed zv\u011bt\u0161en\u00ed
+dialog.addmapsource.cloudstyle=\u010c\u00edslo stylu
+dialog.addmapsource.noname=Bez n\u00e1zvu
+dialog.gpsies.column.name=N\u00e1zev trasy
+dialog.gpsies.column.length=D\u00e9lka
+dialog.gpsies.description=Popis
+dialog.gpsies.nodescription=Bez popisu
+dialog.gpsies.nonefound=Nenalezeny \u017e\u00e1dn\u00e9 trasy
+dialog.gpsies.username=U\u017eiv. jm\u00e9no k gpsies
+dialog.gpsies.password=Heslo k gpsies
+dialog.gpsies.keepprivate=Trasu nezve\u0159ej\u0148ovat
+dialog.gpsies.confirmopenpage=Otev\u0159\u00edt nahranou trasu v internetov\u00e9m prohl\u00ed\u017ee\u010di?
+dialog.gpsies.activities=Aktivita
+dialog.gpsies.activity.trekking=Turistika
+dialog.gpsies.activity.walking=Ch\u016fze
+dialog.gpsies.activity.jogging=B\u011bh
+dialog.gpsies.activity.biking=Kolo
+dialog.gpsies.activity.motorbiking=Motorka
+dialog.gpsies.activity.snowshoe=Sn\u011b\u017enice
+dialog.gpsies.activity.sailing=Lo\u010f
+dialog.gpsies.activity.skating=Bruslen\u00ed
+dialog.correlate.notimestamps=U bod\u016f nejsou \u010dasov\u00e9 zna\u010dky, tak\u017ee nen\u00ed s \u010d\u00edm fotografie sladit.
+dialog.correlate.nouncorrelatedphotos=V\u0161echny fotografie jsou slad\u011bn\u00e9.\nOpravdu chcete pokra\u010dovat?
+dialog.correlate.photoselect.intro=Vyberte jednu z t\u011bchto slad\u011bn\u00fdch fotografi\u00ed pro ur\u010den\u00ed \u010dasov\u00e9ho posunu
+dialog.correlate.photoselect.photoname=N\u00e1zev fotografie
+dialog.correlate.photoselect.timediff=\u010casov\u00fd rozd\u00edl
+dialog.correlate.photoselect.photolater=Vyfoceno pozd\u011bji
+dialog.correlate.options.tip=Tip: kdy\u017e ru\u010dn\u011b slad\u00edte aspo\u0148 jednu fotografii, \u010dasov\u00fd posun bude vypo\u010d\u00edtat za v\u00e1s.
+dialog.correlate.options.intro=Upravte mo\u017enosti automatick\u00e9ho slad\u011bn\u00ed
+dialog.correlate.options.offsetpanel=\u010casov\u00fd posun
+dialog.correlate.options.offset=Posun
+dialog.correlate.options.offset.hours=hodin,
+dialog.correlate.options.offset.minutes=minut a
+dialog.correlate.options.offset.seconds=sekund
+dialog.correlate.options.photolater=Fotografie pozd\u011bj\u0161\u00ed ne\u017e bod
+dialog.correlate.options.pointlater=Bod pozd\u011bj\u0161\u00ed ne\u017e fotografie
+dialog.correlate.options.limitspanel=Limity slad\u011bn\u00ed
+dialog.correlate.options.notimelimit=Bez \u010dasov\u00e9ho limitu
+dialog.correlate.options.timelimit=\u010casov\u00fd limit
+dialog.correlate.options.nodistancelimit=Bez d\u00e9lkov\u00e9ho limitu
+dialog.correlate.options.distancelimit=D\u00e9lkov\u00fd limit
+dialog.correlate.options.correlate=Sladit
+dialog.correlate.alloutsiderange=V\u0161echny fotografie le\u017e\u00ed mimo \u010dasov\u00e9 rozmez\u00ed trasy, tak\u017ee nemohou b\u00fdt slad\u011bny.\nPokuste se zm\u011bnit \u010dasov\u00fd posun nebo ru\u010dn\u011b sla\u010fte aspo\u0148 jednu fotografii.
+dialog.rearrangephotos.desc=Vyberte um\u00edst\u011bn\u00ed a uspo\u0159\u00e1d\u00e1n\u00ed bod\u016f fotografi\u00ed
+dialog.rearrangephotos.tostart=P\u0159en\u00e9st na za\u010d\u00e1tek
+dialog.rearrangephotos.toend=P\u0159en\u00e9st na konec
+dialog.rearrangephotos.nosort=Neuspo\u0159\u00e1d\u00e1vat
+dialog.rearrangephotos.sortbyfilename=Uspo\u0159\u00e1dat dle n\u00e1zvu souboru
+dialog.rearrangephotos.sortbytime=Uspo\u0159\u00e1dat dle \u010dasu
+dialog.compress.nonefound=Nemohou b\u00fdt odstran\u011bny \u017e\u00e1dn\u00e9 body trasy
+dialog.compress.closepoints.title=Odstran\u011bn\u00ed bl\u00edzk\u00fdch bod\u016f
+dialog.compress.closepoints.paramdesc=Koeficient bl\u00edzkosti
+dialog.compress.wackypoints.title=Odstran\u011bn\u00ed ust\u0159elen\u00fdch bod\u016f
+dialog.compress.wackypoints.paramdesc=Koeficient vzd\u00e1lnosti
+dialog.compress.singletons.title=Odstran\u011bn\u00ed osamocen\u00fdch bod\u016f
+dialog.compress.singletons.paramdesc=Koeficient vzd\u00e1lenosti
+dialog.compress.duplicates.title=Odstran\u011bn\u00ed zdvojen\u00fdch bod\u016f
+dialog.compress.summarylabel=Bod\u016f ke smaz\u00e1n\u00ed
+dialog.pastecoordinates.desc=Zadejte sou\u0159adnice
+dialog.pastecoordinates.coords=Sou\u0159adnice
+dialog.pastecoordinates.nothingfound=Pros\u00edm ov\u011b\u0159te sou\u0159adnice a zkuste znovu
+dialog.help.help=V\u00edce informac\u00ed v\u010detn\u011b manu\u00e1l\u016f (bohu\u017eel nikoli v \u010de\u0161tin\u011b) naleznete na adrese:\n http://activityworkshop.net/software/prune/
+dialog.about.version=Verze
+dialog.about.build=Build
+dialog.about.summarytext1=Prune je program k na\u010d\u00edt\u00e1n\u00ed, zobrazov\u00e1n\u00ed a editaci dat z navigac\u00ed GPS.
+dialog.about.summarytext2=Je vyd\u00e1n pod licenc\u00ed GNU GPL, tak\u017ee je zdarma a voln\u011b k u\u017e\u00edv\u00e1n\u00ed a vylep\u0161ov\u00e1n\u00ed.<br>Kop\u00edrov\u00e1n\u00ed, redistribuce a \u00fapravy jsou povoleny a podporov\u00e1ny<br>podle podm\u00ednek popsan\u00fdch v souboru <code>licence.txt</code>.
+dialog.about.summarytext3=V\u00edce informac\u00ed v\u010detn\u011b manu\u00e1l\u016f (bohu\u017eel nikoli v \u010de\u0161tin\u011b) naleznete<br> na adrese: <code style="font-weight:bold">http://activityworkshop.net/</code>.
+dialog.about.languages=Dostupn\u00e9 jazyky
+dialog.about.translatedby=\u010cesk\u00fd p\u0159eklad od prot_d.
+dialog.about.systeminfo=Syst\u00e9mov\u00e9 informace
+dialog.about.systeminfo.os=Opera\u010dn\u00ed syst\u00e9m
+dialog.about.systeminfo.java=Java Runtime
+dialog.about.systeminfo.java3d=Java3d nainstalov\u00e1n
+dialog.about.systeminfo.povray=Povray nainstalov\u00e1n
+dialog.about.systeminfo.exiftool=Exiftool nainstalov\u00e1n
+dialog.about.systeminfo.gpsbabel=Gpsbabel nainstalov\u00e1n
+dialog.about.systeminfo.gnuplot=Gnuplot nainstalov\u00e1n
+dialog.about.systeminfo.exiflib=Knihovna Exif
+dialog.about.systeminfo.exiflib.internal=Intern\u00ed
+dialog.about.systeminfo.exiflib.internal.failed=Intern\u00ed (nenalezeno)
+dialog.about.systeminfo.exiflib.external=Extern\u00ed
+dialog.about.systeminfo.exiflib.external.failed=Extern\u00ed (nenalezeno)
+dialog.about.yes=Ano
+dialog.about.no=Ne
+dialog.about.credits=Auto\u0159i a spolupracovn\u00edci
+dialog.about.credits.code=Programov\u00e1n\u00ed
+dialog.about.credits.exifcode=Knihovna Exif
+dialog.about.credits.icons=N\u011bkter\u00e9 ikony od
+dialog.about.credits.translators=P\u0159ekladatel\u00e9
+dialog.about.credits.translations=P\u0159eklady s pomoc\u00ed
+dialog.about.credits.devtools=V\u00fdvojov\u00e9 n\u00e1stroje
+dialog.about.credits.othertools=Dal\u0161\u00ed n\u00e1stroje
+dialog.about.credits.thanks=D\u011bkujeme
+dialog.about.readme=Readme
+dialog.checkversion.error=\u010c\u00edslo verze se nepoda\u0159ilo zkontrolovat.\nPros\u00edm ov\u011b\u0159te p\u0159ipojen\u00ed k internetu.
+dialog.checkversion.uptodate=Pou\u017e\u00edv\u00e1te posledn\u00ed verzi Prune.
+dialog.checkversion.newversion1=Nov\u00e1 verze Prune je u\u017e dostupn\u00e1! Posledn\u00ed verze m\u00e1 \u010d\u00edslo
+dialog.checkversion.newversion2=.
+dialog.checkversion.releasedate1=Tato verze byla vyd\u00e1na
+dialog.checkversion.releasedate2=.
+dialog.checkversion.download=Novou verzi m\u016f\u017eete st\u00e1hnout na adrese http://activityworkshop.net/software/prune/download.html.
+dialog.keys.intro=M\u00edsto my\u0161i m\u016f\u017eete pou\u017e\u00edvat n\u00e1sleduj\u00edc\u00ed kl\u00e1vesov\u00e9 zkratky
+dialog.keys.keylist=<table><tr><td>\u0160ipky</td><td>Posunout mapu vlevo, vpravo, nahoru, dol\u016f</td></tr><tr><td>Ctrl + \u0161ipka vlevo, vpravo</td><td>Vybrat p\u0159edchoz\u00ed nebo n\u00e1sleduj\u00edc\u00ed bod</td></tr><tr><td>Ctrl + \u0161ipka nahoru, dol\u016f</td><td>P\u0159ibl\u00ed\u017eit, odd\u00e1lit</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Vybrat p\u0159edchoz\u00ed, n\u00e1sleduj\u00edc\u00ed \u010d\u00e1st trasy</td></tr><tr><td>Ctrl + Home, End</td><td>Vybrat prvn\u00ed, posledn\u00ed bod</td></tr><tr><td>Del</td><td>Smazat aktu\u00e1ln\u00ed bod</td></tr></table>
+dialog.keys.normalmodifier=Ctrl
+dialog.keys.macmodifier=Command
+dialog.saveconfig.desc=N\u00e1sleduj\u00edc\u00ed volby mohou b\u00fdt ulo\u017eeny do konfigura\u010dn\u00edho souboru :
+dialog.saveconfig.prune.trackdirectory=Adres\u00e1\u0159 s trasami
+dialog.saveconfig.prune.photodirectory=Ad\u0159es\u00e1\u0159 s fotografiemi
+dialog.saveconfig.prune.languagecode=K\u00f3d jazyka
+dialog.saveconfig.prune.languagefile=Soubor jazyka
+dialog.saveconfig.prune.gpsdevice=Za\u0159\u00edzen\u00ed GPS
+dialog.saveconfig.prune.gpsformat=Form\u00e1t GPS
+dialog.saveconfig.prune.povrayfont=Font Povray
+dialog.saveconfig.prune.metricunits=Pou\u017e\u00edvat metrick\u00e9 jednotky?
+dialog.saveconfig.prune.gnuplotpath=Cesta k gnuplot
+dialog.saveconfig.prune.gpsbabelpath=Cesta k gpsbabel
+dialog.saveconfig.prune.exiftoolpath=Cesta k exiftool
+dialog.saveconfig.prune.mapsource=Vybran\u00fd zdroj map
+dialog.saveconfig.prune.mapsourcelist=Zdroje map
+dialog.saveconfig.prune.diskcache=Cache s mapami
+dialog.saveconfig.prune.kmzimagewidth=\u0160\u00ed\u0159ka bitmapy KMZ
+dialog.saveconfig.prune.kmzimageheight=V\u00fd\u0161ka bitmapy KMZ
+dialog.saveconfig.prune.colourscheme=Barevn\u00e9 sch\u00e9ma
+dialog.saveconfig.prune.kmltrackcolour=Barva trasy v KML
+dialog.setpaths.intro=Je-li to t\u0159eba, m\u016f\u017eete nastavit cesty k extern\u00edm aplikac\u00edm:
+dialog.setpaths.found=Cesta nalezena?
+dialog.addaltitude.noaltitudes=Vybran\u00e9 rozmez\u00ed neobsahuje nadmo\u0159skou v\u00fd\u0161ku
+dialog.addaltitude.desc=P\u0159idat v\u00fd\u0161kov\u00fd posun
+dialog.lookupsrtm.overwritezeros=P\u0159epsat hodnoty nadmo\u0159sk\u00e9 v\u00fd\u0161ky na nulu?
+dialog.setcolours.intro=Kliknut\u00edm zvolte barvu
+dialog.setcolours.background=Pozad\u00ed
+dialog.setcolours.borders=Okraje
+dialog.setcolours.lines=\u010c\u00e1ry
+dialog.setcolours.primary=Prim\u00e1rn\u00ed
+dialog.setcolours.secondary=Sekund\u00e1rn\u00ed
+dialog.setcolours.point=Body
+dialog.setcolours.selection=V\u00fdb\u011br
+dialog.setcolours.text=Text
+dialog.colourchooser.title=Zvolte barvu
+dialog.colourchooser.red=\u010cerven\u00e1
+dialog.colourchooser.green=Zelen\u00e1
+dialog.colourchooser.blue=Modr\u00e1
+dialog.setlanguage.firstintro=M\u016f\u017eete bu\u010f zvolit jeden z vypsan\u00fdch jazyk\u016f,<p>nebo vybrat textov\u00fd soubor
+dialog.setlanguage.secondintro=Aby do\u0161lo ke zm\u011bn\u011b jazyka, je t\u0159eba ulo\u017eit nastaven\u00ed<p> a potom restartovat program Prune.
+dialog.setlanguage.language=Jazyk
+dialog.setlanguage.languagefile=Jazykov\u00fd soubor
+dialog.setlanguage.endmessage=Aby do\u0161lo ke zm\u011bn\u011b jazyka, nyn\u00ed ulo\u017ete nastaven\u00ed\na spus\u0165te Prune nanovo.
+dialog.diskcache.save=Ukl\u00e1dat mapov\u00e9 podklady na disk
+dialog.diskcache.dir=Adres\u00e1\u0159 s cache
+dialog.diskcache.createdir=Vytvo\u0159it adres\u00e1\u0159
+dialog.diskcache.nocreate=Adres\u00e1\u0159 nebyl vytvo\u0159en
+dialog.deletefieldvalues.intro=Vyberte pole, kter\u00e9 se m\u00e1 z aktu\u00e1ln\u00edho rozmez\u00ed odstranit
+
+# 3d window
+dialog.3d.title=Trojrozm\u011brn\u00e9 zobrazen\u00ed Prune
+dialog.3d.altitudefactor=Faktor zd\u016frazn\u011bn\u00ed v\u00fd\u0161ky
+dialog.3dlines.title=Linky m\u0159\u00ed\u017eky Prune
+dialog.3dlines.empty=Nejsou \u017e\u00e1dn\u00e9 linky k zobrazen\u00ed!
+dialog.3dlines.intro=Toto jsou linky m\u0159\u00ed\u017eky trojrozm\u011brn\u00e9ho zobrazen\u00ed
+
+# Confirm messages
+confirm.loadfile=Data na\u010dtena ze souboru
+confirm.save.ok1=\u00dasp\u011b\u0161n\u011b ulo\u017eeno
+confirm.save.ok2=bod\u016f do souboru
+confirm.deletepoint.single=bod byl odstran\u011bn
+confirm.deletepoint.multi=body byly odstran\u011bny
+confirm.point.edit=bod zm\u011bn\u011bn
+confirm.mergetracksegments=\u010c\u00e1sti trasy spojeny
+confirm.reverserange=Rozmez\u00ed obr\u00e1ceno
+confirm.addtimeoffset=\u010casov\u00fd posun zm\u011bn\u011bn
+confirm.addaltitudeoffset=V\u00fd\u0161kov\u00fd posun zm\u011bn\u011bn
+confirm.rearrangewaypoints=Body p\u0159euspo\u0159\u00e1d\u00e1ny
+confirm.rearrangephotos=Fotografie p\u0159euspo\u0159\u00e1d\u00e1ny
+confirm.cutandmove=V\u00fdb\u011br p\u0159esunut
+confirm.convertnamestotimes=N\u00e1zvy bod\u016f p\u0159evedeny
+confirm.saveexif.ok1=Ulo\u017eeno
+confirm.saveexif.ok2=fotografi\u00ed
+confirm.undo.single=operace vr\u00e1cena
+confirm.undo.multi=operac\u00ed vr\u00e1ceno
+confirm.jpegload.single=fotografie p\u0159id\u00e1na
+confirm.jpegload.multi=fotografie p\u0159id\u00e1ny
+confirm.photo.connect=fotografie propojena
+confirm.photo.disconnect=fotografie odpojena
+confirm.correlate.single=fotografie slad\u011bna
+confirm.correlate.multi=fotografie slad\u011bny
+confirm.createpoint=bod vytvo\u0159en
+confirm.rotatephoto=fotografie oto\u010dena
+confirm.running=Prob\u00edh\u00e1 ...
+confirm.lookupsrtm1=Nalezeno
+confirm.lookupsrtm2=v\u00fd\u0161kov\u00fdch hodnot
+confirm.deletefieldvalues=Hodnoty pole smaz\u00e1ny
+
+# Buttons
+button.ok=OK
+button.back=Zp\u011bt
+button.next=Vp\u0159ed
+button.finish=Dokon\u010dit
+button.cancel=Zru\u0161it
+button.overwrite=P\u0159epsat
+button.moveup=Posunout nahoru
+button.movedown=Posunout dol\u016f
+button.showlines=Zobrazit linky m\u0159\u00ed\u017eky
+button.edit=Editovat
+button.exit=Konec
+button.close=Zav\u0159\u00edt
+button.continue=Pokra\u010dovat
+button.yes=Ano
+button.no=Ne
+button.yestoall=Ano u v\u0161eho
+button.notoall=Ne u v\u0161eho
+button.select=Vybrat
+button.selectall=Vybrat v\u0161e
+button.selectnone=Zru\u0161it v\u00fdb\u011br
+button.preview=N\u00e1hled
+button.load=Na\u010d\u00edst
+button.upload=Upload
+button.guessfields=Odhadnout pole
+button.showwebpage=Zobrazit str\u00e1nku
+button.check=Zkontrolovat
+button.resettodefaults=Resetovat
+button.browse=Proch\u00e1zet...
+button.addnew=P\u0159idat nov\u00e9
+button.delete=Smazat
+
+# File types
+filetype.txt=soubory TXT
+filetype.jpeg=soubory JPG
+filetype.kmlkmz=soubory KML, KMZ
+filetype.kml=soubory KML
+filetype.kmz=soubory KMZ
+filetype.gpx=soubory GPX
+filetype.pov=soubory POV
+filetype.svg=soubory SVG
+
+# Display components
+display.nodata=\u017d\u00e1dn\u00e1 data
+display.noaltitudes=Trasa neobsahuje informace o v\u00fd\u0161ce
+display.notimestamps=Trasa neobsahuje \u010dasov\u00e9 zna\u010dky
+details.trackdetails=Detaily trasy
+details.notrack=\u017d\u00e1dn\u00e1 trasa
+details.track.points=Body
+details.track.file=Soubor
+details.track.numfiles=Po\u010det soubor\u016f
+details.pointdetails=Detaily bodu
+details.index.selected=Bod \u010d.
+details.index.of=z
+details.nopointselection=Bod nevybr\u00e1n
+details.photofile=Soubor s foto
+details.norangeselection=Rozmez\u00ed nevybr\u00e1no
+details.rangedetails=Detaily rozmez\u00ed
+details.range.selected=Vybr\u00e1ny body
+details.range.to=a\u017e
+details.altitude.to=a\u017e
+details.range.climb=Nastoup\u00e1no
+details.range.descent=Nakles\u00e1no
+details.coordformat=Form\u00e1t sou\u0159adnic
+details.distanceunits=Jednotky d\u00e9lky
+display.range.time.secs=s
+display.range.time.mins=m
+display.range.time.hours=h
+display.range.time.days=d
+details.range.avespeed=Pr\u016fm. rychlost
+details.range.avemovingspeed=Okam\u017e. rychlost
+details.range.maxspeed=Max. rychlost
+details.range.numsegments=Po\u010det segment\u016f
+details.range.pace=Tempo
+details.range.gradient=Sp\u00e1d
+details.waypointsphotos.waypoints=V\u00fdzna\u010dn\u00e9 body
+details.waypointsphotos.photos=Fotografie
+details.photodetails=Detaily fotografie
+details.nophoto=Fotografie nevybr\u00e1na
+details.photo.loading=Na\u010d\u00edt\u00e1m
+details.photo.connected=P\u0159ipojeno
+map.overzoom=P\u0159i tomto p\u0159ibl\u00ed\u017een\u00ed mapa nen\u00ed k dispozici
+
+# Field names
+fieldname.latitude=Zem. \u0161\u00ed\u0159ka
+fieldname.longitude=Zem. d\u00e9lka
+fieldname.altitude=Nadm. v\u00fd\u0161ka
+fieldname.timestamp=\u010cas
+fieldname.time=\u010cas
+fieldname.waypointname=N\u00e1zev
+fieldname.waypointtype=Typ
+fieldname.newsegment=Segment
+fieldname.custom=Vlastn\u00ed
+fieldname.prefix=Pole
+fieldname.distance=Vzd\u00e1lenost
+fieldname.movingdistance=Najeto
+fieldname.duration=Celkov\u00fd \u010das
+fieldname.speed=Rychlost
+fieldname.verticalspeed=Vertik. rychlost
+
+# Measurement units
+units.original=P\u016fvodn\u00ed
+units.default=Implicitn\u00ed
+units.metres=Metry
+units.metres.short=m
+units.feet=Stopy
+units.feet.short=stop
+units.kilometres=Kilometry
+units.kilometres.short=km
+units.kmh=km/h
+units.miles=M\u00edle
+units.miles.short=mil
+units.mph=mph
+units.metrespersec=m/s
+units.feetpersec=stop/s
+units.hours=hodin
+units.degminsec=Deg-min-sec
+units.degmin=Deg-min
+units.deg=Stupn\u011b
+units.iso8601=ISO 8601
+
+# External urls
+url.googlemaps=maps.google.cz
+
+# Cardinals for 3d plots
+cardinal.n=N
+cardinal.s=S
+cardinal.e=E
+cardinal.w=W
+
+# Undo operations
+undo.load=na\u010d\u00edst data
+undo.loadphotos=na\u010d\u00edst fotografie
+undo.editpoint=upravit bod
+undo.deletepoint=smazat bod
+undo.deletephoto=odebrat fotografii
+undo.deleterange=smazat rozmez\u00ed
+undo.compress=zkomprimovat trasu
+undo.insert=vlo\u017eit body
+undo.reverse=obr\u00e1tit rozmez\u00ed
+undo.mergetracksegments=slou\u010dit \u010d\u00e1sti trasy
+undo.addtimeoffset=p\u0159idat \u010dasov\u00fd posun
+undo.addaltitudeoffset=p\u0159idat v\u00fd\u0161kov\u00fd posun
+undo.rearrangewaypoints=p\u0159euspo\u0159\u00e1dat body
+undo.cutandmove=p\u0159esunout v\u00fdb\u011br
+undo.connectphoto=p\u0159ipojit fotografii
+undo.disconnectphoto=odpojit fotografii
+undo.correlate=sladit fotografie
+undo.rearrangephotos=uspo\u0159\u00e1dat fotografie
+undo.createpoint=vytvo\u0159it bod
+undo.rotatephoto=oto\u010dit fotografii
+undo.convertnamestotimes=p\u0159ev\u00e9st n\u00e1zvy na \u010dasy
+undo.lookupsrtm=na\u010d\u00edst nadm. v\u00fd\u0161ky ze SRTM
+undo.deletefieldvalues=smazat hodnoty pol\u00ed
+
+# Error messages
+error.save.dialogtitle=Chyba p\u0159i ukl\u00e1d\u00e1n\u00ed
+error.save.nodata=Nen\u00ed co ulo\u017eit
+error.save.failed=Chyba p\u0159i ukl\u00e1d\u00e1n\u00ed dat do souboru
+error.saveexif.filenotfound=Soubor s fotografi\u00ed nenalezen
+error.saveexif.cannotoverwrite1=Soubor
+error.saveexif.cannotoverwrite2=je jen ke \u010dten\u00ed a nelze ho p\u0159epsat. Ulo\u017eit do kopie?
+error.saveexif.failed1=Nepoda\u0159ilo se ulo\u017eit
+error.saveexif.failed2=fotografi\u00ed
+error.saveexif.forced1=P\u0159i ukl\u00e1d\u00e1n\u00ed
+error.saveexif.forced2=fotografi\u00ed do\u0161lo k nepodstatn\u00e9 chyb\u011b
+error.load.dialogtitle=Chyba p\u0159i na\u010d\u00edt\u00e1n\u00ed
+error.load.noread=Nelze na\u010d\u00edst soubor
+error.load.nopoints=V souboru nenalezeny \u017e\u00e1dn\u00e9 informace o sou\u0159adnic\u00edch
+error.load.unknownxml=Nezn\u00e1m\u00fd form\u00e1t XML:
+error.load.noxmlinzip=Uvnit\u0159 archivu zip nenalezen soubor XML
+error.load.othererror=Chyba p\u0159i \u010dten\u00ed souboru:
+error.jpegload.dialogtitle=Chyba p\u0159i na\u010d\u00edt\u00e1n\u00ed fotografi\u00ed
+error.jpegload.nofilesfound=Nenalezeny \u017e\u00e1dn\u00e9 soubory
+error.jpegload.nojpegsfound=Nenalezeny \u017e\u00e1dn\u00e9 soubory jpeg
+error.jpegload.noexiffound=Nenalezena informace EXIF
+error.jpegload.nogpsfound=Nenalezena informace GPS
+error.jpegload.exifreadfailed=Nepoda\u0159ilo se na\u010d\u00edst informaci EXIF. Tu nelze na\u010d\u00edst\nbez intern\u00ed nebo extern\u00ed knihovny.
+error.gpsload.unknown=Nezn\u00e1m\u00e1 chyba
+error.undofailed.title=Selhalo undo
+error.undofailed.text=Nepoda\u0159ilo se vr\u00e1tit operaci
+error.function.noop.title=Operace nic neprovedla
+error.rearrange.noop=P\u0159euspo\u0159\u00e1d\u00e1n\u00ed nic neprovedlo
+error.function.notavailable.title=Funkce nen\u00ed dostupn\u00e1
+error.function.nojava3d=Tato funkce vy\u017eaduje knihovnu Java3d,\ndostupnou na Sun.com.
+error.3d=P\u0159i trojrozm\u011brn\u00e9m zobrazen\u00ed do\u0161lo k chyb\u011b
+error.readme.notfound=Nenalezen soubor readme
+error.osmimage.dialogtitle=Chyba p\u0159i na\u010d\u00edt\u00e1n\u00ed mapov\u00fdch podklad\u016f
+error.osmimage.failed=Selhalo na\u010dten\u00ed mapov\u00fdch podklad\u016f. Pros\u00edm zkontrolujte p\u0159ipojen\u00ed k internetu.
+error.language.wrongfile=Vybran\u00fd soubor nevypad\u00e1 jako jazykov\u00fd soubor pro Prune
+error.convertnamestotimes.nonames=N\u00e1zvy nemohou b\u00fdt p\u0159evedeny na \u010dasov\u00e9 zna\u010dky
+error.lookupsrtm.nonefound=Pro tyto body nen\u00ed k dispozici informace o nadmo\u0159sk\u00e9 v\u00fd\u0161ce
+error.lookupsrtm.nonerequired=U v\u0161ech bod\u016f u\u017e je informaci o v\u00fd\u0161ce, tak\u017ee nen\u00ed co dohled\u00e1vat
+error.gpsies.uploadnotok=Server gpsies vr\u00e1til hl\u00e1\u0161en\u00ed
+error.gpsies.uploadfailed=Chyba - nepoda\u0159ilo se nahr\u00e1t data.
# Menu entries
menu.file=Datei
menu.file.addphotos=Fotos laden
-menu.file.save=Speichern
+menu.file.save=Als Text Speichern
menu.file.exit=Beenden
menu.track=Track
-menu.track.undo=Rückgängig
-menu.track.clearundo=Liste der letzten Änderungen löschen
-menu.track.deletemarked=Komprimierte Punkte löschen
+menu.track.undo=R\u00fcckg\u00e4ngig
+menu.track.clearundo=Liste der letzten Änderungen l\u00f6schen
+menu.track.deletemarked=Komprimierte Punkte l\u00f6schen
menu.track.rearrange=Wegpunkte reorganisieren
menu.track.rearrange.start=Alle Wegpunkte zum Anfang
menu.track.rearrange.end=Alle Wegpunkte ans Ende
-menu.track.rearrange.nearest=Jeden Wegpunkt zum nächsten Trackpunkt verschieben
+menu.track.rearrange.nearest=Jeden Wegpunkt zum n\u00e4chsten Trackpunkt verschieben
menu.range=Bereich
menu.range.all=Alles markieren
menu.range.none=Nichts markieren
menu.range.start=Startpunkt setzen
menu.range.end=Endpunkt setzen
-menu.range.deleterange=Bereich löschen
+menu.range.deleterange=Bereich l\u00f6schen
menu.range.interpolate=Interpolieren
menu.range.average=Durchschnitt berechnen
menu.range.reverse=Bereich umkehren
menu.range.cutandmove=Schneiden und verschieben
menu.point=Punkt
menu.point.editpoint=Punkt bearbeiten
-menu.point.deletepoint=Punkt löschen
+menu.point.deletepoint=Punkt l\u00f6schen
menu.photo=Foto
menu.photo.saveexif=Exif Daten speichern
-menu.photo.connect=Mit Punkt verknüpfen
+menu.photo.connect=Mit Punkt verkn\u00fcpfen
menu.photo.disconnect=Vom Punkt trennen
menu.photo.delete=Foto entfernen
menu.view=Ansicht
+menu.view.showsidebars=Seitenleisten anzeigen
menu.view.browser=Karte in Browser
menu.settings=Einstellungen
menu.settings.onlinemode=Karten aus dem Internet laden
# Popup menu for map
menu.map.zoomin=Hineinzoomen
menu.map.zoomout=Herauszoomen
-menu.map.zoomfull=Auf Bildschirmgröße zoomen
+menu.map.zoomfull=Auf Bildschirmgr\u00f6\u00dfe zoomen
menu.map.newpoint=Neuen Punkt erzeugen
menu.map.connect=Trackpunkte mit Linie anzeigen
menu.map.autopan=Autozentrierung
menu.map.showmap=Karte zeigen
-menu.map.showscalebar=Maßstab anzeigen
+menu.map.showscalebar=Ma\u00dfstab anzeigen
# Alt keys for menus
altkey.menu.file=D
shortcut.menu.help.help=H
# Functions
-function.open=Datei öffnen
+function.open=Datei \u00f6ffnen
function.loadfromgps=Vom GPS laden
function.sendtogps=zum GPS schicken
function.exportkml=KML exportieren
function.exportgpx=GPX exportieren
function.exportpov=POV exportieren
+function.exportsvg=SVG exportieren
function.editwaypointname=Wegpunkt Name bearbeiten
function.compress=Track komprimieren
function.addtimeoffset=Zeitverschiebung aufrechnen
-function.addaltitudeoffset=Höhenverschiebung aufrechnen
+function.addaltitudeoffset=H\u00f6henverschiebung aufrechnen
+function.convertnamestotimes=Wegpunktenamen in Zeitstempel umwandeln
+function.deletefieldvalues=Werte eines Feldes löschen
function.findwaypoint=Wegpunkt finden
-function.convertnamestotimes=Wegpunktenamen in Zeitstempeln verwandeln
function.pastecoordinates=Neue Koordinaten eingeben
function.charts=Diagramme
function.show3d=3D Ansicht
function.distances=Entfernungen
-function.fullrangedetails=Zusätzliche Bereichdetails
+function.fullrangedetails=Zus\u00e4tzliche Bereichdetails
function.setmapbg=Karte Hintergrund setzen
-function.setkmzimagesize=Bildgröße im KMZ setzen
+function.setkmzimagesize=Bildgr\u00f6\u00dfe im KMZ setzen
function.setpaths=Programmpfade setzen
-function.setcolours=Farben einstellen
-function.setlanguage=Sprache einstellen
function.getgpsies=Gpsies Tracks holen
-function.lookupsrtm=Höhendaten von SRTM holen
+function.uploadgpsies=Daten zum Gpsies hochladen
+function.lookupsrtm=H\u00f6hendaten von SRTM holen
function.duplicatepoint=Punkt verdoppeln
+function.setcolours=Farben einstellen
+function.setlanguage=Sprache einstellen
function.correlatephotos=Fotos korrelieren
function.rearrangephotos=Fotos reorganisieren
function.rotatephotoleft=Foto nach Links drehen
function.ignoreexifthumb=Exif Vorschaubild ignorieren
function.help=Hilfe
function.showkeys=Tastenkombinationen anzeigen
-function.about=Über Prune
+function.about=\u00dcber Prune
function.checkversion=Nach neuen Versionen suchen
function.saveconfig=Einstellungen speichern
-function.diskcache=Karten auf Disk speichern
+function.diskcache=Karten auf Festplatte speichern
# Dialogs
dialog.exit.confirm.title=Prune beenden
dialog.exit.confirm.text=Ihre Daten wurden nicht gespeichert. Wollen Sie das Programm trotzdem beenden?
-dialog.openappend.title=Daten anhängen oder ersetzen
-dialog.openappend.text=Diese Daten an die aktuellen Daten anhängen?
-dialog.deletepoint.title=Punkt löschen
-dialog.deletepoint.deletephoto=Das zu diesem Punkt gehörende Foto ebenfalls löschen?
+dialog.openappend.title=Daten anh\u00e4ngen oder ersetzen
+dialog.openappend.text=Diese Daten an die aktuellen Daten anh\u00e4ngen?
+dialog.deletepoint.title=Punkt l\u00f6schen
+dialog.deletepoint.deletephoto=Das zu diesem Punkt geh\u00f6rende Foto ebenfalls l\u00f6schen?
dialog.deletephoto.title=Foto entfernen
-dialog.deletephoto.deletepoint=Den zu diesem Foto gehörenden Punkt auch löschen?
-dialog.openoptions.title=Öffnen
+dialog.deletephoto.deletepoint=Den zu diesem Foto geh\u00f6renden Punkt auch l\u00f6schen?
+dialog.openoptions.title=\u00d6ffnen
dialog.openoptions.filesnippet=Dateiausschnitt
dialog.load.table.field=Feld
dialog.load.table.datatype=Datentyp
dialog.openoptions.deliminfo.records=Aufnahmen, mit
dialog.openoptions.deliminfo.fields=Feldern
dialog.openoptions.deliminfo.norecords=Keine Rekords
-dialog.openoptions.altitudeunits=Höhe Maßeinheiten
-dialog.open.contentsdoubled=Diese Datei enthält zwei Kopien von jedem Punkt,\neinmal als Waypoint und einmal als Trackpunkt.
+dialog.openoptions.altitudeunits=H\u00f6he Ma\u00dfeinheiten
+dialog.open.contentsdoubled=Diese Datei enth\u00e4lt zwei Kopien von jedem Punkt,\neinmal als Waypoint und einmal als Trackpunkt.
+dialog.selecttracks.intro=W\u00e4hlen Sie den Track oder die Tracks aus, die Sie laden m\u00f6chten
+dialog.selecttracks.noname=Unbenannt
dialog.jpegload.subdirectories=Unterordner mit durchsuchen
dialog.jpegload.loadjpegswithoutcoords=Auch Fotos ohne Koordinaten laden
-dialog.jpegload.loadjpegsoutsidearea=Auch Fotos ausserhalb vom Track laden
+dialog.jpegload.loadjpegsoutsidearea=Auch Fotos ausserhalb des Tracks laden
dialog.jpegload.progress.title=Fotos werden geladen
-dialog.jpegload.progress=Bitte warten während die Fotos durchgesucht werden
+dialog.jpegload.progress=Bitte warten w\u00e4hrend die Fotos durchsucht werden
dialog.gpsload.nogpsbabel=Programm gpsbabel wurde nicht gefunden. Weiter?
-dialog.gpsload.device=Gerätename
+dialog.gpsload.device=Ger\u00e4tename
dialog.gpsload.format=Format
dialog.gpsload.getwaypoints=Wegpunkte laden
dialog.gpsload.gettracks=Tracks laden
-dialog.gpsload.save=nach Datei speichern
+dialog.gpsload.save=Als Datei speichern
dialog.gpssend.sendwaypoints=Wegpunkte senden
dialog.gpssend.sendtracks=Tracks senden
dialog.gpssend.trackname=Track Name
dialog.saveoptions.title=Datei speichern
dialog.save.fieldstosave=Zu speichernde Felder
dialog.save.table.field=Feld
-dialog.save.table.hasdata=Enthält Daten
+dialog.save.table.hasdata=Enth\u00e4lt Daten
dialog.save.table.save=Speichern
dialog.save.headerrow=Titelzeile speichern
-dialog.save.coordinateunits=Koordinaten Maßeinheiten
-dialog.save.altitudeunits=Höhe Maßeinheiten
+dialog.save.coordinateunits=Koordinaten Ma\u00dfeinheiten
+dialog.save.altitudeunits=H\u00f6he Ma\u00dfeinheiten
dialog.save.timestampformat=Zeitstempelformat
dialog.save.overwrite.title=Datei schon vorhanden
-dialog.save.overwrite.text=Diese Datei gibt es schon. Wollen Sie die vorhandene Datei überschreiben?
-dialog.save.notypesselected=Keine Punktetypen sind ausgewählt
-dialog.exportkml.text=Titel für die Daten
-dialog.exportkml.altitude=Absolute Höheninformation (für Luftfahrt)
+dialog.save.overwrite.text=Diese Datei gibt es schon. Wollen Sie die vorhandene Datei \u00fcberschreiben?
+dialog.save.notypesselected=Keine Punktetypen sind ausgew\u00e4hlt
+dialog.exportkml.text=Titel f\u00fcr die Daten
+dialog.exportkml.altitude=Absolute H\u00f6heninformation (f\u00fcr Luftfahrt)
dialog.exportkml.kmz=Daten in kmz Datei komprimieren
dialog.exportkml.exportimages=Vorschaubilder mit in kmz exportieren
dialog.exportkml.trackcolour=Trackfarbe
dialog.exportgpx.desc=Beschreibung
dialog.exportgpx.includetimestamps=Zeitstempel mit exportieren
dialog.exportgpx.copysource=Xml von Quelle kopieren
-dialog.exportpov.text=Geben Sie die Parameter für den POV Export ein
+dialog.exportpov.text=Geben Sie die Parameter f\u00fcr den POV Export ein
dialog.exportpov.font=Font
dialog.exportpov.camerax=Kamera X
dialog.exportpov.cameray=Kamera Y
dialog.exportpov.cameraz=Kamera Z
dialog.exportpov.modelstyle=Modellstil
-dialog.exportpov.ballsandsticks=Bälle und Stangen
-dialog.exportpov.tubesandwalls=Röhren und Wände
-dialog.exportpov.warningtracksize=Dieser Track hat sehr viele Punkte, die Java3D vielleicht nicht bearbeiten kann.\nMöchten Sie den Vorgang trotzdem fortsetzen?
+dialog.exportpov.ballsandsticks=B\u00e4lle und Stangen
+dialog.exportpov.tubesandwalls=R\u00f6hren und W\u00e4nde
+dialog.exportpov.warningtracksize=Dieser Track hat sehr viele Punkte, die Java3D vielleicht nicht bearbeiten kann.\nM\u00f6chten Sie den Vorgang trotzdem fortsetzen?
+dialog.exportsvg.text=Wählen Sie die Parameter für den SVG Export aus
+dialog.exportsvg.phi=Richtungswinkel \u03D5
+dialog.exportsvg.theta=Neigungswinkel \u03B8
+dialog.exportsvg.gradients=Farbverläufe verwenden
dialog.pointtype.desc=Folgende Punkttypen speichern:
dialog.pointtype.track=Trackpunkte
dialog.pointtype.waypoint=Wegpunkte
dialog.pointtype.photo=Fotopunkte
dialog.pointtype.selection=Nur aktuellen Bereich
-dialog.confirmreversetrack.title=Umkehrung bestätigen
-dialog.confirmreversetrack.text=Diese Daten enthalten Zeitangaben, die bei einer Umkehrung in falscher Reihenfolge erscheinen würden.\nSind Sie sicher, dass Sie diesen Bereich umkehren wollen?
-dialog.confirmcutandmove.title=Verschieben bestätigen
-dialog.confirmcutandmove.text=Diese Daten enthalten Zeitangaben, die nach dem Verschieben in falscher Reihenfolge erscheinen würden.\nSind Sie sicher, dass Sie diesen Bereich verschieben wollen?
+dialog.confirmreversetrack.title=Umkehrung best\u00e4tigen
+dialog.confirmreversetrack.text=Diese Daten enthalten Zeitangaben, die bei einer Umkehrung in falscher Reihenfolge erscheinen w\u00fcrden.\nSind Sie sicher, dass Sie diesen Bereich umkehren wollen?
+dialog.confirmcutandmove.title=Verschieben best\u00e4tigen
+dialog.confirmcutandmove.text=Diese Daten enthalten Zeitangaben, die nach dem Verschieben in falscher Reihenfolge erscheinen w\u00fcrden.\nSind Sie sicher, dass Sie diesen Bereich verschieben wollen?
dialog.interpolate.title=Punkte interpolieren
-dialog.interpolate.parameter.text=Anzahl Punkte, die zwischen den gewählten Punkten eingefügt werden sollen
-dialog.undo.title=Aktionen Rückgängig
-dialog.undo.pretext=Bitte die Operationen, die rückgängig gemacht werden sollen, auswählen.
-dialog.undo.none.title=Undo nicht möglich
-dialog.undo.none.text=Keine Operationen können rückgängig gemacht werden.
-dialog.clearundo.title=Undo-Liste löschen
-dialog.clearundo.text=Wollen Sie wirklich die Undo-Liste löschen?\nAlle Undo- Informationen werden verloren gehen!
+dialog.interpolate.parameter.text=Anzahl Punkte, die zwischen den gew\u00e4hlten Punkten eingef\u00fcgt werden sollen
+dialog.undo.title=Aktionen R\u00fcckg\u00e4ngig
+dialog.undo.pretext=Bitte die Operationen, die r\u00fcckg\u00e4ngig gemacht werden sollen, ausw\u00e4hlen.
+dialog.undo.none.title=Undo nicht m\u00f6glich
+dialog.undo.none.text=Keine Operationen k\u00f6nnen r\u00fcckg\u00e4ngig gemacht werden.
+dialog.clearundo.title=Undo-Liste l\u00f6schen
+dialog.clearundo.text=Wollen Sie wirklich die Undo-Liste l\u00f6schen?\nAlle Undo- Informationen werden verloren gehen!
dialog.pointedit.title=Punkt bearbeiten
-dialog.pointedit.text=Wählen Sie die Felder aus, die Sie bearbeiten möchten, und verwenden Sie den 'Bearbeiten' Knopf, um den Wert zu ändern
+dialog.pointedit.text=W\u00e4hlen Sie die Felder aus, die Sie bearbeiten m\u00f6chten, und verwenden Sie den 'Bearbeiten' Knopf, um den Wert zu \u00e4ndern
dialog.pointedit.table.field=Feld
dialog.pointedit.table.value=Wert
-dialog.pointedit.table.changed=Geändert
-dialog.pointedit.changevalue.text=Geben Sie den neuen Wert für dieses Feld ein
+dialog.pointedit.table.changed=Ge\u00e4ndert
+dialog.pointedit.changevalue.text=Geben Sie den neuen Wert f\u00fcr dieses Feld ein
dialog.pointedit.changevalue.title=Feld bearbeiten
dialog.pointnameedit.name=Wegpunkt Name
-dialog.pointnameedit.uppercase=GROß geschrieben
+dialog.pointnameedit.uppercase=GRO\u00df geschrieben
dialog.pointnameedit.lowercase=klein geschrieben
dialog.pointnameedit.sentencecase=Gemischt geschrieben
dialog.addtimeoffset.add=Zeit addieren
dialog.findwaypoint.intro=Geben Sie einen Teil des Namens ein
dialog.findwaypoint.search=Suche
dialog.saveexif.title=Exif speichern
-dialog.saveexif.intro=Wählen Sie die Fotos zum Speichern aus
-dialog.saveexif.nothingtosave=Koordinaten sind unverändert. Es gibt nichts zu speichern.
+dialog.saveexif.intro=W\u00e4hlen Sie die Fotos zum Speichern aus
+dialog.saveexif.nothingtosave=Koordinaten sind unver\u00e4ndert. Es gibt nichts zu speichern.
dialog.saveexif.noexiftool=Kein exiftool Programm gefunden. Trotzdem fortfahren?
dialog.saveexif.table.photoname=Foto Name
dialog.saveexif.table.status=Status
dialog.saveexif.photostatus.connected=Verbunden
dialog.saveexif.photostatus.disconnected=Getrennt
dialog.saveexif.photostatus.modified=Modifiziert
-dialog.saveexif.overwrite=Dateien überschreiben
-dialog.saveexif.force=Forzieren trotz Warnungen
+dialog.saveexif.overwrite=Dateien \u00fcberschreiben
+dialog.saveexif.force=Erzwingen trotz geringf\u00fcgiger Fehler
dialog.charts.xaxis=X Achse
dialog.charts.yaxis=Y Achse
dialog.charts.output=Ausgabe
-dialog.charts.screen=Ausgabe zum Bildschirm
+dialog.charts.screen=Ausgabe auf Bildschirm
dialog.charts.svg=Ausgabe in SVG Datei
dialog.charts.svgwidth=SVG Breite
-dialog.charts.svgheight=SVG Höhe
-dialog.charts.needaltitudeortimes=Ohne Daten über Höhe und Zeit kann kein Diagramm erzeugt werden.
+dialog.charts.svgheight=SVG H\u00f6he
+dialog.charts.needaltitudeortimes=Ohne Daten \u00fcber H\u00f6he und Zeit kann kein Diagramm erzeugt werden.
dialog.charts.gnuplotnotfound=Gnuplot konnte im angegebenen Pfad nicht gefunden werden
dialog.distances.intro=Luftlinienentfernung zwischen Punkten
dialog.distances.column.from=Vom Punkt
dialog.distances.column.to=Zum Punkt
dialog.distances.currentpoint=Aktueller Punkt
dialog.distances.toofewpoints=Diese Funktion braucht Wegpunkte um die Distanzen zu berechnen
-dialog.fullrangedetails.intro=Hier sind die Details vom markierten Bereich
-dialog.setmapbg.intro=Eine von den Quellen auswählen, oder eine neue hinzufügen
-dialog.addmapsource.title=Neue Kartequelle hinzufügen
-dialog.addmapsource.sourcename=Sourcename
-dialog.addmapsource.layer1url=URL für erste Ebene
-dialog.addmapsource.layer2url=URL für obere Ebene (falls nötig)
+dialog.fullrangedetails.intro=Hier sind die Details des markierten Bereichs
+dialog.setmapbg.intro=Eine der Quellen ausw\u00e4hlen oder eine neue hinzuf\u00fcgen
+dialog.addmapsource.title=Neue Kartenquelle hinzuf\u00fcgen
+dialog.addmapsource.sourcename=Name der Quelle
+dialog.addmapsource.layer1url=URL f\u00fcr erste Ebene
+dialog.addmapsource.layer2url=URL f\u00fcr obere Ebene (falls n\u00f6tig)
dialog.addmapsource.maxzoom=Maximales Zoom
dialog.addmapsource.cloudstyle=Stilnummer
dialog.addmapsource.noname=Unbenannt
dialog.gpsies.column.name=Track Name
-dialog.gpsies.column.length=Länge
+dialog.gpsies.column.length=L\u00e4nge
dialog.gpsies.description=Beschreibung
dialog.gpsies.nodescription=Keine Beschreibung
dialog.gpsies.nonefound=Keine Tracks gefunden
-dialog.correlate.notimestamps=Die Punkte enthalten keine Zeitangaben, deshalb können die Fotos nicht zugeordnet werden.
+dialog.gpsies.username=Gpsies Username
+dialog.gpsies.password=Gpsies Passwort
+dialog.gpsies.keepprivate=Track privat halten
+dialog.gpsies.confirmopenpage=Webseite für den hochgeladenen Track öffnen?
+dialog.gpsies.activities=Aktivit\u00e4ten
+dialog.gpsies.activity.trekking=Wandern
+dialog.gpsies.activity.walking=Walking
+dialog.gpsies.activity.jogging=Laufen
+dialog.gpsies.activity.biking=Fahrradtour
+dialog.gpsies.activity.motorbiking=Motorrad
+dialog.gpsies.activity.snowshoe=Schneeschuh
+dialog.gpsies.activity.sailing=Segeln
+dialog.gpsies.activity.skating=Inline-Skating
+dialog.correlate.notimestamps=Die Punkte enthalten keine Zeitangaben, deshalb k\u00f6nnen die Fotos nicht zugeordnet werden.
dialog.correlate.nouncorrelatedphotos=Alle Fotos sind schon zugeordnet.\nWollen Sie trotzdem fortfahren?
-dialog.correlate.photoselect.intro=Wählen Sie eines dieser Fotos aus, um die Zeitdifferenz zu berechnen
+dialog.correlate.photoselect.intro=W\u00e4hlen Sie eines dieser Fotos aus, um die Zeitdifferenz zu berechnen
dialog.correlate.photoselect.photoname=Bezeichnung des Fotos
dialog.correlate.photoselect.timediff=Zeitdifferenz
-dialog.correlate.photoselect.photolater=Foto später
-dialog.correlate.options.tip=Tipp: Mit mindestens einem korrelierten Foto kann die Zeitdifferenz automatisch berechnet werden.
-dialog.correlate.options.intro=Wählen Sie die Optionen für die Korrelation aus
+dialog.correlate.photoselect.photolater=Foto sp\u00e4ter
+dialog.correlate.options.tip=Tipp: Mit mindestens einem manuell korrelierten Foto kann die Zeitdifferenz automatisch berechnet werden.
+dialog.correlate.options.intro=W\u00e4hlen Sie die Optionen f\u00fcr die Korrelation aus
dialog.correlate.options.offsetpanel=Zeitunterschied
dialog.correlate.options.offset=Unterschied
dialog.correlate.options.offset.hours=Stunden,
dialog.correlate.options.offset.minutes=Minuten und
dialog.correlate.options.offset.seconds=Sekunden
-dialog.correlate.options.photolater=Foto später als Punkt
-dialog.correlate.options.pointlater=Punkt später als Foto
+dialog.correlate.options.photolater=Foto sp\u00e4ter als Punkt
+dialog.correlate.options.pointlater=Punkt sp\u00e4ter als Foto
dialog.correlate.options.limitspanel=Korrelation Grenzen
dialog.correlate.options.notimelimit=Keine Zeitgrenzen
dialog.correlate.options.timelimit=Zeitgrenzen
dialog.correlate.options.nodistancelimit=Keine Distanzgrenzen
dialog.correlate.options.distancelimit=Distanzgrenzen
dialog.correlate.options.correlate=Korrelieren
-dialog.correlate.alloutsiderange=Alle Fotos sind außerhalb vom Track Zeitraum. Sie können nicht korreliert werden.\nVersuchen Sie es mit einem anderen Offset oder binden Sie manuell mindestens ein Foto ein.
+dialog.correlate.alloutsiderange=Alle Fotos sind au\u00dferhalb des Track Zeitraums. Sie k\u00f6nnen nicht korreliert werden.\nVersuchen Sie es mit einem anderen Offset oder binden Sie manuell mindestens ein Foto ein.
dialog.rearrangephotos.desc=Setzen Sie das Ziel und die Reihenfolge der Fotopunkte
dialog.rearrangephotos.tostart=Am Anfang
dialog.rearrangephotos.toend=Am Ende
dialog.rearrangephotos.sortbyfilename=per Dateiname sortieren
dialog.rearrangephotos.sortbytime=per Zeitstempel sortieren
dialog.compress.nonefound=Es konnten keine Punkte entfernt werden
-dialog.compress.duplicates.title=Duplikate entfernen
dialog.compress.closepoints.title=Nahegelegene Punkte entfernen
dialog.compress.closepoints.paramdesc=Span Faktor
-dialog.compress.wackypoints.title=Ungewöhnliche Punkte entfernen
+dialog.compress.wackypoints.title=Ungew\u00f6hnliche Punkte entfernen
dialog.compress.wackypoints.paramdesc=Distanzfaktor
dialog.compress.singletons.title=Singletons (isolierte Punkte) entfernen
dialog.compress.singletons.paramdesc=Distanzfaktor
+dialog.compress.duplicates.title=Duplikate entfernen
dialog.compress.summarylabel=Punkte zu entfernen
dialog.pastecoordinates.desc=Geben Sie die Koordinaten ein
dialog.pastecoordinates.coords=Koordinaten
-dialog.pastecoordinates.nothingfound=Bitte prüfen Sie die Koordinaten und versuchen nochmals
+dialog.pastecoordinates.nothingfound=Bitte pr\u00fcfen Sie die Koordinaten und versuchen Sie es nochmals
dialog.help.help=Weitere Informationen und Benutzeranleitungen finden Sie unter\n http://activityworkshop.net/software/prune/
dialog.about.version=Version
dialog.about.build=Build
-dialog.about.summarytext1=Prune ist ein Programm zum Laden, Darstellen und Editieren von Daten von GPS Geräten.
-dialog.about.summarytext2=Es wird unter der Gnu GPL zur Verfügung gestellt, zum freien, kostenlosen und offenen Gebrauch und zur Weiterentwicklung.<br>Kopieren, Weiterverbreitung und Veränderungen sind erlaubt und willkommen<br>unter den in der <code>license.txt</code> Datei enthaltenen Bedingungen.
-dialog.about.summarytext3=Auf der Seite <code style="font-weight:bold">http://activityworkshop.net/</code> finden Sie weitere Information und Benutzeranleitungen.
-dialog.about.languages=Verfügbare Sprachen
-dialog.about.translatedby=Deutsche Übersetzung von activityworkshop.
-dialog.about.systeminfo=System Information
-dialog.about.systeminfo.os=Betriebsystem
+dialog.about.summarytext1=Prune ist ein Programm zum Laden, Darstellen und Editieren von Daten von GPS Ger\u00e4ten.
+dialog.about.summarytext2=Es wird unter der Gnu GPL zur Verf\u00fcgung gestellt, zum freien, kostenlosen und offenen Gebrauch und zur Weiterentwicklung.<br>Kopieren, Weiterverbreitung und Ver\u00e4nderungen sind erlaubt und willkommen<br>unter den in der <code>license.txt</code> Datei enthaltenen Bedingungen.
+dialog.about.summarytext3=Auf der Seite <code style="font-weight:bold">http://activityworkshop.net/</code> finden Sie weitere Informationen und Bedienungsanleitungen.
+dialog.about.languages=Verf\u00fcgbare Sprachen
+dialog.about.translatedby=Deutsche \u00dcbersetzung von activityworkshop.
+dialog.about.systeminfo=System Informationen
+dialog.about.systeminfo.os=Betriebssystem
dialog.about.systeminfo.java=Java Runtime
dialog.about.systeminfo.java3d=Java3d installiert
dialog.about.systeminfo.povray=Povray installiert
dialog.about.credits.exifcode=Exif Code von
dialog.about.credits.icons=Einige Bilder von
dialog.about.credits.translators=Dolmetscher
-dialog.about.credits.translations=Übersetzungen mit Hilfe von
+dialog.about.credits.translations=\u00dcbersetzungen mit Hilfe von
dialog.about.credits.devtools=Entwicklungsprogramme
dialog.about.credits.othertools=Andere Programme
-dialog.about.credits.thanks=Danke an
+dialog.about.credits.thanks=Dank an
dialog.about.readme=Liesmich
-dialog.checkversion.error=Die Versionnummer konnte nicht ermittelt werden.\nBitte prüfen Sie die Internet Verbindung.
-dialog.checkversion.uptodate=Sie haben schon die letzte Version vom Prune.
-dialog.checkversion.newversion1=Eine neue Version vom Prune ist jetzt verfügbar! Die neue Version heißt Version
+dialog.checkversion.error=Die Versionnummer konnte nicht ermittelt werden.\nBitte pr\u00fcfen Sie die Internet Verbindung.
+dialog.checkversion.uptodate=Sie haben schon die neueste Version von Prune.
+dialog.checkversion.newversion1=Eine neue Version vom Prune ist jetzt verf\u00fcgbar! Die neue Version ist Version
dialog.checkversion.newversion2=.
dialog.checkversion.releasedate1=Diese neue Version ist am
-dialog.checkversion.releasedate2=veröffentlicht worden.
+dialog.checkversion.releasedate2=ver\u00f6ffentlicht worden.
dialog.checkversion.download=Um die neue Version herunterzuladen, gehen Sie zu http://activityworkshop.net/software/prune/download.html.
-dialog.keys.intro=Anstatt die Maus können Sie diesen Taste-Kombinationen nutzen
-dialog.keys.keylist=<table><tr><td>Pfeil Tasten</td><td>Karte verschieben</td></tr><tr><td>Strg + links, rechts Pfeil</td><td>Vorherigen oder nächsten Punkt markieren</td></tr><tr><td>Strg + auf, abwärts Pfeil</td><td>Ein- oder Auszoomen</td></tr><tr><td>Strg + Bild auf, ab</td><td>Vorherigen oder nächsten Segment markieren</td></tr><tr><td>Strg + Pos1, Ende</td><td>Ersten oder letzten Punkt markieren</td></tr><tr><td>Entf</td><td>Aktuellen Punkt entfernen</td></tr></table>
-dialog.saveconfig.desc=Die folgende Einstellungen können gespeichert werden :
+dialog.keys.intro=Anstelle der Maus k\u00f6nnen Sie folgende Tastenkombinationen nutzen
+dialog.keys.keylist=<table><tr><td>Pfeil Tasten</td><td>Karte verschieben</td></tr><tr><td>Strg + links, rechts Pfeil</td><td>Vorherigen oder n\u00e4chsten Punkt markieren</td></tr><tr><td>Strg + auf, abw\u00e4rts Pfeil</td><td>Ein- oder Auszoomen</td></tr><tr><td>Strg + Bild auf, ab</td><td>Vorherigen oder n\u00e4chsten Segment markieren</td></tr><tr><td>Strg + Pos1, Ende</td><td>Ersten oder letzten Punkt markieren</td></tr><tr><td>Entf</td><td>Aktuellen Punkt entfernen</td></tr></table>
+dialog.keys.normalmodifier=Strg
+dialog.keys.macmodifier=Kommando
+dialog.saveconfig.desc=Die folgende Einstellungen k\u00f6nnen gespeichert werden:
dialog.saveconfig.prune.trackdirectory=Datenverzeichnis
dialog.saveconfig.prune.photodirectory=Fotoverzeichnis
-dialog.saveconfig.prune.languagecode=Sprachecode (DE)
-dialog.saveconfig.prune.languagefile=Sprachedatei
-dialog.saveconfig.prune.gpsdevice=GPS Gerätename
+dialog.saveconfig.prune.languagecode=Sprachcode (DE)
+dialog.saveconfig.prune.languagefile=Sprachdatei
+dialog.saveconfig.prune.gpsdevice=GPS Ger\u00e4tename
dialog.saveconfig.prune.gpsformat=GPS Format
dialog.saveconfig.prune.povrayfont=Povray Font
dialog.saveconfig.prune.metricunits=Metrische Einheiten verwenden?
dialog.saveconfig.prune.gpsbabelpath=Gpsbabel Pfad
dialog.saveconfig.prune.exiftoolpath=Exiftool Pfad
dialog.saveconfig.prune.mapsource=Kartenserver Index
-dialog.saveconfig.prune.mapsourcelist=Kartenservers
+dialog.saveconfig.prune.mapsourcelist=Kartenserver
dialog.saveconfig.prune.diskcache=Kartenordner
dialog.saveconfig.prune.kmzimagewidth=Bildbreite in KMZ
-dialog.saveconfig.prune.kmzimageheight=Bildhöhe in KMZ
-dialog.saveconfig.prune.colourscheme=Farbenschema
+dialog.saveconfig.prune.kmzimageheight=Bildh\u00f6he in KMZ
+dialog.saveconfig.prune.colourscheme=Farbschema
dialog.saveconfig.prune.kmltrackcolour=KML Trackfarbe
-dialog.setpaths.intro=Sie können hier die Pfade für externe Applikationen setzen:
+dialog.setpaths.intro=Sie k\u00f6nnen hier die Pfade f\u00fcr externe Applikationen setzen:
dialog.setpaths.found=Pfad gefunden?
-dialog.addaltitude.noaltitudes=Der markierten Bereich enthält keine Höhenangaben
-dialog.addaltitude.desc=Höhenverschiebung aufzurechnen
-dialog.setcolours.intro=Klicken Sie auf einer Farbe um sie zu ändern
+dialog.addaltitude.noaltitudes=Der markierte Bereich enth\u00e4lt keine H\u00f6henangaben
+dialog.addaltitude.desc=Hinzuzurechnende H\u00f6henverschiebung
+dialog.lookupsrtm.overwritezeros=H\u00f6henangaben von null \u00fcberschreiben?
+dialog.setcolours.intro=Klicken Sie auf eine Farbe um sie zu \u00e4ndern
dialog.setcolours.background=Hintergrund
dialog.setcolours.borders=Umrandungen
dialog.setcolours.lines=Linien
-dialog.setcolours.primary=Primär
-dialog.setcolours.secondary=Secondär
+dialog.setcolours.primary=Prim\u00e4r
+dialog.setcolours.secondary=Second\u00e4r
dialog.setcolours.point=Punkte
dialog.setcolours.selection=Bereich
dialog.setcolours.text=Texte
-dialog.colourchooser.title=Farbe auswählen
+dialog.colourchooser.title=Farbe ausw\u00e4hlen
dialog.colourchooser.red=Rot
-dialog.colourchooser.green=Grün
+dialog.colourchooser.green=Gr\u00fcn
dialog.colourchooser.blue=Blau
-dialog.setlanguage.firstintro=Sie können entweder eine von den eingebauten Sprachen<p>oder eine Text-Datei auswählen.
-dialog.setlanguage.secondintro=Sie müssen Ihre Einstellungen speichern und dann<p>Prune wieder neustarten um die Sprache zu ändern.
+dialog.setlanguage.firstintro=Sie k\u00f6nnen entweder eine von den mitgelieferten Sprachen<p>oder eine Text-Datei ausw\u00e4hlen.
+dialog.setlanguage.secondintro=Sie m\u00fcssen Ihre Einstellungen speichern und dann<p>Prune neu starten um die Sprache zu \u00e4ndern.
dialog.setlanguage.language=Sprache
-dialog.setlanguage.languagefile=Sprache Datei
-dialog.setlanguage.endmessage=Nun speichern Sie Ihre Einstellungen und starten Sie Prune neu\num die neue Sprache zu verwenden.
-dialog.diskcache.save=Karten zum Disk speichern
+dialog.setlanguage.languagefile=Sprachdatei
+dialog.setlanguage.endmessage=Speichern Sie nun Ihre Einstellungen und starten Sie Prune neu\num die neue Sprache zu verwenden.
+dialog.diskcache.save=Karten auf Festplatte speichern
dialog.diskcache.dir=Kartenordner
-dialog.diskcache.createdir=Ordner kreieren
-dialog.diskcache.nocreate=Ordner wurde nicht kreiert
+dialog.diskcache.createdir=Ordner anlegen
+dialog.diskcache.nocreate=Ordner wurde nicht angelegt
+dialog.deletefieldvalues.intro=W\u00e4hlen Sie das Feld aus, die Sie l\u00f6schen m\u00f6chten
# 3d window
dialog.3d.title=Prune 3D Ansicht
-dialog.3d.altitudecap=Minimum Höhenskala
+dialog.3d.altitudecap=Minimum H\u00f6henskala
+dialog.3d.altitudefactor=Vervielfachungsfaktor für Höhen
dialog.3dlines.title=Prune Gitterlinien
dialog.3dlines.empty=Keine Linien zum Anzeigen!
-dialog.3dlines.intro=Hier sind die Linien für die 3D Ansicht
+dialog.3dlines.intro=Hier sind die Linien f\u00fcr die 3D Ansicht
# Confirm messages || These are displayed as confirmation in the status bar
-confirm.loadfile=Daten geladen vom
+confirm.loadfile=Daten aus Datei geladen
confirm.save.ok1=Es wurden
confirm.save.ok2=Punkte gespeichert nach
confirm.deletepoint.single=Punkt wurde entfernt
confirm.mergetracksegments=Trackabschnitte verbunden
confirm.reverserange=Bereich umgekehrt
confirm.addtimeoffset=Zeitverschiebung aufgerechnet
-confirm.addaltitudeoffset=Höhenverschiebung aufgerechnet
+confirm.addaltitudeoffset=H\u00f6henverschiebung aufgerechnet
confirm.rearrangewaypoints=Wegpunkte reorganisiert
confirm.rearrangephotos=Fotos reorganisiert
confirm.cutandmove=Bereich verschoben
-confirm.convertnamestotimes=Wegpunktnamen verwandelt
+confirm.convertnamestotimes=Wegpunktnamen umgewandelt
confirm.saveexif.ok1=Es wurden
confirm.saveexif.ok2=Fotodateien geschrieben
-confirm.undo.single=Operation rückgängig gemacht
-confirm.undo.multi=Operationen rückgängig gemacht
+confirm.undo.single=Operation r\u00fcckg\u00e4ngig gemacht
+confirm.undo.multi=Operationen r\u00fcckg\u00e4ngig gemacht
confirm.jpegload.single=Foto wurde geladen
confirm.jpegload.multi=Fotos wurden geladen
confirm.photo.connect=Foto verbunden
confirm.photo.disconnect=Foto getrennt
confirm.correlate.single=Foto wurde korreliert
confirm.correlate.multi=Fotos wurden korreliert
-confirm.createpoint=Punkt kreiert
-confirm.rotatephoto=Foto umgedreht
+confirm.createpoint=Punkt erzeugt
+confirm.rotatephoto=Foto gedreht
confirm.running=In Bearbeitung ...
-confirm.lookupsrtm1=Es wurde
-confirm.lookupsrtm2=Höhenwerte gefunden
+confirm.lookupsrtm1=Es wurden
+confirm.lookupsrtm2=H\u00f6henwerte gefunden
+confirm.deletefieldvalues=Feldwerte gelöscht
-# Buttons
+# Buttons || These are all the texts for buttons
button.ok=OK
-button.back=Zurück
-button.next=Vorwärts
+button.back=Zur\u00fcck
+button.next=Vorw\u00e4rts
button.finish=Fertig
button.cancel=Abbrechen
-button.overwrite=Überschreiben
+button.overwrite=\u00dcberschreiben
button.moveup=Nach oben verschieben
button.movedown=Nach unten verschieben
button.showlines=Linien anzeigen
button.edit=Bearbeiten
button.exit=Beenden
-button.close=Schließen
+button.close=Schlie\u00dfen
button.continue=Fortsetzen
button.yes=Ja
button.no=Nein
-button.yestoall=Ja für alle
-button.notoall=Nein für alle
-button.select=Auswählen
-button.selectall=Alle auswählen
-button.selectnone=Nichts auswählen
+button.yestoall=Ja f\u00fcr alle
+button.notoall=Nein f\u00fcr alle
+button.select=Ausw\u00e4hlen
+button.selectall=Alle ausw\u00e4hlen
+button.selectnone=Nichts ausw\u00e4hlen
button.preview=Vorschau
button.load=Laden
+button.upload=Hochladen
button.guessfields=Felder erraten
button.showwebpage=Webseite anzeigen
-button.check=Prüfen
-button.resettodefaults=Zurücksetzen
+button.check=Pr\u00fcfen
+button.resettodefaults=Zur\u00fccksetzen
button.browse=Durchsuchen...
-button.addnew=Hinzufügen
+button.addnew=Hinzuf\u00fcgen
button.delete=Entfernen
# File types
# Display components
display.nodata=Keine Daten geladen
-display.noaltitudes=Track enthält keine Höhenangaben
-display.notimestamps=Track enthält keine Zeitstempeln
-details.trackdetails=Details vom Track
+display.noaltitudes=Track enth\u00e4lt keine H\u00f6henangaben
+display.notimestamps=Track enth\u00e4lt keine Zeitstempel
+details.trackdetails=Details des Tracks
details.notrack=Kein Track geladen
details.track.points=Punkte
details.track.file=Datei
details.track.numfiles=Anzahl Dateien
-details.pointdetails=Details vom Punkt
+details.pointdetails=Details des Punkts
details.index.selected=Index
details.index.of=von
details.nopointselection=Nichts selektiert
details.photofile=Fotodatei
-details.norangeselection=Kein Bereich ausgewählt
+details.norangeselection=Kein Bereich ausgew\u00e4hlt
details.rangedetails=Details der Auswahl
details.range.selected=Markiert
details.range.to=bis
details.range.climb=Aufstieg
details.range.descent=Abstieg
details.coordformat=Koordinatenformat
-details.distanceunits=Distanz Maßeinheiten
+details.distanceunits=Distanz Ma\u00dfeinheiten
display.range.time.secs=s
display.range.time.mins=m
display.range.time.hours=h
display.range.time.days=T
-details.range.avespeed=Geschwindigkeit
-details.range.avemovingspeed=Geschwindigkeit unterwegs
-details.range.maxspeed=Höchstgeschwindigkeit
+details.range.avespeed=Durchschnittsgeschwindigkeit
+details.range.avemovingspeed=Durchschnittsgeschwindigkeit unterwegs
+details.range.maxspeed=H\u00f6chstgeschwindigkeit
details.range.numsegments=Anzahl Abschnitte
details.range.pace=Tempo
-details.range.gradient=Gefälle
+details.range.gradient=Gef\u00e4lle
details.waypointsphotos.waypoints=Wegpunkte
details.waypointsphotos.photos=Fotos
details.photodetails=Fotodetails
-details.nophoto=Kein Foto ausgewählt
+details.nophoto=Kein Foto ausgew\u00e4hlt
details.photo.loading=Laden
details.photo.connected=Verbunden
-map.overzoom=Keine Karten für diesen Zoomfaktor verfügbar
+map.overzoom=Keine Karten f\u00fcr diesen Zoomfaktor verf\u00fcgbar
# Field names
fieldname.latitude=Breitengrad
-fieldname.longitude=Längengrad
-fieldname.altitude=Höhe
+fieldname.longitude=L\u00e4ngengrad
+fieldname.altitude=H\u00f6he
fieldname.timestamp=Zeitstempel
fieldname.time=Zeit
fieldname.waypointname=Name
fieldname.newsegment=Segment
fieldname.custom=Custom
fieldname.prefix=Feld
-fieldname.distance=Länge
+fieldname.distance=L\u00e4nge
fieldname.movingdistance=Wegstrecke
fieldname.duration=Zeitdauer
fieldname.speed=Geschwindigkeit
undo.load=Daten laden
undo.loadphotos=Fotos laden
undo.editpoint=Punkt bearbeiten
-undo.deletepoint=Punkt löschen
+undo.deletepoint=Punkt l\u00f6schen
undo.deletephoto=Foto entfernen
-undo.deleterange=Bereich löschen
+undo.deleterange=Bereich l\u00f6schen
undo.compress=Track komprimieren
-undo.insert=Punkte hinzufügen
+undo.insert=Punkte hinzuf\u00fcgen
undo.reverse=Bereich umdrehen
undo.mergetracksegments=Trackabschnitte verbinden
undo.addtimeoffset=Zeitverschiebung aufrechnen
-undo.addaltitudeoffset=Höhenverschiebung aufrechnen
+undo.addaltitudeoffset=H\u00f6henverschiebung aufrechnen
undo.rearrangewaypoints=Wegpunkte reorganisieren
undo.cutandmove=Bereich verschieben
undo.connectphoto=Foto verbinden
undo.disconnectphoto=Foto trennen
undo.correlate=Fotos korrelieren
undo.rearrangephotos=Fotos reorganisieren
-undo.rotatephoto=Foto umdrehen
undo.createpoint=Punkt erzeugen
-undo.convertnamestotimes=Namen in Zeitstempeln verwandeln
-undo.lookupsrtm=Höhendaten von SRTM holen
+undo.rotatephoto=Foto umdrehen
+undo.convertnamestotimes=Namen in Zeitstempel umwandeln
+undo.lookupsrtm=H\u00f6hendaten von SRTM holen
+undo.deletefieldvalues=Feldwerte löschen
# Error messages
error.save.dialogtitle=Fehler beim Speichern
-error.save.nodata=Keine Daten zum Sichern vorhanden
+error.save.nodata=Keine Daten zum Speichern vorhanden
error.save.failed=Speichern von Daten in Datei fehlgeschlagen
error.saveexif.filenotfound=Foto Datei nicht gefunden
error.saveexif.cannotoverwrite1=Foto Datei
-error.saveexif.cannotoverwrite2=ist schreib-geschützt. Als Kopie speichern?
+error.saveexif.cannotoverwrite2=ist schreibgesch\u00fctzt. Als Kopie speichern?
error.saveexif.failed1=
-error.saveexif.failed2=von den Bildern konnten nicht gespeichert werden
-error.saveexif.forced1=
-error.saveexif.forced2=von den Bildern mussten forziert werden
+error.saveexif.failed2=Bilder konnten nicht gespeichert werden
+error.saveexif.forced1=Bei
+error.saveexif.forced2=der Bilder musste das Speichern erzwungen werden
error.load.dialogtitle=Fehler beim Laden
error.load.noread=Datei konnte nicht gelesen werden
-error.load.nopoints=Keine gültigen Daten in Datei gefunden
+error.load.nopoints=Keine g\u00fcltigen Daten in Datei gefunden
error.load.unknownxml=Unbekanntes xml Format:
error.load.noxmlinzip=Keine xml Datei in Zip Datei gefunden
-error.load.othererror=Fehler beim Lesen von der Datei:
+error.load.othererror=Fehler beim Lesen der Datei:
error.jpegload.dialogtitle=Fehler beim Laden von Fotos
error.jpegload.nofilesfound=Keine Dateien gefunden
error.jpegload.nojpegsfound=Keine Jpeg Dateien gefunden
error.jpegload.noexiffound=Keine EXIF Information gefunden
error.jpegload.nogpsfound=Keine GPS Information gefunden
-error.jpegload.exifreadfailed=EXIF Aufruf fehlgeschlagen. Keine EXIF Information können gelesen werden\nohne einen internen oder externen Bibliothek.
-error.gpsload.unknown=Unbekanntes Fehler
+error.jpegload.exifreadfailed=EXIF Aufruf fehlgeschlagen. Keine EXIF Information k\u00f6nnen gelesen werden\nohne einen internen oder externen Bibliothek.
+error.gpsload.unknown=Unbekannter Fehler
error.undofailed.title=Undo fehlgeschlagen
-error.undofailed.text=Operation konnte nicht rückgängig gemacht werden
+error.undofailed.text=Operation konnte nicht r\u00fcckg\u00e4ngig gemacht werden
error.function.noop.title=Funktion hat nichts bewirkt
error.rearrange.noop=Die Punkte zu reorganisieren hatte keinen Effekt
-error.function.notavailable.title=Funktion nicht verfügbar
-error.function.nojava3d=Diese Funktion benötigt die Java3d Library,\nvon Sun.com erhältlich.
+error.function.notavailable.title=Funktion nicht verf\u00fcgbar
+error.function.nojava3d=Diese Funktion ben\u00f6tigt die Java3d Library,\nvon Sun.com erh\u00e4ltlich.
error.3d=Ein Fehler ist bei der 3D Darstellung aufgetreten
error.readme.notfound=Liesmich Datei nicht gefunden
error.osmimage.dialogtitle=Laden von Karten-Bildern fehlgeschlagen
-error.osmimage.failed=Laden von Karten-Bildern fehlgeschlagen. Bitte prüfen Sie die Internetverbindung.
-error.language.wrongfile=Die ausgewählte Datei scheint keine Sprache-Datei für Prune zu sein
-error.convertnamestotimes.nonames=Keine Namen konnten verwandelt werden
-error.lookupsrtm.none=Keine Höhendaten gefunden
+error.osmimage.failed=Laden von Karten-Bildern fehlgeschlagen. Bitte pr\u00fcfen Sie die Internetverbindung.
+error.language.wrongfile=Die ausgew\u00e4hlte Datei scheint keine Sprachdatei f\u00fcr Prune zu sein
+error.convertnamestotimes.nonames=Es konnten keine Namen umgewandelt werden
+error.lookupsrtm.nonefound=Keine H\u00f6hendaten verfügbar für diese Punkte
+error.lookupsrtm.nonerequired=Alle Punkte haben schon Höhendaten
+error.gpsies.uploadnotok=Der Gpsies Server hat geantwortet
+error.gpsies.uploadfailed=Das Hochladen ist fehlgeschlagen
# Menu entries
menu.file=File
menu.file.addphotos=Fötelis innätue
-menu.file.save=Speichere
+menu.file.save=Als Text Speichere
menu.file.exit=Beände
menu.track=Track
menu.track.undo=Undo
menu.photo.disconnect=Vonem Punkt trännä
menu.photo.delete=Föteli entfernä
menu.view=Aasicht
+menu.view.showsidebars=Seiteleischten aazeige
menu.view.browser=Karte inem Browser
menu.settings=Iistellige
menu.settings.onlinemode=Karte uusem Internet lade
function.exportkml=KML exportierä
function.exportgpx=GPX exportierä
function.exportpov=POV exportierä
+function.exportsvg=SVG exportierä
function.editwaypointname=Waypoint Name editiere
function.compress=Track komprimierä
function.addtimeoffset=Ziitverschiebig zutue
function.addaltitudeoffset=Höchiverschiebig zutue
function.findwaypoint=Waypoint suechä
function.convertnamestotimes=Waypointname ins Ziitstämple verwondle
+function.deletefieldvalues=Werte von nem Fäld lösche
function.pastecoordinates=Noii Koordinaten iigebe
function.charts=Diagramme
function.show3d=Drüü-D Aasicht
function.fullrangedetails=Zuesätzlichi Beriichinfos
function.setmapbg=Karte Hintegrund setzä
function.getgpsies=Gpsies Tracks holä
+function.uploadgpsies=Date zum Gpsies uufaladä
function.lookupsrtm=Höhendate vonem SRTM hole
function.duplicatepoint=Punkt verdopplä
function.correlatephotos=Fötelis korrelierä
dialog.openoptions.deliminfo.norecords=Kei Rekords
dialog.openoptions.altitudeunits=Höchi Masseiheite
dialog.open.contentsdoubled=Dieses File hät zwei Kopien von jädem Punkt,\neimol als Waypoint und eimol als Trackpunkt.
+dialog.selecttracks.intro=Wählet Sie die Tracks uus zum ladä
+dialog.selecttracks.noname=Unbenannt
dialog.jpegload.subdirectories=Subordnern au
dialog.jpegload.loadjpegswithoutcoords=Au Fötelis ohni Koordinate
dialog.jpegload.loadjpegsoutsidearea=Au Fötelis uuserhalb vonem Track
dialog.exportpov.ballsandsticks=Bälle und Schtange
dialog.exportpov.tubesandwalls=Röhre und Wände
dialog.exportpov.warningtracksize=Dieser Track hät mega viele Punkte, die Java3D villiicht nöd chann bearbeite.\nSind Sie sicher, Sie wend trotzdem fortsetze?
+dialog.exportsvg.text=Wählet Sie die Parameter fürs SVG Export uus
+dialog.exportsvg.phi=Richtigswinkel \u03D5
+dialog.exportsvg.theta=Neigigswinkel \u03B8
+dialog.exportsvg.gradients=Farbeverläufe verwände
dialog.pointtype.desc=Folgende Punkttype speichere:
dialog.pointtype.track=Trackpunkte
dialog.pointtype.waypoint=Waypoints
dialog.gpsies.description=Beschriebig
dialog.gpsies.nodescription=Kei Beschriebig
dialog.gpsies.nonefound=Kei Tracks gfunde
+dialog.gpsies.username=Gpsies Username
+dialog.gpsies.password=Gpsies Passwort
+dialog.gpsies.keepprivate=Track privat halte
+dialog.gpsies.confirmopenpage=Websiite fürn uufageladenen Track öffne?
+dialog.gpsies.activities=Aktivit\u00e4ten
+dialog.gpsies.activity.trekking=Wandere
+dialog.gpsies.activity.walking=Z'Fuess gah
+dialog.gpsies.activity.jogging=Seggle
+dialog.gpsies.activity.biking=Velotour
+dialog.gpsies.activity.motorbiking=Motorrad
+dialog.gpsies.activity.snowshoe=Schneeschuh
+dialog.gpsies.activity.sailing=Segle
+dialog.gpsies.activity.skating=Inline-Skate
dialog.correlate.notimestamps=Es hät kei Ziitstämpel inem Track innä, so s'isch nöd möglech die Fötelis zu korrelierä.
dialog.correlate.nouncorrelatedphotos=Alle Fötelis sin scho korreliert.\nWend Sie trotzdem fortsetzä?
dialog.correlate.photoselect.intro=Wählet Sie eini vo deren Föteli uus, um die Ziitdifferänz zu berächnä
dialog.checkversion.download=Um die noii Version runterzlade, schauet Sie na http://activityworkshop.net/software/prune/download.html.
dialog.keys.intro=Aastatt d'Muus könnet Sie diese Tastekombinationen nutze
dialog.keys.keylist=<table><tr><td>Pfiil Taste</td><td>Karte verschiebe</td></tr><tr><td>Strg + links, rächts Pfiil</td><td>Vorherigi oder nöchsti Punkt markiere</td></tr><tr><td>Strg + uuf, aba Pfiil</td><td>Ii- oder Uusezoome</td></tr><tr><td>Strg + Bild uuf, ab</td><td>Vorherigi oder nöchsti Segmänt markiere</td></tr><tr><td>Strg + Pos1, Ende</td><td>Erschti oder letschti Punkt markiere</td></tr><tr><td>Entf</td><td>Aktuelli Punkt lösche</td></tr></table>
+dialog.keys.normalmodifier=Strg
+dialog.keys.macmodifier=Kommando
dialog.saveconfig.desc=Die folgendi Iinstellige könne gspeicheret werde :
dialog.saveconfig.prune.trackdirectory=Trackverzeichnis
dialog.saveconfig.prune.photodirectory=Föteliverzeichnis
dialog.setpaths.found=Pfad gfunde?
dialog.addaltitude.noaltitudes=Dr seläktierte Beriich hät keini Höchiinformation
dialog.addaltitude.desc=Höchiverschiebig zuzutue
+dialog.lookupsrtm.overwritezeros=Höchiwärte von null überschriebä?
dialog.setcolours.intro=Klicket Sie uuf ne Farb um sie z'verändere
dialog.setcolours.background=Hintergrund
dialog.setcolours.borders=Rande
dialog.diskcache.dir=Kartenordner
dialog.diskcache.createdir=Ordner kreiere
dialog.diskcache.nocreate=Ordner isch nöd kreiert worde
+dialog.deletefieldvalues.intro=Wählet Sie s Fäld uus zum lösche
# 3d window
dialog.3d.title=Prune Drüü-d Aasicht
dialog.3d.altitudecap=Minimum Höhenskala
+dialog.3d.altitudefactor=Höchivervilfachigsfaktor
dialog.3dlines.title=Prune Gitterlinie
dialog.3dlines.empty=Kei Linie zum aazeigä!
dialog.3dlines.intro=Hier sin die Linie für die drüü-D Aasicht
-# Confirm messages || These are displayed as confirmation in the status bar
+# Confirm messages
confirm.loadfile=Date glade vom
confirm.save.ok1=Es sin
confirm.save.ok2=Punkte gspeicheret worde na
confirm.running=Am Laufe ...
confirm.lookupsrtm1=Es sin
confirm.lookupsrtm2=Höhenwerte gfunde
+confirm.deletefieldvalues=Feldwärte glöscht
# Buttons
button.ok=OK
button.selectnone=Nüüt uuswähle
button.preview=Vorschauä
button.load=Ladä
+button.upload=Uufaladä
button.guessfields=Fälde erratä
button.showwebpage=Websiite aazeigä
button.check=Prüefa
undo.createpoint=Punkt kreierä
undo.rotatephoto=Föteli umadräya
undo.convertnamestotimes=Name ins Ziitstämple verwondlä
-undo.lookupsrtm=Höhendate vonem SRTM hole
+undo.lookupsrtm=Höhendate vonem SRTM holä
+undo.deletefieldvalues=Feldwärte löschä
# Error messages
error.save.dialogtitle=Fähle bim Speichere
error.osmimage.failed=Map Bildli könne nöd glade werde. Gits ne Internet Verbindig?
error.language.wrongfile=Die uusgewählti Datei scheint kei Sproch-Datei für Prune z'sii
error.convertnamestotimes.nonames=Kei Namen han könnet verwondlet werde
-error.lookupsrtm.none=Kei Höhendate gfunde
+error.lookupsrtm.nonefound=Kei Höhendate verfüegbar für d'Punkte
+error.lookupsrtm.nonerequired=Alle Punkte han die Höhendate scho. Nüüt z'tue.
+error.gpsies.uploadnotok=Der Gpsies Server hät gseit gha
+error.gpsies.uploadfailed=S Uufalade isch fehlgschlage
# Menu entries
menu.file=File
menu.file.addphotos=Add photos
-menu.file.save=Save
+menu.file.save=Save as text
menu.file.exit=Exit
menu.track=Track
menu.track.undo=Undo
menu.photo.disconnect=Disconnect from point
menu.photo.delete=Remove photo
menu.view=View
-menu.view.browser=Map in browser
+menu.view.showsidebars=Show sidebars
+menu.view.browser=Map in a browser window
menu.view.browser.google=Google maps
menu.view.browser.openstreetmap=Openstreetmap
menu.view.browser.mapquest=Mapquest
function.exportkml=Export KML
function.exportgpx=Export GPX
function.exportpov=Export POV
+function.exportsvg=Export SVG
function.editwaypointname=Edit waypoint name
function.compress=Compress track
function.addtimeoffset=Add time offset
function.addaltitudeoffset=Add altitude offset
function.findwaypoint=Find waypoint
function.convertnamestotimes=Convert waypoint names to times
+function.deletefieldvalues=Delete field values
function.pastecoordinates=Enter new coordinates
function.charts=Charts
function.show3d=Three-D view
function.distances=Distances
function.fullrangedetails=Full range details
function.getgpsies=Get Gpsies tracks
+function.uploadgpsies=Upload track to Gpsies
function.lookupsrtm=Get altitudes from SRTM
function.duplicatepoint=Duplicate point
function.correlatephotos=Correlate photos
dialog.openoptions.deliminfo.norecords=No records
dialog.openoptions.altitudeunits=Altitude units
dialog.open.contentsdoubled=This file contains two copies of each point,\nonce as waypoints and once as track points.
+dialog.selecttracks.intro=Select the track or tracks to load
+dialog.selecttracks.noname=Unnamed
dialog.jpegload.subdirectories=Include subdirectories
dialog.jpegload.loadjpegswithoutcoords=Include photos without coordinates
dialog.jpegload.loadjpegsoutsidearea=Include photos outside current area
dialog.exportpov.ballsandsticks=Balls and sticks
dialog.exportpov.tubesandwalls=Tubes and walls
dialog.exportpov.warningtracksize=This track has a large number of points, which Java3D might not be able to display.\nAre you sure you want to continue?
+dialog.exportsvg.text=Select the parameters for the SVG export
+dialog.exportsvg.phi=Azimuth angle \u03D5
+dialog.exportsvg.theta=Elevation angle \u03B8
+dialog.exportsvg.gradients=Use gradients for shading
dialog.pointtype.desc=Save the following point types:
dialog.pointtype.track=Track points
dialog.pointtype.waypoint=Waypoints
dialog.gpsies.description=Description
dialog.gpsies.nodescription=No description
dialog.gpsies.nonefound=No tracks found
+dialog.gpsies.username=Gpsies username
+dialog.gpsies.password=Gpsies password
+dialog.gpsies.keepprivate=Keep track private
+dialog.gpsies.confirmopenpage=Open the web page for the uploaded track?
+dialog.gpsies.activities=Activity types
+dialog.gpsies.activity.trekking=Hiking
+dialog.gpsies.activity.walking=Walking
+dialog.gpsies.activity.jogging=Running
+dialog.gpsies.activity.biking=Cycling
+dialog.gpsies.activity.motorbiking=Motorbiking
+dialog.gpsies.activity.snowshoe=Snowshoeing
+dialog.gpsies.activity.sailing=Sailing
+dialog.gpsies.activity.skating=Skating
dialog.correlate.notimestamps=There are no timestamps in the data points, so there is nothing to correlate with the photos.
dialog.correlate.nouncorrelatedphotos=There are no uncorrelated photos.\nAre you sure you want to continue?
dialog.correlate.photoselect.intro=Select one of these correlated photos to use as the time offset
dialog.checkversion.download=To download the new version, go to http://activityworkshop.net/software/prune/download.html.
dialog.keys.intro=You can use the following shortcut keys instead of using the mouse
dialog.keys.keylist=<table><tr><td>Arrow keys</td><td>Pan map left right, up, down</td></tr><tr><td>Ctrl + left, right arrow</td><td>Select previous or next point</td></tr><tr><td>Ctrl + up, down arrow</td><td>Zoom in or out</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Select previous, next segment</td></tr><tr><td>Ctrl + Home, End</td><td>Select first, last point</td></tr><tr><td>Del</td><td>Delete current point</td></tr></table>
+dialog.keys.normalmodifier=Ctrl
+dialog.keys.macmodifier=Command
dialog.saveconfig.desc=The following settings can be saved to a configuration file :
dialog.saveconfig.prune.trackdirectory=Track directory
dialog.saveconfig.prune.photodirectory=Photo directory
dialog.setpaths.found=Path found?
dialog.addaltitude.noaltitudes=The selected range does not contain altitudes
dialog.addaltitude.desc=Altitude offset to add
+dialog.lookupsrtm.overwritezeros=Overwrite altitude values of zero?
dialog.setcolours.intro=Click on a colour patch to change the colour
dialog.setcolours.background=Background
dialog.setcolours.borders=Borders
dialog.diskcache.dir=Cache directory
dialog.diskcache.createdir=Create directory
dialog.diskcache.nocreate=Cache directory not created
+dialog.deletefieldvalues.intro=Select the field to delete for the current range
# 3d window
dialog.3d.title=Prune Three-d view
-dialog.3d.altitudecap=Minimum altitude range
+dialog.3d.altitudecap=
+dialog.3d.altitudefactor=Altitude exaggeration factor
dialog.3dlines.title=Prune gridlines
dialog.3dlines.empty=No gridlines to display!
dialog.3dlines.intro=These are the gridlines for the three-d view
confirm.running=Running ...
confirm.lookupsrtm1=Found
confirm.lookupsrtm2=altitude values
+confirm.deletefieldvalues=Field values deleted
# Buttons
button.ok=OK
button.selectnone=Select none
button.preview=Preview
button.load=Load
+button.upload=Upload
button.guessfields=Guess fields
button.showwebpage=Show webpage
button.check=Check
undo.createpoint=create point
undo.convertnamestotimes=convert names to times
undo.lookupsrtm=lookup altitudes from SRTM
+undo.deletefieldvalues=delete field values
# Error messages
error.save.dialogtitle=Error saving data
error.osmimage.failed=Failed to load map images. Please check internet connection.
error.language.wrongfile=The selected file doesn't appear to be a language file for Prune
error.convertnamestotimes.nonames=No names could be converted into times
-error.lookupsrtm.none=No altitude values found
+error.lookupsrtm.nonefound=No altitude values available for these points
+error.lookupsrtm.nonerequired=All points already have altitudes, so there's nothing to lookup
+error.gpsies.uploadnotok=The gpsies server returned the message
+error.gpsies.uploadfailed=The upload failed with the error
menu.photo.disconnect=Desconectar de punto
menu.photo.delete=Eliminar foto
menu.view=Ver
-menu.view.browser=Mapa en un navegador
+menu.view.showsidebars=Mostrar barras laterales
+menu.view.browser=Mapa en una ventana del navegador
menu.view.browser.google=Google maps
menu.view.browser.openstreetmap=Openstreetmap
menu.view.browser.mapquest=Mapquest
menu.view.browser.yahoo=Mapas Yahoo
menu.view.browser.bing=Mapas Bing
menu.settings=Preferencias
+menu.settings.onlinemode=Cargar mapas de Internet
menu.help=Ayuda
# Popup menu for map
menu.map.zoomin=Ampliar zoom
menu.map.zoomout=Reducir zoom
menu.map.zoomfull=Mostrar todo
-menu.map.newpoint=Crear uno punto nuevo
+menu.map.newpoint=Crear un punto nuevo
menu.map.connect=Conectar puntos de track
menu.map.autopan=Posicionar autom\u00e1ticamente
menu.map.showmap=Mostrar el mapa
function.exportkml=Exportar KML
function.exportgpx=Exportar GPX
function.exportpov=Exportar POV
+function.exportsvg=Exportar SVG
function.editwaypointname=Editar nombre de waypoint
function.compress=Comprimir track
function.addtimeoffset=A\u00f1adir compensar tiempo
function.addaltitudeoffset=A\u00f1adir compensar altitud
function.convertnamestotimes=Convertir los nombres de los "waypoints" a tiempo
+function.deletefieldvalues=Borrar valores del campo
function.findwaypoint=Buscar waypoint
function.pastecoordinates=Insertar nuevas coordenadas
function.charts=Diagramas
function.setkmzimagesize=Configurar tama\u00f1os de las im\u00e1genes KMZ
function.setpaths=Configurar rutas del programas
function.getgpsies=Bajar ruta de Gpsies
+function.uploadgpsies=Subir recorrido a Gpsies
+function.lookupsrtm=Obtener altitudes de SRTM
function.duplicatepoint=Duplicar punto
function.setcolours=Establecer color
function.setlanguage=Establecer lenguaje
function.rearrangephotos=Reacomodar fotos
function.rotatephotoleft=Girar a la izquierda
function.rotatephotoright=Girar a la derecha
-function.ignoreexifthumb=Ignorar "thumbnail" de exif
+function.ignoreexifthumb=Ignorar miniatura exif
function.help=Ayuda
function.showkeys=Mostrar teclas o combinaciones de atajo
function.about=Acerca de Prune
function.checkversion=Buscar una nueva versi\u00f3n
function.saveconfig=Guardar preferencias
+function.diskcache=Guardar mapas en disco
# Dialogs
dialog.exit.confirm.title=Salir de Prune
-dialog.exit.confirm.text=Los datos han sido modificados. Desea salir de Prune?
-dialog.openappend.title=Agregar a datos existentes
-dialog.openappend.text=Agregar estos datos a los datos ya guardados?
+dialog.exit.confirm.text=¿Los datos han sido modificados. Desea salir de Prune?
+dialog.openappend.title=¿Agregar a datos existentes
+dialog.openappend.text=¿Agregar estos datos a los datos ya guardados?
dialog.deletepoint.title=Borrar punto
-dialog.deletepoint.deletephoto=Borrar la foto tambien?
+dialog.deletepoint.deletephoto=¿Borrar la foto tambien?
dialog.deletephoto.title=Borrar foto
-dialog.deletephoto.deletepoint=Borrar el punto tambien?
+dialog.deletephoto.deletepoint=¿Borrar el punto tambien?
dialog.openoptions.title=Opciones de abrir
dialog.openoptions.filesnippet=Extraer archivo
dialog.load.table.field=Campo
dialog.openoptions.deliminfo.fields=campos
dialog.openoptions.deliminfo.norecords=Ningun dato
dialog.openoptions.altitudeunits=Unidades altitud
+dialog.open.contentsdoubled=Este archivo contiene dos copias de cada punto,\nuna como "waypoints" y otra como puntos de recorrido.
+dialog.selecttracks.intro=Seleccionar recorrido/s a cargar
+dialog.selecttracks.noname=Innominados
dialog.jpegload.subdirectories=Incluir subdirectorios
dialog.jpegload.loadjpegswithoutcoords=Fotos sin coordenadas tambien
dialog.jpegload.loadjpegsoutsidearea=Incluir fotos fuera del \u00e1rea
dialog.jpegload.progress.title=Cargando fotos
dialog.jpegload.progress=Por favor espere mientras se buscan las fotos
-dialog.gpsload.nogpsbabel=gpsbabel program no encontrado. Desea continuar?
+dialog.gpsload.nogpsbabel=No se ha encontrado el programa gpsbabel. ¿Desea continuar?
dialog.gpsload.device=Dispositivo
dialog.gpsload.format=Formato
dialog.gpsload.getwaypoints=Cargar waypoints
dialog.gpsload.gettracks=Cargar tracks
dialog.gpsload.save=Salvar al archivo
-dialog.gpssend.sendwaypoints=enviar "waypoints"
-dialog.gpssend.sendtracks=enviar tracks
+dialog.gpssend.sendwaypoints=Enviar "waypoints"
+dialog.gpssend.sendtracks=Enviar tracks
dialog.gpssend.trackname=Nombre del track
dialog.saveoptions.title=Guardar archivo
dialog.save.fieldstosave=Campos a guardar
dialog.save.headerrow=T\u00edtulo fila
dialog.save.coordinateunits=Unidades de las coordenadas
dialog.save.altitudeunits=Unidades de las altitudes
-dialog.save.timestampformat=Format del tiempo
+dialog.save.timestampformat=Formato del tiempo
dialog.save.overwrite.title=El archivo ya existe
-dialog.save.overwrite.text=El archivo ya existe, desea sobreescribirlo?
+dialog.save.overwrite.text=El archivo ya existe, ¿desea sobreescribirlo?
dialog.save.notypesselected=No se han seleccionado tipos de puntos
dialog.exportkml.text=Descripci\u00f3n para los datos
dialog.exportkml.altitude=Absoluta altitudes (para aviaci\u00f3n)
dialog.exportpov.ballsandsticks=Balas en palos
dialog.exportpov.tubesandwalls=Tubos y paredes
dialog.exportpov.warningtracksize=Este track contiene un gran numero de puntos. Puede ser que Java3D no los pueda visualizar. Est\u00e1 seguro de que desea continuar?
+dialog.exportsvg.text=Seleccione los par\u00e1metros para exportar a SVG
+dialog.exportsvg.phi=Ángulo de azimuth \u03d5
+dialog.exportsvg.theta=Ángulo de elevaci\u00f3n
+dialog.exportsvg.gradients=Usar degradado para sombras
dialog.pointtype.desc=Salvar los siguientes tipos de puntos:
dialog.pointtype.track=Puntos de track
dialog.pointtype.photo=Puntos de foto
dialog.pointtype.selection=Solo selecci\u00f3n
dialog.confirmreversetrack.title=Confirmar inversi\u00f3n
-dialog.confirmreversetrack.text=Este track contiene informaci\u00f3n sobre la fecha, que estar\u00e1 fuera de secuencia despu\u00e9s de la inversi\u00f3n. Esta seguro que desea invertir esta secci\u00f3n?
+dialog.confirmreversetrack.text=Este track contiene informaci\u00f3n sobre la fecha, que estar\u00e1 fuera de secuencia despu\u00e9s de la inversi\u00f3n. ¿Est\u00e1 seguro que desea invertir esta secci\u00f3n?
dialog.confirmcutandmove.title=Confirmar accion cortar/pegar
-dialog.confirmcutandmove.text=Este track contiene informaci\u00f3n sobre la fecha, que estar\u00e1 fuera de secuencia despu\u00e9s de la .... Esta seguro que desea ... esta secci\u00f3n?
+dialog.confirmcutandmove.text=Este track contiene informaci\u00f3n sobre la fecha, que estar\u00e1 fuera de secuencia despu\u00e9s de mover.\n¿Esta seguro que desea mover esta secci\u00f3n?
dialog.interpolate.title=Interpolar puntos
dialog.interpolate.parameter.text=N\u00famero de los puntos a insertar entre los puntos elegidos
dialog.undo.title=Deshacer
dialog.undo.none.title=No se puede deshacer
dialog.undo.none.text=Ninguna operaci\u00f3n a deshacer
dialog.clearundo.title=Despejar la lista de deshacer
-dialog.clearundo.text=Esta seguro que desea despejar la lista de deshacer?, se perder\u00e1 toda la informaci\u00f3n!
+dialog.clearundo.text=¿Esta seguro que desea despejar la lista de deshacer?, ¡se perder\u00e1 toda la informaci\u00f3n!
dialog.pointedit.title=Editar punto
dialog.pointedit.text=Seleccione cada campo a editar y use el bot\u00f3n 'Editar' para modificar el valor
dialog.pointedit.table.field=Campo
dialog.pointnameedit.uppercase=May\u00fasculas
dialog.pointnameedit.lowercase=min\u00fasculas
dialog.pointnameedit.sentencecase=Mezcla
-dialog.addtimeoffset.add=a\u00f1adir tiempo
-dialog.addtimeoffset.subtract=sustraer tiempo
+dialog.addtimeoffset.add=A\u00f1adir tiempo
+dialog.addtimeoffset.subtract=Sustraer tiempo
dialog.addtimeoffset.days=Dias
dialog.addtimeoffset.hours=Horas
dialog.addtimeoffset.minutes=Minutos
-dialog.addtimeoffset.notimestamps=No se puede a\u00f1adir tiempo de puesta a esta selecci\u00f3n si \u00e9sta no contiene ninguna informaci\u00f3n de "timestamp"
+dialog.addtimeoffset.notimestamps=No se puede a\u00f1adir un margen de tiempo a esta selecci\u00f3n ya que no contiene informaci\u00f3n de tiempo.
dialog.findwaypoint.intro=Ingresar parte del nombre de "waypoint"
dialog.findwaypoint.search=Buscar
dialog.saveexif.title=Guardar Exif
dialog.saveexif.intro=Seleccione fotos a guardar
dialog.saveexif.nothingtosave=Coordenadas no modificadas, nada que guardar
-dialog.saveexif.noexiftool=exiftool program no encontrado. Desea continuar?
+dialog.saveexif.noexiftool=No se encuentra el programa exiftool. ¿Desea continuar?
dialog.saveexif.table.photoname=Nombre de la foto
dialog.saveexif.table.status=Estado
dialog.saveexif.table.save=Guardar
dialog.saveexif.photostatus.connected=Conectada
dialog.saveexif.photostatus.disconnected=Desconectada
dialog.saveexif.photostatus.modified=Modificada
-dialog.saveexif.overwrite=Sobreescribirlar archivos?
+dialog.saveexif.overwrite=Sobreescribir archivos
dialog.saveexif.force=Fuerza despreciar errores menores
dialog.charts.xaxis=Eje de abscisas
dialog.charts.yaxis=Eje vertical
dialog.charts.svgwidth=Ancho de SVG
dialog.charts.svgheight=Alto de SVG
dialog.charts.needaltitudeortimes=La pista debe tener altitudes o informaci\u00f3n de tiempo en orden para crear las tablas
-dialog.charts.gnuplotnotfound=No pudo ser encontrado gnuplot con el camino o la direcci\u00f3n proporcionada
+dialog.charts.gnuplotnotfound=No pudo ser encontrado gnuplot con la ruta proporcionada
dialog.distances.intro=L\u00edneas rectas entre puntos
dialog.distances.column.from=De punto
dialog.distances.column.to=Al punto
dialog.distances.currentpoint=Punto actual
dialog.distances.toofewpoints=Esta funcion necesita "waypoints" para poder calcular las distancias entre ellos
dialog.fullrangedetails.intro=Aqui estan los detalles para la selecci\u00f3n de rangos
-dialog.addmapsource.sourcename=Nombre de la fuente
+dialog.setmapbg.intro=Seleccione un proveedor de mapas o a\u00f1ada uno nuevo
+dialog.addmapsource.title=A\u00f1adir un proveedor de mapas
+dialog.addmapsource.sourcename=Nombre del proveedor
+dialog.addmapsource.layer1url=URL de la primera capa
+dialog.addmapsource.layer2url=URL opcional de la segunda capa
+dialog.addmapsource.maxzoom=M\u00e1ximo nivel de zoom
dialog.addmapsource.cloudstyle=N\u00famero del estilo
dialog.addmapsource.noname=Innominada
dialog.gpsies.column.name=Nombre del track
dialog.gpsies.column.length=Distancia
dialog.gpsies.description=Descripci\u00f3n
-dialog.gpsies.nodescription=Sin Descripci\u00f3n
+dialog.gpsies.nodescription=Sin descripci\u00f3n
dialog.gpsies.nonefound=No se encontraron pistas
+dialog.gpsies.username=Nombre de usuario en Gpsies
+dialog.gpsies.password=Contrase\u00f1a de Gpsies
+dialog.gpsies.keepprivate=Mantener el recorrido como privado
+dialog.gpsies.confirmopenpage=Abrir la p\u00e1gina web del recorrido subido
+dialog.gpsies.activities=Apto para
+dialog.gpsies.activity.trekking=Excursi\u00f3n
+dialog.gpsies.activity.walking=Caminar
+dialog.gpsies.activity.jogging=Correr
+dialog.gpsies.activity.biking=En bicicleta
+dialog.gpsies.activity.motorbiking=En moto
+dialog.gpsies.activity.snowshoe=Raquetas de nieve
+dialog.gpsies.activity.sailing=Vela
+dialog.gpsies.activity.skating=Patinaje
dialog.correlate.notimestamps=No hay informaci\u00f3n de tiempo para los puntos, as\u00ed que no hay nada que correlacionar con las fotos.
-dialog.correlate.nouncorrelatedphotos=No hay fotos no correlacionadas.\nEst\u00e1 seguro de que desea continuar?
+dialog.correlate.nouncorrelatedphotos=No hay fotos no correlacionadas.\n¿Est\u00e1 seguro de que desea continuar?
dialog.correlate.photoselect.intro=Seleccione una de estas fotos correlacionadas para usar como margen de tiempo
dialog.correlate.photoselect.photoname=Nombre de la foto
dialog.correlate.photoselect.timediff=Diferencia de tiempo
dialog.rearrangephotos.sortbytime=Sortear por tiempo
dialog.compress.nonefound=Ning\u00fan punto eliminado
dialog.compress.closepoints.title=remover puntos cercanos
+dialog.compress.closepoints.paramdesc=Factor de extensi\u00f3n
+dialog.compress.wackypoints.title=Eliminar puntos an\u00f3malos
dialog.compress.wackypoints.paramdesc=Factor distancia
+dialog.compress.singletons.title=Eliminar puntos aislados
dialog.compress.singletons.paramdesc=Factor distancia
dialog.compress.duplicates.title=Eliminar duplicados
dialog.compress.summarylabel=Puntos para eliminar
dialog.about.summarytext2=Distribuido bajo el GNU GPL para uso libre y gratuito.<br>Se permite (y se anima) la copia, redistribuci\u00f3n y modificaci\u00f3n de acuerdo<br>a las condiciones incluidas en el archivo <code>licence.txt</code>.
dialog.about.summarytext3=Por favor, ver <code style="font-weight:bold">http://activityworkshop.net/</code> para m\u00e1s informaci\u00f3n y gu\u00edas del usuario.
dialog.about.languages=Idiomas disponibles
-dialog.about.translatedby=Traducci\u00f3n al espa\u00f1ol realizada por activityworkshop y amigos muy amables!
+dialog.about.translatedby=Traducci\u00f3n al espa\u00f1ol realizada por Miguel, In\u00e9s, josatoc y Javier
dialog.about.systeminfo=Informacion del sistema
dialog.about.systeminfo.os=Sistema operativo
dialog.about.systeminfo.java=Java Runtime
dialog.about.systeminfo.exiftool=Exiftool instalado
dialog.about.systeminfo.gpsbabel=Gpsbabel instalado
dialog.about.systeminfo.gnuplot=Gnuplot instalado
-dialog.about.systeminfo.exiflib=Bibliotheca exif
+dialog.about.systeminfo.exiflib=Biblioteca exif
dialog.about.systeminfo.exiflib.internal=Interna
dialog.about.systeminfo.exiflib.internal.failed=Interna (no encontrada)
dialog.about.systeminfo.exiflib.external=Externa
dialog.about.systeminfo.exiflib.external.failed=Externa (no encontrada)
dialog.about.yes=Si
dialog.about.no=No
-dialog.about.credits=Creditos
+dialog.about.credits=Cr\u00e9ditos
dialog.about.credits.code=El c\u00f3digo de Prune fue escrito por
dialog.about.credits.exifcode=El c\u00f3digo Exif por
dialog.about.credits.icons=Algunos iconos se tomaron de
dialog.about.credits.othertools=Otras herramientas
dialog.about.credits.thanks=Gracias a
dialog.about.readme=Readme
-dialog.checkversion.error=El numero de versi\u00f3n no pudo ser verificada.\n Por favor verificar la conexi\u00f3n de internet
+dialog.checkversion.error=El numero de versi\u00f3n no pudo ser verificada.\n Por favor verificar la conexi\u00f3n de Internet
dialog.checkversion.uptodate=Esta usted utilizando la \u00faltima versi\u00f3n de Prune
-dialog.checkversion.newversion1=Una nueva versi\u00f3n de Prune est\u00e1 disponible! La \u00daltima versi\u00f3n es ahora versi\u00f3n
+dialog.checkversion.newversion1=¡Una nueva versi\u00f3n de Prune est\u00e1 disponible! La \u00faltima es ahora la versi\u00f3n
dialog.checkversion.newversion2=.
dialog.checkversion.releasedate1=La nueva versi\u00f3n fue lanzada en
dialog.checkversion.releasedate2=.
+dialog.checkversion.download=Para descargar la nueva versi\u00f3n visite http://activityworkshop.net/software/prune/download.html.
dialog.keys.intro=Usted puede usar el siguiente atajo en lugar de usar el rat\u00f3n
+dialog.keys.keylist=<table><tr><td>Teclas de cursor</td><td>Desplazar a la izquierde, derecha, arriba, abajo</td></tr><tr><td>Ctrl + cursor izquierda, derecha</td><td>Seleccionar punto siguiente o anterior</td></tr><tr><td>Ctrl + cursor arriba, abajo</td><td>Ampliar o reducir zoom</td></tr><tr><td>Ctrl + Av Pag, Re Pag</td><td>Seleccionar segmento siguiente, anterior</td></tr><tr><td>Ctrl + Inicio, Fin</td><td>Seleccionar primer, \u00faltimo punto</td></tr><tr><td>Supr</td><td>Eliminar punto actual</td></tr></table>
dialog.saveconfig.desc=La siguiente configuraci\u00f3n puede ser salvada en un archivo de configuraci\u00f3n
dialog.saveconfig.prune.trackdirectory=Directorio de pista
dialog.saveconfig.prune.photodirectory=Directorio de foto
dialog.saveconfig.prune.gpsdevice=Dispositivo GPS
dialog.saveconfig.prune.gpsformat=Formato GPS
dialog.saveconfig.prune.povrayfont=Fuente povray
-dialog.saveconfig.prune.metricunits=Usar unidades m\u00e9tricas?
-dialog.saveconfig.prune.gnuplotpath=Camino a gnuplot
-dialog.saveconfig.prune.gpsbabelpath=Camino a gpsbabel
-dialog.saveconfig.prune.exiftoolpath=Camino a exiftool
-dialog.saveconfig.prune.mapserverindex=\u00cdndice de mapa del servidor
-dialog.saveconfig.prune.mapserverurl=Direcci\u00f3n URL de mapa del servidor
-dialog.saveconfig.prune.mapsourcelist=Fuentes de cartas
-dialog.saveconfig.prune.diskcache=Directorio de cartas
-dialog.saveconfig.prune.kmzimagewidth=Ancho de im\u00e1genes en kmz
-dialog.saveconfig.prune.kmzimageheight=Alto de im\u00e1genes en kmz
+dialog.saveconfig.prune.metricunits=¿Usar unidades m\u00e9tricas?
+dialog.saveconfig.prune.gnuplotpath=Ruta a gnuplot
+dialog.saveconfig.prune.gpsbabelpath=Ruta a gpsbabel
+dialog.saveconfig.prune.exiftoolpath=Ruta a exiftool
+dialog.saveconfig.prune.mapsource=Proveedor de mapas seleccionado
+dialog.saveconfig.prune.mapsourcelist=Proveedor de mapas
+dialog.saveconfig.prune.diskcache=Memoria intermedia de mapas
+dialog.saveconfig.prune.kmzimagewidth=Ancho de im\u00e1genes en KMZ
+dialog.saveconfig.prune.kmzimageheight=Alto de im\u00e1genes en KMZ
dialog.saveconfig.prune.colourscheme=Color de esquema
dialog.saveconfig.prune.kmltrackcolour=Color de pista de KML
dialog.setpaths.intro=Si usted necesita, puede escoger las rutas a aplicaciones externas
+dialog.setpaths.found=¿Ruta encontrada?
dialog.addaltitude.noaltitudes=Los rangos seleccionados no contienen altitudes
-dialog.addaltitude.desc=
-dialog.setcolours.intro=Clickear sobre una placa de color para cambiar el color
+dialog.addaltitude.desc=Desplazamiento de altitud a a\u00f1adir
+dialog.lookupsrtm.overwritezeros=¿Sobrescribir valores de altitud nulos?
+dialog.setcolours.intro=Haga clic sobre una placa de color para cambiar el color
dialog.setcolours.background=Fondo
dialog.setcolours.borders=Bordes
dialog.setcolours.lines=L\u00edneas
dialog.colourchooser.green=Verde
dialog.colourchooser.blue=Azul
dialog.setlanguage.firstintro=Puede usted seleccionar algunos de los lenguajes incluidos,<p>o puede en lugar de esto seleccionar un archivo de texto
-dialog.setlanguage.secondintro=Usted necesita salvar su configuraci\u00f3n y luego<p>reiniciar Prune para cambiar el lenguaje
+dialog.setlanguage.secondintro=Usted necesita guardar sus preferencias y luego<p>reiniciar Prune para cambiar el lenguaje
dialog.setlanguage.language=Lenguaje
dialog.setlanguage.languagefile=Archivo de lenguaje
-dialog.setlanguage.endmessage=Ahora salve su configuraci\u00f3n y reinicie Prune\npara que los cambios tomen efecto.
-dialog.diskcache.save=Cargar cartas
-dialog.diskcache.dir=Directorio de cartas
+dialog.setlanguage.endmessage=Ahora guarde sus preferencias y reinicie Prune\npara que los cambios tomen efecto.
+dialog.diskcache.save=Guardar im\u00e1genes de mapa a disco
+dialog.diskcache.dir=Directorio de mapas
dialog.diskcache.createdir=Crear directorio
+dialog.diskcache.nocreate=No se ha creado el directorio de mapas
+dialog.deletefieldvalues.intro=Seleccionar el campo a eliminar para el rango actual
# 3d window
dialog.3d.title=Prune vista 3-D
dialog.3d.altitudecap=Escala de las altitudes
+dialog.3d.altitudefactor=Factor de exageraci\u00f3n de altura
dialog.3dlines.title=Cuadr\u00edcula Prune
-dialog.3dlines.empty=No hay ninguna cuadr\u00edcula!
+dialog.3dlines.empty=¡No hay ninguna cuadr\u00edcula!
dialog.3dlines.intro=Informaci\u00f3n de la cuadr\u00edcula
-# Confirm messages || These are displayed as confirmation in the status bar
+# Confirm messages
confirm.loadfile=Dato cargado de
-confirm.save.ok1=Guardando
+confirm.save.ok1=Guardado correctamente
confirm.save.ok2=puntos al archivo
confirm.deletepoint.single=punto eliminado
confirm.deletepoint.multi=puntos eliminados
confirm.point.edit=Punto editado
confirm.mergetracksegments=Segmentos unidos
confirm.reverserange=Rango invertido
+confirm.addtimeoffset=A\u00f1adido margen de tiempo
+confirm.addaltitudeoffset=A\u00f1adido margen de altitud
confirm.rearrangewaypoints=Waypoints reorganizados
confirm.rearrangephotos=Fotos reacomodadas
confirm.cutandmove=Mover Selecci\u00f3n
-confirm.saveexif.ok1=Guardando
+confirm.convertnamestotimes=Nombres de "waypoint" convertidos
+confirm.saveexif.ok1=Guardado
confirm.saveexif.ok2=fotos
-confirm.undo.single=operaci\u00f3n no realizada
-confirm.undo.multi=operaci\u00f3n(es) no realizada(s)
+confirm.undo.single=operaci\u00f3n deshecha
+confirm.undo.multi=operaci\u00f3n(es) deshechas(s)
confirm.jpegload.single=Foto incluida
confirm.jpegload.multi=Fotos incluidas
-confirm.photo.connect=Foto conectado
-confirm.photo.disconnect=Foto desconectado
-confirm.correlate.single=foto fue correlada
-confirm.correlate.multi=fotos fueron correladas
+confirm.photo.connect=Foto conectada
+confirm.photo.disconnect=Foto desconectada
+confirm.correlate.single=foto fue correlacionada
+confirm.correlate.multi=fotos fueron correlacionadas
confirm.createpoint=punto creado
-confirm.rotatephoto=Foto rotada
+confirm.rotatephoto=foto rotada
confirm.running=Trabajando ...
+confirm.lookupsrtm1=Encontrados
+confirm.lookupsrtm2=valor de altitud para la funci\u00f3n de b\u00fasqueda SRTM
+confirm.deletefieldvalues=Valores del campo eliminados
-# Buttons || These are all the texts for buttons
+# Buttons
button.ok=Aceptar
button.back=Anterior
button.next=Siguiente
button.selectnone=Seleccionar nada
button.preview=Previsualizaci\u00f3n
button.load=Cargar
+button.upload=Subir
button.guessfields=Adivinar campos
button.showwebpage=Mostrar p\u00e1gina web
button.check=Verificar
button.resettodefaults=Restablecer valores a los predeterminados
+button.browse=Navegar...
+button.addnew=A\u00f1adir nuevo
button.delete=Eliminar
# File types
filetype.pov=Archivos POV
filetype.svg=Archivos SVG
-# Display components || These are all for the side panels showing point/range details
+# Display components
display.nodata=Ning\u00fan dato cargado
display.noaltitudes=Los datos del track no incluyen altitudes
-display.notimestamps=Los datos del track no incluyen tiempos
+display.notimestamps=Los datos de recorrido no incluyen marcas de tiempo
details.trackdetails=Detalles del track
details.notrack=Ning\u00fan track cargado
details.track.points=Puntos
details.range.avemovingspeed=Moviendo promedio
details.range.maxspeed=Velocidad m\u00e1xima
details.range.numsegments=N\u00famero de segmentos
+details.range.pace=Ritmo
details.range.gradient=Gradiente
details.waypointsphotos.waypoints=Waypoints
details.waypointsphotos.photos=Fotos
-details.photodetails=Detalles del Foto
+details.photodetails=Detalles de la foto
details.nophoto=Ninguna foto seleccionada
details.photo.loading=Cargando
details.photo.connected=Conectada
cardinal.e=E
cardinal.w=O
-# Undo operations || These will be displayed in the undo list after you've performed the operation, to tell you what you did
+# Undo operations
undo.load=cargar datos
undo.loadphotos=cargar fotos
undo.editpoint=editar punto
undo.insert=insertar puntos
undo.reverse=invertir rango
undo.mergetracksegments=unir los segmentos de track
+undo.addtimeoffset=a\u00f1adir margen de tiempo
+undo.addaltitudeoffset=a\u00f1adir margen de altitud
undo.rearrangewaypoints=reordenar waypoints
+undo.cutandmove=mover secci\u00f3n
undo.connectphoto=conectar foto
undo.disconnectphoto=desconectar foto
undo.correlate=correlacionar fotos
+undo.rearrangephotos=reordenar fotos
undo.createpoint=crear punto
undo.rotatephoto=girar foto
+undo.convertnamestotimes=convertir nombres a tiempo
+undo.lookupsrtm=obtener altitudes de SRTM
+undo.deletefieldvalues=Eliminar valores de campo
# Error messages
error.save.dialogtitle=Fallo al guardar datos
-error.save.nodata=Ning\u00fan dato salvado
+error.save.nodata=Ning\u00fan dato guardado
error.save.failed=Fallo al guardar datos al archivo
error.saveexif.filenotfound=Archivo no encontrado
error.saveexif.cannotoverwrite1=No se puede guardar
-error.saveexif.cannotoverwrite2=. Guardar a una copia?
-error.saveexif.failed1=Fall\u00f3 al salvar
+error.saveexif.cannotoverwrite2=es s\u00f3lo-lectura y no se puede sobreescribir. Guardar a una copia?
+error.saveexif.failed1=Fall\u00f3 al guardar
error.saveexif.failed2=de las im\u00e1genes
+error.saveexif.forced1=
+error.saveexif.forced2=de las im\u00e1genes requiere forzar
error.load.dialogtitle=Fallo al cargar datos
error.load.noread=No se puede leer el fichero
-error.load.nopoints=Ninguna informaci\u00f3n coordenadas encontrada
+error.load.nopoints=No se encuentra ninguna informaci\u00f3n de coordenadas en el archivo
error.load.unknownxml=Formato xml no reconocido:
-error.load.noxmlinzip=Ning\u00fan xml archivo encontrado
+error.load.noxmlinzip=No se encuentra ning\u00fan archivo xml en el archivo zip
error.load.othererror=Fallo al cargar datos:
error.jpegload.dialogtitle=Error cargando fotos
-error.jpegload.nofilesfound=Ning\u00fan archivo encontrado
-error.jpegload.nojpegsfound=Ning\u00fan archivo jpeg encontrado
-error.jpegload.noexiffound=Ninguna informaci\u00f3n EXIF encontrada
-error.jpegload.nogpsfound=Ninguna informaci\u00f3n GPS encontrada
+error.jpegload.nofilesfound=No se encuentra ning\u00fan archivo
+error.jpegload.nojpegsfound=No se encuentra ning\u00fan archivo jpeg
+error.jpegload.noexiffound=No se encuentra informaci\u00f3n EXIF
+error.jpegload.nogpsfound=No se encuentra informaci\u00f3n GPS
+error.jpegload.exifreadfailed=Fallo al leer la informaci\u00f3n EXIF. No se puede leer ninguna informaci\u00f3n EXIF\ncon las librer\u00edas internas ni externas.
error.gpsload.unknown=Error desconocido
error.undofailed.title=Fallo al deshacer
error.undofailed.text=No ha sido posible deshacer la operaci\u00f3n
error.function.noop.title=La funci\u00f3n no se ha efectuado
error.rearrange.noop=Reordenaci\u00f3n de puntos no se ha efectuado
error.function.notavailable.title=Funci\u00f3n no disponible
-error.function.nojava3d=Esta funci\u00f3n requiere la librer\u00eda Java3d, disponible en Sun.com.
+error.function.nojava3d=Esta funci\u00f3n requiere la librer\u00eda Java3d,\ndisponible en Sun.com.
error.3d=Ha ocurrido un error con la funci\u00f3n 3-D
error.readme.notfound=Archivo readme no encontrado
error.osmimage.dialogtitle=Error al cargar el mapa
error.osmimage.failed=Imposible cargar el mapa. Por favor, compruebe la conexi\u00f3n a internet.
error.language.wrongfile=El archivo seleccionado no parece ser un archivo de lenguaje para Prune
error.convertnamestotimes.nonames=Los nombres no pudieron ser convertidos en tiempos
+error.lookupsrtm.nonefound=No se encontraron valores de altitud
+error.lookupsrtm.nonerequired=Todos los puntos tienen altitudes, as\u00ed que no hay nada que buscar.
+error.gpsies.uploadnotok=El servidor de gpsies ha devuelto el mensaje
+error.gpsies.uploadfailed=La carga ha fallado con el error
--- /dev/null
+# Text entries for the Prune application
+# Persian (Farsi) entries as extra
+
+# Menu entries
+menu.file=\u067e\u0648\u0634\u0647
+menu.file.addphotos=\u0627\u0636\u0627\u0641\u0647 \u06a9\u0631\u062f\u0646 \u0639\u06a9\u0633
+menu.file.save=\u0630\u062e\u064a\u0631\u0647
+menu.file.exit=\u062e\u0631\u0648\u062c
+menu.track=\u0645\u0633\u064a\u0631
+menu.track.undo=\u0628\u0627\u0637\u0644 \u06a9\u0631\u062f\u0646 \u06a9\u0627\u0631 \u0642\u0628\u0644\u064a
+menu.track.clearundo=\u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u0644\u064a\u0633\u062a \u06a9\u0627\u0631\u0647\u0627\u06cc \u0627\u0646\u062c\u0627\u0645 \u0634\u062f\u0647
+menu.track.deletemarked=\u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u0646\u0642\u0627\u0637 \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647
+menu.track.rearrange=\u0628\u0627\u0632 \u0686\u064a\u0646\u06cc \u0646\u0642\u0627\u0637 \u0645\u0633\u064a\u0631
+menu.track.rearrange.start=\u0647\u0645\u0647 \u0646\u0642\u0627\u0637 \u0628\u0647 \u0627\u0628\u062a\u062f\u0627\u06cc \u0645\u0633\u064a\u0631
+menu.track.rearrange.end=\u0647\u0645\u0647 \u0646\u0642\u0627\u0637 \u0628\u0647 \u0627\u0646\u062a\u0647\u0627\u06cc \u0645\u0633\u064a\u0631
+menu.track.rearrange.nearest=\u0647\u0631 \u064a\u06a9 \u0628\u0647 \u0646\u0632\u062f\u064a\u06a9 \u0646\u0642\u0637\u0647 \u0645\u0633\u064a\u0631
+menu.range=\u0686\u064a\u0646\u0634
+menu.range.all=\u0627\u0646\u062a\u062e\u0627\u0628 \u0647\u0645\u0647 \u0646\u0642\u0627\u0637
+menu.range.none=\u0627\u0646\u062a\u062e\u0627\u0628 \u0647\u064a\u0686 \u064a\u06a9 \u0627\u0632 \u0646\u0642\u0627\u0637
+menu.range.start=\u062a\u0646\u0638\u064a\u0645 \u0634\u0631\u0648\u0639 \u0686\u064a\u0646\u0634
+menu.range.end=\u062a\u0646\u0638\u064a\u0645 \u0627\u0646\u062a\u0647\u0627\u06cc \u0686\u064a\u0646\u0634
+menu.range.deleterange=\u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u0686\u064a\u0646\u0634
+menu.range.interpolate=\u062f\u0631\u0648\u0646\u064a\u0627\u0628\u06cc
+menu.range.average=\u0645\u06cc\u0627\u0646\u06af\u064a\u0646 \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647 \u0647\u0627
+menu.range.reverse=\u0686\u064a\u0646\u0634 \u0645\u0639\u06a9\u0648\u0633
+menu.range.mergetracksegments=\u0627\u062a\u0635\u0627\u0644 \u0642\u0633\u0645\u062a \u0647\u0627\u06cc \u0645\u0633\u064a\u0631
+menu.range.cutandmove=\u062c\u062f\u0627 \u06a9\u0631\u062f\u0646 \u0642\u0633\u0645\u062a \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647
+menu.point=\u0646\u0642\u0637\u0647
+menu.point.editpoint=\u062a\u0646\u0638\u064a\u0645\u0627\u062a \u0646\u0642\u0637\u0647
+menu.point.deletepoint=\u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u0646\u0642\u0637\u0647
+menu.photo=\u0639\u06a9\u0633
+menu.photo.saveexif=\u0630\u062e\u064a\u0631\u0647 \u062f\u0631 \u0641\u0627\u064a\u0644 \u0636\u0645\u064a\u0645\u0647 \u0639\u06a9\u0633
+menu.photo.connect=\u0627\u062a\u0635\u0627\u0644 \u0628\u0647 \u0646\u0642\u0637\u0647
+menu.photo.disconnect=\u0642\u0637\u0639 \u0627\u062a\u0635\u0627\u0644 \u0627\u0632 \u0646\u0642\u0637\u0647
+menu.photo.delete=\u0628\u0631\u062f\u0627\u0634\u062a\u0646 \u0639\u06a9\u0633
+menu.view=\u062f\u064a\u062f
+menu.view.browser=\u0646\u0642\u0634\u0647 \u062f\u0631\u062c\u0633\u062a\u062c\u0648\u06af\u0631
+menu.view.browser.google=Google Maps
+menu.view.browser.openstreetmap=OpenStreetMap
+menu.view.browser.mapquest=MapQuest
+menu.view.browser.yahoo=Yahoo Maps
+menu.view.browser.bing=Bing Maps
+menu.settings=\u062a\u0646\u0638\u06cc\u0645\u0627\u062a
+menu.settings.onlinemode=\u062f\u0627\u0646\u0644\u0648\u062f \u0646\u0642\u0634\u0647 \u0627\u0632 \u0627\u064a\u0646\u062a\u0631\u0646\u062a
+menu.help=\u0631\u0627\u0647\u0646\u0645\u0627
+# Popup menu for map
+menu.map.zoomin=\u0628\u0632\u0631\u06af \u0646\u0645\u0627\u064a\u06cc
+menu.map.zoomout=\u06a9\u0648\u0686\u06a9 \u0646\u0645\u0627\u064a\u06cc
+menu.map.zoomfull=\u0646\u0645\u0627\u064a\u0634 \u062f\u0631 \u0627\u0646\u062f\u0627\u0632\u0647 \u06a9\u0627\u0645\u0644
+menu.map.newpoint=\u0627\u064a\u062c\u0627\u062f \u0646\u0642\u0637\u0647 \u062c\u062f\u064a\u062f
+menu.map.connect=\u0627\u062a\u0635\u0627\u0644 \u0646\u0642\u0627\u0637 \u0645\u0633\u064a\u0631
+menu.map.autopan=\u0646\u0645\u0627\u064a\u0634 \u062f\u0627\u0626\u0645 \u0646\u0642\u0637\u0647
+menu.map.showmap=\u0646\u0645\u0627\u064a\u0634 \u0646\u0642\u0637\u0647
+menu.map.showscalebar=\u0646\u0645\u0627\u064a\u0634 \u062a\u0646\u0638\u064a\u0645\u0627\u062a \u0645\u0642\u064a\u0627\u0633
+
+# Alt keys for menus
+altkey.menu.file=\u067e
+altkey.menu.track=\u0645
+altkey.menu.range=\u0686
+altkey.menu.point=\u0646
+altkey.menu.view=\u062f
+altkey.menu.photo=\u0639
+altkey.menu.settings=\u062a
+altkey.menu.help=\u0631
+
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=\u0628
+shortcut.menu.file.load=\u062f
+shortcut.menu.file.save=\u0630
+shortcut.menu.track.undo=\u0638
+shortcut.menu.edit.compress=\u062a
+shortcut.menu.range.all=\u0686
+shortcut.menu.help.help=\u0631
dialog.gpsies.description=Description
dialog.gpsies.nodescription=Aucune description
dialog.gpsies.nonefound=Aucun trace trouv\u00e9
+dialog.gpsies.activities=Activit\u00e9
+dialog.gpsies.activity.trekking=Trekking
+dialog.gpsies.activity.walking=Randonn\u00e9e
+dialog.gpsies.activity.jogging=Jogging
+dialog.gpsies.activity.biking=V\u00e9lo
+dialog.gpsies.activity.motorbiking=Moto
+dialog.gpsies.activity.snowshoe=Raquette
+dialog.gpsies.activity.sailing=Volle
+dialog.gpsies.activity.skating=Skating
dialog.correlate.notimestamps=Les points n'ont pas d'indication de temps, il n'est pas possible de les corr\u00e9ler.
dialog.correlate.nouncorrelatedphotos=Il n'y a pas de photos non-corr\u00e9l\u00e9es.\nVoulez-vous continuer ?
dialog.correlate.photoselect.intro=S\u00e9lectionner une de ces photos corr\u00e9l\u00e9es pour d\u00e9finir le d\u00e9calage de temps
error.osmimage.failed=Erreur du chargement des portions de cartes. V\u00e9rifiez votre connexion internet.
error.language.wrongfile=Le fichier s\u00e9lectionn\u00e9 n'est pas un fichier de langue pour Prune
error.convertnamestotimes.nonames=Aucun nom n'a pu \u00eatre converti en horaire
-error.lookupsrtm.none=Aucune valeur d'altitude trouv\u00e9e
+error.lookupsrtm.nonefound=Aucune valeur d'altitude trouv\u00e9e pour les points
menu.file.exit=Esci
menu.track=Traccia
menu.track.undo=Annulla
-menu.track.clearundo=Cancella lista ultime modifiche
-menu.point.editpoint=Edita punto
-menu.point.deletepoint=Cancella punto
-menu.range.deleterange=Cancella la serie
+menu.track.clearundo=Cancella lista annulla
menu.track.deletemarked=Cancella punti marcati
-menu.range.interpolate=Interpola
-menu.range.average=Crea punto medio della selezione
-menu.range.reverse=Inverti la serie
-menu.range.mergetracksegments=Unisci segmenti traccia
menu.track.rearrange=Riorganizza waypoint
menu.track.rearrange.start=Tutti all'inizio del file
menu.track.rearrange.end=Tutti alla fine del file
menu.track.rearrange.nearest=Sul punto pi\u00f9 vicino
-menu.range.cutandmove=Taglia e muovi la selezione
menu.range=Serie
-menu.point=Punto
menu.range.all=Seleziona tutto
menu.range.none=Deseleziona tutto
menu.range.start=Imposta inizio serie
menu.range.end=Imposta fine serie
+menu.range.deleterange=Cancella la serie
+menu.range.interpolate=Interpola
+menu.range.average=Crea punto medio della selezione
+menu.range.reverse=Inverti la serie
+menu.range.mergetracksegments=Unisci segmenti traccia
+menu.range.cutandmove=Taglia e muovi la selezione
+menu.point=Punto
+menu.point.editpoint=Edita Punto
+menu.point.deletepoint=Cancella Punto
menu.photo=Foto
menu.photo.saveexif=Salva su Exif
menu.photo.connect=Collega al punto
menu.photo.disconnect=Scollega dal punto
menu.photo.delete=Rimuovi foto
menu.view=Visualizza
+menu.view.showsidebars=Mostra barre laterali
menu.view.browser=Mappa sul browser
menu.view.browser.google=Google maps
menu.view.browser.openstreetmap=Openstreetmap
menu.view.browser.yahoo=mappe Yahoo
menu.view.browser.bing=mappe Bing
menu.settings=Preferenze
+menu.settings.onlinemode=Carica mappa da internet
menu.help=Aiuto
# Popup menu for map
menu.map.zoomin=Zoom +
menu.map.zoomout=Zoom -
menu.map.zoomfull=Zoom tutto
-menu.map.newpoint=Crea punto nuovo
+menu.map.newpoint=Crea nuovo punto
menu.map.connect=Aggancia ai punti
menu.map.autopan=Autopan
menu.map.showmap=Mostra sulla mappa
function.exportkml=Esporta in KML
function.exportgpx=Esporta in GPX
function.exportpov=Esporta in POV
-function.editwaypointname=Edita nome waypoint
+function.exportsvg=Esporta in SVG
+function.editwaypointname=Modifica nome waypoint
function.compress=Comprimi la traccia
function.addtimeoffset=Aggiungi uno scarto temporale
function.addaltitudeoffset=Aggiungi uno scarto di altitudine
+function.convertnamestotimes=Converti nomi dei waypoint in orari
+function.deletefieldvalues=Cancella i valori del campo
function.findwaypoint=Trova waypoint
+function.pastecoordinates=Aggiungi coordinate
function.charts=Diagrammi
function.show3d=Mostra in 3D
function.distances=Mostra distanze
+function.fullrangedetails=Mostra dettagli
function.setmapbg=Configura sfondo mappa
function.setkmzimagesize=Configura dimensione immagine KMZ
function.setpaths=Configura percorsi programmi
function.getgpsies=Ottieni traccie da Gpsies
+function.uploadgpsies=Carica traccia su Gpsies
+function.lookupsrtm=Ottieni quote da SRTM
+function.duplicatepoint=Duplica punto corrente in coda
+function.setcolours=Scegli colori
+function.setlanguage=Scegli la lingua
function.correlatephotos=Correla le foto
+function.rearrangephotos=Riordina foto
+function.rotatephotoleft=Ruota foto a sinistra
+function.rotatephotoright=Ruota foto a destra
+function.ignoreexifthumb=Ignora anteprima foto exif
function.help=Aiuto
function.showkeys=Visualizza tasti scelta rapida
function.about=Informazioni su Prune
function.checkversion=Controlla gli aggiornamenti
function.saveconfig=Salva configurazione
+function.diskcache=Salva mappe su disco
# Dialogs
dialog.exit.confirm.title=Esci da Prune
dialog.openoptions.deliminfo.fields=campi
dialog.openoptions.deliminfo.norecords=Nessun record
dialog.openoptions.altitudeunits=Unit\u00e0 di misura altitudine
+dialog.open.contentsdoubled=Questo file contiene due copie di ogni punto,\nuno \u00e8 un waypoint e uno \u00e8 un punto traccia
+dialog.selecttracks.intro=Seleziona la traccia o le tracce da caricare
+dialog.selecttracks.noname=Senza nome
dialog.jpegload.subdirectories=Includi sottocartelle
dialog.jpegload.loadjpegswithoutcoords=Includi foto senza coordinate
dialog.jpegload.loadjpegsoutsidearea=Includi foto fuori dall'area corrente
dialog.gpsload.format=Formato
dialog.gpsload.getwaypoints=Carica waypoint
dialog.gpsload.gettracks=Carica tracce
-dialog.gpssend.sendwaypoints=Invia waypoints
+dialog.gpsload.save=Salva
+dialog.gpssend.sendwaypoints=Invia waypoint
dialog.gpssend.sendtracks=Invia tracce
-dialog.gpssend.trackname=Nome del tracce
+dialog.gpssend.trackname=Nome della traccia
dialog.saveoptions.title=Salva il file
dialog.save.fieldstosave=Campi da salvare
dialog.save.table.field=Campo
-dialog.save.table.hasdata=Ha dati
+dialog.save.table.hasdata=Contiene dati
dialog.save.table.save=Salva
dialog.save.headerrow=Regista l'intestazione delle righe
dialog.save.coordinateunits=Unit\u00e0 di misura coordinate
dialog.save.timestampformat=Formato della data
dialog.save.overwrite.title=File gi\u00e0 esistente
dialog.save.overwrite.text=Questo file esiste gi\u00e0. Sei sicuro di volerlo sovrascrivere?
+dialog.save.notypesselected=Nessun tipo di punto \u00e8 stato selezionato
dialog.exportkml.text=Titolo dei dati
dialog.exportkml.altitude=Includi altitudine (per aviazione)
dialog.exportkml.kmz=Comprimi per file kmz
dialog.exportkml.exportimages=Esporta le anteprime delle immagini per kmz
+dialog.exportkml.trackcolour=Colore della traccia
dialog.exportgpx.name=Nome
dialog.exportgpx.desc=Descrizione
dialog.exportgpx.includetimestamps=Includi dati temporali
+dialog.exportgpx.copysource=Copia xml sorgente
dialog.exportpov.text=Per favore inserisci i parametri per l'esportazione in POV
dialog.exportpov.font=Font
dialog.exportpov.camerax=Camera X
dialog.exportpov.modelstyle=Stile del modello
dialog.exportpov.ballsandsticks=Palle e bacchette
dialog.exportpov.tubesandwalls=Tubi e pareti
-dialog.exportpov.warningtracksize=Questa traccia ha un elevato numero di punti, e Java3D pu\u00f2 non essere in grado di visualizzarli.\nSei sicuro di voler continuare?
+dialog.exportpov.warningtracksize=Questa traccia ha un elevato numero di punti, e Java3D potrebbe non essere in grado di visualizzarli.\nSei sicuro di voler continuare?
+dialog.exportsvg.text=Seleziona i parametri per esportare in SVG
+dialog.exportsvg.phi=Angolo orizzontale \u03d5
+dialog.exportsvg.theta=Angolo di elevazione \u03b8
+dialog.exportsvg.gradients=Usa il gradiente per le ombre
dialog.pointtype.desc=Salva i tipi di punti seguenti:
dialog.pointtype.track=Punti traccia
dialog.pointtype.waypoint=Waypoints
dialog.pointtype.photo=Punti foto
+dialog.pointtype.selection=Solo la selezione
dialog.confirmreversetrack.title=Conferma l'inversione
dialog.confirmreversetrack.text=Questa traccia contiene informazioni sull'orario di scatto che possono essere messe fuori sequenza dopo l'inversione.\nSei sicuro di voler invertire questa sezione?
dialog.confirmcutandmove.title=Conferma il taglio e lo spostamento
dialog.pointedit.table.value=Valore
dialog.pointedit.table.changed=Cambiato
dialog.pointedit.changevalue.text=Inserisci il nuovo valore di questo campo
-dialog.pointedit.changevalue.title=Edita il campo
+dialog.pointedit.changevalue.title=Modifica il campo
dialog.pointnameedit.name=Nome del waypoint
dialog.pointnameedit.uppercase=MAIUSCOLE
dialog.pointnameedit.lowercase=minuscole
dialog.saveexif.photostatus.disconnected=Scollegata
dialog.saveexif.photostatus.modified=Modificata
dialog.saveexif.overwrite=Sovrascrivi il file
+dialog.saveexif.force=Ignora errori minori
dialog.charts.xaxis=Asse X
dialog.charts.yaxis=Asse Y
dialog.charts.output=Output
dialog.distances.column.to=Al punto
dialog.distances.currentpoint=Punto attuale
dialog.distances.toofewpoints=Questa funzione necessita di waypoints per calcolare le distanze tra loro
-dialog.setmapbg.mapnik=Mapnik (default)
-dialog.setmapbg.osma=Osma
-dialog.setmapbg.cyclemap=Mappa ciclistica
-dialog.setmapbg.other=Altro
-dialog.setmapbg.server=URL server
+dialog.fullrangedetails.intro=Qui i dettagli della selezione
+dialog.setmapbg.intro=Selezione una fonte delle mappe o aggiungine una nuova
+dialog.addmapsource.title=Aggiungi nuova fonte delle mappa
+dialog.addmapsource.sourcename=Nome della fonte
+dialog.addmapsource.layer1url=URL del primo layer
+dialog.addmapsource.layer2url=URL opzionale del secondo layer
+dialog.addmapsource.maxzoom=Massimo livello di zoom
+dialog.addmapsource.cloudstyle=Stile numero
+dialog.addmapsource.noname=Senza nome
dialog.gpsies.column.name=Nome traccia
dialog.gpsies.column.length=Lunghezza
dialog.gpsies.description=Descrizione
dialog.gpsies.nodescription=Senza descrizione
+dialog.gpsies.nonefound=Nessuna traccia trovata
+dialog.gpsies.username=Gpsies username
+dialog.gpsies.password=Gpsies password
+dialog.gpsies.keepprivate=Rendi la traccia privata
+dialog.gpsies.confirmopenpage=Apri la pagina web per caricare la traccia?
+dialog.gpsies.activities=Attivit\u00e0
+dialog.gpsies.activity.trekking=Trekking
+dialog.gpsies.activity.walking=Camminare
+dialog.gpsies.activity.jogging=Jogging
+dialog.gpsies.activity.biking=Ciclismo
+dialog.gpsies.activity.motorbiking=Motocicletta
+dialog.gpsies.activity.snowshoe=Trekking sulla neve
+dialog.gpsies.activity.sailing=Navigazione
+dialog.gpsies.activity.skating=Pattinaggio
dialog.correlate.notimestamps=Non ci sono informazioni temporali tra i dati dei punti, non c'\u00e8 niente per collegarli con le foto.
dialog.correlate.nouncorrelatedphotos=Non ci sono foto non correlate.\nSei sicuro di voler continuare?
dialog.correlate.photoselect.intro=Selezione una delle foto correlate da usare come scarto dell'orario
dialog.correlate.options.distancelimit=Distanza limite
dialog.correlate.options.correlate=Correlate
dialog.correlate.alloutsiderange=Tutte le foto sono fuori dall'orario della traccia, e nessuna pu\u00f2 essere correlata.\nProva a cambiare lo scarto o correla manualmente almeno una foto.
+dialog.rearrangephotos.desc=Seleziona la destinazione e l'ordine dei punti foto
+dialog.rearrangephotos.tostart=Sposta all'inizio
+dialog.rearrangephotos.toend=Sposta alla fine
+dialog.rearrangephotos.nosort=Non mettere in ordine
+dialog.rearrangephotos.sortbyfilename=Metti in ordine di nome del file
+dialog.rearrangephotos.sortbytime=Metti in ordine di tempo
dialog.compress.nonefound=Nessun punto rimosso
dialog.compress.closepoints.title=Cancella punti vicini
dialog.compress.closepoints.paramdesc=Fattore vicinanza
dialog.compress.singletons.paramdesc=Fattore distanza
dialog.compress.duplicates.title=Cancella duplicati
dialog.compress.summarylabel=Punti da cancellare
+dialog.pastecoordinates.desc=Inserisci o incolla qui le coordinate
+dialog.pastecoordinates.coords=Coordinate
+dialog.pastecoordinates.nothingfound=Per favore, controlla le coordinate e riprova
dialog.help.help=Per favore vedi\n http://activityworkshop.net/software/prune/\nper maggiori informazioni e per la guida utente.
dialog.about.version=Versione
dialog.about.build=Build
dialog.about.systeminfo.exiftool=Exiftool installato
dialog.about.systeminfo.gpsbabel=Gpsbabel installato
dialog.about.systeminfo.gnuplot=Gnuplot installato
+dialog.about.systeminfo.exiflib=Libreria exif
+dialog.about.systeminfo.exiflib.internal=Interna
+dialog.about.systeminfo.exiflib.internal.failed=Interna (non trovata)
+dialog.about.systeminfo.exiflib.external=Esterna
+dialog.about.systeminfo.exiflib.external.failed=Esterna (non trovata)
dialog.about.yes=S\u00ec
dialog.about.no=No
dialog.about.credits=Crediti
dialog.checkversion.download=Per scaricare la nuova versione vai a http://activityworkshop.net/software/prune/download.html.
dialog.keys.intro=Puoi utilizzare i seguenti tast di scelta rapida al posto del mouse
dialog.keys.keylist=<table><tr><td>Tasti freccia</td><td>Muovi mappa destra, sinistra, su, giu'</td></tr><tr><td>Ctrl + freccia destra, sinistra</td><td>Selezione punto successivo o precedente</td></tr><tr><td>Ctrl + freccia su, giu'</td><td>Zoom in o out</td></tr><tr><td>Del</td><td>Cancella punto attuale</td></tr></table>
+dialog.keys.normalmodifier=Ctrl
+dialog.keys.macmodifier=Comando
dialog.saveconfig.desc=Le configurazioni seguenti possono essere salvati in un file di configurazione:
dialog.saveconfig.prune.trackdirectory=Cartella traccie
dialog.saveconfig.prune.photodirectory=Cartella foto
-dialog.saveconfig.prune.languagecode=Codice linguaggio (EN)
+dialog.saveconfig.prune.languagecode=Codice lingua (IT)
+dialog.saveconfig.prune.languagefile=File lingua
dialog.saveconfig.prune.gpsdevice=Nome del Dispositivo GPS
dialog.saveconfig.prune.gpsformat=Formato GPS
dialog.saveconfig.prune.povrayfont=Font povray
dialog.saveconfig.prune.gnuplotpath=Path gnuplot
dialog.saveconfig.prune.gpsbabelpath=Path gpsbabel
dialog.saveconfig.prune.exiftoolpath=Path exiftool
-dialog.saveconfig.prune.mapserverindex=Indice server mappe
-dialog.saveconfig.prune.mapserverurl=URL del server mappe
+dialog.saveconfig.prune.mapsource=Selezionale la fonte delle mappe
+dialog.saveconfig.prune.mapsourcelist=Fonte delle mappe
+dialog.saveconfig.prune.diskcache=Cache delle mappe
dialog.saveconfig.prune.kmzimagewidth=larghezza immagine KMZ
dialog.saveconfig.prune.kmzimageheight=altezza immagine KMZ
+dialog.saveconfig.prune.colourscheme=Schema colori
+dialog.saveconfig.prune.kmltrackcolour=Colore della traccia KML
dialog.setpaths.intro=Se necessario, puoi indicare il percorso delle applicazioni esterne:
+dialog.setpaths.found=trovato?
dialog.addaltitude.noaltitudes=L'intervallo selezionato non contiene altitudini
dialog.addaltitude.desc=Scarto altitudine da aggiungere
+dialog.lookupsrtm.overwritezeros=Sovrascrivere le quote pari a zero?
+dialog.setcolours.intro=Fai clic su un riquadro per cambiare il colore
+dialog.setcolours.background=Sfondo
+dialog.setcolours.borders=Bordi
+dialog.setcolours.lines=Linee
+dialog.setcolours.primary=Primario
+dialog.setcolours.secondary=Secondario
+dialog.setcolours.point=Punti
+dialog.setcolours.selection=Selezione
+dialog.setcolours.text=Testo
+dialog.colourchooser.title=Scegli colore
+dialog.colourchooser.red=Rosso
+dialog.colourchooser.green=Verde
+dialog.colourchooser.blue=Blu
+dialog.setlanguage.firstintro=Puoi selezionare una delle lingue incluse,<p>oppure selezionare un file di testo.
+dialog.setlanguage.secondintro=Devi salvare le impostazioni e<p> riavviare Prune per cambiare la lingua.
+dialog.setlanguage.language=Lingua
+dialog.setlanguage.languagefile=File della lingua
+dialog.setlanguage.endmessage=Ora salva le tue preferenze e riavvia Prune\n per rendere effettivo il cambio di lingua
+dialog.diskcache.save=Salva la mappa sul disco
+dialog.diskcache.dir=Cartella della cache
+dialog.diskcache.createdir=Crea cartella
+dialog.diskcache.nocreate=Cartella della cache non creata
+dialog.deletefieldvalues.intro=Selezione il campo da cancellare dall'intervallo corrente
# 3d window
dialog.3d.title=Visione Prune in 3D
dialog.3d.altitudecap=Intervallo altitudine minimo
+dialog.3d.altitudefactor=Fattore di moltiplicazione della quota
dialog.3dlines.title=Griglia di Prune
dialog.3dlines.empty=Nessuna griglia mostrata!
dialog.3dlines.intro=Queste sono le linee della griglia per la visione 3D
-# Confirm messages || These are displayed as confirmation in the status bar
+# Confirm messages
confirm.loadfile=Dati caricati da file
confirm.save.ok1=Salvati con successo
confirm.save.ok2=punti nel file
confirm.addtimeoffset=Scarto temporale aggiunto
confirm.addaltitudeoffset=Scarto altitudine aggiunto
confirm.rearrangewaypoints=Waypoint riorganizzati
+confirm.rearrangephotos=Foto riorganizzate
confirm.cutandmove=Selezione spostata
+confirm.convertnamestotimes=Nome del waypoint convertito
confirm.saveexif.ok1=Salvato
confirm.saveexif.ok2=foto
confirm.undo.single=operazione annullate
confirm.correlate.single=foto era correlata
confirm.correlate.multi=foto erano correlate
confirm.createpoint=punto creato
+confirm.rotatephoto=foto ruotata
confirm.running=Operazione in corso...
+confirm.lookupsrtm1=Trovato
+confirm.lookupsrtm2=valori di quota
+confirm.deletefieldvalues=Valori del campo cancellati
-# Buttons || These are all the texts for buttons
+# Buttons
button.ok=OK
button.back=Precedente
button.next=Prossimo
button.selectnone=Deseleziona tutto
button.preview=Anteprima
button.load=Carica
+button.upload=Caricato
button.guessfields=Campi soluzione
button.showwebpage=Mostra pagina
button.check=Controlla
+button.resettodefaults=Ripristina predefinito
+button.browse=Sfoglia...
+button.addnew=Aggiungi nuovo
+button.delete=Cancella
# File types
filetype.txt=File TXT
filetype.jpeg=File JPG
filetype.kmlkmz=File KML, KMZ
filetype.kml=File KML
-filetype.kmz=FIle KMZ
+filetype.kmz=File KMZ
filetype.gpx=File GPX
filetype.pov=File POV
filetype.svg=File SVG
-# Display components || These are all for the side panels showing point/range details
+# Display components
display.nodata=Nessun dato caricato
display.noaltitudes=I dati della traccia non includono l'altitudine
+display.notimestamps=La traccia non include dati temporali
details.trackdetails=Dettagli della traccia
details.notrack=Nessuna traccia caricata
details.track.points=Punti
display.range.time.days=g
details.range.avespeed=Velocit\u00e0 media
details.range.avemovingspeed=Velocit\u00e0 media in movimento
+details.range.maxspeed=Velocit\u00e0 massima
+details.range.numsegments=Numero di segmenti
details.range.pace=Passo
+details.range.gradient=Gradiente
details.waypointsphotos.waypoints=Waypoint
details.waypointsphotos.photos=Foto
details.photodetails=Dettagli foto
cardinal.e=E
cardinal.w=O
-# Undo operations || These will be displayed in the undo list after you've performed the operation, to tell you what you did
+# Undo operations
undo.load=carica dati
undo.loadphotos=carica foto
undo.editpoint=edita punto
undo.connectphoto=collega foto
undo.disconnectphoto=scollega foto
undo.correlate=correla foto
+undo.rearrangephotos=riorganizza foto
undo.createpoint=crea punto
+undo.rotatephoto=ruota foto
+undo.convertnamestotimes=converti nomi in orari
+undo.lookupsrtm=cerca quote in SRTM
+undo.deletefieldvalues=cancellare i valori del campo
# Error messages
error.save.dialogtitle=Errore nel salvataggio dati
error.saveexif.filenotfound=Non trovato un file di foto
error.saveexif.cannotoverwrite1=File di foto
error.saveexif.cannotoverwrite2=\u00e8 in sola lettura e non pu\u00f2 essere sovrascritto. Creo una copia?
+error.saveexif.failed1=Salvataggio fallito
+error.saveexif.failed2=delle immagini
+error.saveexif.forced1=
+error.saveexif.forced2=delle immagini richiede forzatura
error.load.dialogtitle=Errore nel caricamento dati
error.load.noread=Non posso leggere il file
error.load.nopoints=Non ci sono coordinate nel file
error.jpegload.nojpegsfound=File jpeg non trovato
error.jpegload.noexiffound=Informazioni EXIF non trovate
error.jpegload.nogpsfound=Informazioni GPS non trovate
+error.jpegload.exifreadfailed=Lettera dei dati EXIF fallita. I dati EXIF non possono\n essere letti senza una libreria interna o esterna.
+error.gpsload.unknown=Errore sconosciuto
error.undofailed.title=Impossibile annullare
error.undofailed.text=Impossibile annullare l'operazione
error.function.noop.title=La funzione non ha avuto effetto
-error.rearrange.noop=La riorganizzazione dei waypoint non ha avuto effetto
+error.rearrange.noop=La riorganizzazione dei punto non ha avuto effetto
error.function.notavailable.title=Funzione non disponibile
error.function.nojava3d=Questa funzione richiede la libreria Java3d,\ndisponibile all'indirizzo Sun.com.
error.3d=\u00c8 avvenuto un errore nella visualizzazione 3D
error.readme.notfound=Non ho trovato il file Leggimi
error.osmimage.dialogtitle=Errore nel caricamento nelle immagini della mappa
error.osmimage.failed=Impossibile caricare le immagini della mappa. Per favore verifica la connessione a internet.
+error.language.wrongfile=Il file selezionato non sembra essere un file di lingua per Prune
+error.convertnamestotimes.nonames=Nomi non convertibili in orari
+error.lookupsrtm.nonefound=Valori di quota non trovati
+error.lookupsrtm.nonerequired=Tutti i punti hanno gi\u00e0 una quota, non c'\u00e8 niente da cercare
+error.gpsies.uploadnotok=Il server Gpsies ha riportato il messaggio
+error.gpsies.uploadfailed=Il caricamento \u00e8 fallito con l'errore
dialog.gpsies.description=\u8a18\u8ff0
dialog.gpsies.nodescription=\u8a18\u8ff0\u304c\u3042\u308a\u307e\u305b\u3093
dialog.gpsies.nonefound=\u30c8\u30e9\u30c3\u30af\u304c\u3042\u308a\u307e\u305b\u3093
+dialog.gpsies.activities=\u6d3b\u52d5\u306b\u9069\u3057\u3066
+dialog.gpsies.activity.trekking=\u30cf\u30a4\u30ad\u30f3\u30b0
+dialog.gpsies.activity.walking=\u30a6\u30a9\u30fc\u30ad\u30f3\u30b0
+dialog.gpsies.activity.jogging=\u5b9f\u884c\u4e2d
+dialog.gpsies.activity.biking=\u30b5\u30a4\u30af\u30ea\u30f3\u30b0
+dialog.gpsies.activity.snowshoe=\u30b9\u30ce\u30fc\u30b7\u30e5\u30fc\u30a4\u30f3\u30b0
+dialog.gpsies.activity.sailing=\u30bb\u30fc\u30ea\u30f3\u30b0
+dialog.gpsies.activity.skating=\u30d5\u30a3\u30ae\u30e5\u30a2\u30b9\u30b1\u30fc\u30c8
dialog.correlate.notimestamps=\u30c7\u30fc\u30bf\u30dd\u30a4\u30f3\u30c8\u306b\u306f\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u304c\u306a\u3044\u306e\u3067\u3001\u5199\u771f\u3092\u95a2\u9023\u4ed8\u3051\u3089\u308c\u308b\u7269\u304c\u3042\u308a\u307e\u305b\u3093\u3002
dialog.correlate.nouncorrelatedphotos=\u95a2\u9023\u4ed8\u3051\u3089\u308c\u306a\u304b\u3063\u305f\u5199\u771f\u306f\u3042\u308a\u307e\u305b\u3093\u3002\n\u7d9a\u3051\u307e\u3059\u304b\uff1f
dialog.correlate.photoselect.intro=\u6642\u9593\u504f\u4f4d\u3092\u4f5c\u308b\u305f\u3081\u306e\u5199\u771f\u3092\u4e00\u3064\u9078\u3093\u3067\u304f\u3060\u3055\u3044\u3002
--- /dev/null
+# Text entries for the Prune application
+# Dutch entries as extra
+
+# Menu entries
+menu.file=Bestand
+menu.file.addphotos=Foto's toevoegen
+menu.file.save=Opslaan als tekst
+menu.file.exit=Afsluiten
+menu.track=Route
+menu.track.undo=Ongedaan maken
+menu.track.clearundo=Ongedaan-maken lijst wissen
+menu.track.deletemarked=Verwijderen gemarkeerde punten
+menu.track.rearrange=Rangschikken waypoints
+menu.track.rearrange.start=Alles naar begin route
+menu.track.rearrange.end=Alles naar einde route
+menu.track.rearrange.nearest=Alles naar dichtstbijzijnde routepunt
+menu.range=Reeks
+menu.range.all=Selecteer alles
+menu.range.none=Selecteer geen
+menu.range.start=Start van reeks
+menu.range.end=Einde van reeks
+menu.range.deleterange=Verwijder reeks
+menu.range.interpolate=Interpoleren
+menu.range.average=Cre\u00eber punt obv gemiddelde van reeks
+menu.range.reverse=Reeks omkeren
+menu.range.mergetracksegments=Samenvoegen route segmenten
+menu.range.cutandmove=Knip en plak selectie
+menu.point=Punt
+menu.point.editpoint=Wijzig punt
+menu.point.deletepoint=Verwijder punt
+menu.photo=Foto
+menu.photo.saveexif=Opslaan naar Exif
+menu.photo.connect=Aan punt vastzetten
+menu.photo.disconnect=Van punt losmaken
+menu.photo.delete=Verwijder foto
+menu.view=Bekijken
+menu.view.showsidebars=Toon panelen
+menu.view.browser=Kaart in browser
+menu.view.browser.google=Google maps
+menu.view.browser.openstreetmap=Openstreetmap
+menu.view.browser.mapquest=Mapquest
+menu.view.browser.yahoo=Yahoo maps
+menu.view.browser.bing=Bing maps
+menu.settings=Instellingen
+menu.settings.onlinemode=Kaarten van internet ophalen
+menu.help=Help
+# Popup menu for map
+menu.map.zoomin=Zoom +
+menu.map.zoomout=Zoom -
+menu.map.zoomfull=Zoom alles
+menu.map.newpoint=Maak nieuw punt
+menu.map.connect=Verbind route punten
+menu.map.autopan=Autopan
+menu.map.showmap=Toon kaart
+menu.map.showscalebar=Toon schaal
+
+# Alt keys for menus
+altkey.menu.file=F
+altkey.menu.track=R
+altkey.menu.range=E
+altkey.menu.point=P
+altkey.menu.view=B
+altkey.menu.photo=F
+altkey.menu.settings=I
+altkey.menu.help=H
+
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=O
+shortcut.menu.file.load=L
+shortcut.menu.file.save=S
+shortcut.menu.track.undo=Z
+shortcut.menu.edit.compress=C
+shortcut.menu.range.all=A
+shortcut.menu.help.help=H
+
+# Functions
+function.open=Open bestand
+function.loadfromgps=Gegevens lezen van GPS
+function.sendtogps=Gegevens verzenden naar GPS
+function.exportkml=Export KML
+function.exportgpx=Export GPX
+function.exportpov=Export POV
+function.exportsvg=Export SVG
+function.editwaypointname=Hernoem waypoint
+function.compress=Route comprimeren
+function.addtimeoffset=Tijdsverschil toevoegen
+function.addaltitudeoffset=Hoogteverschil toevoegen
+function.convertnamestotimes=Converteer waypointnamen naar tijden
+function.deletefieldvalues=Verwijder veldwaarden
+function.findwaypoint=Zoek waypoint
+function.pastecoordinates=Nieuwe co\u00f6rdinaten ingeven
+function.charts=Diagram
+function.show3d=3D beeld
+function.distances=Afstanden
+function.fullrangedetails=Reeks details
+function.setmapbg=Instellen kaart achtergrond
+function.setkmzimagesize=Instellen KMZ afbeelding grootte
+function.setpaths=Instellen programmapaden
+function.getgpsies=Routes van Gpsies ophalen
+function.uploadgpsies=Upload routes naar Gpsies
+function.lookupsrtm=Hoogtes van SRTM ophalen
+function.duplicatepoint=Dupliceer punt
+function.setcolours=Instellen kleuren
+function.setlanguage=Instellen taal
+function.correlatephotos=Correleer foto's
+function.rearrangephotos=Foto's herschikken
+function.rotatephotoleft=Roteer foto linksom
+function.rotatephotoright=Roteer foto rechtsom
+function.ignoreexifthumb=Negeer exif thumbnail
+function.help=Help
+function.showkeys=Toon sneltoetsen
+function.about=Over Prune
+function.checkversion=Controleer op nieuwe versie
+function.saveconfig=Instellingen opslaan
+function.diskcache=Kaart opslaan op schijf
+
+# Dialogs
+dialog.exit.confirm.title=Prune afsluiten
+dialog.exit.confirm.text=Uw data is niet opgeslagen. Weet u zeker dat u wilt afsluiten?
+dialog.openappend.title=Toevoegen aan bestaande data
+dialog.openappend.text=Wilt u deze data toevoegen aan de reeds geladen data?
+dialog.deletepoint.title=Verwijder punt
+dialog.deletepoint.deletephoto=Wilt u de foto die aan dit punt is gekoppeld verwijderen?
+dialog.deletephoto.title=Verwijder foto
+dialog.deletephoto.deletepoint=Wilt u het punt dat aan deze foto is gekoppeld verwijderen?
+dialog.openoptions.title=Instellingen openen
+dialog.openoptions.filesnippet=Samenvatting van bestand
+dialog.load.table.field=Veld
+dialog.load.table.datatype=Datatype
+dialog.load.table.description=Omschrijving
+dialog.delimiter.label=Scheidingsteken
+dialog.delimiter.comma=Komma ,
+dialog.delimiter.tab=Tab
+dialog.delimiter.space=Spatie
+dialog.delimiter.semicolon=Puntkomma ;
+dialog.delimiter.other=Overig
+dialog.openoptions.deliminfo.records=bestanden, met
+dialog.openoptions.deliminfo.fields=velden
+dialog.openoptions.deliminfo.norecords=Geen bestanden
+dialog.openoptions.altitudeunits=Hoogte eenheden
+dialog.open.contentsdoubled=Dit bestand bevat twee kopie\u00ebn van ieder punt,\neenkeer als als waypoint en eenkeer als punt
+dialog.selecttracks.intro=Selecteer route of routes om te laden
+dialog.selecttracks.noname=Onbenoemd
+dialog.jpegload.subdirectories=Submappen meenemen
+dialog.jpegload.loadjpegswithoutcoords=Foto's zonder co\u00f6rdinaten meenemen
+dialog.jpegload.loadjpegsoutsidearea=Foto's buiten huidige gebied meenemen
+dialog.jpegload.progress.title=Foto's laden
+dialog.jpegload.progress=Foto's worden gezocht, even geduld aub.
+dialog.gpsload.nogpsbabel=GPSBabel niet gevonden. Doorgaan?
+dialog.gpsload.device=Naam van het apparaat
+dialog.gpsload.format=Formaat
+dialog.gpsload.getwaypoints=Waypoints laden
+dialog.gpsload.gettracks=Routes laden
+dialog.gpsload.save=Opslaan naar bestand
+dialog.gpssend.sendwaypoints=Verstuur waypoint
+dialog.gpssend.sendtracks=Verstuur routes
+dialog.gpssend.trackname=Routenaam
+dialog.saveoptions.title=Bestand opslaan
+dialog.save.fieldstosave=Velden op te slaan
+dialog.save.table.field=Veld
+dialog.save.table.hasdata=Bevat data
+dialog.save.table.save=Opslaan
+dialog.save.headerrow=Ook kopregel opslaan
+dialog.save.coordinateunits=Eenheid co\u00f6rdinaten
+dialog.save.altitudeunits=Eenheid hoogten
+dialog.save.timestampformat=Formaat tijdnotatie
+dialog.save.overwrite.title=Bestand bestaat reeds
+dialog.save.overwrite.text=Bestand bestaat reeds. Weet u zeker dat u wilt overschrijven?
+dialog.save.notypesselected=Geen punttypen geselecteerd
+dialog.exportkml.text=Titel voor de data
+dialog.exportkml.altitude=Absolute hoogten (voor luchtvaart)
+dialog.exportkml.kmz=Comprimeren voor kmz bestand
+dialog.exportkml.exportimages=Exporteer thumbnails naar kzm
+dialog.exportkml.trackcolour=Routekleur
+dialog.exportgpx.name=Naam
+dialog.exportgpx.desc=Omschrijving
+dialog.exportgpx.includetimestamps=Tijden meenemen
+dialog.exportgpx.copysource=Kopieer bron xml
+dialog.exportpov.text=Geef parameters voor POV export
+dialog.exportpov.font=Lettertype
+dialog.exportpov.camerax=Camera X
+dialog.exportpov.cameray=Camera Y
+dialog.exportpov.cameraz=Camera Z
+dialog.exportpov.modelstyle=Model stijl
+dialog.exportpov.ballsandsticks=Balletjes en stokjes
+dialog.exportpov.tubesandwalls=Tubes en muren
+dialog.exportpov.warningtracksize=Deze route heeft een groot aantal punten. Java3D kan deze mogelijk niet tonen.\nWeet u zeker dat u door wilt gaan?
+dialog.exportsvg.text=Selecteer de camera hoeken voor SVG export
+dialog.exportsvg.phi=Azimut hoek \u03d5
+dialog.exportsvg.theta=Stijgingshoek \u03b8
+dialog.exportsvg.gradients=Gebruik gradaties voor schaduw
+dialog.pointtype.desc=Sla de volgende punttypen op:
+dialog.pointtype.track=Routepunten
+dialog.pointtype.waypoint=Waypoints
+dialog.pointtype.photo=Fotopunten
+dialog.pointtype.selection=Alleen selectie
+dialog.confirmreversetrack.title=Bevestig omkering
+dialog.confirmreversetrack.text=Deze route bevat tijd-informatie die niet meer klopt na een omkering.\nWeet u zeker dat u deze sectie wilt omkeren?
+dialog.confirmcutandmove.title=Bevestig knip en verplaats
+dialog.confirmcutandmove.text=Deze route bevat tijd-informatie die niet meer klopt na een verplaatsing.\nWeet u zeker dat u de sectie wilt verplaatsen?
+dialog.interpolate.title=Interpoleer punten
+dialog.interpolate.parameter.text=Aantal punten om in te voegen tussen de geselecteerde punten
+dialog.undo.title=Actie(s) ongedaan maken
+dialog.undo.pretext=Selecteer de acties die u ongedaan wilt maken.
+dialog.undo.none.title=Kan niet ongedaan gemaakt worden.
+dialog.undo.none.text=Geen acties om ongedaan te maken
+dialog.clearundo.title=Ongedaan-maken lijst wissen
+dialog.clearundo.text=Weet u zeker dat u de ongedaan-maken lijst wilt wissen?\nAlle informatie zal verloren gaan!
+dialog.pointedit.title=Wijzig punt
+dialog.pointedit.text=Selecteer ieder te wijzigen veld en gebruik de "Wijzigen" knop om de waarden aan te passen.
+dialog.pointedit.table.field=Veld
+dialog.pointedit.table.value=Waarde
+dialog.pointedit.table.changed=Gewijzigd
+dialog.pointedit.changevalue.text=Geef de nieuwe waarde voor dit veld
+dialog.pointedit.changevalue.title=Wijzig veld
+dialog.pointnameedit.name=Naam van het waypoint
+dialog.pointnameedit.uppercase=HOOFDLETTERS
+dialog.pointnameedit.lowercase=kleine letters
+dialog.pointnameedit.sentencecase=Ieder woord begint met hoofdletter
+dialog.addtimeoffset.add=Tijd toevoegen
+dialog.addtimeoffset.subtract=Tijd aftrekken
+dialog.addtimeoffset.days=Dagen
+dialog.addtimeoffset.hours=Uren
+dialog.addtimeoffset.minutes=Minuten
+dialog.addtimeoffset.notimestamps=Kan geen tijdsverschil aan deze selectie toevoegen, omdat deze geen tijdinformatie bevat
+dialog.findwaypoint.intro=Voer een deel van de waypoint naam in
+dialog.findwaypoint.search=Zoeken
+dialog.saveexif.title=Opslaan Exif
+dialog.saveexif.intro=Selecteer de foto's die u wilt opslaan door deze aan te vinken
+dialog.saveexif.nothingtosave=Co\u00f6rdinaten zijn ongewijzigd, niets om op te slaan
+dialog.saveexif.noexiftool=Exiftool niet gevonden. Doorgaan?
+dialog.saveexif.table.photoname=Fotonaam
+dialog.saveexif.table.status=Status
+dialog.saveexif.table.save=Opslaan
+dialog.saveexif.photostatus.connected=Verbonden
+dialog.saveexif.photostatus.disconnected=Ontkoppeld
+dialog.saveexif.photostatus.modified=Aangepast
+dialog.saveexif.overwrite=Bestanden overschrijven
+dialog.saveexif.force=Negeer kleine fouten
+dialog.charts.xaxis=X-as
+dialog.charts.yaxis=Y-as
+dialog.charts.output=Output
+dialog.charts.screen=Output naar scherm
+dialog.charts.svg=Output naar SVG bestand
+dialog.charts.svgwidth=SVG breedte
+dialog.charts.svgheight=SVG hoogte
+dialog.charts.needaltitudeortimes=De route moet of hoogte- of tijd-informatie bevatten om een diagram te kunnen maken
+dialog.charts.gnuplotnotfound=Kon gnuplot niet vinden op het aangegeven pad
+dialog.distances.intro=Hemelsbrede afstand tussen punten
+dialog.distances.column.from=Van punt
+dialog.distances.column.to=Naar punt
+dialog.distances.currentpoint=Huidige punt
+dialog.distances.toofewpoints=Deze functie heeft waypoints nodig om de afstand ertussen te berekenen
+dialog.fullrangedetails.intro=Dit zijn de details van de geselecteerde reeks
+dialog.setmapbg.intro=Selecteer een kaart-bron, of voeg een nieuwe bron toe.
+dialog.addmapsource.title=Nieuwe kaart-bron toevoegen
+dialog.addmapsource.sourcename=Naam van de bron
+dialog.addmapsource.layer1url=URL van de eerste laag
+dialog.addmapsource.layer2url=URL van de tweede laag (optioneel)
+dialog.addmapsource.maxzoom=Maximaal zoom-niveau
+dialog.addmapsource.cloudstyle=Stijl nummer
+dialog.addmapsource.noname=Onbenoemd
+dialog.gpsies.column.name=Routenaam
+dialog.gpsies.column.length=Lengte
+dialog.gpsies.description=Omschrijving
+dialog.gpsies.nodescription=Geen omschrivjing
+dialog.gpsies.nonefound=Geen routes gevonden
+dialog.gpsies.username=Gpsies gebruikersnaam
+dialog.gpsies.password=Gpsies wachtwoord
+dialog.gpsies.keepprivate=Houd route priv\u00e9
+dialog.gpsies.confirmopenpage=Webpagina van de ge\u00fcploade route openen?
+dialog.gpsies.activities=Aktiviteit
+dialog.gpsies.activity.trekking=Trekking
+dialog.gpsies.activity.walking=Lopen
+dialog.gpsies.activity.jogging=Hardlopen
+dialog.gpsies.activity.biking=Fietsen
+dialog.gpsies.activity.motorbiking=Motor
+dialog.gpsies.activity.snowshoe=Sneeuwschoen
+dialog.gpsies.activity.sailing=Zeilen
+dialog.gpsies.activity.skating=Skating
+dialog.correlate.notimestamps=Er zit geen tijdinformatie in de punten, dus kunnen ze niet aan foto's gekoppeld worden.
+dialog.correlate.nouncorrelatedphotos=Er zijn geen ongekoppelde foto's.\nWeet u zeker dat u wilt doorgaan?
+dialog.correlate.photoselect.intro=Selecteer \u00e9\u00e9n van deze gekoppelde foto's om het tijdsverschil te gebruiken
+dialog.correlate.photoselect.photoname=Fotonaam
+dialog.correlate.photoselect.timediff=Tijdsverschil
+dialog.correlate.photoselect.photolater=Foto later
+dialog.correlate.options.tip=Tip: Door handmatig een foto te koppelen kan het tijdsverschil voor u berekend worden.
+dialog.correlate.options.intro=Selecteer de opties voor automatisch koppelen
+dialog.correlate.options.offsetpanel=Tijdverschil
+dialog.correlate.options.offset=Verschil
+dialog.correlate.options.offset.hours=uren,
+dialog.correlate.options.offset.minutes=minuten en
+dialog.correlate.options.offset.seconds=seconden
+dialog.correlate.options.photolater=Foto later dan punt
+dialog.correlate.options.pointlater=Punt later dan foto
+dialog.correlate.options.limitspanel=Koppelingslimieten
+dialog.correlate.options.notimelimit=Geen tijdslimiet
+dialog.correlate.options.timelimit=Tijdslimiet
+dialog.correlate.options.nodistancelimit=Geen afstandlimiet
+dialog.correlate.options.distancelimit=Afstandlimeit
+dialog.correlate.options.correlate=Koppelen
+dialog.correlate.alloutsiderange=Alle foto's zijn buiten het bereik van de route en kunnen dus niet gekoppeld worden.\nPas het tijdsverschil aan, of maak minimaal \u00e9\u00e9n koppeling handmatig.
+dialog.rearrangephotos.desc=Selecteer doel en sorteervolgorde van de foto punten
+dialog.rearrangephotos.tostart=Naar begin
+dialog.rearrangephotos.toend=Naar einde
+dialog.rearrangephotos.nosort=Niet sorteren
+dialog.rearrangephotos.sortbyfilename=Sorteren op bestandsnaam
+dialog.rearrangephotos.sortbytime=Sorteren op tijd
+dialog.compress.nonefound=Er konden geen punten verwijderd worden
+dialog.compress.closepoints.title=Verwijder nabijliggende punten
+dialog.compress.closepoints.paramdesc=Bereik
+dialog.compress.wackypoints.title=Vreemde punten verwijderen
+dialog.compress.wackypoints.paramdesc=Afstandfactor
+dialog.compress.singletons.title=Singletons verwijderen
+dialog.compress.singletons.paramdesc=Afstandfactor
+dialog.compress.duplicates.title=Verwijderen duplicaten
+dialog.compress.summarylabel=Te verwijderen punten
+dialog.pastecoordinates.desc=Geef co\u00f6rdinaten in
+dialog.pastecoordinates.coords=Co\u00f6rdinaten
+dialog.pastecoordinates.nothingfound=Controleer de co\u00f6rdinaten en probeer het nogmaals
+dialog.help.help=Ga naar\n http://activityworkshop.net/software/prune/\nvoor meer informatie en handleidingen.
+dialog.about.version=Versie
+dialog.about.build=Build
+dialog.about.summarytext1=Prune is een programma voor het laden, tonen en wijzigen van data uit GPS ontvangers.
+dialog.about.summarytext2=Uitgebracht onder de Gnu GPL voor gratis, open, wereldwijd gebruik en verbetering<br>Kopieren, verspreiding en aanpassing is toegestaan en aangemoedigd<br>volgens de voorwaarden in het bestand <code>license.txt</code>.
+dialog.about.summarytext3=Ga naar <code style="font-weight:bold">http://activityworkshop.net/</code> voor meer informatie en handleidingen.
+dialog.about.languages=Beschikbare talen
+dialog.about.translatedby=Nederlandse vertaling door JFO
+dialog.about.systeminfo=Systeeminformatie
+dialog.about.systeminfo.os=Besturingssysteem
+dialog.about.systeminfo.java=Java Runtime
+dialog.about.systeminfo.java3d=Java3d ge\u00efnstalleerd
+dialog.about.systeminfo.povray=Povray ge\u00efnstalleerd
+dialog.about.systeminfo.exiftool=Exiftool ge\u00efnstalleer
+dialog.about.systeminfo.gpsbabel=Gpsbabel ge\u00efnstalleer
+dialog.about.systeminfo.gnuplot=Gnuplot ge\u00efnstalleer
+dialog.about.systeminfo.exiflib=Exif bibliotheek
+dialog.about.systeminfo.exiflib.internal=Intern
+dialog.about.systeminfo.exiflib.internal.failed=Intern (niet gevonden)
+dialog.about.systeminfo.exiflib.external=Extern
+dialog.about.systeminfo.exiflib.external.failed=Extern (niet gevonden)
+dialog.about.yes=Ja
+dialog.about.no=Nee
+dialog.about.credits=Credits
+dialog.about.credits.code=Prune code geschreven door
+dialog.about.credits.exifcode=Exif code door
+dialog.about.credits.icons=Sommige iconen overgenomen van
+dialog.about.credits.translators=Vertalers
+dialog.about.credits.translations=Vertaling geholpen door
+dialog.about.credits.devtools=Ontwikkeltool
+dialog.about.credits.othertools=Overige tools
+dialog.about.credits.thanks=Dank aan
+dialog.about.readme=Leesmij
+dialog.checkversion.error=Versienummer kon niet worden gecontroleerd.\nControleer de internetverbinding.
+dialog.checkversion.uptodate=U gebruikt de laatste versie van Prune.
+dialog.checkversion.newversion1=Een nieuwe versie van Prune is beschikbaar. De nieuwste versie is nu versie
+dialog.checkversion.newversion2=.
+dialog.checkversion.releasedate1=Deze nieuwe versie was vrijgegeven op
+dialog.checkversion.releasedate2=.
+dialog.checkversion.download=Om de nieuwst versie te downloaden, ga naar http://activityworkshop.net/software/prune/download.html.
+dialog.keys.intro=De volgende sneltoetsen vervangen muisacties
+dialog.keys.keylist=<table><tr><td>Pijltjestoetsen</td><td>verschuif de kaart links, rechts, omhoog, omlaag</td></tr><tr><td>Ctrl + pijltje naar links, rechts</td><td>Selecteer volgende, vorige punt</td></tr><tr><td>Ctrl + pijltje omhoog, omlaag</td><td>Zoom in of uit</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Selecteer vorig, volgend segment</td></tr><tr><td>Ctrl + Home, End</td><td>Select eerste, laatste punt</td></tr><tr><td>Del</td><td>Verwijder huidige punt</td></tr></table>
+dialog.keys.normalmodifier=Ctrl
+dialog.keys.macmodifier=Command
+dialog.saveconfig.desc=De volgende instellingen kunnen worden opgeslagen in een configuratiebestand:
+dialog.saveconfig.prune.trackdirectory=Route map
+dialog.saveconfig.prune.photodirectory=Foto map
+dialog.saveconfig.prune.languagecode=Taalcode (NL)
+dialog.saveconfig.prune.languagefile=Taal bestand
+dialog.saveconfig.prune.gpsdevice=GPS apparaat
+dialog.saveconfig.prune.gpsformat=GPS formaat
+dialog.saveconfig.prune.povrayfont=Povray lettertype
+dialog.saveconfig.prune.metricunits=Metrisch systeem gebruiken?
+dialog.saveconfig.prune.gnuplotpath=Pad naar gnuplot
+dialog.saveconfig.prune.gpsbabelpath=Pad naar gpsbabel
+dialog.saveconfig.prune.exiftoolpath=Pad naar exiftool
+dialog.saveconfig.prune.mapsource=Geselecteerde kaartbron
+dialog.saveconfig.prune.mapsourcelist=Kaartbronnen
+dialog.saveconfig.prune.diskcache=Kaartcache
+dialog.saveconfig.prune.kmzimagewidth=KMZ afbeelding breedte
+dialog.saveconfig.prune.kmzimageheight=KMZ afbeelding hoogte
+dialog.saveconfig.prune.colourscheme=Kleurenschema
+dialog.saveconfig.prune.kmltrackcolour=KML routekleur
+dialog.setpaths.intro=Indien nodig kan je de paden naar externe applicaties kiezen:
+dialog.setpaths.found=Pad gevonden?
+dialog.addaltitude.noaltitudes=De geselecteerde reeks bevat geen hoogtes
+dialog.addaltitude.desc=Toe te voegen hoogteverschil
+dialog.lookupsrtm.overwritezeros=Hoogtewaarde 0 overschijven?
+dialog.setcolours.intro=Klik op een kleur om de kleur te wijzigen
+dialog.setcolours.background=Achtergrond
+dialog.setcolours.borders=Randen
+dialog.setcolours.lines=Lijnen
+dialog.setcolours.primary=Primair
+dialog.setcolours.secondary=Secondair
+dialog.setcolours.point=Punten
+dialog.setcolours.selection=Selectie
+dialog.setcolours.text=Tekst
+dialog.colourchooser.title=Selecteer een kleur
+dialog.colourchooser.red=Rood
+dialog.colourchooser.green=Groen
+dialog.colourchooser.blue=Blauw
+dialog.setlanguage.firstintro=U kunt kiezen uit \u00e9\u00e9n van de meegeleverde talen,<p>of selecteer een tekstbestand.
+dialog.setlanguage.secondintro=U dient uw instellingen op te slaan en<p>Prune te herstarten om de taal te kunnen wijzigen
+dialog.setlanguage.language=Taal
+dialog.setlanguage.languagefile=Taal bestand
+dialog.setlanguage.endmessage=Sla nu uw instellingen op en herstart Prune\nom de taalwijziging te activeren
+dialog.diskcache.save=Kaartafbeeldingen opslaan op schijf
+dialog.diskcache.dir=Cache map
+dialog.diskcache.createdir=Cre\u00eber map
+dialog.diskcache.nocreate=Cache map niet aangemaakt
+dialog.deletefieldvalues.intro=Selecteer het te verwijderen veld voor de huidige reeks
+
+# 3d window
+dialog.3d.title=Prune in 3D
+dialog.3d.altitudecap=Minimale hoogte
+dialog.3d.altitudefactor=Hoogte overdrijvingsfactor
+dialog.3dlines.title=Prune raster
+dialog.3dlines.empty=Geen raster om af te beelden
+dialog.3dlines.intro=Dit is het raster voor 3D
+
+# Confirm messages
+confirm.loadfile=Data van schijf geladen
+confirm.save.ok1=Succesvol opgeslagen
+confirm.save.ok2=Punten naar bestand
+confirm.deletepoint.single=punt was verwijderd
+confirm.deletepoint.multi=punten waren verwijderd
+confirm.point.edit=punt gewijzigd
+confirm.mergetracksegments=Route segmenten samengevoegd
+confirm.reverserange=Reeks ge\u00efnverteerd
+confirm.addtimeoffset=Tijdsverschil toegevoegd
+confirm.addaltitudeoffset=Hoogteverschil toegevoegd
+confirm.rearrangewaypoints=Waypoints herschikt
+confirm.rearrangephotos=Foto herschikt
+confirm.cutandmove=Selectie verplaatst
+confirm.convertnamestotimes=Namen waypoint geconverteerd
+confirm.saveexif.ok1=Opgeslagen
+confirm.saveexif.ok2=foto bestanden
+confirm.undo.single=Actie geannuleerd
+confirm.undo.multi=Acties geannuleerd
+confirm.jpegload.single=foto was toegevoegd
+confirm.jpegload.multi=foto's waren toegevoegd
+confirm.photo.connect=foto's gekoppeld
+confirm.photo.disconnect=foto's ontkoppeld
+confirm.correlate.single=Foto was gecorreleerd
+confirm.correlate.multi=Foto's waren gecorreleerd
+confirm.createpoint=punt aangemaakt
+confirm.rotatephoto=foto rgeroteerd
+confirm.running=Bezig...
+confirm.lookupsrtm1=Gevonden
+confirm.lookupsrtm2=hoote waarden
+confirm.deletefieldvalues=Veldwaarden gewist
+
+# Buttons
+button.ok=OK
+button.back=Terug
+button.next=Volgende
+button.finish=Einde
+button.cancel=Annuleren
+button.overwrite=Overschrijven
+button.moveup=Omhoog
+button.movedown=Omlaag
+button.showlines=Toon raster
+button.edit=Wijzigen
+button.exit=Afsluiten
+button.close=Sluiten
+button.continue=Doorgaan
+button.yes=Ja
+button.no=Nee
+button.yestoall=Ja op alles
+button.notoall=Nee op alles
+button.select=Selecteer
+button.selectall=Selecteer alles
+button.selectnone=Selecteer niets
+button.preview=Voorbeeld
+button.load=Laden
+button.guessfields=Raad velden
+button.showwebpage=Toon webpagina
+button.check=Controleren
+button.resettodefaults=Terug naar beginwaarden
+button.browse=Browse...
+button.addnew=Nieuwe toevoegen
+button.delete=Verwijderen
+
+# File types
+filetype.txt=TXT bestand
+filetype.jpeg=JPG bestand
+filetype.kmlkmz=KML, KMZ bestand
+filetype.kml=KML bestand
+filetype.kmz=KMZ bestand
+filetype.gpx=GPX bestand
+filetype.pov=POV bestand
+filetype.svg=SVG bestand
+
+# Display components
+display.nodata=Geen gegevens geladen
+display.noaltitudes=Route gegevens bevatten geen hoogte
+display.notimestamps=Route gegevens bevatten geen tijdinformatie
+details.trackdetails=Route details
+details.notrack=Geen route geladen
+details.track.points=Punten
+details.track.file=Bestand
+details.track.numfiles=Aantal bestanden
+details.pointdetails=Puntdetails
+details.index.selected=Index
+details.index.of=van
+details.nopointselection=Geen punt geselecteerd
+details.photofile=Fotobestand
+details.norangeselection=Geen reeks geselecteerd
+details.rangedetails=Reeksdetails
+details.range.selected=Geselecteerd
+details.range.to=tot
+details.altitude.to=tot
+details.range.climb=Stijgen
+details.range.descent=Dalen
+details.coordformat=Co\u00f6rdinatenformaat
+details.distanceunits=Lengte eenheid
+display.range.time.secs=s
+display.range.time.mins=m
+display.range.time.hours=u
+display.range.time.days=d
+details.range.avespeed=Gem snelheid
+details.range.avemovingspeed=Gem snelheid in beweging
+details.range.maxspeed=Max snelheid
+details.range.numsegments=Aantal segmenten
+details.range.pace=Tempo
+details.range.gradient=Helling
+details.waypointsphotos.waypoints=Waypoints
+details.waypointsphotos.photos=Foto
+details.photodetails=Foto details
+details.nophoto=Geen foto geselecteerd
+details.photo.loading=Bezig met laden
+details.photo.connected=Geconnecteerd
+map.overzoom=Geen kaarten beschikbaar op dit zoom-niveau
+
+# Field names
+fieldname.latitude=Breedtegraad
+fieldname.longitude=Lengtegraad
+fieldname.altitude=Hoogte
+fieldname.timestamp=Tijd
+fieldname.time=Tijd
+fieldname.waypointname=Naam
+fieldname.waypointtype=Type
+fieldname.newsegment=Segment
+fieldname.custom=Custom
+fieldname.prefix=Veld
+fieldname.distance=Afstand
+fieldname.movingdistance=Snelheid in beweging
+fieldname.duration=Duur
+fieldname.speed=Snelheid
+fieldname.verticalspeed=Verticale snelheid
+
+# Measurement units
+units.original=Oorspronkelijke
+units.default=Default
+units.metres=Meters
+units.metres.short=m
+units.feet=Voet
+units.feet.short=ft
+units.kilometres=Kilometers
+units.kilometres.short=km
+units.kmh=km/u
+units.miles=Mijlen
+units.miles.short=mi
+units.mph=mph
+units.metrespersec=m/s
+units.feetpersec=ft/s
+units.hours=uren
+units.degminsec=Grd-min-sec
+units.degmin=Grd-min
+units.deg=Graden
+units.iso8601=ISO 8601
+
+# External urls
+url.googlemaps=maps.google.nl
+
+# Cardinals for 3d plots
+cardinal.n=N
+cardinal.s=Z
+cardinal.e=O
+cardinal.w=W
+
+# Undo operations
+undo.load=gegevens laden
+undo.loadphotos=foto's laden
+undo.editpoint=wijzigen punt
+undo.deletepoint=verwijderen punt
+undo.deletephoto=verwijderen foto
+undo.deleterange=verwijderen reeks
+undo.compress=comprimeren route
+undo.insert=punten invoegen
+undo.reverse=reeks omkeren
+undo.mergetracksegments=Samenvoegen route segmenten
+undo.addtimeoffset=Tijdsverschil toevoegen
+undo.addaltitudeoffset=Hoogteverschil toevoegen
+undo.rearrangewaypoints=Herschikken waypoint
+undo.cutandmove=Verschuif sectie
+undo.connectphoto=Koppel foto
+undo.disconnectphoto=Loskoppelen foto
+undo.correlate=Correleer foto
+undo.rearrangephotos=Herschikken foto's
+undo.createpoint=Cre\u00eber punt
+undo.rotatephoto=Roteer foto
+undo.convertnamestotimes=Converteer namen naar tijden
+undo.lookupsrtm=Opzoeken hoogtes in SRTM
+undo.deletefieldvalues=Verwijder veldwaarden
+
+# Error messages
+error.save.dialogtitle=Fout bij opslaan gegevens
+error.save.nodata=Geen gegevens om op te slaan
+error.save.failed=Kon de gegevens niet naar bestand wegschrijven
+error.saveexif.filenotfound=Fotobestand niet gevonden
+error.saveexif.cannotoverwrite1=Fotobestand
+error.saveexif.cannotoverwrite2=is alleen-lezen en kan niet worden overschreven. Wegschrijven naar kopie?
+error.saveexif.failed1=Kon
+error.saveexif.failed2=van de foto's niet wegschrijven
+error.saveexif.forced1=
+error.saveexif.forced2=van de foto's hadden "forcing" nodig
+error.load.dialogtitle=Fout gegevens laden
+error.load.noread=Kan bestand niet lezen
+error.load.nopoints=Geen co\u00f6rdinaat informatie gevonden in bestand
+error.load.unknownxml=Onbekend xml-formaat:
+error.load.noxmlinzip=Geen xml-bestand gevonden in zipbestand
+error.load.othererror=Fout bij lezen bestand:
+error.jpegload.dialogtitle=Fout bij inlezen foto's
+error.jpegload.nofilesfound=Bestanden niet gevonden
+error.jpegload.nojpegsfound=Geen jpeg-bestanden gevonden
+error.jpegload.noexiffound=Geen EXIF informatie gevonden
+error.jpegload.nogpsfound=Geen GPS informatie gevonden
+error.jpegload.exifreadfailed=Kon geen EXIF informatie inlezen. EXIF informatie kan niet worden gelezen\n zonder interne of externe bibliotheek.
+error.gpsload.unknown=Onbekende fout
+error.undofailed.title=Terugdraaien mislukt
+error.undofailed.text=Kon actie niet terugdraaien
+error.function.noop.title=Functie had geen effect
+error.rearrange.noop=Herschikken van punten had geen effect
+error.function.notavailable.title=Functie niet beschikbaar
+error.function.nojava3d=Deze functie heeft Java3d nodig,verkrijgbaar bij sun.com.
+error.3d=Er is een fout opgetreden bij de 3d afbeelding
+error.readme.notfound=Leesmij bestand niet gevonden
+error.osmimage.dialogtitle=Fout bij inlezen kaart afbeeldingen
+error.osmimage.failed=Fout bij inlezen kaart afbeeldingen. Controleer je internet verbinding
+error.language.wrongfile=Het geselecteerde bestand is vermoedelijk geen taalbestand voor Prune
+error.convertnamestotimes.nonames=Namen konden niet naar tijden worden geconverteerd
+error.lookupsrtm.nonefound=Geen hoogtewaarden beschikbaar voor deze punten
+error.lookupsrtm.nonerequired=Alle punten hebben reeds hoogte, er hoeft niets te worden opgezocht.
+error.gpsies.uploadnotok=Gpsies server antwoordde met
+error.gpsies.uploadfailed=De upload is mislukt. Fout
dialog.gpsies.description=Opis
dialog.gpsies.nodescription=Brak opisu
dialog.gpsies.nonefound=Nie znalaz\u0142em \u015bcie\u017cek
+dialog.gpsies.activities=Aktywno\u015b\u0107
+dialog.gpsies.activity.trekking=W\u0119drowa\u0107
+dialog.gpsies.activity.walking=Walking
+dialog.gpsies.activity.jogging=Jogging
+dialog.gpsies.activity.biking=Wycieczka rowerowa
+dialog.gpsies.activity.motorbiking=Motocykl
+dialog.gpsies.activity.snowshoe=Snowshoeing
+dialog.gpsies.activity.sailing=Sailing
+dialog.gpsies.activity.skating=Skating
dialog.correlate.notimestamps=Punkty nie maj\u0105 znacznik\u00f3w czasu, nie mo\u017cna ich powi\u0105za\u0107 ze zdj\u0119ciami.
dialog.correlate.nouncorrelatedphotos=Nie ma nie powi\u0105zanych zdj\u0119\u0107.\nCzy na pewno chcesz kontynuowa\u0107?
dialog.correlate.photoselect.intro=Wybierz jedno z powi\u0105zanych zdj\u0119\u0107 i u\u017cyj go jako wzorca do przesuni\u0119cia czasu
error.osmimage.failed=B\u0142\u0105d przy \u0142adowaniu obraz\u00f3w map. Sprawd\u017a po\u0142\u0105czenie z internetem.
error.language.wrongfile=Wybrany plik nie jest plikiem z t\u0142umaczeniem dla Prune
error.convertnamestotimes.nonames=\u017badne nazwy nie mog\u0142y zosta\u0107 zmienione na czas
-error.lookupsrtm.none=Nie znaleziono danych o wysoko\u015bci.
+error.lookupsrtm.nonefound=Nie znaleziono danych o wysoko\u015bci.
menu.track=Track
menu.track.undo=Desfazer
menu.track.clearundo=Limpar lista de desfazer
-menu.point.editpoint=Editar ponto
-menu.point.deletepoint=Remover ponto
-menu.range.deleterange=Remover intervalo
menu.track.deletemarked=Remover pontos marcados
-menu.range.interpolate=Interpolar
-menu.range.average=Sele\u00e7\u00e3o m\u00e9dia
-menu.range.reverse=Reverter intervalo
-menu.range.mergetracksegments=Mesclar trechos da rota
menu.track.rearrange=Rearrumar pontos
menu.track.rearrange.start=Tudo para o in\u00edcio do arquivo
menu.track.rearrange.end=Tudo para o fim do arquivo
menu.track.rearrange.nearest=Cada um para o ponto da rota mais pr\u00f3ximo
-menu.range.cutandmove=Recortar e mover sele\u00e7\u00e3o
menu.range=Intervalo
-menu.point=Ponto
menu.range.all=Selectionar tudo
menu.range.none=N\u00e3o selecionar nenhuns
menu.range.start=Definir in\u00edcio do intervalo
menu.range.end=Definir fim do intervalo
+menu.range.deleterange=Remover intervalo
+menu.range.interpolate=Interpolar
+menu.range.average=Sele\u00e7\u00e3o m\u00e9dia
+menu.range.reverse=Reverter intervalo
+menu.range.mergetracksegments=Mesclar trechos da rota
+menu.range.cutandmove=Recortar e mover sele\u00e7\u00e3o
+menu.point=Ponto
+menu.point.editpoint=Editar ponto
+menu.point.deletepoint=Remover ponto
menu.photo=Foto
menu.photo.saveexif=Salvar para Exif
menu.photo.connect=Conectar ao ponto
menu.view.browser.yahoo=Mapas do Yahoo
menu.view.browser.bing=Mapas do Bing
menu.settings=Configura\u00e7\u00f5es
+menu.settings.onlinemode=Carregar mapas da Internet
menu.help=Ajuda
# Popup menu for map
menu.map.zoomin=Ampliar
function.setkmzimagesize=Definir tamanho da imagem KMZ
function.setpaths=Definir caminhos do programa
function.getgpsies=Obter rotas Gpsies
+function.lookupsrtm=Obter altitudes a partir do SRTM
function.duplicatepoint=Duplicar ponto
function.setcolours=Definir cores
function.setlanguage=Definir idioma
function.about=Sobre o Prune
function.checkversion=Verificar novas vers\u00f5es
function.saveconfig=Salvar configura\u00e7\u00f5es
+function.diskcache=Salvar mapas para o disco
# Dialogs
dialog.exit.confirm.title=Sair do Prune
dialog.openoptions.deliminfo.fields=campos
dialog.openoptions.deliminfo.norecords=Sem registros
dialog.openoptions.altitudeunits=Unidades de altitude
+dialog.open.contentsdoubled=Este arquivo cont\u00e9m duas c\u00f3pias de cada ponto,\nsendo uma como ponto normal e uma como ponto de rota.
dialog.jpegload.subdirectories=Incluir subpastas
dialog.jpegload.loadjpegswithoutcoords=Incluir fotos sem coordenadas
dialog.jpegload.loadjpegsoutsidearea=Incluir fotos fora da \u00e1rea atual
dialog.distances.currentpoint=Ponto atual
dialog.distances.toofewpoints=Esta fun\u00e7\u00e3o precisa de pontos para calcular a dist\u00e3ncia entre eles
dialog.fullrangedetails.intro=Aqui est\u00e3o os detalhes para o intervalo selecionado
-dialog.setmapbg.mapnik=Mapnik (padr\u00e3o)
-dialog.setmapbg.osma=Osma
-dialog.setmapbg.cyclemap=Cyclemap
-dialog.setmapbg.other=Outro
-dialog.setmapbg.server=URL do Servidor
+dialog.setmapbg.intro=Selecione uma das fontes de mapas ou adicione uma nova
+dialog.addmapsource.title=Adicionar nova fonte de mapas
+dialog.addmapsource.sourcename=Nome da fonte
+dialog.addmapsource.layer1url=URL da primeira camada
+dialog.addmapsource.layer2url=URL opcional da segunda camada
+dialog.addmapsource.maxzoom=N\u00edvel de amplia\u00e7\u00e3o m\u00e1ximo
+dialog.addmapsource.cloudstyle=N\u00famero do estilo
+dialog.addmapsource.noname=Sem nome
dialog.gpsies.column.name=Nome da rota
dialog.gpsies.column.length=Extens\u00e3o
dialog.gpsies.description=Descri\u00e7\u00e3o
dialog.gpsies.nodescription=Sem descri\u00e7\u00e3o
dialog.gpsies.nonefound=Nenhuma rota encontrada
+dialog.gpsies.activity.trekking=Trilha
+dialog.gpsies.activity.walking=Caminhada
+dialog.gpsies.activity.jogging=Corrida
+dialog.gpsies.activity.biking=Ciclismo
+dialog.gpsies.activity.motorbiking=Motocross
+dialog.gpsies.activity.snowshoe=Snowshoeing
+dialog.gpsies.activity.sailing=Sailing
+dialog.gpsies.activity.skating=Patina\u00e7\u00e3o
dialog.correlate.notimestamps=N\u00e3o existem data-hora nos dados dos pontos, assim n\u00e3o h\u00e1 nada para correlacionar com as fotos
dialog.correlate.nouncorrelatedphotos=Existem fotos n\u00e3o correlacionadas.\nVoc\u00ea tem certeza que deseja continuar?
dialog.correlate.photoselect.intro=Selecione uma destas fotos correlacionadas para usar como diferen\u00e7a de tempo
dialog.about.summarytext2=Isto est\u00e1 lan\u00e7ado sob a Gnu GPL para uso e melhoria livre, aberto e em todo o mundo.<br>A c\u00f3pia, redistribui\u00e7\u00e3o e modifica\u00e7\u00e3o s\u00e3o permitidas e encorajadas<br>de acordo coma as condi\u00e7\u00f5es no arquivo <code>license.txt</code>inclu\u00eddo.
dialog.about.summarytext3=Por favor, veja <code style="font-weight:bold">http://activityworkshop.net/</code> para mais informa\u00e7\u00f5es e guia do usu\u00e1rio.
dialog.about.languages=Idiomas dispon\u00edveis
-dialog.about.translatedby=Texto em portugu\u00eas por amigo anónimo.
+dialog.about.translatedby=Texto em portugu\u00eas por Marcus Gama.
dialog.about.systeminfo=Informa\u00e7\u00f5es do sistema
dialog.about.systeminfo.os=Sistema Operacional
dialog.about.systeminfo.java=M\u00f3dulo Java
dialog.about.systeminfo.exiftool=Exittool instalado
dialog.about.systeminfo.gpsbabel=Gpsbabel instalado
dialog.about.systeminfo.gnuplot=Gnuplot instalado
+dialog.about.systeminfo.exiflib=Biblioteca do Exif
+dialog.about.systeminfo.exiflib.internal=Interna
+dialog.about.systeminfo.exiflib.internal.failed=Interna (n\u00e3o encontrada)
+dialog.about.systeminfo.exiflib.external=Externa
+dialog.about.systeminfo.exiflib.external.failed=Externa (n\u00e3o encontrada)
dialog.about.yes=Sim
dialog.about.no=N\u00e3o
dialog.about.credits=Cr\u00e9ditos
dialog.checkversion.download=Para baixar a nova vers\u00e3o, v\u00e1 para http://activityworkshop.net/software/prune/download.html.
dialog.keys.intro=Voc\u00ea pode usar os seguintes atalhos de teclado ao inv\u00e9s de usar o mouse
dialog.keys.keylist=<table><tr><td>Cursores</td><td>Move o mapa para esquerda, direita, acima e abaixo</td></tr><tr><td>Ctrl + cursores esquerdo e direito</td><td>Seleciona o pr\u00f3ximo ponto ou o anterior</td></tr><tr><td>Ctrl + cursores acima e abaixo</td><td>Amplia ou reduz</td></tr><tr><td>Del</td><td>Remove o ponto atual</td></tr></table>
+dialog.keys.normalmodifier=Ctrl
+dialog.keys.macmodifier=Command
dialog.saveconfig.desc=As seguintes configura\u00e7\u00f5es podem ser salvas para um arquivo de configura\u00e7\u00e3o.
dialog.saveconfig.prune.trackdirectory=Pasta de rotas
dialog.saveconfig.prune.photodirectory=Pasta de fotos
dialog.saveconfig.prune.gnuplotpath=Caminho para o gnuplot
dialog.saveconfig.prune.gpsbabelpath=Caminho para o gpsbabel
dialog.saveconfig.prune.exiftoolpath=Caminho para o exiftool
-dialog.saveconfig.prune.mapserverindex=\u00cdndice do servidor de mapas
-dialog.saveconfig.prune.mapserverurl=URL do servidor de mapas
+dialog.saveconfig.prune.mapsource=Selecionar fonte de mapas
+dialog.saveconfig.prune.mapsourcelist=Fontes de mapas
+dialog.saveconfig.prune.diskcache=Cache de mapas
dialog.saveconfig.prune.kmzimagewidth=Largura da imagem KMZ
dialog.saveconfig.prune.kmzimageheight=Altura da imagem KMZ
dialog.saveconfig.prune.colourscheme=Esquema de cores
dialog.saveconfig.prune.kmltrackcolour=Cor da rota KML
dialog.setpaths.intro=Se voc\u00ea precisar, voc\u00ea pode escolher os caminhos para as aplica\u00e7\u00f5es externas:
+dialog.setpaths.found=Caminho encontrado?
dialog.addaltitude.noaltitudes=O intervalo selecionado n\u00e3o cont\u00e9m altitudes
dialog.addaltitude.desc=Diferen\u00e7a de altitude a adicionar
dialog.setcolours.intro=Clique em um trecho de cor para mudar a cor
dialog.setlanguage.language=Idioma
dialog.setlanguage.languagefile=Arquivo de idioma
dialog.setlanguage.endmessage=Agora salve suas configura\u00e7\u00f5es e reinicie o Prune\npara que a mudan\u00e7a de idioma ocorra.
+dialog.diskcache.save=Salvar imagens do mapa para o disco
+dialog.diskcache.dir=Diret\u00f3rio da cache
+dialog.diskcache.createdir=Criar diret\u00f3rio
+dialog.diskcache.nocreate=Diret\u00f3rio da cache n\u00e3o foi criado
# 3d window
dialog.3d.title=Vista 3D do Prune
confirm.createpoint=ponto criado
confirm.rotatephoto=foto rotacionada
confirm.running=Rodando...
+confirm.lookupsrtm1=Encontrado
+confirm.lookupsrtm2=valores de altitude
# Buttons || These are all the texts for buttons
button.ok=Ok
button.check=Verificar
button.resettodefaults=Restaurar para os padr\u00f5es
button.browse=Navegar...
+button.addnew=Adicionar novo
+button.delete=Remover
# File types
filetype.txt=Arquivos TXT
# Display components || These are all for the side panels showing point/range details
display.nodata=Nenhum dado carregado
display.noaltitudes=Dados da rota n\u00e3o incluem altitudes
+display.notimestamps=Dados da rota n\u00e3o incluem data-hora
details.trackdetails=Detalhes da track
details.notrack=Nenhuma rota carrgeada
details.track.points=Pontos
display.range.time.days=d
details.range.avespeed=Velocidade m\u00e9dia
details.range.avemovingspeed=Movimento m\u00e9dio
+details.range.maxspeed=Velocidade m\u00e1xima
details.range.numsegments=N\u00famero de segmentos
details.range.pace=Passo
details.range.gradient=Gradiente
units.iso8601=ISO 8601
# External urls
-url.googlemaps=maps.google.pt
+url.googlemaps=maps.google.com.br
# Cardinals for 3d plots
cardinal.n=N
undo.createpoint=criar ponto
undo.rotatephoto=rotacionar foto
undo.convertnamestotimes=converter nomes para tempos
+undo.lookupsrtm=procurar altitudes a partir do STRM
# Error messages
error.save.dialogtitle=Erro ao salvar dados
error.jpegload.nojpegsfound=Nenhum arquivo jpeg encontrado
error.jpegload.noexiffound=Nenhuma informa\u00e7\u00e3o EXIF encontrada
error.jpegload.nogpsfound=Nenhuma informa\u00e7\u00e3o de GPS encontrada
+error.jpegload.exifreadfailed=Falha ao ler informa\u00e7\u00f5es do EXIF. Nenhuma informa\u00e7\u00e3o do EXIF pode ser lida\nseja na biblioteca interna, seja na externa.
error.gpsload.unknown=Erro desconhecido
error.undofailed.title=Falha ao desfazer
error.undofailed.text=Falha para desfazer opera\u00e7\u00e3o
error.osmimage.failed=Falha ao carregar imagens do mapa. Por favor, verifique a conex\u00e3o \u00e0 Internet.
error.language.wrongfile=O arquivo selecionado n\u00e3o parece ser um arquivo de idioma do Prune
error.convertnamestotimes.nonames=Nenhum nome pode ser convertido para tempo
+error.lookupsrtm.nonefound=Nenhum valor de altitude encontrado
dialog.gpsies.description=A\u00e7\u0131klama
dialog.gpsies.nodescription=A\u00e7\u0131klama yok
dialog.gpsies.nonefound=Herhangi bir yol bulunmad\u0131
+dialog.gpsies.activities=Etkinlik
+dialog.gpsies.activity.trekking=Y\u00fcr\u00fcy\u00fc\u015f
+dialog.gpsies.activity.walking=Y\u00fcr\u00fcme
+dialog.gpsies.activity.jogging=Ko\u015fma
+dialog.gpsies.activity.biking=Bisiklet
+dialog.gpsies.activity.sailing=Yelken
+dialog.gpsies.activity.skating=Paten
dialog.correlate.photoselect.photoname=Foto ad\u0131
dialog.correlate.photoselect.photolater=Foto sonra
dialog.correlate.options.offset.hours=saat,
menu.file.addphotos=\u6dfb\u52a0\u76f8\u7247
menu.file.save=\u4fdd\u5b58
menu.file.exit=\u9000\u51fa
+menu.track=\u8f68\u8ff9
menu.track.undo=\u64a4\u9500
menu.track.clearundo=\u6e05\u9664\u64a4\u9500\u6e05\u5355
-menu.point.editpoint=\u7f16\u8f91\u8f68\u8ff9\u70b9
-menu.point.deletepoint=\u5220\u9664\u8f68\u8ff9\u70b9
-menu.range.deleterange=\u5220\u9664\u8f68\u8ff9\u70b9\u6bb5
menu.track.deletemarked=\u5220\u9664\u5df2\u6807\u793a\u8f68\u8ff9\u70b9
-menu.range.interpolate=\u63d2\u5165\u8f68\u8ff9\u70b9
-menu.range.average=\u8bbe\u7f6e\u5e73\u5747\u8f68\u8ff9\u70b9
-menu.range.reverse=\u8f68\u8ff9\u70b9\u53cd\u5411
-menu.range.mergetracksegments=\u5408\u5e76\u8f68\u8ff9\u6bb5
menu.track.rearrange=\u822a\u70b9\u91cd\u7f6e
menu.track.rearrange.start=\u81f3\u8d77\u59cb\u4f4d\u7f6e
menu.track.rearrange.end=\u81f3\u672b\u4f4d\u7f6e
menu.track.rearrange.nearest=\u81f3\u6700\u8fd1\u8f68\u8ff9\u70b9
-menu.range.cutandmove=\u79fb\u52a8
+menu.range=\u822a\u6bb5
menu.range.all=\u5168\u9009
menu.range.none=\u64a4\u9500\u9009\u62e9
menu.range.start=\u8bbe\u7f6e\u8d77\u70b9
menu.range.end=\u8bbe\u7f6e\u672b\u70b9
+menu.range.deleterange=\u5220\u9664\u8f68\u8ff9\u70b9\u6bb5
+menu.range.interpolate=\u63d2\u5165\u8f68\u8ff9\u70b9
+menu.range.average=\u8bbe\u7f6e\u5e73\u5747\u8f68\u8ff9\u70b9
+menu.range.reverse=\u8f68\u8ff9\u70b9\u53cd\u5411
+menu.range.mergetracksegments=\u5408\u5e76\u8f68\u8ff9\u6bb5
+menu.range.cutandmove=\u79fb\u52a8
+menu.point=\u8f68\u8ff9\u70b9
+menu.point.editpoint=\u7f16\u8f91\u8f68\u8ff9\u70b9
+menu.point.deletepoint=\u5220\u9664\u8f68\u8ff9\u70b9
menu.photo=\u76f8\u7247
menu.photo.saveexif=\u5750\u6807\u4fdd\u5b58\u81f3Exif
menu.photo.connect=\u94fe\u63a5\u76f8\u7247
menu.view.browser.openstreetmap=Openstreet\u5730\u56fe
menu.view.browser.mapquest=Mapquest\u5730\u56fe
menu.view.browser.yahoo=Yahoo\u5730\u56fe
+menu.view.browser.bing=Bing(\u5fc5\u5e94\uff09\u5730\u56fe
menu.settings=\u8bbe\u7f6e
+menu.settings.onlinemode=\u4ece\u7f51\u4e0a\u5bfc\u5165\u5730\u56fe
menu.help=\u5e2e\u52a9
# Popup menu for map
menu.map.zoomin=\u653e\u5927
function.compress=\u538b\u7f29\u8f68\u8ff9(\u6807\u793a\u8981\u5220\u9664\u822a\u70b9\uff09
function.addtimeoffset=\u52a0\u5165\u65f6\u95f4\u5dee
function.addaltitudeoffset=\u52a0\u5165\u9ad8\u5ea6\u504f\u79fb
+function.convertnamestotimes=\u822a\u70b9\u540d\u79f0\u8f6c\u4e3a\u65f6\u95f4
function.findwaypoint=\u67e5\u627e\u822a\u70b9
+function.pastecoordinates=\u8f93\u5165\u65b0\u5750\u6807
function.charts=\u9ad8\u5ea6\u901f\u5ea6\u56fe\u8868
function.show3d=3-D\u89c6\u56fe
function.distances=\u8ddd\u79bb
+function.fullrangedetails=\u5168\u822a\u6bb5\u8be6\u7ec6\u4fe1\u606f
function.setmapbg=\u80cc\u666f\u5730\u56fe
function.setkmzimagesize=\u8bbe\u7f6eKMZ\u56fe\u50cf\u5c3a\u5bf8
function.setpaths=\u8bbe\u7f6e\u7a0b\u5e8f\u8def\u5f84
function.getgpsies=Gpsies\u8f68\u8ff9
+function.lookupsrtm=\u4eceSRTM\u83b7\u5f97\u9ad8\u5ea6\u4fe1\u606f
+function.duplicatepoint=\u590d\u5236\u70b9
+function.setcolours=\u8bbe\u7f6e\u989c\u8272
+function.setlanguage=\u8bbe\u7f6e\u8bed\u8a00
function.correlatephotos=\u94fe\u63a5\u76f8\u7247
+function.rearrangephotos=\u91cd\u6392\u76f8\u7247
+function.rotatephotoleft=\u5de6\u65cb\u8f6c
+function.rotatephotoright=\u53f3\u65cb\u8f6c
+function.ignoreexifthumb=\u5ffd\u7565Exif\u7f29\u7565\u56fe
function.help=\u5e2e\u52a9
function.showkeys=\u663e\u793a\u5feb\u6377\u952e
function.about=\u5173\u4e8ePrune
function.checkversion=\u68c0\u67e5\u66f4\u65b0
function.saveconfig=\u4fdd\u5b58\u8bbe\u7f6e
+function.diskcache=\u4fdd\u5b58\u5730\u56fe
# Dialogs
dialog.exit.confirm.title=\u9000\u51fa
dialog.openoptions.deliminfo.fields=\u6570\u636e\u6bb5
dialog.openoptions.deliminfo.norecords=\u65e0\u7eaa\u5f55
dialog.openoptions.altitudeunits=\u9ad8\u5ea6\u5355\u4f4d
+dialog.open.contentsdoubled=\u6587\u4ef6\u542b\u6709\u4e24\u5957\u70b9\u4fe1\u606f\uff0c\u4e00\u5957\u822a\u70b9\u4fe1\u606f\u548c\u4e00\u5957\u8f68\u8ff9\u70b9\u4fe1\u606f
dialog.jpegload.subdirectories=\u542b\u6b21\u7ea7\u65b9\u4f4d
dialog.jpegload.loadjpegswithoutcoords=\u542b\u65e0\u5750\u6807\u70b9\u76f8\u7247
dialog.jpegload.loadjpegsoutsidearea=\u542b\u533a\u57df\u5916\u76f8\u7247
dialog.gpsload.format=GPS\u6587\u4ef6\u683c\u5f0f
dialog.gpsload.getwaypoints=\u5bfc\u5165\u822a\u70b9
dialog.gpsload.gettracks=\u5bfc\u5165\u8f68\u8ff9
+dialog.gpsload.save=\u4fdd\u5b58\u5230\u6587\u4ef6
dialog.gpssend.sendwaypoints=\u53d1\u9001\u822a\u70b9
dialog.gpssend.sendtracks=\u53d1\u9001\u8f68\u8ff9
dialog.gpssend.trackname=\u8f68\u8ff9\u540d
dialog.save.timestampformat=\u65f6\u95f4\u683c\u5f0f
dialog.save.overwrite.title=\u6587\u4ef6\u5df2\u5b58\u5728
dialog.save.overwrite.text=\u6587\u4ef6\u5df2\u5b58\u5728\uff0c\u662f\u5426\u8986\u76d6\uff1f
+dialog.save.notypesselected=\u70b9\u7c7b\u578b\u672a\u9009\u5b9a
dialog.exportkml.text=\u6570\u636e\u540d\u79f0
dialog.exportkml.altitude=\u7edd\u5bf9\u9ad8\u5ea6\uff08\u822a\u7a7a\u7528\uff09
dialog.exportkml.kmz=\u538b\u7f29\u6210KMZ\u6587\u4ef6
dialog.exportkml.exportimages=\u8f93\u51fa\u76f8\u7247\u7d22\u5f15\u56fe\u81f3KMZ
+dialog.exportkml.trackcolour=\u8f68\u8ff9\u989c\u8272
dialog.exportgpx.name=\u540d\u79f0
dialog.exportgpx.desc=\u63cf\u8ff0
dialog.exportgpx.includetimestamps=\u5305\u542b\u65f6\u95f4
+dialog.exportgpx.copysource=\u4ece\u6e90XML\u6587\u4ef6\u590d\u5236
dialog.exportpov.text=\u8bf7\u8f93\u5165POV\u53c2\u6570
dialog.exportpov.font=\u5b57\u4f53
dialog.exportpov.camerax=X\u76f8\u673a
dialog.pointtype.track=\u8f68\u8ff9\u70b9
dialog.pointtype.waypoint=\u822a\u70b9
dialog.pointtype.photo=\u76f8\u7247\u70b9
+dialog.pointtype.selection=\u4ec5\u5df2\u9009\u62e9\u822a\u6bb5
dialog.confirmreversetrack.title=\u786e\u8ba4\u53cd\u5411
dialog.confirmreversetrack.text=\u8f68\u8ff9\u5305\u542b\u65f6\u95f4\u4fe1\u606f\uff0c\u53cd\u5411\u540e\u53ef\u80fd\u4e22\u5931\n\u662f\u5426\u7ee7\u7eed\uff1f
dialog.confirmcutandmove.title=\u786e\u8ba4\u526a\u5207\u548c\u79fb\u52a8
dialog.saveexif.photostatus.disconnected=\u672a\u94fe\u63a5
dialog.saveexif.photostatus.modified=\u5df2\u6539\u53d8
dialog.saveexif.overwrite=\u8986\u76d6\u6587\u4ef6
+dialog.saveexif.force=\u5f3a\u5236\u6267\u884c\u5ffd\u7565\u9519\u8bef
dialog.charts.xaxis=X\u8f74
dialog.charts.yaxis=Y\u8f74
dialog.charts.output=\u8f93\u51fa
dialog.distances.column.to=\u5230\u6b64\u70b9
dialog.distances.currentpoint=\u5f53\u524d\u70b9
dialog.distances.toofewpoints=\u9700\u8981\u822a\u70b9\u6765\u8ba1\u7b97\u8ddd\u79bb
-dialog.setmapbg.mapnik=Mapnik(\u7f3a\u7701)
-dialog.setmapbg.osma=Osma
-dialog.setmapbg.cyclemap=Cyclemap
-dialog.setmapbg.other=\u5176\u4ed6(\u5728\u4e0b\u9762\u8f93\u5165URL)
-dialog.setmapbg.server=\u5730\u56fe\u670d\u52a1\u5668URL
+dialog.fullrangedetails.intro=\u822a\u6bb5\u8be6\u60c5
+dialog.setmapbg.intro=\u8bf7\u9009\u62e9\u5730\u56fe\uff0c\u6216\u6dfb\u52a0\u5730\u56fe
+dialog.addmapsource.title=\u6dfb\u52a0\u5730\u56fe
+dialog.addmapsource.sourcename=\u5730\u56fe\u6765\u6e90\u540d\u79f0
+dialog.addmapsource.layer1url=\u7b2c\u4e00\u5c42URL
+dialog.addmapsource.layer2url=\u53ef\u9009\u7b2c\u4e8c\u5c42URL
+dialog.addmapsource.maxzoom=\u6700\u5927\u7f29\u653e\u7ea7\u6570
+dialog.addmapsource.cloudstyle=\u7c7b\u578b\u53f7
+dialog.addmapsource.noname=\u672a\u547d\u540d
dialog.gpsies.column.name=\u8f68\u8ff9\u540d\u79f0
dialog.gpsies.column.length=\u957f\u5ea6
dialog.gpsies.description=\u63cf\u8ff0
dialog.gpsies.nodescription=\u65e0\u63cf\u8ff0
+dialog.gpsies.nonefound=\u672a\u627e\u5230\u8f68\u8ff9
+dialog.gpsies.activities=\u6d3b\u52a8,\u9002\u5408
+dialog.gpsies.activity.trekking=\u5f92\u6b65
+dialog.gpsies.activity.walking=\u7ade\u8d70
+dialog.gpsies.activity.jogging=\u8dd1\u6b65
+dialog.gpsies.activity.biking=\u9a91\u81ea\u884c\u8f66
+dialog.gpsies.activity.motorbiking=\u7535\u52a8\u81ea\u884c\u8f66
+dialog.gpsies.activity.snowshoe=\u96ea\u978b\u5065\u884c
+dialog.gpsies.activity.sailing=\u5e06\u8239
+dialog.gpsies.activity.skating=\u6ed1\u51b0
dialog.correlate.notimestamps=\u6570\u636e\u70b9\u4e2d\u65e0\u65f6\u95f4\u4fe1\u606f\uff0c\u76f8\u7247\u65e0\u6cd5\u94fe\u63a5
dialog.correlate.nouncorrelatedphotos=\u6240\u6709\u76f8\u7247\u5df2\u94fe\u63a5\n\u7ee7\u7eed\uff1f
dialog.correlate.photoselect.intro=\u9009\u62e9\u5df2\u94fe\u63a5\u76f8\u7247\u4f5c\u4e3a\u65f6\u95f4\u504f\u79fb
dialog.correlate.options.distancelimit=\u8ddd\u79bb\u9650\u5236
dialog.correlate.options.correlate=\u94fe\u63a5
dialog.correlate.alloutsiderange=\u65e0\u6cd5\u94fe\u63a5\uff0c\u6240\u6709\u76f8\u7247\u8d85\u51fa\u8f68\u8ff9\u65f6\u95f4\u8303\u56f4\n\u8bf7\u6539\u53d8\u65f6\u95f4\u504f\u79fb\u6216\u624b\u52a8\u94fe\u63a5\u81f3\u5c11\u4e00\u5f20\u76f8\u7247
+dialog.rearrangephotos.desc=\u9009\u62e9\u76ee\u7684\u5730\u53ca\u6392\u76f8\u7247\u70b9
+dialog.rearrangephotos.tostart=\u79fb\u5230\u5f00\u59cb
+dialog.rearrangephotos.toend=\u79fb\u5230\u672b\u5c3e
+dialog.rearrangephotos.nosort=\u4e0d\u6392\u5e8f
+dialog.rearrangephotos.sortbyfilename=\u6309\u540d\u79f0\u6392\u5e8f
+dialog.rearrangephotos.sortbytime=\u6309\u65f6\u95f4\u6392\u5e8f
dialog.compress.nonefound=\u65e0\u6cd5\u5220\u9664\u6570\u636e\u70b9
dialog.compress.closepoints.title=\u90bb\u8fd1\u70b9\u5220\u9664
dialog.compress.closepoints.paramdesc=\u8303\u56f4\u7cfb\u6570
dialog.compress.singletons.paramdesc=\u8ddd\u79bb\u7cfb\u6570
dialog.compress.duplicates.title=\u91cd\u590d\u70b9\u5220\u9664
dialog.compress.summarylabel=\u8981\u5220\u9664\u7684\u70b9
+dialog.pastecoordinates.desc=\u5728\u6b64\u8f93\u5165\u6216\u7c98\u8d34\u5750\u6807\u70b9
+dialog.pastecoordinates.coords=\u5750\u6807\u70b9
+dialog.pastecoordinates.nothingfound=\u8bf7\u68c0\u67e5\u5750\u6807\u6570\u636e\u5e76\u91cd\u8bd5
dialog.help.help=\u66f4\u591a\u4fe1\u606f\u548c\u7528\u6cd5\uff0c\u8bf7\u53c2\u8003\u7f51\u7ad9\nhttp://activityworkshop.net/software/prune///
dialog.about.version=\u7248\u672c
dialog.about.build=Build
dialog.about.systeminfo.exiftool=Exiftool \u662f\u5426\u5b89\u88c5
dialog.about.systeminfo.gpsbabel=Gpsbabel \u662f\u5426\u5b89\u88c5
dialog.about.systeminfo.gnuplot=Gnuplot \u662f\u5426\u5b89\u88c5
+dialog.about.systeminfo.exiflib=Exif \u5e93
+dialog.about.systeminfo.exiflib.internal=\u5185\u90e8
+dialog.about.systeminfo.exiflib.internal.failed=\u5185\u90e8\uff08\u672a\u627e\u5230\uff09
+dialog.about.systeminfo.exiflib.external=\u5916\u90e8
+dialog.about.systeminfo.exiflib.external.failed=\u5916\u90e8\uff08\u672a\u627e\u5230\uff09
dialog.about.yes=\u662f
dialog.about.no=\u5426
dialog.about.credits=\u81f4\u8c22
dialog.checkversion.releasedate2=
dialog.checkversion.download=\u4e0b\u8f7d\u6700\u65b0\u7248\u672c\uff0c\u8bf7\u767b\u9646\u7f51\u7ad9\uff1a\nhttp://activityworkshop.net/software/prune/download.html
dialog.keys.intro=\u53ef\u7528\u4e0b\u5217\u5feb\u6377\u952e\u66ff\u4ee3\u9f20\u6807
+dialog.keys.keylist=<table><tr><td>\u7bad\u5934</td><td>\u4e0a\u4e0b\u5de6\u53f3\u79fb\u52a8\u5730\u56fe</td></tr><tr><td>Ctrl + \u5de6\u53f3\u7bad\u5934</td><td>\u9009\u53d6\u524d\uff0c\u540e\u70b9</td></tr><tr><td>Ctrl + \u4e0a\u4e0b\u7bad\u5934</td><td>\u653e\u5927\u7f29\u5c0f</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>\u9009\u62e9\u524d\u540e\u6bb5</td></tr><tr><td>Ctrl + Home, End</td><td>\u9009\u62e9\u9996\u672b\u70b9</td></tr><tr><td>Del</td><td>\u5220\u9664\u5f53\u524d\u70b9</td></tr></table>
+dialog.keys.normalmodifier=Ctrl
+dialog.keys.macmodifier=Command
dialog.saveconfig.desc=\u4e0b\u5217\u8bbe\u7f6e\u5c06\u4fdd\u5b58\u5230\u8bbe\u7f6e\u6587\u4ef6
dialog.saveconfig.prune.trackdirectory=\u8f68\u8ff9\u6587\u4ef6\u5939
dialog.saveconfig.prune.photodirectory=\u76f8\u7247\u6587\u4ef6\u5939
dialog.saveconfig.prune.languagecode=\u8bed\u8a00\u9009\u62e9(ZH)
+dialog.saveconfig.prune.languagefile=\u8bed\u8a00\u6587\u4ef6\u5305
dialog.saveconfig.prune.gpsdevice=GPS\u7aef\u53e3\u540d\u79f0
dialog.saveconfig.prune.gpsformat=GPS\u6587\u4ef6\u683c\u5f0f
dialog.saveconfig.prune.povrayfont=Povray \u5b57\u4f53
dialog.saveconfig.prune.gnuplotpath=gnuplot\u8def\u5f84
dialog.saveconfig.prune.gpsbabelpath=gpsbabel\u8def\u5f84
dialog.saveconfig.prune.exiftoolpath=exiftool\u8def\u5f84
-dialog.saveconfig.prune.mapserverindex=\u80cc\u666f\u5730\u56fe\u7801(1-4)
-dialog.saveconfig.prune.mapserverurl=\u90094\u65f6\u5730\u56fe\u670d\u52a1\u5668URL
+dialog.saveconfig.prune.mapsource=\u5df2\u9009\u62e9\u7684\u5730\u56fe\u6e90
+dialog.saveconfig.prune.mapsourcelist=\u5730\u56fe\u6e90
+dialog.saveconfig.prune.diskcache=\u5b58\u50a8\u8def\u5f84
dialog.saveconfig.prune.kmzimagewidth=KMZ\u56fe\u50cf\u5bbd\u5ea6
dialog.saveconfig.prune.kmzimageheight=KMZ\u56fe\u50cf\u9ad8\u5ea6
+dialog.saveconfig.prune.colourscheme=\u989c\u8272
+dialog.saveconfig.prune.kmltrackcolour=KML\u8f68\u8ff9\u989c\u8272
dialog.setpaths.intro=\u82e5\u9700\u8981\uff0c\u53ef\u8bbe\u5b9a\u5916\u6302\u7a0b\u5e8f\u8def\u5f84
+dialog.setpaths.found=\u627e\u5230\u8def\u5f84\uff1f
dialog.addaltitude.noaltitudes=\u8f68\u8ff9\u4e0d\u542b\u9ad8\u5ea6\u4fe1\u606f
dialog.addaltitude.desc=\u9ad8\u5ea6\u504f\u79fb
+dialog.setcolours.intro=\u70b9\u6309\u8272\u677f\u4ee5\u6539\u53d8\u989c\u8272
+dialog.setcolours.background=\u80cc\u666f
+dialog.setcolours.borders=\u8fb9\u754c
+dialog.setcolours.lines=\u7ebf\u4f53
+dialog.setcolours.primary=\u4e3b\u8981
+dialog.setcolours.secondary=\u8f85\u52a9
+dialog.setcolours.point=\u70b9
+dialog.setcolours.selection=\u9009\u62e9
+dialog.setcolours.text=\u6587\u5b57
+dialog.colourchooser.title=\u8bf7\u9009\u62e9\u989c\u8272
+dialog.colourchooser.red=\u7ea2
+dialog.colourchooser.green=\u7eff
+dialog.colourchooser.blue=\u84dd
+dialog.setlanguage.firstintro=\u4f60\u53ef\u4ee5\u9009\u62e9\u5df2\u6709\u8bed\u8a00,<p>\u6216\u9009\u62e9\u5916\u6302\u8bed\u8a00\u5305
+dialog.setlanguage.secondintro=\u8bf7\u4fdd\u5b58\u8bbe\u7f6e<p>\u5e76\u91cd\u542fPrune\u4f7f\u8bbe\u7f6e\u751f\u6548
+dialog.setlanguage.language=\u8bed\u8a00
+dialog.setlanguage.languagefile=\u8bed\u8a00\u5305
+dialog.setlanguage.endmessage=\u73b0\u5728\u8bf7\u4fdd\u5b58\u8bbe\u7f6e\u5e76\u91cd\u542fPrune\n\u4f7f\u8bbe\u7f6e\u751f\u6548
+dialog.diskcache.save=\u5730\u56fe\u56fe\u7247\u4fdd\u5b58\u5230\u7535\u8111
+dialog.diskcache.dir=\u4fdd\u5b58\u8def\u5f84
+dialog.diskcache.createdir=\u65b0\u5efa\u8def\u5f84
+dialog.diskcache.nocreate=\u672a\u65b0\u5efa\u8def\u5f84
# 3d window
dialog.3d.title=Prune 3D \u663e\u793a
confirm.mergetracksegments=\u5df2\u5408\u5e76\u7684\u8f68\u8ff9\u6bb5
confirm.reverserange=\u53cd\u5411\u7684\u8303\u56f4
confirm.addtimeoffset=\u5df2\u52a0\u4e0a\u65f6\u95f4\u504f\u5dee
+confirm.addaltitudeoffset=\u5df2\u52a0\u4e0a\u9ad8\u5ea6\u504f\u5dee
confirm.rearrangewaypoints=\u91cd\u65b0\u914d\u7f6e\u7684\u822a\u70b9
+confirm.rearrangephotos=\u76f8\u7247\u5df2\u91cd\u6392
confirm.cutandmove=\u5df2\u79fb\u52a8\u7684\u8f68\u8ff9\u6bb5
+confirm.convertnamestotimes=\u822a\u70b9\u540d\u79f0\u5df2\u8f6c\u6362
confirm.saveexif.ok1=\u5df2\u4fdd\u5b58
confirm.saveexif.ok2=\u76f8\u7247\u6587\u4ef6
confirm.undo.single=\u5df2\u64a4\u9500\u7684\u64cd\u4f5c
confirm.correlate.single=\u76f8\u7247\u5df2\u94fe\u63a5
confirm.correlate.multi=\u76f8\u7247\u5df2\u94fe\u63a5
confirm.createpoint=\u5df2\u521b\u5efa\u70b9
+confirm.rotatephoto=\u76f8\u7247\u5df2\u65cb\u8f6c
confirm.running=\u8bf7\u7a0d\u7b49...
+confirm.lookupsrtm1=\u627e\u5230
+confirm.lookupsrtm2=\u9ad8\u5ea6\u503c
# Buttons || These are all the texts for buttons
button.ok=\u786e\u5b9a
button.guessfields=\u731c\u4f30\u533a\u57df\u5185\u5bb9
button.showwebpage=\u663e\u793a\u7f51\u9875
button.check=\u68c0\u67e5
+button.resettodefaults=\u6062\u590d\u9ed8\u8ba4
+button.browse=\u6d4f\u89c8...
+button.addnew=\u6dfb\u52a0
+button.delete=\u5220\u9664
# File types
filetype.txt=TXT\u6587\u4ef6
# Display components || These are all for the side panels showing point/range details
display.nodata=\u65e0\u6570\u636e
display.noaltitudes=\u8f68\u8ff9\u6570\u636e\u4e0d\u542b\u9ad8\u5ea6\u4fe1\u606f
+display.notimestamps=\u8f68\u8ff9\u6570\u636e\u672a\u542b\u65f6\u95f4\u4fe1\u606f
details.trackdetails=\u8f68\u8ff9\u4fe1\u606f
details.notrack=\u65e0\u8f68\u8ff9
details.track.points=\u8f68\u8ff9\u70b9
display.range.time.days=\u5929
details.range.avespeed=\u5e73\u5747\u901f\u5ea6
details.range.avemovingspeed=\u5e73\u5747\u79fb\u52a8
+details.range.maxspeed=\u6700\u5927\u901f\u5ea6
+details.range.numsegments=\u6bb5\u6570
details.range.pace=\u6b65\u901f
+details.range.gradient=\u5761\u5ea6
details.waypointsphotos.waypoints=\u822a\u70b9
details.waypointsphotos.photos=\u76f8\u7247
details.photodetails=\u76f8\u7247\u4fe1\u606f
undo.connectphoto=\u94fe\u63a5\u76f8\u7247
undo.disconnectphoto=\u65ad\u5f00\u94fe\u63a5
undo.correlate=\u94fe\u63a5\u76f8\u7247
+undo.rearrangephotos=\u91cd\u62cd\u76f8\u7247
undo.createpoint=\u521b\u5efa\u8f68\u8ff9\u70b9
+undo.rotatephoto=\u65cb\u8f6c\u76f8\u7247
+undo.convertnamestotimes=\u540d\u79f0\u8f6c\u4e3a\u65f6\u95f4
+undo.lookupsrtm=\u4eceSRTM\u67e5\u627e\u9ad8\u5ea6
# Error messages
error.save.dialogtitle=\u4fdd\u5b58\u6570\u636e\u9519\u8bef
error.saveexif.filenotfound=\u627e\u4e0d\u5230\u76f8\u7247\u6587\u4ef6
error.saveexif.cannotoverwrite1=\u76f8\u7247\u6587\u4ef6
error.saveexif.cannotoverwrite2=\u53ea\u8bfb\u6587\u4ef6\uff0c\u4fdd\u5b58\u526f\u672c\uff1f
+error.saveexif.failed1=\u56fe\u7247
+error.saveexif.failed2=\u4fdd\u5b58\u5931\u8d25
+error.saveexif.forced1=
+error.saveexif.forced2=\u4e2a\u56fe\u7247\u9700\u8981\u5f3a\u5236\u6267\u884c
error.load.dialogtitle=\u5bfc\u5165\u6570\u636e\u9519\u8bef
error.load.noread=\u65e0\u6cd5\u8bfb\u6587\u4ef6
error.load.nopoints=\u6587\u4ef6\u4e2d\u65e0\u5750\u6807\u4fe1\u606f
error.jpegload.nojpegsfound=\u627e\u4e0d\u5230Jpeg\u6587\u4ef6
error.jpegload.noexiffound=\u627e\u4e0d\u5230EXIF\u4fe1\u606f
error.jpegload.nogpsfound=\u627e\u4e0d\u5230GPS\u4fe1\u606f
+error.jpegload.exifreadfailed=Exif\u8bfb\u53d6\u9519\u8bef\u3002\u9700\u8981\u5185\u90e8\n\u6216\u8005\u5916\u90e8\u5e93\u624d\u80fd\u8bfb\u53d6
+error.gpsload.unknown=\u672a\u77e5\u9519\u8bef
error.undofailed.title=\u64a4\u9500\u5931\u8d25
error.undofailed.text=\u64a4\u9500\u64cd\u4f5c\u5931\u8d25
error.function.noop.title=\u529f\u80fd\u65e0\u6548
error.readme.notfound=\u627e\u4e0d\u5230\u7248\u672c\u4fe1\u606f\u6587\u4ef6
error.osmimage.dialogtitle=\u5bfc\u5165\u5730\u56fe\u65f6\u9519\u8bef
error.osmimage.failed=\u5bfc\u5165\u5730\u56fe\u9519\u8bef\uff0c\u68c0\u67e5\u7f51\u7edc\u8fde\u63a5
+error.language.wrongfile=\u6240\u9009\u8bed\u8a00\u5305\u6587\u4ef6\u683c\u5f0f\u9519\u8bef
+error.convertnamestotimes.nonames=\u540d\u79f0\u65e0\u6cd5\u8f6c\u6362\u6210\u65f6\u95f4
{
String upperValue = inValue.toUpperCase();
// This is a header line so look for english or local text
- return upperValue.equals("SEGMENT");
+ return upperValue.equals("SEGMENT")
+ || upperValue.equals(I18nManager.getText("fieldname.newsegment").toUpperCase());
}
else
{
// Send data back to app
_app.informDataLoaded(handler.getFieldArray(), handler.getDataArray(), Altitude.Format.METRES,
- new SourceInfo(_deviceField.getText(), SourceInfo.FILE_TYPE.GPSBABEL));
+ new SourceInfo(_deviceField.getText(), SourceInfo.FILE_TYPE.GPSBABEL),
+ handler.getTrackNameList());
}
}
if (timestamp == null && jpegData.getOriginalTimestamp() != null) {
timestamp = createTimestamp(jpegData.getOriginalTimestamp());
}
+ if (timestamp == null && jpegData.getDigitizedTimestamp() != null) {
+ timestamp = createTimestamp(jpegData.getDigitizedTimestamp());
+ }
photo.setExifThumbnail(jpegData.getThumbnailImage());
// Also extract orientation tag for setting rotation state of photo
photo.setRotation(jpegData.getRequiredRotation());
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
{
_dialog = new JDialog(_parentFrame, I18nManager.getText("dialog.openoptions.title"), true);
_dialog.setLocationRelativeTo(_parentFrame);
- _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ _dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
+ // add closing listener
+ _dialog.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ _dialog.dispose();
+ _app.informNoDataLoaded();
+ }
+ });
_dialog.getContentPane().add(makeDialogComponents());
// select best separator according to row counts (more is better)
--- /dev/null
+package tim.prune.load;
+
+import java.util.ArrayList;
+
+/**
+ * Class to hold and manage a list of track names
+ * from a gpx file, and report back which points
+ * belong to which track
+ */
+public class TrackNameList
+{
+ /** Current point number */
+ private int _pointNum = -1;
+ /** Current track number */
+ private int _trackNum = -1;
+ /** List of unique track names */
+ private ArrayList<String> _trackNames = new ArrayList<String>();
+ /** List of point numbers at the start of each track */
+ private ArrayList<Integer> _startIndices = new ArrayList<Integer>();
+
+
+ /**
+ * Inform list of a new point
+ * @param inTrackNum number of track, starting at zero
+ * @param inTrackName name of track, if any
+ * @param inIsTrackpoint true if point is a trackpoint
+ */
+ public void addPoint(int inTrackNum, String inTrackName, boolean inIsTrackpoint)
+ {
+ _pointNum++;
+ if (inIsTrackpoint)
+ {
+ // System.out.println("Point " + _pointNum + " is in track '" + inTrackName + "' (" + inTrackNum + ")");
+ if (inTrackNum != _trackNum) {
+ _trackNames.add(inTrackName);
+ _startIndices.add(new Integer(_pointNum));
+ }
+ }
+ _trackNum = inTrackNum;
+ }
+
+ /**
+ * @return number of tracks found in file
+ */
+ public int getNumTracks()
+ {
+ return _trackNames.size();
+ }
+
+ /**
+ * @param inTrackNum index of track, starting from zero
+ * @return name of specified track (or null if none given)
+ */
+ public String getTrackName(int inTrackNum)
+ {
+ if (inTrackNum < 0 || inTrackNum >= getNumTracks()) {return "";}
+ String name = _trackNames.get(inTrackNum);
+ return name;
+ }
+
+ /**
+ * @param inTrackNum index of track, starting from zero
+ * @return number of points in the specified track
+ */
+ public int getNumPointsInTrack(int inTrackNum)
+ {
+ if (inTrackNum < 0 || inTrackNum >= getNumTracks()) {return 0;}
+ if (inTrackNum == (getNumTracks()-1)) {
+ // last track, use total points
+ return _pointNum - _startIndices.get(inTrackNum) + 1;
+ }
+ return _startIndices.get(inTrackNum+1) - _startIndices.get(inTrackNum);
+ }
+
+ /**
+ * @param inTrackNum index of track, starting from zero
+ * @return start index of the specified track
+ */
+ public int getStartIndex(int inTrackNum)
+ {
+ if (inTrackNum < 0 || inTrackNum >= getNumTracks()) {return 0;}
+ return _startIndices.get(inTrackNum);
+ }
+
+ /**
+ * Print summary for debug
+ * @deprecated
+ */
+ public void summarize()
+ {
+ System.out.println("File has " + getNumTracks() + " tracks:");
+ for (int i=0; i<getNumTracks(); i++) {
+ System.out.println(" Track " + i + " is called '" + _trackNames.get(i) + "' and has " + getNumPointsInTrack(i) + " points");
+ }
+ }
+}
import org.xml.sax.SAXException;
import tim.prune.data.Field;
+import tim.prune.load.TrackNameList;
/**
*/
public class GpxHandler extends XmlHandler
{
+ private boolean _insidePoint = false;
private boolean _insideWaypoint = false;
private boolean _insideName = false;
private boolean _insideElevation = false;
private boolean _insideTime = false;
private boolean _insideType = false;
private boolean _startSegment = true;
+ private boolean _isTrackPoint = false;
+ private int _trackNum = -1;
+ private String _trackName = null;
private String _name = null, _latitude = null, _longitude = null;
private String _elevation = null;
private String _time = null;
private String _type = null;
private ArrayList<String[]> _pointList = new ArrayList<String[]>();
+ private TrackNameList _trackNameList = new TrackNameList();
+
/**
* Receive the start of a tag
// Read the parameters for waypoints and track points
if (qName.equalsIgnoreCase("wpt") || qName.equalsIgnoreCase("trkpt") || qName.equalsIgnoreCase("rtept"))
{
+ _insidePoint = true;
_insideWaypoint = qName.equalsIgnoreCase("wpt");
+ _isTrackPoint = qName.equalsIgnoreCase("trkpt");
int numAttributes = attributes.getLength();
for (int i=0; i<numAttributes; i++)
{
}
else if (qName.equalsIgnoreCase("name"))
{
+ _name = null;
_insideName = true;
}
else if (qName.equalsIgnoreCase("time"))
{
_startSegment = true;
}
+ else if (qName.equalsIgnoreCase("trk"))
+ {
+ _trackNum++;
+ _trackName = null;
+ }
super.startElement(uri, localName, qName, attributes);
}
if (qName.equalsIgnoreCase("wpt") || qName.equalsIgnoreCase("trkpt") || qName.equalsIgnoreCase("rtept"))
{
processPoint();
+ _insidePoint = false;
}
else if (qName.equalsIgnoreCase("ele"))
{
{
String value = new String(ch, start, length);
if (_insideName && _insideWaypoint) {_name = checkCharacters(_name, value);}
+ if (_insideName && !_insidePoint) {_trackName = checkCharacters(_trackName, value);}
else if (_insideElevation) {_elevation = checkCharacters(_elevation, value);}
else if (_insideTime) {_time = checkCharacters(_time, value);}
else if (_insideType) {_type = checkCharacters(_type, value);}
}
values[6] = _type;
_pointList.add(values);
+ _trackNameList.addPoint(_trackNum, _trackName, _isTrackPoint);
}
}
return result;
}
+
+
+ /**
+ * @return track name list
+ */
+ public TrackNameList getTrackNameList() {
+ return _trackNameList;
+ }
}
SourceInfo sourceInfo = new SourceInfo(inFile,
(handler instanceof GpxHandler?SourceInfo.FILE_TYPE.GPX:SourceInfo.FILE_TYPE.KML));
_app.informDataLoaded(handler.getFieldArray(), handler.getDataArray(),
- Altitude.Format.METRES, sourceInfo);
+ Altitude.Format.METRES, sourceInfo, handler.getTrackNameList());
}
}
catch (Exception e) {
SourceInfo sourceInfo = new SourceInfo(_file,
(_handler instanceof GpxHandler?SourceInfo.FILE_TYPE.GPX:SourceInfo.FILE_TYPE.KML));
_app.informDataLoaded(_handler.getFieldArray(), _handler.getDataArray(),
- Altitude.Format.METRES, sourceInfo);
+ Altitude.Format.METRES, sourceInfo, _handler.getTrackNameList());
}
}
catch (Exception e)
import org.xml.sax.helpers.DefaultHandler;
import tim.prune.data.Field;
+import tim.prune.load.TrackNameList;
/**
* Abstract superclass of xml handlers
* @return field array describing fields of data
*/
public abstract Field[] getFieldArray();
+
+ /**
+ * Can be overriden (eg by gpx handler) to provide a track name list
+ * @return track name list object if any, or null
+ */
+ public TrackNameList getTrackNameList()
+ {
+ return null;
+ }
}
/** App for callback of file loading */
private App _app = null;
/** Object to do the handling of the xml */
- XmlFileLoader _xmlLoader = null;
+ private XmlFileLoader _xmlLoader = null;
/**
* Constructor
SourceInfo sourceInfo = new SourceInfo(inFile,
(handler instanceof GpxHandler?SourceInfo.FILE_TYPE.GPX:SourceInfo.FILE_TYPE.KML));
_app.informDataLoaded(handler.getFieldArray(), handler.getDataArray(),
- Altitude.Format.METRES, sourceInfo);
+ Altitude.Format.METRES, sourceInfo, handler.getTrackNameList());
xmlFound = true;
}
}
else {
// Send back to app
_app.informDataLoaded(handler.getFieldArray(), handler.getDataArray(),
- Altitude.Format.METRES, new SourceInfo("gpsies", SourceInfo.FILE_TYPE.GPSIES));
+ Altitude.Format.METRES, new SourceInfo("gpsies", SourceInfo.FILE_TYPE.GPSIES),
+ handler.getTrackNameList());
xmlFound = true;
}
}
-Prune version 10
+Prune version 11
================
Prune is an application for viewing, editing and managing coordinate data from GPS systems,
=======
To run Prune from the jar file, simply call it from a command prompt or shell:
- java -jar prune_10.jar
+ java -jar prune_11.jar
If the jar file is saved in a different directory, you will need to include the path.
Depending on your system settings, you may be able to click or double-click on the jar file
or other link can of course be made should you wish.
To specify a language other than the default, use an additional parameter, eg:
- java -jar prune_10.jar --lang=DE
+ java -jar prune_11.jar --lang=DE
+
+New with version 11
+===================
+
+The following features were added since version 10:
+ - Option to select which of the named tracks to load out of a gpx file or gps
+ - Function to delete all values of a single field (eg all altitudes, all timestamps)
+ - Export of 3d view to svg file
+ - Function to upload current track to gpsies.com
+ - Option to hide sidebars (left panel, right panel and lower panel) to just show map
+ - Various bugfixes, especially with gpx export, track compression and scale bar
+ - Dutch and Czech translations thanks to generous volunteers
New with version 10
===================
To obtain the source code (if it wasn't included in your jar file), or for further information,
please visit the website: http://activityworkshop.net/
-You will find there user guides and screenshots illustrating the major features.
+You will find there user guides, screenshots and demo videos illustrating the major features.
As Prune is further developed, subsequent versions of the program will also be made freely
available at this website.
import java.awt.event.ActionListener;
import java.io.File;
+import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
{
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
- panel.add(new JLabel(I18nManager.getText("dialog.saveexif.intro")), BorderLayout.NORTH);
+ // Label at top
+ JLabel topLabel = new JLabel(I18nManager.getText("dialog.saveexif.intro"));
+ topLabel.setBorder(BorderFactory.createEmptyBorder(8, 6, 5, 6));
+ panel.add(topLabel, BorderLayout.NORTH);
// centre panel with most controls
JPanel centrePanel = new JPanel();
centrePanel.setLayout(new BorderLayout());
_fileChooser = new JFileChooser();
_fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
_fileChooser.addChoosableFileFilter(new GenericFileFilter("filetype.txt", new String[] {"txt", "text"}));
- _fileChooser.addChoosableFileFilter(new GenericFileFilter("filetype.gpx", new String[] {"gpx"}));
- _fileChooser.addChoosableFileFilter(new GenericFileFilter("filetype.kml", new String[] {"kml"}));
_fileChooser.setAcceptAllFileFilterUsed(true);
// start from directory in config which should be set
String configDir = Config.getConfigString(Config.KEY_TRACK_DIR);
}
}
+ // Correct chosen filename if necessary
+ final File saveFile = (isFilenameOk(inSaveFile)?inSaveFile:new File(inSaveFile.getAbsolutePath() + ".txt"));
+
// Check if file exists, and confirm overwrite if necessary
Object[] buttonTexts = {I18nManager.getText("button.overwrite"), I18nManager.getText("button.cancel")};
- if (!inSaveFile.exists() || JOptionPane.showOptionDialog(_parentFrame,
+ if (!saveFile.exists() || JOptionPane.showOptionDialog(_parentFrame,
I18nManager.getText("dialog.save.overwrite.text"),
I18nManager.getText("dialog.save.overwrite.title"), JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE, null, buttonTexts, buttonTexts[1])
try
{
// Create output file
- writer = new FileWriter(inSaveFile);
+ writer = new FileWriter(saveFile);
// Determine delimiter character to use
final char delimiter = getDelimiter();
FieldInfo info = null;
writer.write(lineSeparator);
}
// Store directory in config for later
- Config.setConfigString(Config.KEY_TRACK_DIR, inSaveFile.getParentFile().getAbsolutePath());
+ Config.setConfigString(Config.KEY_TRACK_DIR, saveFile.getParentFile().getAbsolutePath());
// Save successful
UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.save.ok1")
+ " " + numSaved + " " + I18nManager.getText("confirm.save.ok2")
- + " " + inSaveFile.getAbsolutePath());
+ + " " + saveFile.getAbsolutePath());
_app.informDataSaved();
}
catch (IOException ioe)
// Wasn't any of those so must be 'other'
return _otherDelimiterText.getText().charAt(0);
}
+
+
+ /**
+ * Check the selected filename to see if it is acceptable
+ * @param inFile chosen file to save
+ * @return true if filename is ok
+ */
+ private static boolean isFilenameOk(File inFile)
+ {
+ String filename = inFile.getName().toLowerCase();
+ return (filename.length() <4 || (!filename.endsWith(".gpx")
+ && !filename.endsWith(".kml") && !filename.endsWith(".kmz") && !filename.endsWith(".zip")));
+ }
}
+++ /dev/null
-package tim.prune.save;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import tim.prune.data.DataPoint;
-import tim.prune.data.SourceInfo;
-
-/**
- * Class to read in a GPX file and cache all the point strings
- */
-public class GpxCacher extends DefaultHandler
-{
- private SourceInfo _sourceInfo = null;
- private String _headerString = null;
- private String[] _strings = null;
- private int _pointNum = 0;
- private boolean _insidePoint = false;
- private StringBuilder _builder = null;
-
-
- /**
- * Constructor
- * @param inSourceInfo source information
- */
- public GpxCacher(SourceInfo inInfo)
- {
- _sourceInfo = inInfo;
- _strings = new String[inInfo.getNumPoints()];
- _pointNum = 0;
- // Should be a gpx file, but might be raw, zipped or gzipped
- File gpxFile = inInfo.getFile();
- String fileName = gpxFile.getName().toLowerCase();
- if (gpxFile.exists() && gpxFile.canRead())
- {
- try {
- SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
- if (fileName.endsWith(".gpx") || fileName.endsWith(".xml")) {
- saxParser.parse(inInfo.getFile(), this);
- }
- else if (fileName.endsWith(".zip")) {
- saxParser.parse(getZipInputStream(inInfo.getFile()), this);
- }
- else if (fileName.endsWith(".gz")) {
- saxParser.parse(new GZIPInputStream(new FileInputStream(inInfo.getFile())), this);
- }
- else {
- System.out.println("GpxCacher unrecognised file type: " + inInfo.getFile().getName());
- }
- } catch (Exception e) {
- // TODO: Handle errors here with a list of warnings?
- e.printStackTrace();
- }
- }
- _builder = null;
- }
-
-
- /**
- * Receive the start of a tag
- */
- public void startElement(String inUri, String inLocalName, String inTagName,
- Attributes inAttributes) throws SAXException
- {
- if (inTagName.equalsIgnoreCase("gpx"))
- {
- // store initial gpx tag
- _builder = new StringBuilder(60);
- appendTag(_builder, inTagName, inAttributes);
- _headerString = _builder.toString();
- }
- else
- {
- if (inTagName.equalsIgnoreCase("wpt") || inTagName.equalsIgnoreCase("trkpt")
- || inTagName.equalsIgnoreCase("rtept"))
- {
- _insidePoint = true;
- _builder = new StringBuilder(60);
- }
- if (_insidePoint) {
- appendTag(_builder, inTagName, inAttributes);
- }
- }
- super.startElement(inUri, inLocalName, inTagName, inAttributes);
- }
-
- /**
- * Receive characters between tags (inside or outside)
- */
- public void characters(char[] inChars, int inStart, int inLength)
- throws SAXException
- {
- if (_insidePoint) {
- _builder.append(new String(inChars, inStart, inLength));
- }
- super.characters(inChars, inStart, inLength);
- }
-
- /**
- * Receive end of xml tag
- */
- public void endElement(String inUri, String inLocalName, String inTagName)
- throws SAXException
- {
- if (_insidePoint) {
- _builder.append("</").append(inTagName).append('>');
- }
- if (inTagName.equalsIgnoreCase("wpt") || inTagName.equalsIgnoreCase("trkpt")
- || inTagName.equalsIgnoreCase("rtept"))
- {
- _strings[_pointNum] = _builder.toString();
- _pointNum++;
- _insidePoint = false;
- }
- super.endElement(inUri, inLocalName, inTagName);
- }
-
-
- /**
- * Append the current tag to the supplied StringBuilder
- * @param inBuilder Stringbuilder object to append tag to
- * @param inTagName name of tag
- * @param inAttributes attributes of tag
- */
- private static void appendTag(StringBuilder inBuilder, String inTagName, Attributes inAttributes)
- {
- inBuilder.append('<').append(inTagName);
- int numAtts = inAttributes.getLength();
- for (int i=0; i<numAtts; i++) {
- inBuilder.append(' ').append(inAttributes.getQName(i)).append("=\"")
- .append(inAttributes.getValue(i)).append('"');
- }
- inBuilder.append('>');
- }
-
-
- /**
- * @return the header string from the GPX tag
- */
- public String getHeaderString()
- {
- return _headerString;
- }
-
- /**
- * Get the source string for the given point
- * @param inPoint point to retrieve
- * @return string if found, otherwise null
- */
- public String getSourceString(DataPoint inPoint)
- {
- int index = _sourceInfo.getIndex(inPoint);
- if (index >= 0) {
- return _strings[index];
- }
- return null;
- }
-
- /**
- * Get an inputstream of a GPX file inside a zip
- * @param inFile File object describing zip file
- * @return input stream for Xml parser
- */
- private static InputStream getZipInputStream(File inFile)
- {
- try
- {
- ZipInputStream zis = new ZipInputStream(new FileInputStream(inFile));
- while (zis.available() > 0)
- {
- ZipEntry entry = zis.getNextEntry();
- String entryName = entry.toString();
- if (entryName != null && entryName.length() > 4)
- {
- String suffix = entryName.substring(entryName.length()-4).toLowerCase();
- if (suffix.equals(".gpx") || suffix.equals(".xml")) {
- // First matching file so must be gpx
- return zis;
- }
- }
- }
- }
- catch (Exception e) {} // ignore errors
- // not found - error!
- return null;
- }
-}
import tim.prune.data.Timestamp;
import tim.prune.data.TrackInfo;
import tim.prune.load.GenericFileFilter;
+import tim.prune.save.xml.GpxCacherList;
+
/**
* Class to export track information
if (point.isWaypoint()) {
if (exportWaypoints)
{
- String pointSource = (inUseCopy?gpxCachers.getSourceString(point):null);
+ String pointSource = (inUseCopy?getPointSource(gpxCachers, point):null);
if (pointSource != null) {
inWriter.write(pointSource);
inWriter.write('\n');
if ((point.getPhoto()==null && inExportTrackpoints) || (point.getPhoto()!=null && inExportPhotos))
{
// get the source from the point (if any)
- String pointSource = (inCachers!=null?inCachers.getSourceString(point):null);
+ String pointSource = getPointSource(inCachers, point);
boolean writePoint = (pointSource != null && pointSource.toLowerCase().startsWith(inPointTag))
|| (pointSource == null && !inOnlyCopies);
if (writePoint)
return numSaved;
}
+
+ /**
+ * Get the point source for the specified point
+ * @param inCachers list of GPX cachers to ask for source
+ * @param inPoint point object
+ * @return xml source if available, or null otherwise
+ */
+ private static String getPointSource(GpxCacherList inCachers, DataPoint inPoint)
+ {
+ if (inCachers == null || inPoint == null) {return null;}
+ String source = inCachers.getSourceString(inPoint);
+ if (source == null || !inPoint.isModified()) {return source;}
+ // 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
+ return source;
+ }
+
+ /**
+ * Replace the given value into the given XML string
+ * @param inSource source XML for point
+ * @param inStartTag start tag for field
+ * @param inEndTag end tag for field
+ * @param inValue value to replace between start tag and end tag
+ * @return modified String, or null if not possible
+ */
+ private static String replaceGpxTags(String inSource, String inStartTag, String inEndTag, String inValue)
+ {
+ if (inSource == null) {return null;}
+ // Look for start and end tags within source
+ final int startPos = inSource.indexOf(inStartTag);
+ final int endPos = inSource.indexOf(inEndTag, startPos+inStartTag.length());
+ if (startPos > 0 && endPos > 0)
+ {
+ String origValue = inSource.substring(startPos + inStartTag.length(), endPos);
+ if (inValue != null && origValue.equals(inValue)) {
+ // Value unchanged
+ return inSource;
+ }
+ else if (inValue == null || inValue.equals("")) {
+ // Need to delete value
+ return inSource.substring(0, startPos) + inSource.substring(endPos + inEndTag.length());
+ }
+ else {
+ // Need to replace value
+ return inSource.substring(0, startPos+inStartTag.length()) + inValue + inSource.substring(endPos);
+ }
+ }
+ // Value not found for this field in original source
+ if (inValue == null || inValue.equals("")) {return inSource;}
+ return null;
+ }
+
/**
* Get the header string for the gpx
* @param inCachers cacher list to ask for headers, if available
import java.util.ArrayList;
import java.util.Iterator;
+import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.SwingConstants;
import tim.prune.App;
-import tim.prune.GenericFunction;
import tim.prune.I18nManager;
import tim.prune.UpdateMessageBroker;
import tim.prune.config.Config;
+import tim.prune.data.NumberUtils;
import tim.prune.data.Track;
+import tim.prune.function.Export3dFunction;
import tim.prune.load.GenericFileFilter;
import tim.prune.threedee.LineDialog;
import tim.prune.threedee.ThreeDModel;
/**
- * Class to export track information
- * into a specified Pov file
+ * Class to export a 3d scene of the track to a specified Pov file
*/
-public class PovExporter extends GenericFunction
+public class PovExporter extends Export3dFunction
{
private Track _track = null;
private JDialog _dialog = null;
private JFileChooser _fileChooser = null;
private String _cameraX = null, _cameraY = null, _cameraZ = null;
private JTextField _cameraXField = null, _cameraYField = null, _cameraZField = null;
- private JTextField _fontName = null, _altitudeCapField = null;
- private int _altitudeCap = ThreeDModel.MINIMUM_ALTITUDE_CAP;
+ private JTextField _fontName = null, _altitudeFactorField = null;
private JRadioButton _ballsAndSticksButton = null;
// defaults
/**
- * Constructor giving frame and track
+ * Constructor
* @param inApp App object
*/
public PovExporter(App inApp)
double cameraDist = Math.sqrt(inX*inX + inY*inY + inZ*inZ);
if (cameraDist > 0.0)
{
- _cameraX = "" + (inX / cameraDist * DEFAULT_CAMERA_DISTANCE);
- _cameraY = "" + (inY / cameraDist * DEFAULT_CAMERA_DISTANCE);
+ _cameraX = NumberUtils.formatNumber(inX / cameraDist * DEFAULT_CAMERA_DISTANCE, 5);
+ _cameraY = NumberUtils.formatNumber(inY / cameraDist * DEFAULT_CAMERA_DISTANCE, 5);
// Careful! Need to convert from java3d (right-handed) to povray (left-handed) coordinate system!
- _cameraZ = "" + (-inZ / cameraDist * DEFAULT_CAMERA_DISTANCE);
- }
- }
-
-
- /**
- * @param inAltitudeCap altitude cap to use
- */
- public void setAltitudeCap(int inAltitudeCap)
- {
- _altitudeCap = inAltitudeCap;
- if (_altitudeCap < ThreeDModel.MINIMUM_ALTITUDE_CAP)
- {
- _altitudeCap = ThreeDModel.MINIMUM_ALTITUDE_CAP;
+ _cameraZ = NumberUtils.formatNumber(-inZ / cameraDist * DEFAULT_CAMERA_DISTANCE, 5);
}
}
_cameraXField.setText(_cameraX);
_cameraYField.setText(_cameraY);
_cameraZField.setText(_cameraZ);
- // Set vertical scale
- _altitudeCapField.setText("" + _altitudeCap);
+ _altitudeFactorField.setText("" + _altFactor);
// Show dialog
_dialog.pack();
_dialog.setVisible(true);
{
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
- panel.add(new JLabel(I18nManager.getText("dialog.exportpov.text")), BorderLayout.NORTH);
+ JLabel introLabel = new JLabel(I18nManager.getText("dialog.exportpov.text"));
+ introLabel.setBorder(BorderFactory.createEmptyBorder(4, 4, 6, 4));
+ panel.add(introLabel, BorderLayout.NORTH);
// OK, Cancel buttons
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
centralPanel.add(cameraZLabel);
_cameraZField = new JTextField("" + _cameraZ);
centralPanel.add(_cameraZField);
- // Altitude capping
- JLabel altitudeCapLabel = new JLabel(I18nManager.getText("dialog.3d.altitudecap"));
+ // Altitude exaggeration
+ JLabel altitudeCapLabel = new JLabel(I18nManager.getText("dialog.3d.altitudefactor"));
altitudeCapLabel.setHorizontalAlignment(SwingConstants.TRAILING);
centralPanel.add(altitudeCapLabel);
- _altitudeCapField = new JTextField("" + _altitudeCap);
- centralPanel.add(_altitudeCapField);
+ _altitudeFactorField = new JTextField("1.0");
+ centralPanel.add(_altitudeFactorField);
// Radio buttons for style - balls on sticks or tubes
JPanel stylePanel = new JPanel();
try
{
// try to use given altitude cap
- _altitudeCap = Integer.parseInt(_altitudeCapField.getText());
- model.setAltitudeCap(_altitudeCap);
+ double altFactor = Double.parseDouble(_altitudeFactorField.getText());
+ model.setAltitudeFactor(altFactor);
+ }
+ catch (NumberFormatException nfe) { // parse failed, reset
+ _altitudeFactorField.setText("1.0");
}
- catch (NumberFormatException nfe) {}
model.scale();
// Create file and write basics
--- /dev/null
+package tim.prune.save;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.text.NumberFormat;
+import java.util.Iterator;
+import java.util.TreeSet;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+
+import tim.prune.App;
+import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
+import tim.prune.config.Config;
+import tim.prune.data.Track;
+import tim.prune.function.Export3dFunction;
+import tim.prune.load.GenericFileFilter;
+import tim.prune.threedee.ThreeDModel;
+
+/**
+ * Class to export a 3d scene of the track to a specified Svg file
+ */
+public class SvgExporter extends Export3dFunction
+{
+ private Track _track = null;
+ private JDialog _dialog = null;
+ private JFileChooser _fileChooser = null;
+ private double _phi = 0.0, _theta = 0.0;
+ private JTextField _phiField = null, _thetaField = null;
+ private JTextField _altitudeFactorField = null;
+ private JCheckBox _gradientsCheckbox = null;
+ private static double _scaleFactor = 1.0;
+
+
+ /**
+ * Constructor
+ * @param inApp App object
+ */
+ public SvgExporter(App inApp)
+ {
+ super(inApp);
+ _track = inApp.getTrackInfo().getTrack();
+ // Set default rotation angles
+ _phi = 30; _theta = 55;
+ }
+
+ /** Get the name key */
+ public String getNameKey() {
+ return "function.exportsvg";
+ }
+
+ /**
+ * Set the rotation angles using coordinates for the camera
+ * @param inX X coordinate of camera
+ * @param inY Y coordinate of camera
+ * @param inZ Z coordinate of camera
+ */
+ public void setCameraCoordinates(double inX, double inY, double inZ)
+ {
+ // Calculate phi and theta based on camera x,y,z
+ _phi = Math.toDegrees(Math.atan2(inX, inZ));
+ _theta = Math.toDegrees(Math.atan2(inY, Math.sqrt(inX*inX + inZ*inZ)));
+ }
+
+
+ /**
+ * Show the dialog to select options and export file
+ */
+ public void begin()
+ {
+ // Make dialog window to select angles, colours etc
+ if (_dialog == null)
+ {
+ _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+ _dialog.setLocationRelativeTo(_parentFrame);
+ _dialog.getContentPane().add(makeDialogComponents());
+ }
+
+ // Set angles
+ NumberFormat threeDP = NumberFormat.getNumberInstance();
+ threeDP.setMaximumFractionDigits(3);
+ _phiField.setText(threeDP.format(_phi));
+ _thetaField.setText(threeDP.format(_theta));
+ // Set vertical scale
+ _altitudeFactorField.setText("" + _altFactor);
+ // Show dialog
+ _dialog.pack();
+ _dialog.setVisible(true);
+ }
+
+
+ /**
+ * Make the dialog components to select the export options
+ * @return Component holding gui elements
+ */
+ private Component makeDialogComponents()
+ {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ JLabel introLabel = new JLabel(I18nManager.getText("dialog.exportsvg.text"));
+ introLabel.setBorder(BorderFactory.createEmptyBorder(4, 4, 6, 4));
+ panel.add(introLabel, BorderLayout.NORTH);
+ // OK, Cancel buttons
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ JButton okButton = new JButton(I18nManager.getText("button.ok"));
+ okButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ doExport();
+ _dialog.dispose();
+ }
+ });
+ buttonPanel.add(okButton);
+ JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _dialog.dispose();
+ }
+ });
+ buttonPanel.add(cancelButton);
+ panel.add(buttonPanel, BorderLayout.SOUTH);
+
+ // central panel
+ JPanel centralPanel = new JPanel();
+ centralPanel.setLayout(new GridLayout(0, 2, 10, 4));
+
+ // rotation angles
+ JLabel phiLabel = new JLabel(I18nManager.getText("dialog.exportsvg.phi"));
+ phiLabel.setHorizontalAlignment(SwingConstants.TRAILING);
+ centralPanel.add(phiLabel);
+ _phiField = new JTextField("" + _phi);
+ centralPanel.add(_phiField);
+ JLabel thetaLabel = new JLabel(I18nManager.getText("dialog.exportsvg.theta"));
+ thetaLabel.setHorizontalAlignment(SwingConstants.TRAILING);
+ centralPanel.add(thetaLabel);
+ _thetaField = new JTextField("" + _theta);
+ centralPanel.add(_thetaField);
+ // Altitude exaggeration
+ JLabel altFactorLabel = new JLabel(I18nManager.getText("dialog.3d.altitudefactor"));
+ altFactorLabel.setHorizontalAlignment(SwingConstants.TRAILING);
+ centralPanel.add(altFactorLabel);
+ _altitudeFactorField = new JTextField("" + _altFactor);
+ centralPanel.add(_altitudeFactorField);
+ // Checkbox for gradients or not
+ JLabel gradientsLabel = new JLabel(I18nManager.getText("dialog.exportsvg.gradients"));
+ gradientsLabel.setHorizontalAlignment(SwingConstants.TRAILING);
+ centralPanel.add(gradientsLabel);
+ _gradientsCheckbox = new JCheckBox();
+ _gradientsCheckbox.setSelected(true);
+ centralPanel.add(_gradientsCheckbox);
+
+ // add this grid to the holder panel
+ JPanel holderPanel = new JPanel();
+ holderPanel.setLayout(new BorderLayout(5, 5));
+ JPanel boxPanel = new JPanel();
+ boxPanel.setLayout(new BoxLayout(boxPanel, BoxLayout.Y_AXIS));
+ boxPanel.add(centralPanel);
+ holderPanel.add(boxPanel, BorderLayout.CENTER);
+
+ panel.add(holderPanel, BorderLayout.CENTER);
+ return panel;
+ }
+
+
+ /**
+ * Select the file and export data to it
+ */
+ private void doExport()
+ {
+ // Copy camera coordinates
+ _phi = checkAngle(_phiField.getText());
+ _theta = checkAngle(_thetaField.getText());
+
+ // OK pressed, so choose output file
+ if (_fileChooser == null)
+ {
+ _fileChooser = new JFileChooser();
+ _fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
+ _fileChooser.setFileFilter(new GenericFileFilter("filetype.svg", new String[] {"svg"}));
+ _fileChooser.setAcceptAllFileFilterUsed(false);
+ // start from directory in config which should be set
+ final String configDir = Config.getConfigString(Config.KEY_TRACK_DIR);
+ if (configDir != null) {_fileChooser.setCurrentDirectory(new File(configDir));}
+ }
+
+ // Allow choose again if an existing file is selected
+ boolean chooseAgain = false;
+ do
+ {
+ chooseAgain = false;
+ if (_fileChooser.showSaveDialog(_parentFrame) == JFileChooser.APPROVE_OPTION)
+ {
+ // OK pressed and file chosen
+ File file = _fileChooser.getSelectedFile();
+ if (!file.getName().toLowerCase().endsWith(".svg")) {
+ file = new File(file.getAbsolutePath() + ".svg");
+ }
+ // Check if file exists and if necessary prompt for overwrite
+ Object[] buttonTexts = {I18nManager.getText("button.overwrite"), I18nManager.getText("button.cancel")};
+ if (!file.exists() || JOptionPane.showOptionDialog(_parentFrame,
+ I18nManager.getText("dialog.save.overwrite.text"),
+ I18nManager.getText("dialog.save.overwrite.title"), JOptionPane.YES_NO_OPTION,
+ JOptionPane.WARNING_MESSAGE, null, buttonTexts, buttonTexts[1])
+ == JOptionPane.YES_OPTION)
+ {
+ // Export the file
+ if (exportFile(file))
+ {
+ // file saved - store directory in config for later
+ Config.setConfigString(Config.KEY_TRACK_DIR, file.getParentFile().getAbsolutePath());
+ }
+ else {
+ // export failed so need to choose again
+ chooseAgain = true;
+ }
+ }
+ else {
+ // overwrite cancelled so need to choose again
+ chooseAgain = true;
+ }
+ }
+ } while (chooseAgain);
+ }
+
+
+ /**
+ * Export the track data to the specified file
+ * @param inFile File object to save to
+ * @return true if successful
+ */
+ private boolean exportFile(File inFile)
+ {
+ FileWriter writer = null;
+ // find out the line separator for this system
+ String lineSeparator = System.getProperty("line.separator");
+ try
+ {
+ // create and scale model
+ ThreeDModel model = new ThreeDModel(_track);
+ try
+ {
+ // try to use given altitude factor
+ _altFactor = Double.parseDouble(_altitudeFactorField.getText());
+ model.setAltitudeFactor(_altFactor);
+ }
+ catch (NumberFormatException nfe) {}
+ model.scale();
+ _scaleFactor = 200 / model.getModelSize();
+
+ boolean useGradients = _gradientsCheckbox.isSelected();
+
+ // Create file and write basics
+ writer = new FileWriter(inFile);
+ writeStartOfFile(writer, useGradients, lineSeparator);
+ writeBasePlane(writer, model.getModelSize(), lineSeparator);
+ // write out cardinal letters NESW
+ writeCardinals(writer, model.getModelSize(), lineSeparator);
+
+ // write out points
+ writeDataPoints(writer, model, useGradients, lineSeparator);
+ writeEndOfFile(writer, lineSeparator);
+
+ // everything worked
+ UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.save.ok1")
+ + " " + _track.getNumPoints() + " " + I18nManager.getText("confirm.save.ok2")
+ + " " + inFile.getAbsolutePath());
+ return true;
+ }
+ catch (IOException ioe)
+ {
+ JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.save.failed") + " : " + ioe.getMessage(),
+ I18nManager.getText("error.save.dialogtitle"), JOptionPane.ERROR_MESSAGE);
+ }
+ finally
+ {
+ // close file ignoring exceptions
+ try {
+ writer.close();
+ }
+ catch (Exception e) {}
+ }
+ return false;
+ }
+
+
+ /**
+ * Write the start of the Svg file
+ * @param inWriter Writer to use for writing file
+ * @param inUseGradients true to use gradients, false for flat fills
+ * @param inLineSeparator line separator to use
+ * @throws IOException on file writing error
+ */
+ private static void writeStartOfFile(FileWriter inWriter, boolean inUseGradients,
+ String inLineSeparator)
+ throws IOException
+ {
+ inWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
+ inWriter.write(inLineSeparator);
+ inWriter.write("<!-- Svg file produced by Prune - see http://activityworkshop.net/ -->");
+ inWriter.write(inLineSeparator);
+ inWriter.write("<svg width=\"800\" height=\"700\">");
+ inWriter.write(inLineSeparator);
+ if (inUseGradients)
+ {
+ final String defs = "<defs>" +
+ "<radialGradient id=\"wayfill\" cx=\"0.5\" cy=\"0.5\" r=\"0.5\" fx=\"0.5\" fy=\"0.5\">" +
+ "<stop offset=\"0%\" stop-color=\"#2323aa\"/>" +
+ "<stop offset=\"100%\" stop-color=\"#000080\"/>" +
+ "</radialGradient>" + inLineSeparator +
+ "<radialGradient id=\"trackfill\" cx=\"0.5\" cy=\"0.5\" r=\"0.5\" fx=\"0.5\" fy=\"0.5\">" +
+ "<stop offset=\"0%\" stop-color=\"#23aa23\"/>" +
+ "<stop offset=\"100%\" stop-color=\"#008000\"/>" +
+ "</radialGradient>" +
+ "</defs>";
+ inWriter.write(defs);
+ inWriter.write(inLineSeparator);
+ }
+ inWriter.write("<g inkscape:label=\"Layer 1\" inkscape:groupmode=\"layer\" id=\"layer1\">");
+ inWriter.write(inLineSeparator);
+ }
+
+ /**
+ * Write the base plane
+ * @param inWriter Writer to use for writing file
+ * @param inModelSize model size
+ * @param inLineSeparator line separator to use
+ * @throws IOException on file writing error
+ */
+ private void writeBasePlane(FileWriter inWriter, double inModelSize, String inLineSeparator)
+ throws IOException
+ {
+ // Use model size and camera angles to draw path for base rectangle (using 3d transform)
+ int[] coords1 = convertCoordinates(-inModelSize, -inModelSize, 0);
+ int[] coords2 = convertCoordinates(inModelSize, -inModelSize, 0);
+ int[] coords3 = convertCoordinates(inModelSize, inModelSize, 0);
+ int[] coords4 = convertCoordinates(-inModelSize, inModelSize, 0);
+ final String corners = "M " + coords1[0] + "," + coords1[1]
+ + " L " + coords2[0] + "," + coords2[1]
+ + " L " + coords3[0] + "," + coords3[1]
+ + " L " + coords4[0] + "," + coords4[1] + " z";
+ inWriter.write("<path style=\"fill:#446666;stroke:#000000;\" d=\"" + corners + "\" id=\"rect1\" />");
+ inWriter.write(inLineSeparator);
+ }
+
+ /**
+ * Write the cardinal letters NESW
+ * @param inWriter Writer to use for writing file
+ * @param inModelSize model size
+ * @param inLineSeparator line separator to use
+ * @throws IOException on file writing error
+ */
+ private void writeCardinals(FileWriter inWriter, double inModelSize, String inLineSeparator)
+ throws IOException
+ {
+ // Use model size and camera angles to calculate positions
+ int[] coordsN = convertCoordinates(0, inModelSize, 0);
+ writeCardinal(inWriter, coordsN[0], coordsN[1], "cardinal.n", inLineSeparator);
+ int[] coordsE = convertCoordinates(inModelSize, 0, 0);
+ writeCardinal(inWriter, coordsE[0], coordsE[1], "cardinal.e", inLineSeparator);
+ int[] coordsS = convertCoordinates(0, -inModelSize, 0);
+ writeCardinal(inWriter, coordsS[0], coordsS[1], "cardinal.s", inLineSeparator);
+ int[] coordsW = convertCoordinates(-inModelSize, 0, 0);
+ writeCardinal(inWriter, coordsW[0], coordsW[1], "cardinal.w", inLineSeparator);
+ }
+
+ /**
+ * Write a single cardinal letter
+ * @param inWriter Writer to use for writing file
+ * @param inX x coordinate
+ * @param inY y coordinate
+ * @param inKey key for string to write
+ * @param inLineSeparator line separator to use
+ * @throws IOException on file writing error
+ */
+ private static void writeCardinal(FileWriter inWriter, int inX, int inY, String inKey, String inLineSeparator)
+ throws IOException
+ {
+ inWriter.write("<text x=\"" + inX + "\" y=\"" + inY + "\" font-size=\"26\" fill=\"black\" " +
+ "stroke=\"white\" stroke-width=\"0.5\">");
+ inWriter.write(I18nManager.getText(inKey));
+ inWriter.write("</text>");
+ inWriter.write(inLineSeparator);
+ }
+
+ /**
+ * Convert the given 3d coordinates into 2d coordinates by rotating and mapping
+ * @param inX x coordinate (east)
+ * @param inY y coordinate (north)
+ * @param inZ z coordinate (up)
+ * @return 2d coordinates as integer array
+ */
+ private int[] convertCoordinates(double inX, double inY, double inZ)
+ {
+ // Rotate by phi degrees around vertical axis
+ final double cosPhi = Math.cos(Math.toRadians(_phi));
+ final double sinPhi = Math.sin(Math.toRadians(_phi));
+ final double x2 = inX * cosPhi + inY * sinPhi;
+ final double y2 = inY * cosPhi - inX * sinPhi;
+ final double z2 = inZ;
+ // Rotate by theta degrees around horizontal axis
+ final double cosTheta = Math.cos(Math.toRadians(_theta));
+ final double sinTheta = Math.sin(Math.toRadians(_theta));
+ double x3 = x2;
+ double y3 = y2 * sinTheta + z2 * cosTheta;
+ // don't need to calculate z3
+ // Scale results to sensible scale for svg
+ x3 = x3 * _scaleFactor + 400;
+ y3 = -y3 * _scaleFactor + 350;
+ return new int[] {(int) x3, (int) y3};
+ }
+
+ /**
+ * Finish off the file by closing the tags
+ * @param inWriter Writer to use for writing file
+ * @param inLineSeparator line separator to use
+ * @throws IOException on file writing error
+ */
+ private static void writeEndOfFile(FileWriter inWriter, String inLineSeparator)
+ throws IOException
+ {
+ inWriter.write(inLineSeparator);
+ inWriter.write("</g></svg>");
+ inWriter.write(inLineSeparator);
+ }
+
+ /**
+ * Write out all the data points to the file in the balls-and-sticks style
+ * @param inWriter Writer to use for writing file
+ * @param inModel model object for getting data points
+ * @param inUseGradients true to use gradients, false for flat fills
+ * @param inLineSeparator line separator to use
+ * @throws IOException on file writing error
+ */
+ private void writeDataPoints(FileWriter inWriter, ThreeDModel inModel, boolean inUseGradients,
+ String inLineSeparator)
+ throws IOException
+ {
+ final int numPoints = inModel.getNumPoints();
+ TreeSet<SvgFragment> fragments = new TreeSet<SvgFragment>();
+ for (int i=0; i<numPoints; i++)
+ {
+ StringBuilder builder = new StringBuilder();
+ int[] coords = convertCoordinates(inModel.getScaledHorizValue(i), inModel.getScaledVertValue(i),
+ inModel.getScaledAltValue(i));
+ // vertical rod (if altitude positive)
+ if (inModel.getScaledAltValue(i) > 0.0)
+ {
+ int[] baseCoords = convertCoordinates(inModel.getScaledHorizValue(i), inModel.getScaledVertValue(i), 0);
+ builder.append("<line x1=\"").append(baseCoords[0]).append("\" y1=\"").append(baseCoords[1])
+ .append("\" x2=\"").append(coords[0]).append("\" y2=\"").append(coords[1])
+ .append("\" stroke=\"gray\" stroke-width=\"3\" />");
+ builder.append(inLineSeparator);
+ }
+ // ball (different according to type)
+ if (inModel.getPointType(i) == ThreeDModel.POINT_TYPE_WAYPOINT)
+ {
+ // waypoint ball
+ builder.append("<circle cx=\"").append(coords[0]).append("\" cy=\"").append(coords[1])
+ .append("\" r=\"11\" ").append(inUseGradients?"fill=\"url(#wayfill)\"":"fill=\"blue\"")
+ .append(" stroke=\"green\" stroke-width=\"0.2\" />");
+ }
+ else
+ {
+ // normal track point ball
+ builder.append("<circle cx=\"").append(coords[0]).append("\" cy=\"").append(coords[1])
+ .append("\" r=\"7\" ").append(inUseGradients?"fill=\"url(#trackfill)\"":"fill=\"green\"")
+ .append(" stroke=\"blue\" stroke-width=\"0.2\" />");
+ }
+ builder.append(inLineSeparator);
+ // add to set
+ fragments.add(new SvgFragment(builder.toString(), coords[1]));
+ }
+
+ // Iterate over the sorted set and write to file
+ Iterator<SvgFragment> iterator = fragments.iterator();
+ while (iterator.hasNext()) {
+ inWriter.write(iterator.next().getFragment());
+ }
+ }
+
+
+ /**
+ * Check the given angle value
+ * @param inString String entered by user
+ * @return validated value
+ */
+ private static double checkAngle(String inString)
+ {
+ double value = 0.0;
+ try {
+ value = Double.parseDouble(inString);
+ }
+ catch (Exception e) {} // ignore parse failures
+ return value;
+ }
+}
--- /dev/null
+package tim.prune.save;
+
+/**
+ * Class to enable the sorting of Svg fragments
+ */
+public class SvgFragment implements Comparable<SvgFragment>
+{
+ private String _fragment = null;
+ private int _yCoord = 0;
+
+ /**
+ * Constructor
+ * @param inFragment fragment of svg source
+ * @param inYCoord y coordinate of point, for sorting
+ */
+ public SvgFragment(String inFragment, int inYCoord)
+ {
+ _fragment = inFragment;
+ _yCoord = inYCoord;
+ }
+
+ /**
+ * @return svg fragment
+ */
+ public String getFragment()
+ {
+ return _fragment;
+ }
+
+ /**
+ * Compare method
+ */
+ public int compareTo(SvgFragment inOther)
+ {
+ int ycompare = _yCoord - inOther._yCoord;
+ if (ycompare != 0) {return ycompare;}
+ return _fragment.compareTo(inOther._fragment);
+ }
+
+ /**
+ * @param inOther other fragment to compare this one with
+ * @return true if the fragments are equal
+ */
+ public boolean equals(SvgFragment inOther)
+ {
+ return _fragment.equals(inOther._fragment);
+ }
+}
--- /dev/null
+package tim.prune.save.xml;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import tim.prune.data.DataPoint;
+import tim.prune.data.SourceInfo;
+
+/**
+ * Class to read in a GPX file and cache all the point strings
+ */
+public class GpxCacher implements TagReceiver
+{
+ private SourceInfo _sourceInfo = null;
+ private String _headerString = null;
+ private String[] _strings = null;
+ private int _pointNum = 0;
+
+
+ /**
+ * Constructor
+ * @param inSourceInfo source information
+ */
+ public GpxCacher(SourceInfo inInfo)
+ {
+ _sourceInfo = inInfo;
+ _strings = new String[inInfo.getNumPoints()];
+ _pointNum = 0;
+ // Should be a gpx file, but might be raw, zipped or gzipped
+ File gpxFile = inInfo.getFile();
+ String fileName = gpxFile.getName().toLowerCase();
+ if (gpxFile.exists() && gpxFile.canRead())
+ {
+ GpxSlicer slicer = new GpxSlicer(this);
+ InputStream istream = null;
+ BufferedInputStream bstream = null;
+ try {
+ if (fileName.endsWith(".gpx") || fileName.endsWith(".xml")) {
+ istream = new FileInputStream(inInfo.getFile());
+ }
+ else if (fileName.endsWith(".zip")) {
+ istream = getZipInputStream(inInfo.getFile());
+ }
+ else if (fileName.endsWith(".gz")) {
+ istream = new GZIPInputStream(new FileInputStream(inInfo.getFile()));
+ }
+ else {
+ System.out.println("GpxCacher unrecognised file type: " + inInfo.getFile().getName());
+ }
+ if (istream != null) {
+ bstream = new BufferedInputStream(istream);
+ slicer.slice(bstream);
+ bstream.close();
+ }
+ } catch (Exception e) {
+ // TODO: Handle errors here with a list of warnings?
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Accept a tag from the slicer
+ */
+ public void reportTag(String inTag)
+ {
+ if (_headerString == null) {
+ _headerString = inTag;
+ }
+ else {
+ _strings[_pointNum] = inTag;
+ _pointNum++;
+ }
+ }
+
+
+ /**
+ * @return the header string from the GPX tag
+ */
+ public String getHeaderString()
+ {
+ return _headerString;
+ }
+
+ /**
+ * Get the source string for the given point
+ * @param inPoint point to retrieve
+ * @return string if found, otherwise null
+ */
+ public String getSourceString(DataPoint inPoint)
+ {
+ int index = _sourceInfo.getIndex(inPoint);
+ if (index >= 0) {
+ return _strings[index];
+ }
+ return null;
+ }
+
+ /**
+ * Get an inputstream of a GPX file inside a zip
+ * @param inFile File object describing zip file
+ * @return input stream for Xml parser
+ */
+ private static InputStream getZipInputStream(File inFile)
+ {
+ try
+ {
+ ZipInputStream zis = new ZipInputStream(new FileInputStream(inFile));
+ while (zis.available() > 0)
+ {
+ ZipEntry entry = zis.getNextEntry();
+ String entryName = entry.toString();
+ if (entryName != null && entryName.length() > 4)
+ {
+ String suffix = entryName.substring(entryName.length()-4).toLowerCase();
+ if (suffix.equals(".gpx") || suffix.equals(".xml")) {
+ // First matching file so must be gpx
+ return zis;
+ }
+ }
+ }
+ }
+ catch (Exception e) {} // ignore errors
+ // not found - error!
+ return null;
+ }
+}
-package tim.prune.save;
+package tim.prune.save.xml;
import tim.prune.data.DataPoint;
import tim.prune.data.FileInfo;
public String getSourceString(DataPoint inPoint)
{
String str = null;
- // Check if point has been modified, if so return null
- if (inPoint.isModified()) {return null;}
// Loop over sources
for (int i=0; i<_cacherList.length && (str == null); i++) {
GpxCacher cacher = _cacherList[i];
--- /dev/null
+package tim.prune.save.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Class to slice up a gpx stream and report the found tags
+ * back to a listener.
+ * Used by Gpx caching to re-read and store the gpx source
+ */
+public class GpxSlicer
+{
+ /** listener to receive tags */
+ private TagReceiver _receiver = null;
+ /** string builder for copying source xml */
+ private StringBuilder _builder = null;
+
+ // character sequences for start and end of tags
+ private static final char[] GPX_START = "<gpx".toCharArray();
+ private static final char[] GPX_END = ">".toCharArray();
+ private static final char[] TRKPT_START = "<trkpt".toCharArray();
+ private static final char[] TRKPT_END = "/trkpt>".toCharArray();
+ private static final char[] WPT_START = "<wpt".toCharArray();
+ private static final char[] WPT_END = "/wpt>".toCharArray();
+ private static final char[] RTEPT_START = "<rtept".toCharArray();
+ private static final char[] RTEPT_END = "/rtept>".toCharArray();
+ private static final char[] CDATA_START = "<![CDATA[".toCharArray();
+ private static final char[] CDATA_END = "]]>".toCharArray();
+
+
+ /**
+ * Constructor
+ * @param inReceiver listener for tags
+ */
+ public GpxSlicer(TagReceiver inReceiver)
+ {
+ _receiver = inReceiver;
+ }
+
+ /**
+ * Begin the slicing and pass the found tags back to the listener
+ * @param inStream input stream for reading gpx source
+ */
+ public void slice(InputStream inStream)
+ {
+ _builder = new StringBuilder(100);
+ boolean insideTag = false;
+ boolean insideCdata = false;
+ char[] endTag = null;
+ boolean foundHeader = false;
+ int b = 0;
+ try
+ {
+ while ((b = inStream.read()) >= 0)
+ {
+ if (!insideTag && !insideCdata) {
+ if (b == '<') _builder.setLength(0);
+ }
+ // copy character
+ _builder.append((char)b);
+
+ if (insideCdata) {
+ // Just look for end of cdata block
+ if (foundSequence(CDATA_END)) {insideCdata = false;}
+ }
+ else
+ {
+ if (!insideTag)
+ {
+ // Look for start of one of the tags
+ if (!foundHeader && foundSequence(GPX_START)) {
+ insideTag = true;
+ foundHeader = true;
+ endTag = GPX_END;
+ }
+ else if (b == 't')
+ {
+ if (foundSequence(TRKPT_START)) {
+ insideTag = true;
+ endTag = TRKPT_END;
+ }
+ else if (foundSequence(WPT_START)) {
+ insideTag = true;
+ endTag = WPT_END;
+ }
+ else if (foundSequence(RTEPT_START)) {
+ insideTag = true;
+ endTag = RTEPT_END;
+ }
+ }
+ }
+ else
+ {
+ // Look for end of found tag
+ if (foundSequence(endTag)) {
+ _receiver.reportTag(_builder.toString());
+ _builder.setLength(0);
+ insideTag = false;
+ }
+ }
+ // Look for start of cdata block
+ if (foundSequence(CDATA_START)) {insideCdata = true;}
+ }
+ }
+ }
+ catch (IOException e) {} // ignore
+ }
+
+ /**
+ * Look for the given character sequence in the last characters read
+ * @param inChars sequence to look for
+ * @return true if sequence found
+ */
+ private boolean foundSequence(char[] inChars)
+ {
+ final int numChars = inChars.length;
+ final int bufflen = _builder.length();
+ if (bufflen < numChars) {return false;}
+ for (int i=0; i<numChars; i++)
+ {
+ char searchChar = inChars[numChars - 1 - i];
+ char sourceChar = _builder.charAt(bufflen - 1 - i);
+ if (searchChar != sourceChar) {return false;}
+ //if (Character.toLowerCase(searchChar) != Character.toLowerCase(sourceChar)) {return false;}
+ }
+ return true;
+ }
+}
--- /dev/null
+package tim.prune.save.xml;
+
+/**
+ * Interface for receivers of tag strings
+ * used for reading tags from xml and reporting them back to a listener
+ */
+public interface TagReceiver
+{
+ /**
+ * Method to give a tag string to a listener
+ * @param inTag xml tag
+ */
+ public void reportTag(String inTag);
+}
import tim.prune.FunctionLibrary;
import tim.prune.I18nManager;
-import tim.prune.data.Altitude;
import tim.prune.data.Track;
+import tim.prune.function.Export3dFunction;
/**
private JFrame _frame = null;
private ThreeDModel _model = null;
private OrbitBehavior _orbit = null;
- private int _altitudeCap = ThreeDModel.MINIMUM_ALTITUDE_CAP;
+ private double _altFactor = 50.0;
/** only prompt about big track size once */
private static boolean TRACK_SIZE_WARNING_GIVEN = false;
*/
public void show() throws ThreeDException
{
- // Get the altitude cap to use
- String altitudeUnits = getAltitudeUnitsLabel(_track);
- Object altCapString = JOptionPane.showInputDialog(_parentFrame,
- I18nManager.getText("dialog.3d.altitudecap") + " (" + altitudeUnits + ")",
+ // Get the altitude exaggeration to use
+ Object factorString = JOptionPane.showInputDialog(_parentFrame,
+ I18nManager.getText("dialog.3d.altitudefactor"),
I18nManager.getText("dialog.3d.title"),
- JOptionPane.QUESTION_MESSAGE, null, null, "" + _altitudeCap);
- if (altCapString == null) return;
- try
- {
- _altitudeCap = Integer.parseInt(altCapString.toString());
+ JOptionPane.QUESTION_MESSAGE, null, null, _altFactor);
+ if (factorString == null) return;
+ try {
+ _altFactor = Double.parseDouble(factorString.toString());
}
catch (Exception e) {} // Ignore parse errors
+ if (_altFactor < 1.0) {_altFactor = 1.0;}
// Set up the graphics config
GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
// opted to continue, don't show warning again
TRACK_SIZE_WARNING_GIVEN = true;
}
- else
- {
+ else {
// opted to cancel - show warning again next time
return;
}
u.getViewingPlatform().setNominalViewingTransform();
// Add behaviour to rotate using mouse
- _orbit = new OrbitBehavior(canvas, OrbitBehavior.REVERSE_ALL |
- OrbitBehavior.STOP_ZOOM);
+ _orbit = new OrbitBehavior(canvas, OrbitBehavior.REVERSE_ALL | OrbitBehavior.STOP_ZOOM);
BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
_orbit.setSchedulingBounds(bounds);
u.getViewingPlatform().setViewPlatformBehavior(_orbit);
// Make panel for render, close buttons
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
- // Add callback button for render
- JButton renderButton = new JButton(I18nManager.getText("function.exportpov"));
- renderButton.addActionListener(new ActionListener()
- {
- /** Render button pressed */
+ // Add button for exporting pov
+ JButton povButton = new JButton(I18nManager.getText("function.exportpov"));
+ povButton.addActionListener(new ActionListener() {
+ /** Export pov button pressed */
+ public void actionPerformed(ActionEvent e)
+ {
+ if (_orbit != null) {
+ callbackRender(FunctionLibrary.FUNCTION_POVEXPORT);
+ }
+ }});
+ panel.add(povButton);
+ // Add button for exporting svg
+ JButton svgButton = new JButton(I18nManager.getText("function.exportsvg"));
+ svgButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
- if (_orbit != null)
- {
- callbackRender();
+ if (_orbit != null) {
+ callbackRender(FunctionLibrary.FUNCTION_SVGEXPORT);
}
}});
- panel.add(renderButton);
+ panel.add(svgButton);
// Display coordinates of lat/long lines of 3d graph in separate dialog
JButton showLinesButton = new JButton(I18nManager.getText("button.showlines"));
showLinesButton.addActionListener(new ActionListener() {
closeButton.addActionListener(new ActionListener()
{
/** Close button pressed - clean up */
- public void actionPerformed(ActionEvent e)
- {
- _frame.dispose();
- _frame = null;
+ public void actionPerformed(ActionEvent e) {
+ dispose();
_orbit = null;
}
});
_frame.pack();
// Add a listener to clean up when window closed
_frame.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e)
- {
+ public void windowClosing(WindowEvent e) {
dispose();
}
});
// show frame
_frame.setVisible(true);
- if (_frame.getState() == JFrame.ICONIFIED)
- {
+ if (_frame.getState() == JFrame.ICONIFIED) {
_frame.setState(JFrame.NORMAL);
}
}
Box plane = null;
planeAppearance = new Appearance();
planeAppearance.setMaterial(new Material(new Color3f(0.1f, 0.2f, 0.2f),
- new Color3f(0.0f, 0.0f, 0.0f), new Color3f(0.3f, 0.4f, 0.4f),
- new Color3f(0.3f, 0.3f, 0.3f), 0.0f));
+ new Color3f(0.0f, 0.0f, 0.0f), new Color3f(0.3f, 0.4f, 0.4f),
+ new Color3f(0.3f, 0.3f, 0.3f), 0.0f));
plane = new Box(10f, 0.04f, 10f, planeAppearance);
objTrans.addChild(plane);
// N, S, E, W
GeneralPath bevelPath = new GeneralPath();
bevelPath.moveTo(0.0f, 0.0f);
- for (int i=0; i<91; i+= 5)
+ for (int i=0; i<91; i+= 5) {
bevelPath.lineTo((float) (0.1 - 0.1 * Math.cos(Math.toRadians(i))),
(float) (0.1 * Math.sin(Math.toRadians(i))));
- for (int i=90; i>0; i-=5)
+ }
+ for (int i=90; i>0; i-=5) {
bevelPath.lineTo((float) (0.3 + 0.1 * Math.cos(Math.toRadians(i))),
(float) (0.1 * Math.sin(Math.toRadians(i))));
+ }
Font3D compassFont = new Font3D(
new Font(CARDINALS_FONT, Font.PLAIN, 1),
new FontExtrusion(bevelPath));
// create and scale model
_model = new ThreeDModel(_track);
- _model.setAltitudeCap(_altitudeCap);
+ _model.setAltitudeFactor(_altFactor);
_model.scale();
// Lat/Long lines
objTrans.addChild(createDataPoints(_model));
// Create lights
- BoundingSphere bounds =
- new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
+ BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
AmbientLight aLgt = new AmbientLight(new Color3f(1.0f, 1.0f, 1.0f));
aLgt.setInfluencingBounds(bounds);
objTrans.addChild(aLgt);
PointLight pLgt = new PointLight(new Color3f(1.0f, 1.0f, 1.0f),
- new Point3f(0f, 0f, 2f),
- new Point3f(0.25f, 0.05f, 0.0f) );
+ new Point3f(0f, 0f, 2f), new Point3f(0.25f, 0.05f, 0.0f) );
pLgt.setInfluencingBounds(bounds);
objTrans.addChild(pLgt);
PointLight pl2 = new PointLight(new Color3f(0.8f, 0.9f, 0.4f),
- new Point3f(6f, 1f, 6f),
- new Point3f(0.2f, 0.1f, 0.05f) );
+ new Point3f(6f, 1f, 6f), new Point3f(0.2f, 0.1f, 0.05f) );
pl2.setInfluencingBounds(bounds);
objTrans.addChild(pl2);
PointLight pl3 = new PointLight(new Color3f(0.7f, 0.7f, 0.7f),
- new Point3f(0.0f, 12f, -2f),
- new Point3f(0.1f, 0.1f, 0.0f) );
+ new Point3f(0.0f, 12f, -2f), new Point3f(0.1f, 0.1f, 0.0f) );
pl3.setInfluencingBounds(bounds);
objTrans.addChild(pl3);
{
Text3D txt = new Text3D(inFont, inText, inLocn, Text3D.ALIGN_FIRST, Text3D.PATH_RIGHT);
Material mat = new Material(new Color3f(0.5f, 0.5f, 0.55f),
- new Color3f(0.05f, 0.05f, 0.1f), new Color3f(0.3f, 0.4f, 0.5f),
- new Color3f(0.4f, 0.5f, 0.7f), 70.0f);
+ new Color3f(0.05f, 0.05f, 0.1f), new Color3f(0.3f, 0.4f, 0.5f),
+ new Color3f(0.4f, 0.5f, 0.7f), 70.0f);
mat.setLightingEnable(true);
Appearance app = new Appearance();
app.setMaterial(mat);
{
Cylinder latline = new Cylinder(0.1f, (float) (inSize*2));
Transform3D horizShift = new Transform3D();
- horizShift.setTranslation(new Vector3d(0.0, 0.0, inLatitude));
+ horizShift.setTranslation(new Vector3d(0.0, 0.0, -inLatitude));
TransformGroup horizTrans = new TransformGroup(horizShift);
Transform3D zRot = new Transform3D();
zRot.rotZ(Math.toRadians(90.0));
}
+ /** @return track point object */
private static Group createTrackpoint(Point3d inPointPos, byte inHeightCode)
{
Material mat = getTrackpointMaterial(inHeightCode);
// MAYBE: sort symbol scaling
- Sphere dot = new Sphere(0.2f); // * symbolScaling / 100f);
+ Sphere dot = new Sphere(0.2f);
return createBall(inPointPos, dot, mat);
}
+ /** @return Material object for track points with the appropriate colour for the height */
private static Material getTrackpointMaterial(byte inHeightCode)
{
// create default material
new Color3f(1.0f, 0.6f, 0.6f), 70.0f);
// change colour according to height code
if (inHeightCode == 1) mat.setDiffuseColor(new Color3f(0.4f, 0.9f, 0.2f));
- if (inHeightCode == 2) mat.setDiffuseColor(new Color3f(0.7f, 0.8f, 0.2f));
- if (inHeightCode == 3) mat.setDiffuseColor(new Color3f(0.5f, 0.85f, 0.95f));
- if (inHeightCode == 4) mat.setDiffuseColor(new Color3f(0.1f, 0.9f, 0.9f));
- if (inHeightCode >= 5) mat.setDiffuseColor(new Color3f(1.0f, 1.0f, 1.0f));
+ else if (inHeightCode == 2) mat.setDiffuseColor(new Color3f(0.7f, 0.8f, 0.2f));
+ else if (inHeightCode == 3) mat.setDiffuseColor(new Color3f(0.3f, 0.6f, 0.4f));
+ else if (inHeightCode == 4) mat.setDiffuseColor(new Color3f(0.1f, 0.9f, 0.9f));
+ else if (inHeightCode >= 5) mat.setDiffuseColor(new Color3f(1.0f, 1.0f, 1.0f));
// return object
return mat;
}
// Also create rod for ball to sit on
Cylinder rod = new Cylinder(0.1f, (float) inPosition.y);
Material rodMat = new Material(new Color3f(0.2f, 0.2f, 0.2f),
- new Color3f(0.0f, 0.0f, 0.0f), new Color3f(0.2f, 0.2f, 0.2f),
- new Color3f(0.05f, 0.05f, 0.05f), 0.4f);
+ new Color3f(0.0f, 0.0f, 0.0f), new Color3f(0.2f, 0.2f, 0.2f),
+ new Color3f(0.05f, 0.05f, 0.05f), 0.4f);
rodMat.setLightingEnable(true);
Appearance rodApp = new Appearance();
rodApp.setMaterial(rodMat);
rod.setAppearance(rodApp);
Transform3D rodShift = new Transform3D();
- rodShift.setTranslation(new Vector3d(inPosition.x,
- inPosition.y/2.0, inPosition.z));
+ rodShift.setTranslation(new Vector3d(inPosition.x, inPosition.y/2.0, inPosition.z));
TransformGroup rodShiftTrans = new TransformGroup(rodShift);
rodShiftTrans.addChild(rod);
group.addChild(rodShiftTrans);
/**
* Calculate the angles and call them back to the app
+ * @param inFunction function to call (either pov or svg)
*/
- private void callbackRender()
+ private void callbackRender(Export3dFunction inFunction)
{
Transform3D trans3d = new Transform3D();
_orbit.getViewingPlatform().getViewPlatformTransform().getTransform(trans3d);
firstTran.rotY(Math.toRadians(-INITIAL_Y_ROTATION));
Transform3D secondTran = new Transform3D();
secondTran.rotX(Math.toRadians(-INITIAL_X_ROTATION));
- // Apply inverse rotations in reverse order to test point
+ // Apply inverse rotations in reverse order to the test point
Point3d result = new Point3d();
secondTran.transform(point, result);
firstTran.transform(result);
// Callback settings to pov export function
- FunctionLibrary.FUNCTION_POVEXPORT.setCameraCoordinates(result.x, result.y, result.z);
- FunctionLibrary.FUNCTION_POVEXPORT.setAltitudeCap(_altitudeCap);
- FunctionLibrary.FUNCTION_POVEXPORT.begin();
- }
-
-
- /**
- * Get a units label for the altitudes in the given Track
- * @param inTrack Track object
- * @return units label for altitude used in Track
- */
- private static String getAltitudeUnitsLabel(Track inTrack)
- {
- Altitude.Format altitudeFormat = inTrack.getAltitudeRange().getFormat();
- if (altitudeFormat == Altitude.Format.METRES)
- return I18nManager.getText("units.metres.short");
- return I18nManager.getText("units.feet.short");
+ inFunction.setCameraCoordinates(result.x, result.y, result.z);
+ inFunction.setAltitudeExaggeration(_altFactor);
+ inFunction.begin();
}
-
}
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
StringBuffer descBuffer = new StringBuffer();
- if (_latLines == null || _latLines.length == 0 || _lonLines == null || _lonLines.length == 0)
+ final int numLatLines = (_latLines == null?0:_latLines.length);
+ final int numLonLines = (_lonLines == null?0:_lonLines.length);
+ if (numLatLines == 0 && numLonLines == 0)
{
descBuffer.append("<p>").append(I18nManager.getText("dialog.3dlines.empty")).append("</p>");
}
descBuffer.append("<p>").append(I18nManager.getText("dialog.3dlines.intro")).append(":</p>");
descBuffer.append("<p>").append(I18nManager.getText("fieldname.latitude")).append("<ul>");
Latitude lat = null;
- for (int i=0; i<_latLines.length; i++)
+ for (int i=0; i<numLatLines; i++)
{
lat = new Latitude(_latLines[i], Latitude.FORMAT_DEG);
descBuffer.append("<li>").append(lat.output(Latitude.FORMAT_DEG_WHOLE_MIN)).append("</li>");
descBuffer.append("</ul></p>");
descBuffer.append("<p>").append(I18nManager.getText("fieldname.longitude")).append("<ul>");
Longitude lon = null;
- for (int i=0; i<_lonLines.length; i++)
+ for (int i=0; i<numLonLines; i++)
{
lon = new Longitude(_lonLines[i], Longitude.FORMAT_DEG);
descBuffer.append("<li>").append(lon.output(Longitude.FORMAT_DEG_WHOLE_MIN)).append("</li>");
private Track _track = null;
private PointScaler _scaler = null;
private double _modelSize;
- private int _altitudeCap = -1;
private double _scaleFactor = 1.0;
private double _altFactor = 1.0;
// MAYBE: How to store rods (lifts) in data?
private byte[] _pointHeights = null;
private static final double DEFAULT_MODEL_SIZE = 10.0;
- /** Minimum altitude cap */
- public static final int MINIMUM_ALTITUDE_CAP = 100;
// Constants for point types
public static final byte POINT_TYPE_WAYPOINT = 1;
return _track.getNumPoints();
}
-
/**
- * Set the altitude cap
- * @param inAltitudeCap altitude range to cap to (ignored if less than data range)
+ * @param inFactor altitude exaggeration factor (default 1.0)
*/
- public void setAltitudeCap(int inAltitudeCap)
+ public void setAltitudeFactor(double inFactor)
{
- _altitudeCap = inAltitudeCap;
- if (_altitudeCap < MINIMUM_ALTITUDE_CAP)
- {
- _altitudeCap = MINIMUM_ALTITUDE_CAP;
+ if (inFactor >= 1.0) {
+ _altFactor = inFactor;
}
}
-
/**
* Scale all points and calculate factors
*/
_scaleFactor = _modelSize / _scaler.getMaximumVert();
}
}
- // calculate altitude scale factor
- _altFactor = 1.0;
- if (_scaler.getMaximumAlt() >= 0)
- {
- // limit by altitude cap or by data range?
- if (_scaler.getMaximumAlt() > _altitudeCap)
- {
- // data is bigger than cap
- _altFactor = _modelSize / _scaler.getMaximumAlt();
- }
- else
- {
- // capped
- _altFactor = _modelSize / _altitudeCap;
- }
+ // cap altitude scale factor if it's too big
+ double maxScaledAlt = _scaler.getMaxScaledAlt() * _altFactor;
+ if (maxScaledAlt > _modelSize) {
+ // capped
+ _altFactor = _altFactor * _modelSize / maxScaledAlt;
}
// calculate lat/long lines
_scaler.calculateLatLongLines();
for (int i=0; i<numPoints; i++)
{
DataPoint point = _track.getPoint(i);
- _pointTypes[i] = (point.isWaypoint()?POINT_TYPE_WAYPOINT:(point.getSegmentStart()?POINT_TYPE_SEGMENT_START:POINT_TYPE_NORMAL_POINT));
+ _pointTypes[i] = (point.isWaypoint()?POINT_TYPE_WAYPOINT:
+ (point.getSegmentStart()?POINT_TYPE_SEGMENT_START:POINT_TYPE_NORMAL_POINT));
_pointHeights[i] = (byte) (point.getAltitude().getValue(Altitude.Format.METRES) / 500);
}
}
public double getScaledAltValue(int inIndex)
{
// if no altitude, just return 0
- int altVal = _scaler.getAltValue(inIndex);
+ double altVal = _scaler.getAltValue(inIndex);
if (altVal < 0) return 0;
- // scale according to altitude cap
+ // scale according to exaggeration factor
return altVal * _altFactor;
}
import tim.prune.I18nManager;
import tim.prune.UpdateMessageBroker;
import tim.prune.data.Altitude;
+import tim.prune.data.DataPoint;
import tim.prune.data.TrackInfo;
/**
// Perform the inverse operation
final int numPoints = _altitudes.length;
for (int i=0; i<numPoints; i++) {
- inTrackInfo.getTrack().getPoint(i+_startIndex).getAltitude().reset(_altitudes[i]);
+ DataPoint point = inTrackInfo.getTrack().getPoint(i+_startIndex);
+ point.getAltitude().reset(_altitudes[i]);
+ point.setModified(true);
}
_altitudes = null;
+ inTrackInfo.getSelection().markInvalid();
UpdateMessageBroker.informSubscribers();
}
}
public void performUndo(TrackInfo inTrackInfo) throws UndoException
{
// Perform the inverse operation
- inTrackInfo.getTrack().addTimeOffset(_startIndex, _endIndex, -_timeOffset);
+ inTrackInfo.getTrack().addTimeOffset(_startIndex, _endIndex, -_timeOffset, true);
UpdateMessageBroker.informSubscribers();
}
}
for (int i=0; i<_photoPoints.length; i++)\r
{\r
Photo photo = inTrackInfo.getPhotoList().getPhoto(i);\r
- DataPoint point = _photoPoints[i];\r
- photo.setDataPoint(point);\r
- if (point != null) {\r
- point.setPhoto(photo);\r
+ // Only need to look at connected photos, if they're still tagged then leave them\r
+ if (photo.getCurrentStatus() == Photo.Status.CONNECTED)\r
+ {\r
+ DataPoint point = _photoPoints[i];\r
+ photo.setDataPoint(point);\r
+ if (point != null) {\r
+ point.setPhoto(photo);\r
+ }\r
}\r
}\r
// clear selection\r
--- /dev/null
+package tim.prune.undo;\r
+\r
+import tim.prune.I18nManager;\r
+import tim.prune.UpdateMessageBroker;\r
+import tim.prune.data.DataPoint;\r
+import tim.prune.data.Field;\r
+import tim.prune.data.Track;\r
+import tim.prune.data.TrackInfo;\r
+\r
+/**\r
+ * Operation to undo the deletion of field values\r
+ */\r
+public class UndoDeleteFieldValues implements UndoOperation\r
+{\r
+ /** Start and end indices of section */\r
+ private int _startIndex, _endIndex;\r
+ /** Field to be deleted */\r
+ private Field _field = null;\r
+ /** Field values before operation */\r
+ private String[] _fieldValues = null;\r
+\r
+ /**\r
+ * Constructor\r
+ * @param inTrackInfo track info object to copy values from\r
+ * @param inField field to delete\r
+ */\r
+ public UndoDeleteFieldValues(TrackInfo inTrackInfo, Field inField)\r
+ {\r
+ _startIndex = inTrackInfo.getSelection().getStart();\r
+ _endIndex = inTrackInfo.getSelection().getEnd();\r
+ final int numPoints = _endIndex - _startIndex + 1;\r
+ _fieldValues = new String[numPoints];\r
+ _field = inField;\r
+ // Loop over points in selection, and copy field values\r
+ for (int i=_startIndex; i<=_endIndex; i++)\r
+ {\r
+ DataPoint point = inTrackInfo.getTrack().getPoint(i);\r
+ _fieldValues[i-_startIndex] = point.getFieldValue(inField);\r
+ }\r
+ }\r
+\r
+\r
+ /**\r
+ * @return description of operation\r
+ */\r
+ public String getDescription()\r
+ {\r
+ return I18nManager.getText("undo.deletefieldvalues");\r
+ }\r
+\r
+\r
+ /**\r
+ * Perform the undo operation on the given Track\r
+ * @param inTrackInfo TrackInfo object on which to perform the operation\r
+ */\r
+ public void performUndo(TrackInfo inTrackInfo) throws UndoException\r
+ {\r
+ // Sanity check\r
+ Track track = inTrackInfo.getTrack();\r
+ if (track.getNumPoints() <= _endIndex || _endIndex <= _startIndex) {\r
+ throw new UndoException("Cannot undo conversion, track length doesn't match");\r
+ }\r
+ // Loop over points in selection and replace field values\r
+ for (int i=_startIndex; i<=_endIndex; i++)\r
+ {\r
+ String storedValue = _fieldValues[i-_startIndex];\r
+ if (storedValue != null) {\r
+ track.getPoint(i).setFieldValue(_field, storedValue, true);\r
+ }\r
+ }\r
+ track.requestRescale();\r
+ inTrackInfo.getSelection().markInvalid();\r
+ UpdateMessageBroker.informSubscribers();\r
+ }\r
+}\r
{
/** DataPoint objects which didn't have altitudes before */
private DataPoint[] _points;
+ /** Altitude strings if present */
+ private String[] _altitudes;
/**
{
Track track = inTrackInfo.getTrack();
int numPoints = track.getNumPoints();
- // Make array of points without altitudes
+ // Make arrays of points and altitudes
_points = new DataPoint[numPoints];
+ _altitudes = new String[numPoints];
for (int i=0; i<numPoints; i++) {
DataPoint point = track.getPoint(i);
- if (!point.hasAltitude()) {
+ if (!point.hasAltitude() || point.getAltitude().getValue() == 0) {
_points[i] = point;
+ if (point.hasAltitude()) {
+ _altitudes[i] = point.getFieldValue(Field.ALTITUDE);
+ }
}
}
}
for (int i=0; i<numPoints; i++) {
DataPoint point = _points[i];
if (point != null && point.hasAltitude()) {
- point.setFieldValue(Field.ALTITUDE, null, true);
+ if (_altitudes[i] == null) {
+ point.setFieldValue(Field.ALTITUDE, null, true);
+ }
+ else {
+ point.setFieldValue(Field.ALTITUDE, _altitudes[i], true);
+ }
}
}
_points = null;