package tim.prune;
+import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.Set;
import java.util.Stack;
+import java.io.File;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import tim.prune.data.LatLonRectangle;
import tim.prune.data.Latitude;
import tim.prune.data.Longitude;
+import tim.prune.data.NumberUtils;
import tim.prune.data.Photo;
import tim.prune.data.PhotoList;
import tim.prune.data.Track;
import tim.prune.function.browser.UrlGenerator;
import tim.prune.function.edit.FieldEditList;
import tim.prune.function.edit.PointEditor;
-import tim.prune.function.edit.PointNameEditor;
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.save.ExifSaver;
import tim.prune.save.FileSaver;
-import tim.prune.undo.UndoAddTimeOffset;
-import tim.prune.undo.UndoCompress;
-import tim.prune.undo.UndoConnectPhoto;
-import tim.prune.undo.UndoConnectPhotoWithClone;
-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 FileSaver _fileSaver = null;
private Stack<UndoOperation> _undoStack = null;
private boolean _mangleTimestampsConfirmed = false;
+ private Viewport _viewport = null;
+ private ArrayList<File> _dataFiles = null;
+ private boolean _firstDataFile = true;
+
/**
* Constructor
return _undoStack;
}
+ /**
+ * Load the specified data files one by one
+ * @param inDataFiles arraylist containing File objects to load
+ */
+ public void loadDataFiles(ArrayList<File> inDataFiles)
+ {
+ if (inDataFiles == null || inDataFiles.size() == 0) {
+ _dataFiles = null;
+ }
+ else {
+ _dataFiles = inDataFiles;
+ File f = _dataFiles.get(0);
+ _dataFiles.remove(0);
+ // Start load of specified file
+ if (_fileLoader == null)
+ _fileLoader = new FileLoader(this, _frame);
+ _firstDataFile = true;
+ _fileLoader.openFile(f);
+ }
+ }
+
/**
* Complete a function execution
* @param inUndo undo object to be added to stack
}
- /**
- * Edit the name of the currently selected (way)point
- */
- public void editCurrentPointName()
- {
- if (_track != null)
- {
- DataPoint currentPoint = _trackInfo.getCurrentPoint();
- if (currentPoint != null)
- {
- // Open point dialog to display details
- PointNameEditor editor = new PointNameEditor(this, _frame);
- editor.showDialog(currentPoint);
- }
- }
- }
-
-
/**
* Delete the currently selected point
*/
}
+ /**
+ * Complete the add altitude offset function with the specified offset
+ * @param inOffset altitude offset to add as String
+ * @param inFormat altitude format of offset (eg Feet, Metres)
+ */
+ public void finishAddAltitudeOffset(String inOffset, Altitude.Format inFormat)
+ {
+ // Sanity check
+ if (inOffset == null || inOffset.equals("") || inFormat==Altitude.Format.NO_FORMAT) {
+ return;
+ }
+ // Construct undo information
+ UndoAddAltitudeOffset undo = new UndoAddAltitudeOffset(_trackInfo);
+ int selStart = _trackInfo.getSelection().getStart();
+ int selEnd = _trackInfo.getSelection().getEnd();
+ // How many decimal places are given in the offset?
+ int numDecimals = NumberUtils.getDecimalPlaces(inOffset);
+ boolean success = false;
+ // Decimal offset given
+ try {
+ double offsetd = Double.parseDouble(inOffset);
+ success = _trackInfo.getTrack().addAltitudeOffset(selStart, selEnd, offsetd, inFormat, numDecimals);
+ }
+ catch (NumberFormatException nfe) {}
+ if (success)
+ {
+ _undoStack.add(undo);
+ UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_EDITED);
+ UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.addaltitudeoffset"));
+ }
+ }
+
+
/**
* Merge the track segments within the current selection
*/
// Make undo object
UndoMergeTrackSegments undo = new UndoMergeTrackSegments(_track, selStart, selEnd);
// Call track to merge segments
- if (_track.mergeTrackSegments(selStart, selEnd)) {
+ if (_trackInfo.mergeTrackSegments(selStart, selEnd)) {
_undoStack.add(undo);
UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.mergetracksegments"));
}
DataPoint point = new DataPoint(new Latitude(inLat, Coordinate.FORMAT_NONE), new Longitude(inLong, Coordinate.FORMAT_NONE), null);
point.setSegmentStart(true);
_track.appendPoints(new DataPoint[] {point});
- _trackInfo.getSelection().selectPoint(_trackInfo.getTrack().getNumPoints()-1);
+ _trackInfo.selectPoint(_trackInfo.getTrack().getNumPoints()-1);
// add undo object to stack
_undoStack.add(undo);
// update listeners
// Add undo object to stack, set confirm message
_undoStack.add(undo);
- _trackInfo.getSelection().deselectRange();
+ _trackInfo.getSelection().selectRange(-1, -1);
UpdateMessageBroker.informSubscribers();
UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.cutandmove"));
}
}
}
-
- /**
- * Select all points
- */
- public void selectAll()
- {
- _trackInfo.getSelection().select(0, 0, _track.getNumPoints()-1);
- }
-
/**
* Select nothing
*/
_track.clearDeletionMarkers();
}
-
/**
* Receive loaded data and optionally merge with current Track
* @param inFieldArray array of fields
if (loadedTrack.getNumPoints() <= 0)
{
showErrorMessage("error.load.dialogtitle", "error.load.nopoints");
+ // load next file if there's a queue
+ loadNextFile();
return;
}
// Decide whether to load or append
if (_track.getNumPoints() > 0)
{
// ask whether to replace or append
- int answer = JOptionPane.showConfirmDialog(_frame,
- I18nManager.getText("dialog.openappend.text"),
- I18nManager.getText("dialog.openappend.title"),
- JOptionPane.YES_NO_CANCEL_OPTION);
+ int answer = 0;
+ if (_dataFiles == null || _firstDataFile) {
+ answer = JOptionPane.showConfirmDialog(_frame,
+ I18nManager.getText("dialog.openappend.text"),
+ I18nManager.getText("dialog.openappend.title"),
+ JOptionPane.YES_NO_CANCEL_OPTION);
+ }
+ else {
+ // Automatically append if there's a file load queue
+ answer = JOptionPane.YES_OPTION;
+ }
if (answer == JOptionPane.YES_OPTION)
{
// append data to current Track
UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.loadfile") + " '" + inFilename + "'");
// update menu
_menuManager.informFileLoaded();
+ // load next file if there's a queue
+ loadNextFile();
+ }
+
+ /**
+ * Inform the app that NO data was loaded, eg cancel pressed
+ * Only needed if there's another file waiting in the queue
+ */
+ public void informNoDataLoaded()
+ {
+ // Load next file if there's a queue
+ loadNextFile();
+ }
+
+ /**
+ * Load the next file in the waiting list, if any
+ */
+ private void loadNextFile()
+ {
+ _firstDataFile = false;
+ if (_dataFiles == null || _dataFiles.size() == 0) {
+ _dataFiles = null;
+ }
+ else {
+ new Thread(new Runnable() {
+ public void run() {
+ File f = _dataFiles.get(0);
+ _dataFiles.remove(0);
+ _fileLoader.openFile(f);
+ }
+ }).start();
+ }
}
{
UpdateMessageBroker.informSubscribers("" + numPhotosAdded + " " + I18nManager.getText("confirm.jpegload.multi"));
}
- // TODO: Improve message when photo(s) fail to load (eg already added)
+ // MAYBE: Improve message when photo(s) fail to load (eg already added)
UpdateMessageBroker.informSubscribers();
// update menu
_menuManager.informFileLoaded();
JOptionPane.showMessageDialog(_frame, inMessage,
I18nManager.getText(inTitleKey), JOptionPane.ERROR_MESSAGE);
}
+
+ /**
+ * @param inViewport viewport object
+ */
+ public void setViewport(Viewport inViewport)
+ {
+ _viewport = inViewport;
+ }
+
+ /**
+ * @return current viewport object
+ */
+ public Viewport getViewport()
+ {
+ return _viewport;
+ }
}
*/
public abstract class Config
{
- /** Working directory for loading and saving */
- private static File _workingDir = null;
- /** Default language */
- private static String _langCode = null;
- /** GPS device name */
- private static String _gpsDevice = null;
- /** GPS format name */
- private static String _gpsFormat = null;
- /** Font to use for povray */
- private static String _povrayFont = null;
- /** True to use metric units */
- private static boolean _metricUnits = true;
- /** Path to gnuplot executable */
- private static String _gnuplotPath = null;
- /** Index of selected map tile server */
- private static int _mapTileServerIndex = -1;
- /** URL for freeform map tile server */
- private static String _mapTileServerUrl = null;
/** File from which Config was loaded */
private static File _configFile = null;
- // TODO: Need setters for all these parameters if want to make the config saveable
+ /** Hashtable containing all config values */
+ private static Properties _configValues = new Properties();
/** Default config file */
private static final File DEFAULT_CONFIG_FILE = new File(".pruneconfig");
- /** Key for working directory */
- private static final String KEY_WORKING_DIR = "prune.directory";
+ /** Key for track directory */
+ public static final String KEY_TRACK_DIR = "prune.trackdirectory";
+ /** Key for photo directory */
+ public static final String KEY_PHOTO_DIR = "prune.photodirectory";
/** Key for language code */
- private static final String KEY_LANGUAGE_CODE = "prune.languagecode";
+ public static final String KEY_LANGUAGE_CODE = "prune.languagecode";
/** Key for GPS device */
- private static final String KEY_GPS_DEVICE = "prune.gpsdevice";
+ public static final String KEY_GPS_DEVICE = "prune.gpsdevice";
/** Key for GPS format */
- private static final String KEY_GPS_FORMAT = "prune.gpsformat";
+ public static final String KEY_GPS_FORMAT = "prune.gpsformat";
/** Key for Povray font */
- private static final String KEY_POVRAY_FONT = "prune.povrayfont";
+ public static final String KEY_POVRAY_FONT = "prune.povrayfont";
/** Key for metric/imperial */
- private static final String KEY_METRIC_UNITS = "prune.metricunits";
- /** Key for gpsbabel path */
- private static final String KEY_GNUPLOTPATH = "prune.gnuplotpath";
+ public static final String KEY_METRIC_UNITS = "prune.metricunits";
/** Key for map server index */
- private static final String KEY_MAPSERVERINDEX = "prune.mapserverindex";
+ public static final String KEY_MAPSERVERINDEX = "prune.mapserverindex";
/** Key for map server url */
- private static final String KEY_MAPSERVERURL = "prune.mapserverurl";
-
-
- /**
- * @return working directory for loading and saving
- */
- public static File getWorkingDirectory()
- {
- return _workingDir;
- }
+ public static final String KEY_MAPSERVERURL = "prune.mapserverurl";
+ /** Key for show pace flag */
+ public static final String KEY_SHOW_PACE = "prune.showpace";
+ /** Key for width of thumbnails in kmz */
+ public static final String KEY_KMZ_IMAGE_WIDTH = "prune.kmzimagewidth";
+ /** Key for height of thumbnails in kmz */
+ public static final String KEY_KMZ_IMAGE_HEIGHT = "prune.kmzimageheight";
+ /** Key for gpsbabel path */
+ public static final String KEY_GPSBABEL_PATH = "prune.gpsbabelpath";
+ /** Key for gnuplot path */
+ public static final String KEY_GNUPLOT_PATH = "prune.gnuplotpath";
+ /** Key for exiftool path */
+ public static final String KEY_EXIFTOOL_PATH = "prune.exiftoolpath";
- /**
- * @param inDirectory working directory to use
- */
- public static void setWorkingDirectory(File inDirectory)
- {
- _workingDir = inDirectory;
- }
/**
* Load the default configuration file
}
catch (Exception e) {}
}
- // Save the properties we know about, ignore the rest
- _langCode = props.getProperty(KEY_LANGUAGE_CODE);
- String dir = props.getProperty(KEY_WORKING_DIR);
- if (dir != null) {setWorkingDirectory(new File(dir));}
- _gpsDevice = props.getProperty(KEY_GPS_DEVICE);
- _gpsFormat = props.getProperty(KEY_GPS_FORMAT);
- _povrayFont = props.getProperty(KEY_POVRAY_FONT);
- String useMetric = props.getProperty(KEY_METRIC_UNITS);
- _metricUnits = (useMetric == null || useMetric.equals("") || useMetric.toLowerCase().equals("y"));
- _gnuplotPath = props.getProperty(KEY_GNUPLOTPATH);
- if (_gnuplotPath == null || _gnuplotPath.equals("")) {_gnuplotPath = "gnuplot";}
- _mapTileServerIndex = parseInt(props.getProperty(KEY_MAPSERVERINDEX));
- _mapTileServerUrl = props.getProperty(KEY_MAPSERVERURL);
+ // Save all properties from file
+ _configValues.putAll(props);
if (loadFailed) {
throw new ConfigException();
}
props.put(KEY_GPS_DEVICE, "usb:");
props.put(KEY_GPS_FORMAT, "garmin");
props.put(KEY_POVRAY_FONT, "crystal.ttf"); // alternative: DejaVuSans-Bold.ttf
+ props.put(KEY_SHOW_PACE, "0"); // hide by default
+ props.put(KEY_EXIFTOOL_PATH, "exiftool");
+ props.put(KEY_GNUPLOT_PATH, "gnuplot");
+ props.put(KEY_GPSBABEL_PATH, "gpsbabel");
+ props.put(KEY_KMZ_IMAGE_WIDTH, "240");
+ props.put(KEY_KMZ_IMAGE_HEIGHT, "180");
return props;
}
return val;
}
- /** @return language code */
- public static String getLanguageCode()
- {
- return _langCode;
- }
-
- /** @return gps device */
- public static String getGpsDevice()
- {
- return _gpsDevice;
- }
-
- /** @return gps format */
- public static String getGpsFormat()
- {
- return _gpsFormat;
- }
-
- /** @return povray font */
- public static String getPovrayFont()
- {
- return _povrayFont;
- }
-
- /** @return true to use metric units */
- public static boolean getUseMetricUnits()
+ /** @return File from which config was loaded (or null) */
+ public static File getConfigFile()
{
- return _metricUnits;
+ return _configFile;
}
- /** @param inMetric true to use metric units */
- public static void setUseMetricUnits(boolean inMetric)
+ /**
+ * @return config Properties object to allow all config values to be saved
+ */
+ public static Properties getAllConfig()
{
- _metricUnits = inMetric;
+ return _configValues;
}
- /** @return path to gnuplot */
- public static String getGnuplotPath()
+ /**
+ * Store the given configuration setting
+ * @param inKey key (from constants)
+ * @param inValue value as string
+ */
+ public static void setConfigString(String inKey, String inValue)
{
- return _gnuplotPath;
+ if (inKey != null && !inKey.equals(""))
+ {
+ _configValues.put(inKey, inValue);
+ }
}
- /** @param inPath path to Gnuplot */
- public static void setGnuplotPath(String inPath)
+ /**
+ * Store the given configuration setting
+ * @param inKey key (from constants)
+ * @param inValue value as boolean
+ */
+ public static void setConfigBoolean(String inKey, boolean inValue)
{
- _gnuplotPath = inPath;
+ if (inKey != null && !inKey.equals(""))
+ {
+ _configValues.put(inKey, (inValue?"1":"0"));
+ }
}
- /** @return index of map server */
- public static int getMapServerIndex()
+ /**
+ * Store the given configuration setting
+ * @param inKey key (from constants)
+ * @param inValue value as int
+ */
+ public static void setConfigInt(String inKey, int inValue)
{
- return _mapTileServerIndex;
+ if (inKey != null && !inKey.equals(""))
+ {
+ _configValues.put(inKey, "" + inValue);
+ }
}
- /** @param inIndex selected index */
- public static void setMapServerIndex(int inIndex)
+ /**
+ * Get the given configuration setting as a String
+ * @param inKey key
+ * @return configuration setting as a String
+ */
+ public static String getConfigString(String inKey)
{
- _mapTileServerIndex = inIndex;
+ return _configValues.getProperty(inKey);
}
- /** @return url of map server */
- public static String getMapServerUrl()
+ /**
+ * Get the given configuration setting as a boolean
+ * @param inKey key
+ * @return configuration setting as a boolean
+ */
+ public static boolean getConfigBoolean(String inKey)
{
- return _mapTileServerUrl;
+ String val = _configValues.getProperty(inKey);
+ return (val == null || val.equals("1"));
}
- /** @param inUrl url of map server */
- public static void setMapServerUrl(String inUrl)
+ /**
+ * Get the given configuration setting as an int
+ * @param inKey key
+ * @return configuration setting as an int
+ */
+ public static int getConfigInt(String inKey)
{
- _mapTileServerUrl = inUrl;
+ return parseInt(_configValues.getProperty(inKey));
}
- /** @return File from which config was loaded (or null) */
- public static File getConfigFile()
+ /**
+ * Check whether the given key corresponds to a boolean property
+ * @param inKey key to check
+ * @return true if corresponding property is boolean
+ */
+ public static boolean isKeyBoolean(String inKey)
{
- return _configFile;
+ // Only two boolean keys so far
+ return inKey != null && (inKey.equals(KEY_METRIC_UNITS) || inKey.equals(KEY_SHOW_PACE));
}
}
*/
public abstract class ExternalTools
{
+ /** Constant for Exiftool */
+ public static final int TOOL_EXIFTOOL = 0;
+ /** Constant for Gpsbabel */
+ public static final int TOOL_GPSBABEL = 1;
+ /** Constant for Gnuplot */
+ public static final int TOOL_GNUPLOT = 2;
+ /** Config keys in order that the tools are defined above */
+ private static final String[] CONFIG_KEYS = {Config.KEY_EXIFTOOL_PATH, Config.KEY_GPSBABEL_PATH, Config.KEY_GNUPLOT_PATH};
+ /** Verification flags for the tools in the order defined above */
+ private static final String[] VERIFY_FLAGS = {"-v", "-V", "-V"};
- /**
- * Attempt to call Povray to see if it's installed / available in path
- * @return true if found, false otherwise
- */
- public static boolean isPovrayInstalled()
- {
- return check("povray");
- }
-
-
- /**
- * Attempt to call Exiftool to see if it's installed / available in path
- * @return true if found, false otherwise
- */
- public static boolean isExiftoolInstalled()
- {
- return check("exiftool -v");
- }
/**
- * Attempt to call gpsbabel to see if it's installed / available in path
- * @return true if found, false otherwise
+ * Check if the selected tool is installed
+ * @param inToolNum number of tool, from constants
+ * @return true if selected tool is installed
*/
- public static boolean isGpsbabelInstalled()
+ public static boolean isToolInstalled(int inToolNum)
{
- return check("gpsbabel -V");
+ switch (inToolNum) {
+ case TOOL_EXIFTOOL:
+ case TOOL_GPSBABEL:
+ case TOOL_GNUPLOT:
+ String toolPath = Config.getConfigString(CONFIG_KEYS[inToolNum]);
+ if (toolPath != null && toolPath.length() > 0) {
+ return check(toolPath + " " + VERIFY_FLAGS[inToolNum]);
+ }
+ }
+ // Not found
+ return false;
}
/**
- * Attempt to call gnuplot to see if it's installed / available in path
- * @return true if found, false otherwise
+ * Check if the selected tool is installed using the given path
+ * @param inToolNum number of tool, from constants
+ * @param inPath selected path to use instead of configured one
+ * @return true if selected tool is installed
*/
- public static boolean isGnuplotInstalled()
+ public static boolean isToolInstalled(int inToolNum, String inPath)
{
- return check(Config.getGnuplotPath() + " -V");
+ if (inPath == null || inPath.equals("")) {return false;}
+ switch (inToolNum) {
+ case TOOL_EXIFTOOL:
+ case TOOL_GPSBABEL:
+ case TOOL_GNUPLOT:
+ return check(inPath + " " + VERIFY_FLAGS[inToolNum]);
+ }
+ // Not found
+ return false;
}
/**
*/
private static boolean check(String inCommand)
{
+ // System.out.println("Checking tool '" + inCommand + "'");
try
{
Runtime.getRuntime().exec(inCommand);
import tim.prune.correlate.PhotoCorrelator;
import tim.prune.function.AboutScreen;
+import tim.prune.function.AddAltitudeOffset;
import tim.prune.function.AddTimeOffset;
import tim.prune.function.CheckVersionScreen;
+import tim.prune.function.FindWaypoint;
import tim.prune.function.HelpScreen;
import tim.prune.function.RearrangeWaypointsFunction;
+import tim.prune.function.SaveConfig;
+import tim.prune.function.SetKmzImageSize;
import tim.prune.function.SetMapBgFunction;
+import tim.prune.function.ShowKeysScreen;
import tim.prune.function.ShowThreeDFunction;
import tim.prune.function.charts.Charter;
import tim.prune.function.compress.CompressTrackFunction;
import tim.prune.function.distance.DistanceFunction;
+import tim.prune.function.edit.PointNameEditor;
+import tim.prune.function.gpsies.GetGpsiesFunction;
+import tim.prune.function.SetPathsFunction;
import tim.prune.load.GpsLoader;
import tim.prune.save.GpsSaver;
import tim.prune.save.GpxExporter;
public static PovExporter FUNCTION_POVEXPORT = null;
public static GenericFunction FUNCTION_GPSLOAD = null;
public static GenericFunction FUNCTION_GPSSAVE = null;
+ public static GenericFunction FUNCTION_SAVECONFIG = null;
+ public static GenericFunction FUNCTION_EDIT_WAYPOINT_NAME = null;
public static RearrangeWaypointsFunction FUNCTION_REARRANGE_WAYPOINTS = null;
public static GenericFunction FUNCTION_COMPRESS = null;
public static GenericFunction FUNCTION_ADD_TIME_OFFSET = null;
+ public static GenericFunction FUNCTION_ADD_ALTITUDE_OFFSET = null;
+ public static GenericFunction FUNCTION_FIND_WAYPOINT = null;
public static GenericFunction FUNCTION_CORRELATE_PHOTOS = null;
public static GenericFunction FUNCTION_CHARTS = null;
public static GenericFunction FUNCTION_3D = null;
public static GenericFunction FUNCTION_DISTANCES = null;
+ public static GenericFunction FUNCTION_GET_GPSIES = null;
public static GenericFunction FUNCTION_SET_MAP_BG = null;
+ public static GenericFunction FUNCTION_SET_PATHS = null;
+ public static GenericFunction FUNCTION_SET_KMZ_IMAGE_SIZE = null;
public static GenericFunction FUNCTION_HELP = null;
+ public static GenericFunction FUNCTION_SHOW_KEYS = null;
public static GenericFunction FUNCTION_ABOUT = null;
public static GenericFunction FUNCTION_CHECK_VERSION = null;
FUNCTION_POVEXPORT = new PovExporter(inApp);
FUNCTION_GPSLOAD = new GpsLoader(inApp);
FUNCTION_GPSSAVE = new GpsSaver(inApp);
+ FUNCTION_SAVECONFIG = new SaveConfig(inApp);
+ FUNCTION_EDIT_WAYPOINT_NAME = new PointNameEditor(inApp);
FUNCTION_REARRANGE_WAYPOINTS = new RearrangeWaypointsFunction(inApp);
FUNCTION_COMPRESS = new CompressTrackFunction(inApp);
FUNCTION_ADD_TIME_OFFSET = new AddTimeOffset(inApp);
+ FUNCTION_ADD_ALTITUDE_OFFSET = new AddAltitudeOffset(inApp);
+ FUNCTION_FIND_WAYPOINT = new FindWaypoint(inApp);
FUNCTION_CORRELATE_PHOTOS = new PhotoCorrelator(inApp);
FUNCTION_CHARTS = new Charter(inApp);
FUNCTION_3D = new ShowThreeDFunction(inApp);
FUNCTION_DISTANCES = new DistanceFunction(inApp);
+ FUNCTION_GET_GPSIES = new GetGpsiesFunction(inApp);
FUNCTION_SET_MAP_BG = new SetMapBgFunction(inApp);
+ FUNCTION_SET_PATHS = new SetPathsFunction(inApp);
+ FUNCTION_SET_KMZ_IMAGE_SIZE = new SetKmzImageSize(inApp);
FUNCTION_HELP = new HelpScreen(inApp);
+ FUNCTION_SHOW_KEYS = new ShowKeysScreen(inApp);
FUNCTION_ABOUT = new AboutScreen(inApp);
FUNCTION_CHECK_VERSION= new CheckVersionScreen(inApp);
}
import java.awt.BorderLayout;
import java.awt.event.WindowEvent;
import java.io.File;
+import java.io.FileNotFoundException;
import java.util.Locale;
+import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;
import tim.prune.gui.ProfileChart;
import tim.prune.gui.SelectorDisplay;
import tim.prune.gui.StatusBar;
+import tim.prune.gui.Viewport;
import tim.prune.gui.map.MapCanvas;
/**
public class GpsPruner
{
/** Version number of application, used in about screen and for version check */
- public static final String VERSION_NUMBER = "7";
+ public static final String VERSION_NUMBER = "8";
/** Build number, just used for about screen */
- public static final String BUILD_NUMBER = "136";
+ public static final String BUILD_NUMBER = "155";
/** Static reference to App object */
private static App APP = null;
public static void main(String[] args)
{
Locale locale = null;
+ String localeCode = null;
String langFilename = null;
String configFilename = null;
+ ArrayList<File> dataFiles = new ArrayList<File>();
boolean showUsage = false;
for (int i=0; i<args.length; i++)
{
String arg = args[i];
if (arg.startsWith("--locale="))
{
- locale = getLanguage(arg.substring(9));
+ localeCode = arg.substring(9);
+ locale = getLanguage(localeCode);
}
else if (arg.startsWith("--lang="))
{
- locale = getLanguage(arg.substring(7));
+ localeCode = arg.substring(7);
+ locale = getLanguage(localeCode);
}
else if (arg.startsWith("--langfile="))
{
{
configFilename = arg.substring(13);
}
+ else if (arg.startsWith("--help")) {
+ showUsage = true;
+ }
else
{
- if (!arg.startsWith("--help")) {
+ // Check if a data file has been given
+ File f = new File(arg);
+ if (f.exists() && f.canRead()) {
+ dataFiles.add(f);
+ }
+ else {
System.out.println("Unknown parameter '" + arg + "'.");
+ showUsage = true;
}
- showUsage = true;
}
}
if (showUsage) {
catch (ConfigException ce) {
System.err.println("Failed to load config file: " + configFilename);
}
- // Set locale according to Config's language property
- String langCode = Config.getLanguageCode();
- if (locale == null && langCode != null) {
- Locale configLocale = getLanguage(langCode);
- if (configLocale != null) {locale = configLocale;}
+ if (locale != null) {
+ // Make sure Config holds chosen language
+ Config.setConfigString(Config.KEY_LANGUAGE_CODE, localeCode);
+ }
+ else {
+ // Set locale according to Config's language property
+ String configLang = Config.getConfigString(Config.KEY_LANGUAGE_CODE);
+ if (configLang != null) {
+ Locale configLocale = getLanguage(configLang);
+ if (configLocale != null) {locale = configLocale;}
+ }
}
I18nManager.init(locale);
if (langFilename != null) {
- I18nManager.addLanguageFile(langFilename);
+ try {
+ I18nManager.addLanguageFile(langFilename);
+ }
+ catch (FileNotFoundException fnfe) {
+ System.err.println("Failed to load language file: " + langFilename);
+ }
}
// Set up the window and go
- launch();
+ launch(dataFiles);
}
/**
* Launch the main application
+ * @param inDataFiles list of data files to load on startup
*/
- private static void launch()
+ private static void launch(ArrayList<File> inDataFiles)
{
JFrame frame = new JFrame("Prune");
APP = new App(frame);
UpdateMessageBroker.addSubscriber(rightPanel);
MapCanvas mapDisp = new MapCanvas(APP, APP.getTrackInfo());
UpdateMessageBroker.addSubscriber(mapDisp);
+ Viewport viewport = new Viewport(mapDisp);
+ APP.setViewport(viewport);
ProfileChart profileDisp = new ProfileChart(APP.getTrackInfo());
UpdateMessageBroker.addSubscriber(profileDisp);
StatusBar statusBar = new StatusBar();
frame.setVisible(true);
// Set position of map/profile splitter
midPane.setDividerLocation(0.75);
+
+ // Finally, give the files to load to the App
+ APP.loadDataFiles(inDataFiles);
}
}
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Locale;
import java.util.MissingResourceException;
EnglishTexts = ResourceBundle.getBundle(BUNDLE_NAME, BACKUP_LOCALE);
// Get bundle for selected locale, if any
- if (inLocale != null)
+ try
{
- LocalTexts = ResourceBundle.getBundle(BUNDLE_NAME, inLocale);
+ if (inLocale != null)
+ {
+ LocalTexts = ResourceBundle.getBundle(BUNDLE_NAME, inLocale);
+ }
+ else
+ {
+ // locale is null so just use the system default
+ LocalTexts = ResourceBundle.getBundle(BUNDLE_NAME, Locale.getDefault());
+ }
}
- else
- {
- // locale is null so just use the system default
- LocalTexts = ResourceBundle.getBundle(BUNDLE_NAME, Locale.getDefault());
+ catch (MissingResourceException mre) { // ignore error, default to english
}
}
/**
* Add a language file
* @param inFilename filename of file
+ * @throws FileNotFoundException if load failed
*/
- public static void addLanguageFile(String inFilename)
+ public static void addLanguageFile(String inFilename) throws FileNotFoundException
{
FileInputStream fis = null;
+ boolean fileLoaded = false;
try
{
File file = new File(inFilename);
ExternalPropsFile = new Properties();
fis = new FileInputStream(file);
ExternalPropsFile.load(fis);
+ fileLoaded = true; // everything worked
}
catch (IOException ioe) {}
finally { try { fis.close();
} catch (Exception e) {}
}
+ // complain if file wasn't loaded, by throwing a filenotfound exception
+ if (!fileLoaded) throw new FileNotFoundException();
}
+++ /dev/null
-
-== Prune configuration ==
-=========================
-
-Starting with version 6 of Prune, it's possible to create a configuration file which controls a few basic configuration options. Currently there isn't a nice gui to let you select these options, although this may be added in the future. Instead, you can just create a text file with the configuration, and save it with any regular text editor. Then Prune will load these options when it starts up.
-
-== File location ==
-By default, Prune will try to load a file called .pruneconfig from the current directory (note the dot at the start of the filename). If this file isn't there, it doesn't matter, it'll just be ignored and Prune will use default settings as before. The file won't be created for you if it doesn't exist.
-If you create this file in your home directory and you also launch Prune from the same directory, Prune will find the file and use whatever configuration is specified inside.
-
-If you want to use another location for this file, or another name, you'll have to tell Prune where it is. You can do this with an extra commandline parameter, like this:
- java -jar prune.jar --configfile=h:/gps/pruneconfig.txt
-You can obviously set this in any shortcuts or aliases that you're currently using so you don't have to type it in every time. If you specify a file like this and Prune can't find it or can't read it, you'll get a warning message in the console.
-
-== File structure ==
-The configuration file is a simple text file, so you can edit it with any editor like Notepad, Kate or gedit. Each line in the file represents a configuration setting, with the format:
- key=value
-The key should match one of the recognised keys given below. Any unrecognised keys will just be ignored.
-The file can contain any number of settings, in any order. You can have just one in there or all possible settings.
-
-== Possible configuration settings ==
-The following settings can be defined in the file, in any order:
-
-== Working directory ==
-This setting defines the default directory when you start Prune. If your track files are always in a certain directory, you can set this here so that Prune starts from that directory. Example:
- prune.directory=/home/user/gps/
-
-== Language code ==
-This setting defines the language to use for Prune's interface. By default, Prune will try to use the language set in your system. If you use the --lang= command line parameter, you can override this to use a different one. Or you can put a line in your configuration file to define it there instead. Possible codes are currently EN, DE, DE_ch, ES, FR, IT and PL. Example:
- prune.languagecode=ES
-If you use the --lang= command line parameter, this takes priority over what's in the configuration file.
-
-== Metric/imperial units ==
-By default Prune uses metric units, displaying altitudes in metres and distances in kilometres. This setting allows you to specify whether you want metric or imperial units by default. Example:
- prune.metricunits=n
-By using a value of "n" (for "no"), Prune then displays values in imperial units of feet and miles.
-
-== Povray font ==
-When Prune exports to Pov format, it specifies a font to use for the cardinals N, S, E, W. Usually this is "crystal.ttf" because this comes as standard with povray. This setting allows you to change that default if you always want to use a specific font installed on your system. Example:
- prune.povrayfont=DejaVuSans-Bold.ttf
-The available fonts will depend on what you have installed. See the povray documentation for more on this.
-
-== GPS device ==
-When Prune invokes Gpsbabel to load data, it needs to specify the GPS device to load from. The name of this will depend on your GPS receiver and your connection (eg serial/usb). If you call gpsbabel from the command line, it's the -f parameter. This setting allows you to specify the default value used by Prune when you select the load from gps function. Example:
- prune.gpsdevice=usb:
-A GPS connected to the serial port may appear as /dev/ttyS0.
-
-== GPS format ==
-This setting controls the default value of the format parameter to gpsbabel. If you call gpsbabel from the command line, it's the -i parameter. Example:
- prune.gpsformat=garmin
-
-== Gnuplot path ==
-On linux systems this setting is unnecessary as the gnuplot executable will be found in /usr/bin but on Windows the executable must be called pgnuplot (with an extra p) and may not be in the system path. This setting controls the default location searched to call gnuplot.
- prune.gnuplotpath=gnuplot
-
-== Map server ==
-The default map tile server is called Mapnik and shows the maps just like they are in openstreetmap.org. The following two settings allow other tile servers to be used by default. The settings are the same as in the dialog View -> Set map background.
-The "mapserverindex" parameter is a number from 0 to 3, where 0=Mapnik, 1=Osma, 2=Opencyclemap and 3=Other. If the mapserverindex is set to 3, Prune will use the URL given by the "mapserverurl" parameter.
- prune.mapserverindex=3
- prune.mapserverurl=http://openpistemap.org/tiles/contours/
-
-== Example file ==
-The following can be used as a template to make your own file.
-
-# Prune configuration file
-prune.directory=/home/user/gps/
-prune.languagecode=EN
-prune.metricunits=y
-prune.povrayfont=crystal.ttf
-prune.gpsdevice=usb:
-prune.gpsformat=garmin
-prune.gnuplotpath=gnuplot
-prune.mapserverindex=3
-prune.mapserverurl=http://openpistemap.org/tiles/contours/
public PhotoCorrelator(App inApp)
{
super(inApp);
- _dialog = new JDialog(inApp.getFrame(), I18nManager.getText(getNameKey()), true);
- _dialog.setLocationRelativeTo(inApp.getFrame());
- _dialog.getContentPane().add(makeDialogContents());
- _dialog.pack();
}
*/
public void begin()
{
+ // First create dialog if necessary
+ if (_dialog == null)
+ {
+ _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+ _dialog.setLocationRelativeTo(_parentFrame);
+ _dialog.getContentPane().add(makeDialogContents());
+ _dialog.pack();
+ }
// Check whether track has timestamps, exit if not
if (!_app.getTrackInfo().getTrack().hasData(Field.TIMESTAMP))
{
_pointLaterOption.setSelected(!inTimeDiff.getIsPositive());
createPreview(inTimeDiff, true);
CardLayout cl = (CardLayout) _cards.getLayout();
- cl.next(_cards);
+ cl.last(_cards);
_backButton.setEnabled(hasTimeDiff);
_nextButton.setEnabled(false);
// enable ok button if any photos have been selected
*/
public Object getValueAt(int inRowIndex, int inColumnIndex)
{
- // TODO: only show time of photos (not date) if dates all identical
+ // MAYBE: only show time of photos (not date) if dates all identical
PhotoSelectionTableRow row = _list.get(inRowIndex);
if (inColumnIndex == 0) return row.getPhoto().getFile().getName();
else if (inColumnIndex == 1) return row.getPhoto().getTimestamp().getText();
_valid = true;
}
+ /**
+ * @return an exact copy of this Altitude object
+ */
+ public Altitude clone()
+ {
+ return new Altitude(_stringValue, _format);
+ }
+
+ /**
+ * Reset the altitude parameters to the same as the given object
+ * @param inClone clone object to copy
+ */
+ public void reset(Altitude inClone)
+ {
+ _value = inClone._value;
+ _format = inClone._format;
+ _valid = inClone._valid;
+ }
/**
* @return true if the value could be parsed
public String getStringValue(Format inFormat)
{
if (!_valid) {return "";}
- if (inFormat == _format && _stringValue != null && !_stringValue.equals("")) {
+ // Return string value if the same format or "no format" was requested
+ if ((inFormat == _format || inFormat == Format.NO_FORMAT)
+ && _stringValue != null && !_stringValue.equals("")) {
return _stringValue;
}
return "" + getValue(inFormat);
int newValue = startValue + (int) ((endValue - startValue) * inFrac);
return new Altitude(newValue, altFormat);
}
+
+ /**
+ * Add the given offset to the current altitude
+ * @param inOffset offset as double
+ * @param inFormat format of offset, feet or metres
+ * @param inDecimals number of decimal places
+ */
+ public void addOffset(double inOffset, Format inFormat, int inDecimals)
+ {
+ // Use the maximum number of decimal places from current value and offset
+ int numDecimals = NumberUtils.getDecimalPlaces(_stringValue);
+ if (numDecimals < inDecimals) {numDecimals = inDecimals;}
+ // Convert offset to correct units
+ double offset = inOffset;
+ if (inFormat != _format)
+ {
+ if (inFormat == Format.FEET)
+ offset = inOffset * CONVERT_FEET_TO_METRES;
+ else
+ offset = inOffset * CONVERT_METRES_TO_FEET;
+ }
+ // Add the offset
+ double newValue = Double.parseDouble(_stringValue.trim()) + offset;
+ _value = (int) newValue;
+ _stringValue = NumberUtils.formatNumber(newValue, numDecimals);
+ }
}
char currChar;
long[] fields = new long[4]; // needs to be long for lengthy decimals
long[] denoms = new long[4];
- String secondDelim = "";
+ boolean[] otherDelims = new boolean[5]; // remember whether delimiters have non-decimal chars
try
{
// Loop over characters in input string, populating fields array
else
{
inNumeric = false;
- // Remember second delimiter
- if (numFields == 2) {
- secondDelim += currChar;
- }
+ // Remember delimiters
+ if (currChar != ',' && currChar != '.') {otherDelims[numFields] = true;}
}
}
_valid = (numFields > 0);
_fracDenom = 10;
if (numFields == 2)
{
- // String is just decimal degrees
- double numMins = fields[1] * 60.0 / denoms[1];
- _minutes = (int) numMins;
- double numSecs = (numMins - _minutes) * 60.0;
- _seconds = (int) numSecs;
- _fracs = (int) ((numSecs - _seconds) * 10);
- _asDouble = _degrees + 1.0 * fields[1] / denoms[1];
+ if (!otherDelims[1])
+ {
+ // String is just decimal degrees
+ double numMins = fields[1] * 60.0 / denoms[1];
+ _minutes = (int) numMins;
+ double numSecs = (numMins - _minutes) * 60.0;
+ _seconds = (int) numSecs;
+ _fracs = (int) ((numSecs - _seconds) * 10);
+ _asDouble = _degrees + 1.0 * fields[1] / denoms[1];
+ }
+ else
+ {
+ // String is degrees and minutes (due to non-decimal separator)
+ _originalFormat = FORMAT_DEG_MIN;
+ _minutes = (int) fields[1];
+ _seconds = 0;
+ _fracs = 0;
+ _asDouble = 1.0 * _degrees + (_minutes / 60.0);
+ }
}
// Differentiate between d-m.f and d-m-s using . or ,
- else if (numFields == 3 && (secondDelim.equals(".") || secondDelim.equals(",")))
+ else if (numFields == 3 && !otherDelims[2])
{
// String is degrees-minutes.fractions
_originalFormat = FORMAT_DEG_MIN;
{
StringBuffer buffer = new StringBuffer();
buffer.append(PRINTABLE_CARDINALS[_cardinal])
- .append(threeDigitString(_degrees)).append('°')
+ .append(threeDigitString(_degrees)).append('\u00B0')
.append(twoDigitString(_minutes)).append('\'')
.append(twoDigitString(_seconds)).append('.')
.append(formatFraction(_fracs, _fracDenom));
}
case FORMAT_DEG_MIN:
{
- answer = "" + PRINTABLE_CARDINALS[_cardinal] + threeDigitString(_degrees) + "°"
+ answer = "" + PRINTABLE_CARDINALS[_cardinal] + threeDigitString(_degrees) + "\u00B0"
+ (_minutes + _seconds / 60.0 + _fracs / 60.0 / _fracDenom) + "'";
break;
}
case FORMAT_DEG_WHOLE_MIN:
{
- answer = "" + PRINTABLE_CARDINALS[_cardinal] + threeDigitString(_degrees) + "°"
+ answer = "" + PRINTABLE_CARDINALS[_cardinal] + threeDigitString(_degrees) + "\u00B0"
+ (int) Math.floor(_minutes + _seconds / 60.0 + _fracs / 60.0 / _fracDenom + 0.5) + "'";
break;
}
}
else {
// use default altitude format from config
- parseFields(inField, Config.getUseMetricUnits()?Altitude.Format.METRES:Altitude.Format.FEET);
+ parseFields(inField, Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?Altitude.Format.METRES:Altitude.Format.FEET);
}
}
// default kilometres
return inDist / EARTH_RADIUS_KM;
}
+
+ /**
+ * Convert the given distance from metres to miles
+ * @param inMetres number of metres
+ * @return number of miles
+ */
+ public static double convertMetresToMiles(double inMetres)
+ {
+ return inMetres / 1000.0 * CONVERT_KM_TO_MILES;
+ }
}
public static final Field WAYPT_TYPE = new Field("fieldname.waypointtype", FieldType.NONE);
public static final Field NEW_SEGMENT = new Field("fieldname.newsegment", FieldType.BOOL);
+ // TODO: Field for photo filename, ability to load (from text) and save (to text)
+
private static final Field[] ALL_AVAILABLE_FIELDS = {
LATITUDE, LONGITUDE, ALTITUDE, TIMESTAMP, WAYPT_NAME, WAYPT_TYPE, NEW_SEGMENT,
new Field("fieldname.custom", FieldType.NONE)
*/
public class FieldList
{
+ /** Array of Field objects making the list */
private Field[] _fieldArray;
/**
- * Check whether the FieldList contains the given
- * Field object
+ * Check whether the FieldList contains the given Field object
* @param inField Field to check
* @return true if the FieldList contains the given field
*/
{
_latRange = inLatRange;
_lonRange = inLonRange;
- // TODO: Expand range by certain percentage
+ // MAYBE: Expand range by certain percentage
}
/**
--- /dev/null
+package tim.prune.data;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+/**
+ * Abstract class to offer general number manipulation functions
+ */
+public abstract class NumberUtils
+{
+ /** Number formatter object to avoid lots of instantiations */
+ private static final NumberFormat NUM_FORMATTER = NumberFormat.getNumberInstance(Locale.UK);
+ // Select the UK locale for this formatter so that decimal point is always used (not comma)
+ static {
+ if (NUM_FORMATTER instanceof DecimalFormat) ((DecimalFormat) NUM_FORMATTER).applyPattern("0.000");
+ }
+
+ /**
+ * Find the number of decimal places represented in the String
+ * @param inString String to check
+ * @return number of decimal places, or 0 for integer value
+ */
+ public static int getDecimalPlaces(String inString)
+ {
+ if (inString == null || inString.equals("")) {return 0;}
+ int places = 0;
+ final int sLen = inString.length();
+ for (int i=sLen-1; i>=0; i--) {
+ char c = inString.charAt(i);
+ if (c >= '0' && c <= '9') {
+ // Numeric character found
+ places++;
+ }
+ else {
+ // Non-numeric character found, return places
+ return places;
+ }
+ }
+ // No non-numeric characters found, so must be integer
+ return 0;
+ }
+
+ /**
+ * Format the given number to the given number of decimal places
+ * @param inNumber double number to format
+ * @param inDecimalPlaces number of decimal places
+ */
+ public static String formatNumber(double inNumber, int inDecimalPlaces)
+ {
+ NUM_FORMATTER.setMaximumFractionDigits(inDecimalPlaces);
+ NUM_FORMATTER.setMinimumFractionDigits(inDecimalPlaces);
+ return NUM_FORMATTER.format(inNumber);
+ }
+}
\ No newline at end of file
_currentStatus = inStatus;
}
+ /**
+ * @return true if photo is connected to a point
+ */
+ public boolean isConnected()
+ {
+ return _currentStatus != Status.NOT_CONNECTED;
+ }
+
/**
* @return byte array of thumbnail data
*/
private Altitude.Format _altitudeFormat = Altitude.Format.NO_FORMAT;
private long _totalSeconds = 0L, _movingSeconds = 0L;
private double _angDistance = -1.0, _angMovingDistance = -1.0;
+ private boolean _multipleSegments = false;
/**
/**
- * Reset selection to be recalculated
+ * Mark selection invalid so it will be recalculated
*/
- private void reset()
+ public void markInvalid()
{
_valid = false;
}
- /**
- * Select the point at the given index
- * @param inIndex index number of selected point
- */
- public void selectPoint(int inIndex)
- {
- if (inIndex >= -1)
- {
- _currentPoint = inIndex;
- check();
- }
- }
-
- /**
- * Select the specified point and range in one go
- * @param inPointIndex point selection
- * @param inStart range start
- * @param inEnd range end
- */
- public void select(int inPointIndex, int inStart, int inEnd)
- {
- _currentPoint = inPointIndex;
- _startIndex = inStart;
- _endIndex = inEnd;
- reset();
- check();
- }
-
-
- /**
- * Select the previous point
- */
- public void selectPreviousPoint()
- {
- if (_currentPoint > 0)
- selectPoint(_currentPoint - 1);
- }
-
- /**
- * Select the next point
- */
- public void selectNextPoint()
- {
- selectPoint(_currentPoint + 1);
- }
-
/**
* @return the current point index
*/
private void recalculate()
{
_altitudeFormat = Altitude.Format.NO_FORMAT;
+ _multipleSegments = false;
if (_track.getNumPoints() > 0 && hasRangeSelected())
{
_altitudeRange = new IntegerRange();
{
double radians = DataPoint.calculateRadiansBetween(lastPoint, currPoint);
_angDistance += radians;
- if (!currPoint.getSegmentStart()) {
+ if (currPoint.getSegmentStart()) {
+ _multipleSegments = true;
+ }
+ else {
_angMovingDistance += radians;
}
}
}
/**
- * Clear selected point and range
+ * @return true if track has multiple segments
+ */
+ public boolean getHasMultipleSegments()
+ {
+ return _multipleSegments;
+ }
+
+ /**
+ * Clear selected point, range and photo
*/
public void clearAll()
{
_currentPoint = -1;
- deselectRange();
- deselectPhoto();
+ selectRange(-1, -1);
+ _currentPhotoIndex = -1;
+ check();
}
/**
* Deselect range
+ * @param inStartIndex index of start of range
+ * @param inEndIndex index of end of range
*/
- public void deselectRange()
+ public void selectRange(int inStartIndex, int inEndIndex)
{
- _startIndex = _endIndex = -1;
- reset();
+ _startIndex = inStartIndex;
+ _endIndex = inEndIndex;
+ markInvalid();
check();
}
* Set the index for the start of the range selection
* @param inStartIndex start index
*/
- public void selectRangeStart(int inStartIndex)
+ private void selectRangeStart(int inStartIndex)
{
if (inStartIndex < 0)
{
_endIndex = _track.getNumPoints() - 1;
}
}
- reset();
+ markInvalid();
UpdateMessageBroker.informSubscribers();
}
{
_endIndex = inEndIndex;
// Move start of selection to min if necessary
- if (_startIndex > _endIndex || _startIndex < 0)
- {
+ if (_startIndex > _endIndex || _startIndex < 0) {
_startIndex = 0;
}
}
- reset();
+ markInvalid();
UpdateMessageBroker.informSubscribers();
}
_endIndex--;
if (_currentPoint < _startIndex)
_startIndex--;
- reset();
+ markInvalid();
}
check();
}
- /**
- * Deselect photo
- */
- public void deselectPhoto()
- {
- _currentPhotoIndex = -1;
- check();
- }
-
-
/**
* Select the specified photo and point
* @param inPhotoIndex index of selected photo in PhotoList
public void selectPhotoAndPoint(int inPhotoIndex, int inPointIndex)
{
_currentPhotoIndex = inPhotoIndex;
- if (inPointIndex > -1)
- {
- // select associated point, if any
- selectPoint(inPointIndex);
- }
- else
- {
- // Check if not already done
- check();
- }
+ _currentPoint = inPointIndex;
+ check();
}
private double[] _yValues = null;
private boolean _scaled = false;
private int _numPoints = 0;
- private boolean _mixedData = false;
+ private boolean _hasTrackpoint = false;
+ private boolean _hasWaypoint = false;
// Master field list
private FieldList _masterFieldList = null;
// variable ranges
for (int i=0; i<_numPoints; i++)
{
DataPoint point = _dataPoints[i];
- // Don't delete waypoints or photo points
- if (point.isWaypoint() || point.getPhoto() != null || !point.getDeleteFlag())
+ // Don't delete photo points
+ if (point.getPhoto() != null || !point.getDeleteFlag())
{
newPointArray[numCopied] = point;
numCopied++;
return foundTimestamp;
}
-
/**
- * Merge the track segments within the given range
- * @param inStart start index
- * @param inEnd end index
- * @return true if successful
+ * Add the given altitude offset to the specified range
+ * @param inStart start of range
+ * @param inEnd end of range
+ * @param inOffset offset to add (-ve to subtract)
+ * @param inFormat altitude format of offset
+ * @param inDecimals number of decimal places in offset
+ * @return true on success
*/
- public boolean mergeTrackSegments(int inStart, int inEnd)
+ public boolean addAltitudeOffset(int inStart, int inEnd, double inOffset,
+ Altitude.Format inFormat, int inDecimals)
{
- boolean firstTrackPoint = true;
- // Loop between start and end
- for (int i=inStart; i<=inEnd; i++) {
- DataPoint point = getPoint(i);
- // Set all segments to false apart from first track point
- if (point != null && !point.isWaypoint()) {
- point.setSegmentStart(firstTrackPoint);
- firstTrackPoint = false;
+ // sanity check
+ if (inStart < 0 || inEnd < 0 || inStart >= inEnd || inEnd >= _numPoints) {
+ return false;
+ }
+ boolean foundAlt = false;
+ // Loop over all points within range
+ for (int i=inStart; i<=inEnd; i++)
+ {
+ Altitude alt = _dataPoints[i].getAltitude();
+ if (alt != null && alt.isValid())
+ {
+ // This point has an altitude so add the offset to it
+ foundAlt = true;
+ alt.addOffset(inOffset, inFormat, inDecimals);
}
}
- // Find following track point, if any
- DataPoint nextPoint = getNextTrackPoint(inEnd+1);
- if (nextPoint != null) {nextPoint.setSegmentStart(true);}
- UpdateMessageBroker.informSubscribers();
- return true;
+ // needs to be scaled again
+ _scaled = false;
+ return foundAlt;
}
+ // TODO: Function to collect and sort photo points by time or photo filename
+ // TODO: Function to convert waypoint names into timestamps
+
/**
* Collect all waypoints to the start or end of the track
* @param inAtStart true to collect at start, false for end
*/
public boolean cutAndMoveSection(int inSectionStart, int inSectionEnd, int inMoveTo)
{
+ // TODO: Move cut/move into separate function?
// Check that indices make sense
- if (inSectionStart > 0 && inSectionEnd > inSectionStart && inMoveTo > 0
+ if (inSectionStart > 0 && inSectionEnd > inSectionStart && inMoveTo >= 0
&& (inMoveTo < inSectionStart || inMoveTo > (inSectionEnd+1)))
{
// do the cut and move
{
int sectionLength = inSectionEnd - inSectionStart + 1;
// move section to earlier point
- if (inMoveTo > 0)
+ if (inMoveTo > 0) {
System.arraycopy(_dataPoints, 0, newPointArray, 0, inMoveTo); // unchanged points before
+ }
System.arraycopy(_dataPoints, inSectionStart, newPointArray, inMoveTo, sectionLength); // moved bit
// after insertion point, before moved bit
- if (inSectionStart > (inMoveTo + 1))
- System.arraycopy(_dataPoints, inMoveTo, newPointArray, inMoveTo + sectionLength, inSectionStart - inMoveTo);
+ System.arraycopy(_dataPoints, inMoveTo, newPointArray, inMoveTo + sectionLength, inSectionStart - inMoveTo);
// after moved bit
- if (inSectionEnd < (_numPoints - 1))
+ if (inSectionEnd < (_numPoints - 1)) {
System.arraycopy(_dataPoints, inSectionEnd+1, newPointArray, inSectionEnd+1, _numPoints - inSectionEnd - 1);
+ }
}
else
{
// Move section to later point
- if (inSectionStart > 0)
+ if (inSectionStart > 0) {
System.arraycopy(_dataPoints, 0, newPointArray, 0, inSectionStart); // unchanged points before
+ }
// from end of section to move to point
- if (inMoveTo > (inSectionEnd + 1))
+ if (inMoveTo > (inSectionEnd + 1)) {
System.arraycopy(_dataPoints, inSectionEnd+1, newPointArray, inSectionStart, inMoveTo - inSectionEnd - 1);
+ }
// moved bit
System.arraycopy(_dataPoints, inSectionStart, newPointArray, inSectionStart + inMoveTo - inSectionEnd - 1,
inSectionEnd - inSectionStart + 1);
// unchanged bit after
- if (inSectionEnd < (_numPoints - 1))
+ if (inSectionEnd < (_numPoints - 1)) {
System.arraycopy(_dataPoints, inMoveTo, newPointArray, inMoveTo, _numPoints - inMoveTo);
+ }
}
// Copy array references
_dataPoints = newPointArray;
double latitudeDiff = 0.0, longitudeDiff = 0.0;
double totalAltitude = 0;
int numAltitudes = 0;
- Altitude.Format altFormat = Config.getUseMetricUnits()?Altitude.Format.METRES:Altitude.Format.FEET;
+ Altitude.Format altFormat = Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?Altitude.Format.METRES:Altitude.Format.FEET;
// loop between start and end points
for (int i=inStartIndex; i<= inEndIndex; i++)
{
if (!_scaled) scalePoints();
return _altitudeRange;
}
+
/**
* @return the number of (valid) points in the track
*/
*/
public boolean hasData(Field inField)
{
+ // Don't use this method for altitudes
+ if (inField.equals(Field.ALTITUDE)) {return hasAltitudeData();}
return hasData(inField, 0, _numPoints-1);
}
return false;
}
+ /**
+ * @return true if track has altitude data (which are not all zero)
+ */
+ public boolean hasAltitudeData()
+ {
+ return getAltitudeRange().getMaximum() > 0;
+ }
+
+ /**
+ * @return true if track contains at least one trackpoint
+ */
+ public boolean hasTrackPoints()
+ {
+ if (!_scaled) scalePoints();
+ return _hasTrackpoint;
+ }
/**
- * @return true if track contains waypoints and trackpoints
+ * @return true if track contains waypoints
*/
- public boolean hasMixedData()
+ public boolean hasWaypoints()
{
if (!_scaled) scalePoints();
- return _mixedData;
+ return _hasWaypoint;
}
/**
_latRange = new DoubleRange();
_altitudeRange = new AltitudeRange();
int p;
- boolean hasWaypoint = false, hasTrackpoint = false;
+ _hasWaypoint = false; _hasTrackpoint = false;
for (p=0; p < getNumPoints(); p++)
{
DataPoint point = getPoint(p);
_altitudeRange.addValue(point.getAltitude());
}
if (point.isWaypoint())
- hasWaypoint = true;
+ _hasWaypoint = true;
else
- hasTrackpoint = true;
+ _hasTrackpoint = true;
}
}
- _mixedData = hasWaypoint && hasTrackpoint;
// Loop over points and calculate scales
_xValues = new double[getNumPoints()];
for (int i=0; i<numEdits; i++)
{
FieldEdit edit = inEditList.getEdit(i);
- inPoint.setFieldValue(edit.getField(), edit.getValue());
+ Field editField = edit.getField();
+ inPoint.setFieldValue(editField, edit.getValue());
+ // Check that master field list has this field already (maybe point name has been added)
+ if (!_masterFieldList.contains(editField)) {
+ _masterFieldList.extendList(editField);
+ }
// check coordinates
- coordsChanged |= (edit.getField().equals(Field.LATITUDE)
- || edit.getField().equals(Field.LONGITUDE) || edit.getField().equals(Field.ALTITUDE));
+ coordsChanged |= (editField.equals(Field.LATITUDE)
+ || editField.equals(Field.LONGITUDE) || editField.equals(Field.ALTITUDE));
}
// set photo status if coordinates have changed
if (inPoint.getPhoto() != null && coordsChanged)
return _track.cloneRange(_selection.getStart(), _selection.getEnd());
}
+ /**
+ * Merge the track segments within the given range
+ * @param inStart start index
+ * @param inEnd end index
+ * @return true if successful
+ */
+ public boolean mergeTrackSegments(int inStart, int inEnd)
+ {
+ boolean firstTrackPoint = true;
+ // Loop between start and end
+ for (int i=inStart; i<=inEnd; i++) {
+ DataPoint point = _track.getPoint(i);
+ // Set all segments to false apart from first track point
+ if (point != null && !point.isWaypoint()) {
+ point.setSegmentStart(firstTrackPoint);
+ firstTrackPoint = false;
+ }
+ }
+ // Find following track point, if any
+ DataPoint nextPoint = _track.getNextTrackPoint(inEnd+1);
+ if (nextPoint != null) {nextPoint.setSegmentStart(true);}
+ _selection.markInvalid();
+ UpdateMessageBroker.informSubscribers();
+ return true;
+ }
/**
* Interpolate extra points between two selected ones
{
boolean success = _track.average(_selection.getStart(), _selection.getEnd());
if (success) {
- _selection.selectPoint(_selection.getEnd()+1);
+ selectPoint(_selection.getEnd()+1);
}
return success;
}
*/
public void selectPoint(DataPoint inPoint)
{
- // get the index of the given Point
- int index = _track.getPointIndex(inPoint);
+ selectPoint(_track.getPointIndex(inPoint));
+ }
+
+ /**
+ * Select the data point with the given index
+ * @param inPointIndex index of DataPoint to select, or -1 for none
+ */
+ public void selectPoint(int inPointIndex)
+ {
+ if (_selection.getCurrentPointIndex() == inPointIndex || inPointIndex >= _track.getNumPoints()) {return;}
+ // get the index of the current photo
+ int photoIndex = _selection.getCurrentPhotoIndex();
+ // Check if point has photo or not
+ boolean pointHasPhoto = false;
+ if (inPointIndex >= 0)
+ {
+ Photo pointPhoto = _track.getPoint(inPointIndex).getPhoto();
+ pointHasPhoto = (pointPhoto != null);
+ if (pointHasPhoto) {
+ photoIndex = _photoList.getPhotoIndex(pointPhoto);
+ }
+ }
+ // Might need to deselect photo
+ if (!pointHasPhoto)
+ {
+ // selected point hasn't got a photo - deselect photo if necessary
+ if (photoIndex < 0 || _photoList.getPhoto(photoIndex).isConnected()) {
+ photoIndex = -1;
+ }
+ }
// give to selection
- _selection.selectPoint(index);
+ _selection.selectPhotoAndPoint(photoIndex, inPointIndex);
}
/**
*/
public void selectPhoto(int inPhotoIndex)
{
+ if (_selection.getCurrentPhotoIndex() == inPhotoIndex) {return;}
+ // Photo is primary selection here, not as a result of a point selection
+ // Therefore the photo selection takes priority, deselecting point if necessary
// Find Photo object
Photo photo = _photoList.getPhoto(inPhotoIndex);
if (photo != null)
{
// Find point object and its index
int pointIndex = _track.getPointIndex(photo.getDataPoint());
+ // Check whether to deselect current point or not if photo not correlated
+ if (pointIndex < 0)
+ {
+ int currPointIndex = _selection.getCurrentPointIndex();
+ if (currPointIndex >= 0 && _track.getPoint(currPointIndex).getPhoto() == null)
+ {
+ pointIndex = currPointIndex; // Keep currently selected point
+ }
+ }
// give to selection object
_selection.selectPhotoAndPoint(inPhotoIndex, pointIndex);
}
- else
- {
+ else {
// no photo, just reset selection
- _selection.selectPhotoAndPoint(-1, -1);
+ DataPoint currPoint = getCurrentPoint();
+ if (currPoint != null && currPoint.getPhoto() == null) {
+ _selection.selectPhotoAndPoint(-1, _selection.getCurrentPointIndex()); // keep point
+ }
+ else {
+ _selection.selectPhotoAndPoint(-1, -1); // deselect point too
+ }
}
}
}
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ñol, français, italiano, polski,<br>" +
- "schwiizerdüütsch, português, bahasa indonesia, română").append("</p>");
+ .append("deutsch, english, espa\u00F1ol, fran\u00E7ais, italiano, polski, \u4e2d\u6587; (chinese)<br>" +
+ "schwiizerd\u00FC\u00FCtsch, portugu\u00EAs, bahasa indonesia, rom\u00E2n\u0103").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(System.getProperty("java.runtime.version")),
1, 1);
// Create install labels to be populated later
- final int NUM_INSTALL_CHECKS = 5;
+ final int NUM_INSTALL_CHECKS = 4;
_installedLabels = new JLabel[NUM_INSTALL_CHECKS];
for (int i=0; i<NUM_INSTALL_CHECKS; i++) {
_installedLabels[i] = new JLabel("...");
0, 2);
addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[0], 1, 2);
addToGridBagPanel(sysInfoPanel, gridBag, constraints,
- new JLabel(I18nManager.getText("dialog.about.systeminfo.povray") + " : "),
+ new JLabel(I18nManager.getText("dialog.about.systeminfo.exiftool") + " : "),
0, 3);
addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[1], 1, 3);
addToGridBagPanel(sysInfoPanel, gridBag, constraints,
- new JLabel(I18nManager.getText("dialog.about.systeminfo.exiftool") + " : "),
+ new JLabel(I18nManager.getText("dialog.about.systeminfo.gpsbabel") + " : "),
0, 4);
addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[2], 1, 4);
addToGridBagPanel(sysInfoPanel, gridBag, constraints,
- new JLabel(I18nManager.getText("dialog.about.systeminfo.gpsbabel") + " : "),
+ new JLabel(I18nManager.getText("dialog.about.systeminfo.gnuplot") + " : "),
0, 5);
addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[3], 1, 5);
- addToGridBagPanel(sysInfoPanel, gridBag, constraints,
- new JLabel(I18nManager.getText("dialog.about.systeminfo.gnuplot") + " : "),
- 0, 6);
- addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[4], 1, 6);
_tabs.add(I18nManager.getText("dialog.about.systeminfo"), sysInfoPanel);
// Third pane for credits
new JLabel(I18nManager.getText("dialog.about.credits.translators") + " : "),
0, 3);
addToGridBagPanel(creditsPanel, gridBag, constraints,
- new JLabel("Ramon, Miguel, Inés, Piotr, Petrovsk, Josatoc, Weehal,"),
+ new JLabel("Ramon, Miguel, In\u00E9s, Piotr, Petrovsk, Josatoc, Weehal,"),
1, 3);
addToGridBagPanel(creditsPanel, gridBag, constraints,
- new JLabel(" theYinYeti, Rothermographer"),
+ new JLabel(" theYinYeti, Rothermographer, Sam, Rudolph"),
1, 4);
addToGridBagPanel(creditsPanel, gridBag, constraints,
new JLabel(I18nManager.getText("dialog.about.credits.translations") + " : "),
String yesText = I18nManager.getText("dialog.about.yes");
String noText = I18nManager.getText("dialog.about.no");
_installedLabels[0].setText(WindowFactory.isJava3dEnabled()?yesText:noText);
- _installedLabels[1].setText(ExternalTools.isPovrayInstalled()?yesText:noText);
- _installedLabels[2].setText(ExternalTools.isExiftoolInstalled()?yesText:noText);
- _installedLabels[3].setText(ExternalTools.isGpsbabelInstalled()?yesText:noText);
- _installedLabels[4].setText(ExternalTools.isGnuplotInstalled()?yesText:noText);
+ final int[] tools = {ExternalTools.TOOL_EXIFTOOL, ExternalTools.TOOL_GPSBABEL, ExternalTools.TOOL_GNUPLOT};
+ for (int i=0; i<tools.length; i++) {
+ _installedLabels[i+1].setText(ExternalTools.isToolInstalled(tools[i])?yesText:noText);
+ }
}
}
--- /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 java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.data.Altitude;
+import tim.prune.data.Field;
+
+/**
+ * Class to provide the function to add an altitude offset to a track range
+ */
+public class AddAltitudeOffset extends GenericFunction
+{
+ private JDialog _dialog = null;
+ private JLabel _descLabel = null;
+ private JTextField _editField = null;
+ private JButton _okButton = null;
+ private Altitude.Format _altFormat = Altitude.Format.NO_FORMAT;
+
+
+ /**
+ * Constructor
+ * @param inApp application object for callback
+ */
+ public AddAltitudeOffset(App inApp)
+ {
+ super(inApp);
+ }
+
+ /** Get the name key */
+ public String getNameKey() {
+ return "function.addaltitudeoffset";
+ }
+
+ /**
+ * Begin the function
+ */
+ public void begin()
+ {
+ int selStart = _app.getTrackInfo().getSelection().getStart();
+ int selEnd = _app.getTrackInfo().getSelection().getEnd();
+ if (!_app.getTrackInfo().getTrack().hasData(Field.ALTITUDE, selStart, selEnd))
+ {
+ _app.showErrorMessage(getNameKey(), "dialog.addaltitude.noaltitudes");
+ return;
+ }
+ // 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();
+ }
+ // Set label according to altitude units
+ setLabelText(selStart, selEnd);
+ // Select the contents of the edit field
+ _editField.selectAll();
+ _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 mainPanel = new JPanel();
+ _descLabel = new JLabel(I18nManager.getText("dialog.addaltitude.desc") + " (ft)");
+ // Note, this label will be reset at each run
+ mainPanel.add(_descLabel);
+ _editField = new JTextField("0", 6);
+ // Listeners to enable/disable ok button
+ KeyAdapter keyListener = new KeyAdapter() {
+ /** Key released */
+ public void keyReleased(KeyEvent arg0) {
+ _okButton.setEnabled(Math.abs(getOffset()) > 0.001);
+ }
+ };
+ MouseAdapter mouseListener = new MouseAdapter() {
+ public void mouseReleased(java.awt.event.MouseEvent arg0) {
+ _okButton.setEnabled(Math.abs(getOffset()) > 0.001);
+ };
+ };
+ _editField.addKeyListener(keyListener);
+ _editField.addMouseListener(mouseListener);
+ mainPanel.add(_editField);
+ dialogPanel.add(mainPanel, 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);
+ _editField.addActionListener(okListener);
+ 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;
+ }
+
+ /**
+ * Get the value of the altitude to add
+ * @return entered altitude offset as numeric value
+ */
+ private double getOffset()
+ {
+ double ans = 0.0;
+ try {
+ ans = Double.parseDouble(_editField.getText());
+ }
+ catch (Exception e) {}
+ return ans;
+ }
+
+ /**
+ * Set the label text according to the current units
+ * @param inStart start index of selection
+ * @param inEnd end index of selection
+ */
+ private void setLabelText(int inStart, int inEnd)
+ {
+ _altFormat = Altitude.Format.NO_FORMAT;
+ for (int i=inStart; i<=inEnd && _altFormat==Altitude.Format.NO_FORMAT; i++)
+ {
+ Altitude alt = _app.getTrackInfo().getTrack().getPoint(i).getAltitude();
+ if (alt != null) {
+ _altFormat = alt.getFormat();
+ }
+ }
+ if (_altFormat==Altitude.Format.NO_FORMAT) {
+ _altFormat = Altitude.Format.METRES;
+ }
+ final String unitKey = (_altFormat==Altitude.Format.METRES?"units.metres.short":"units.feet.short");
+ _descLabel.setText(I18nManager.getText("dialog.addaltitude.desc") + " (" + I18nManager.getText(unitKey) + ")");
+ }
+
+ /**
+ * Finish the dialog when OK pressed
+ */
+ private void finish()
+ {
+ // Pass information back to App to complete function
+ _app.finishAddAltitudeOffset(_editField.getText(), _altFormat);
+ _dialog.dispose();
+ }
+}
private long getOffsetSecs()
{
long offsetSecs = _minuteField.getValue() * 60L
- + _hourField.getValue() * 60L * 60L
- + _dayField.getValue() * 60L * 60L * 24L;
+ + _hourField.getValue() * 60L * 60L
+ + _dayField.getValue() * 60L * 60L * 24L;
if (_subtractRadio.isSelected()) {offsetSecs = -offsetSecs;}
return offsetSecs;
}
--- /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 java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+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.JTextField;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.data.DataPoint;
+import tim.prune.gui.WaypointNameMatcher;
+
+/**
+ * Class to provide the function to find a waypoint by name
+ */
+public class FindWaypoint extends GenericFunction
+{
+ private WaypointNameMatcher _nameMatcher = null;
+ private JDialog _dialog = null;
+ private JTextField _searchField = null;
+ private JList _pointList = null;
+ private JButton _okButton = null;
+
+
+ /**
+ * Constructor
+ * @param inApp application object for callback
+ */
+ public FindWaypoint(App inApp)
+ {
+ super(inApp);
+ }
+
+ /** Get the name key */
+ public String getNameKey() {
+ return "function.findwaypoint";
+ }
+
+ /**
+ * 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();
+ }
+ // Initialise waypoint list from track
+ _nameMatcher.init(_app.getTrackInfo().getTrack());
+ // Show dialog
+ _searchField.setText("");
+ _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 topPanel = new JPanel();
+ topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
+ topPanel.add(new JLabel(I18nManager.getText("dialog.findwaypoint.intro")));
+ JPanel subPanel = new JPanel();
+ subPanel.add(new JLabel(I18nManager.getText("dialog.findwaypoint.search")));
+ _searchField = new JTextField(12);
+ _searchField.addKeyListener(new KeyAdapter() {
+ public void keyReleased(KeyEvent e)
+ {
+ _nameMatcher.findMatches(_searchField.getText());
+ if (_nameMatcher.getSize() == 0 || _nameMatcher.getSize() < _pointList.getSelectedIndex())
+ _okButton.setEnabled(false);
+ else if (_pointList.getSelectedIndex() >= 0)
+ _okButton.setEnabled(true);
+ // close dialog if escape pressed
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ _dialog.dispose();
+ }
+ }
+ });
+ subPanel.add(_searchField);
+ topPanel.add(subPanel);
+ dialogPanel.add(topPanel, BorderLayout.NORTH);
+
+ // middle panel with list
+ _nameMatcher = new WaypointNameMatcher();
+ _pointList = new JList(_nameMatcher);
+ _pointList.addListSelectionListener(new ListSelectionListener() {
+ public void valueChanged(ListSelectionEvent e)
+ {
+ if (!e.getValueIsAdjusting()) _okButton.setEnabled(true);
+ }});
+ JScrollPane listPane = new JScrollPane(_pointList);
+ dialogPanel.add(listPane, 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;
+ }
+
+ /**
+ * Finish the dialog when OK pressed
+ * Select the point and close the dialog
+ */
+ private void finish()
+ {
+ DataPoint selectedPoint = _nameMatcher.getWaypoint(_pointList.getSelectedIndex());
+ _app.getTrackInfo().selectPoint(selectedPoint);
+ _dialog.dispose();
+ }
+}
--- /dev/null
+package tim.prune.function;
+
+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.FileOutputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import tim.prune.App;
+import tim.prune.Config;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+
+/**
+ * Class to provide the function to save the config settings
+ */
+public class SaveConfig extends GenericFunction
+{
+ private JDialog _dialog = null;
+
+ /**
+ * Constructor
+ * @param inApp application object for callback
+ */
+ public SaveConfig(App inApp)
+ {
+ super(inApp);
+ }
+
+ /** Get the name key */
+ public String getNameKey() {
+ return "function.saveconfig";
+ }
+
+ /**
+ * Begin the function
+ */
+ public void begin()
+ {
+ // Make new dialog window (don't reuse it)
+ _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+ _dialog.setLocationRelativeTo(_parentFrame);
+ _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ _dialog.getContentPane().add(makeDialogComponents());
+ _dialog.pack();
+ _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());
+ dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+ JLabel descLabel = new JLabel(I18nManager.getText("dialog.saveconfig.desc"));
+ dialogPanel.add(descLabel, BorderLayout.NORTH);
+
+ // Grid panel in centre
+ JPanel mainPanel = new JPanel();
+ mainPanel.setLayout(new GridLayout(0, 2, 15, 2));
+ mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
+ Properties conf = Config.getAllConfig();
+ Enumeration<Object> keys = conf.keys();
+ while (keys.hasMoreElements())
+ {
+ String key = keys.nextElement().toString();
+ String keyLabel = I18nManager.getText("dialog.saveconfig." + key);
+ if (!keyLabel.equals("dialog.saveconfig." + key))
+ {
+ mainPanel.add(new JLabel(keyLabel));
+ String val = conf.getProperty(key);
+ if (Config.isKeyBoolean(key)) {
+ val = Config.getConfigBoolean(key)?I18nManager.getText("dialog.about.yes"):I18nManager.getText("dialog.about.no");
+ }
+ else if (val != null && val.length() > 30) {
+ val = val.substring(0, 30) + " ...";
+ }
+ mainPanel.add(new JLabel(val));
+ }
+ }
+ dialogPanel.add(mainPanel, BorderLayout.CENTER);
+
+ // 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();
+ _dialog = null;
+ }
+ });
+ buttonPanel.add(cancelButton);
+ dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+ return dialogPanel;
+ }
+
+
+ /**
+ * Finish the dialog when OK pressed
+ */
+ private void finish()
+ {
+ File configFile = Config.getConfigFile();
+ if (configFile == null) {configFile = new File(".pruneconfig");}
+ JFileChooser chooser = new JFileChooser(configFile.getAbsoluteFile().getParent());
+ chooser.setSelectedFile(configFile);
+ int response = chooser.showSaveDialog(_parentFrame);
+ if (response == JFileChooser.APPROVE_OPTION)
+ {
+ File saveFile = chooser.getSelectedFile();
+ try
+ {
+ Config.getAllConfig().store(new FileOutputStream(saveFile), "Prune config file");
+ }
+ catch (IOException ioe) {
+ _app.showErrorMessageNoLookup(getNameKey(),
+ I18nManager.getText("error.save.failed") + " : " + ioe.getMessage());
+ }
+ }
+ _dialog.dispose();
+ _dialog = null;
+ }
+}
--- /dev/null
+package tim.prune.function;
+
+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.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import tim.prune.App;
+import tim.prune.Config;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.gui.WholeNumberField;
+
+/**
+ * Class to provide the function to set the image size for kmz output
+ */
+public class SetKmzImageSize extends GenericFunction
+{
+ private JDialog _dialog = null;
+ private JButton _okButton = null;
+ private WholeNumberField _widthField = null, _heightField = null;
+
+
+ /**
+ * Constructor
+ * @param inApp application object for callback
+ */
+ public SetKmzImageSize(App inApp)
+ {
+ super(inApp);
+ }
+
+ /** Get the name key */
+ public String getNameKey() {
+ return "function.setkmzimagesize";
+ }
+
+ /**
+ * 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();
+ }
+ // Initialise values from config
+ _widthField.setValue(Config.getConfigInt(Config.KEY_KMZ_IMAGE_WIDTH));
+ _heightField.setValue(Config.getConfigInt(Config.KEY_KMZ_IMAGE_HEIGHT));
+ _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());
+
+ // Make a central panel with the text boxes
+ JPanel mainPanel = new JPanel();
+ mainPanel.setLayout(new GridLayout(0, 2));
+ mainPanel.add(makeRightLabel("dialog.saveconfig.prune.kmzimagewidth"));
+ _widthField = new WholeNumberField(4);
+ mainPanel.add(_widthField);
+ mainPanel.add(makeRightLabel("dialog.saveconfig.prune.kmzimageheight"));
+ _heightField = new WholeNumberField(4);
+ mainPanel.add(_heightField);
+ dialogPanel.add(mainPanel, BorderLayout.CENTER);
+
+ // Listeners to enable/disable ok button
+ KeyAdapter keyListener = new KeyAdapter() {
+ /** Key released */
+ public void keyReleased(KeyEvent arg0) {
+ _okButton.setEnabled(_widthField.getValue()>0 && _heightField.getValue()>0);
+ }
+ };
+ MouseAdapter mouseListener = new MouseAdapter() {
+ public void mouseReleased(java.awt.event.MouseEvent arg0) {
+ _okButton.setEnabled(_widthField.getValue()>0 && _heightField.getValue()>0);
+ };
+ };
+ _widthField.addKeyListener(keyListener);
+ _heightField.addKeyListener(keyListener);
+ _widthField.addMouseListener(mouseListener);
+ _heightField.addMouseListener(mouseListener);
+
+ // 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;
+ }
+
+ /**
+ * @param inKey text key
+ * @return right-aligned label
+ */
+ private static final JLabel makeRightLabel(String inKey)
+ {
+ JLabel label = new JLabel(I18nManager.getText(inKey) + " : ");
+ label.setHorizontalAlignment(SwingConstants.RIGHT);
+ return label;
+ }
+
+
+ /**
+ * Finish the dialog when OK pressed
+ */
+ private void finish()
+ {
+ if (_widthField.getValue() > 0 && _heightField.getValue() > 0)
+ {
+ // Set entered values in Config
+ Config.setConfigInt(Config.KEY_KMZ_IMAGE_WIDTH, _widthField.getValue());
+ Config.setConfigInt(Config.KEY_KMZ_IMAGE_HEIGHT, _heightField.getValue());
+ _dialog.dispose();
+ }
+ }
+}
{
// Get values from config
try {
- _serverRadios[Config.getMapServerIndex()].setSelected(true);
+ _serverRadios[Config.getConfigInt(Config.KEY_MAPSERVERINDEX)].setSelected(true);
}
catch (ArrayIndexOutOfBoundsException e) {} // ignore
- String url = Config.getMapServerUrl();
+ String url = Config.getConfigString(Config.KEY_MAPSERVERURL);
if (url != null) {_serverUrl.setText(url);}
// Choose default if none selected
if (getSelectedServer() < 0) {
{
int serverNum = getSelectedServer();
if (!inputOK()) {serverNum = 0;}
- Config.setMapServerIndex(serverNum);
- Config.setMapServerUrl(_serverUrl.getText());
+ Config.setConfigInt(Config.KEY_MAPSERVERINDEX, serverNum);
+ Config.setConfigString(Config.KEY_MAPSERVERURL, _serverUrl.getText());
UpdateMessageBroker.informSubscribers(DataSubscriber.MAPSERVER_CHANGED);
_dialog.dispose();
}
--- /dev/null
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+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.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+
+import tim.prune.App;
+import tim.prune.Config;
+import tim.prune.ExternalTools;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+
+/**
+ * Function to set the paths for the external programs (eg gnuplot)
+ */
+public class SetPathsFunction extends GenericFunction
+{
+ /** dialog object, cached */
+ private JDialog _dialog = null;
+ /** edit boxes */
+ private JTextField[] _editFields = null;
+ /** yes/no labels */
+ private JLabel[] _installedLabels = null;
+ /** Config keys */
+ private static final String[] CONFIG_KEYS = {Config.KEY_GPSBABEL_PATH, Config.KEY_GNUPLOT_PATH, Config.KEY_EXIFTOOL_PATH};
+ /** Label keys */
+ private static final String[] LABEL_KEYS = {"gpsbabel", "gnuplot", "exiftool"};
+ /** Number of entries */
+ private static final int NUM_KEYS = CONFIG_KEYS.length;
+
+ /**
+ * Constructor from superclass
+ * @param inApp app object
+ */
+ public SetPathsFunction(App inApp)
+ {
+ super(inApp);
+ }
+
+ /**
+ * @return key for function name
+ */
+ public String getNameKey()
+ {
+ return "function.setpaths";
+ }
+
+ /**
+ * Show the dialog
+ */
+ 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();
+ }
+ checkPaths();
+ // Show dialog
+ _dialog.setVisible(true);
+ }
+
+
+ /**
+ * Make the dialog components
+ * @return panel containing gui elements
+ */
+ private JPanel makeDialogComponents()
+ {
+ JPanel dialogPanel = new JPanel();
+ dialogPanel.setLayout(new BorderLayout());
+ dialogPanel.add(new JLabel(I18nManager.getText("dialog.setpaths.intro")), BorderLayout.NORTH);
+
+ // Main panel with edit boxes for paths
+ JPanel mainPanel = new JPanel();
+ mainPanel.setLayout(new GridLayout(3, 3, 10, 1));
+ _editFields = new JTextField[NUM_KEYS];
+ _installedLabels = new JLabel[NUM_KEYS];
+ for (int i=0; i<NUM_KEYS; i++)
+ {
+ JLabel label = new JLabel(I18nManager.getText("dialog.saveconfig.prune." + LABEL_KEYS[i] + "path"));
+ label.setHorizontalAlignment(SwingConstants.RIGHT);
+ mainPanel.add(label);
+ String configVal = Config.getConfigString(CONFIG_KEYS[i]);
+ if (configVal == null) {configVal = "";}
+ _editFields[i] = new JTextField(configVal);
+ mainPanel.add(_editFields[i]);
+ _installedLabels[i] = new JLabel("...");
+ mainPanel.add(_installedLabels[i]);
+ }
+ dialogPanel.add(mainPanel, BorderLayout.CENTER);
+
+ // button panel at bottom
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ JButton checkButton = new JButton(I18nManager.getText("button.check"));
+ checkButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ checkPaths();
+ }
+ });
+ buttonPanel.add(checkButton);
+ JButton okButton = new JButton(I18nManager.getText("button.ok"));
+ ActionListener okListener = new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ finish();
+ }
+ };
+ okButton.addActionListener(okListener);
+ 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;
+ }
+
+ /**
+ * Check all the programs to see if they're installed
+ */
+ private void checkPaths()
+ {
+ String yesText = I18nManager.getText("dialog.about.yes");
+ String noText = I18nManager.getText("dialog.about.no");
+ for (int i=0; i<NUM_KEYS; i++)
+ {
+ String command = _editFields[i].getText();
+ _installedLabels[i].setText(ExternalTools.isToolInstalled(i, command)?yesText:noText);
+ }
+ }
+
+ /**
+ * Set the given paths in the configuration and exit
+ */
+ private void finish()
+ {
+ for (int i=0; i<NUM_KEYS; i++)
+ {
+ String val = _editFields[i].getText();
+ // TODO: Check path values?
+ Config.setConfigString(CONFIG_KEYS[i], val);
+ }
+ _dialog.dispose();
+ }
+}
\ No newline at end of file
--- /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 java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JEditorPane;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+
+/**
+ * Class to show a guide to the shortcut keys
+ */
+public class ShowKeysScreen extends GenericFunction
+{
+ /** dialog window */
+ private JDialog _dialog = null;
+ /** Ok button */
+ private JButton _okButton = null;
+
+
+ /**
+ * Constructor
+ * @param inApp app object
+ */
+ public ShowKeysScreen(App inApp)
+ {
+ super(inApp);
+ }
+
+ /**
+ * Get the name key
+ */
+ public String getNameKey() {
+ return "function.showkeys";
+ }
+
+ /**
+ * Show the screen
+ */
+ public void begin()
+ {
+ if (_dialog == null)
+ {
+ _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()));
+ _dialog.getContentPane().add(makeContents());
+ _dialog.pack();
+ }
+ _dialog.setLocationRelativeTo(_parentFrame);
+ _dialog.setVisible(true);
+ _okButton.requestFocus();
+ }
+
+ /**
+ * @return the contents of the window as a Component
+ */
+ private Component makeContents()
+ {
+ JPanel mainPanel = new JPanel();
+ mainPanel.setLayout(new BorderLayout());
+ JLabel introLabel = new JLabel(I18nManager.getText("dialog.keys.intro") + " :");
+ introLabel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10));
+ mainPanel.add(introLabel, BorderLayout.NORTH);
+
+ JEditorPane kp = new JEditorPane("text/html", I18nManager.getText("dialog.keys.keylist"));
+ kp.setEditable(false);
+ kp.setOpaque(false);
+ kp.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+ mainPanel.add(new JScrollPane(kp), BorderLayout.CENTER);
+
+ // OK button at the bottom
+ JPanel okPanel = new JPanel();
+ okPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
+ _okButton = new JButton(I18nManager.getText("button.ok"));
+ _okButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ _dialog.dispose();
+ }
+ });
+ _okButton.addKeyListener(new KeyListener() {
+ public void keyPressed(KeyEvent e)
+ {
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
+ }
+ public void keyTyped(KeyEvent e) {}
+ public void keyReleased(KeyEvent e) {}
+ });
+ okPanel.add(_okButton);
+ mainPanel.add(okPanel, BorderLayout.SOUTH);
+ return mainPanel;
+ }
+}
else
{
// no which command, so check if os name looks like a mac
- boolean isMacOsx = System.getProperty("os.name").toLowerCase().indexOf("mac os") >= 0;
+ String osName = System.getProperty("os.name").toLowerCase();
+ 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 void begin()
{
+ // First check if gnuplot is available
+ if (!ExternalTools.isToolInstalled(ExternalTools.TOOL_GNUPLOT))
+ {
+ _app.showErrorMessage(getNameKey(), "dialog.charts.gnuplotnotfound");
+ return;
+ }
// Make dialog window
if (_dialog == null)
{
// button panel on bottom
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
- // Gnuplot button
- JButton gnuplotButton = new JButton(I18nManager.getText("button.gnuplotpath"));
- gnuplotButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- setGnuplotPath();
- }
- });
- buttonPanel.add(gnuplotButton);
// Cancel button
JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
cancelButton.addActionListener(new ActionListener() {
OutputStreamWriter writer = null;
try
{
- Process process = Runtime.getRuntime().exec(Config.getGnuplotPath() + " -persist");
+ final String gnuplotPath = Config.getConfigString(Config.KEY_GNUPLOT_PATH);
+ Process process = Runtime.getRuntime().exec(gnuplotPath + " -persist");
writer = new OutputStreamWriter(process.getOutputStream());
if (showSvg)
{
*/
private static String getUnitsLabel(String inMetric, String inImperial)
{
- String key = Config.getUseMetricUnits()?inMetric:inImperial;
+ String key = Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?inMetric:inImperial;
return I18nManager.getText(key);
}
{
totalRads += DataPoint.calculateRadiansBetween(prevPoint, currPoint);
}
- if (Config.getUseMetricUnits()) {
+ if (Config.getConfigBoolean(Config.KEY_METRIC_UNITS)) {
values.setData(i, Distance.convertRadiansToDistance(totalRads, Units.KILOMETRES));
} else {
values.setData(i, Distance.convertRadiansToDistance(totalRads, Units.MILES));
private static ChartSeries getAltitudeValues(Track inTrack)
{
ChartSeries values = new ChartSeries(inTrack.getNumPoints());
- Altitude.Format altFormat = Config.getUseMetricUnits()?Altitude.Format.METRES:Altitude.Format.FEET;
+ Altitude.Format altFormat = Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?Altitude.Format.METRES:Altitude.Format.FEET;
for (int i=0; i<inTrack.getNumPoints(); i++) {
if (inTrack.getPoint(i).hasAltitude()) {
values.setData(i, inTrack.getPoint(i).getAltitude().getValue(altFormat));
+ DataPoint.calculateRadiansBetween(currPoint, nextPoint);
double time = nextPoint.getTimestamp().getSecondsSince(prevPoint.getTimestamp()) / 60.0 / 60.0;
// Convert to distance and pass to chartseries
- if (Config.getUseMetricUnits()) {
+ if (Config.getConfigBoolean(Config.KEY_METRIC_UNITS)) {
values.setData(i, Distance.convertRadiansToDistance(rads, Units.KILOMETRES) / time);
} else {
values.setData(i, Distance.convertRadiansToDistance(rads, Units.MILES) / time);
{
// Calculate speeds and fill in in values array
ChartSeries values = new ChartSeries(inTrack.getNumPoints());
- Altitude.Format altFormat = Config.getUseMetricUnits()?Altitude.Format.METRES:Altitude.Format.FEET;
+ Altitude.Format altFormat = Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?Altitude.Format.METRES:Altitude.Format.FEET;
DataPoint prevPoint = null, currPoint = null, nextPoint = null;
DataPoint[] points = getDataPoints(inTrack, true); // require that points have altitudes too
// Loop over collected points
/**
* Select a file to write for the SVG output
- * @return
+ * @return selected File object or null if cancelled
*/
private File selectSvgFile()
{
_fileChooser.setFileFilter(new GenericFileFilter("filetype.svg", new String[] {"svg"}));
_fileChooser.setAcceptAllFileFilterUsed(false);
// start from directory in config which should be set
- File configDir = Config.getWorkingDirectory();
- if (configDir != null) {_fileChooser.setCurrentDirectory(configDir);}
+ String configDir = Config.getConfigString(Config.KEY_TRACK_DIR);
+ if (configDir != null) {_fileChooser.setCurrentDirectory(new File(configDir));}
}
boolean chooseAgain = true;
while (chooseAgain)
{
return file;
}
- else {
- chooseAgain = true;
- }
+ chooseAgain = true;
}
}
// Cancel pressed so no file selected
if (inNumCharts == 3) {return new int[] {40, 60, 20, 20, 0, 20};}
return new int[] {54, 46, 36, 18, 18, 18, 0, 18};
}
-
- /**
- * Prompt the user to set/edit the path to gnuplot
- */
- private void setGnuplotPath()
- {
- String currPath = Config.getGnuplotPath();
- Object path = JOptionPane.showInputDialog(_dialog,
- I18nManager.getText("dialog.charts.gnuplotpath"),
- I18nManager.getText(getNameKey()),
- JOptionPane.QUESTION_MESSAGE, null, null, "" + currPath);
- if (path != null)
- {
- String pathString = path.toString().trim();
- if (!pathString.equals("") && !pathString.equals(currPath)) {
- Config.setGnuplotPath(pathString);
- // warn if gnuplot still not found
- if (!ExternalTools.isGnuplotInstalled()) {
- _app.showErrorMessage(getNameKey(), "dialog.charts.gnuplotnotfound");
- }
- }
- }
- }
}
for (int i=0; i<deleteFlags.length; i++)
{
DataPoint point = _track.getPoint(i);
- point.setMarkedForDeletion(deleteFlags[i] && !point.isWaypoint() && point.getPhoto() == null);
+ point.setMarkedForDeletion(deleteFlags[i] && point.getPhoto() == null);
}
// Close dialog and inform listeners
if (!inFlags[i])
{
DataPoint currPoint = _track.getPoint(i);
- // Don't delete any waypoints or photo points
- if (!currPoint.isWaypoint() && currPoint.getPhoto() == null)
+ // Don't delete any photo points
+ if (currPoint.getPhoto() == null)
{
// loop over last few points before this one
for (int j=i-NUM_POINTS_TO_BACKTRACK; j<i; j++)
public void recalculate(int inIndex)
{
// Use metric or not?
- _useMetric = Config.getUseMetricUnits();
+ _useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
_distanceLabel = getDistanceLabel(_useMetric);
// Initialize array of distances
int numRows = getRowCount();
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
-import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import tim.prune.App;
+import tim.prune.GenericFunction;
import tim.prune.I18nManager;
import tim.prune.data.DataPoint;
import tim.prune.data.Field;
/**
- * Class to manage the display and editing of waypoint names
+ * Function to manage the display and editing of waypoint names
*/
-public class PointNameEditor
+public class PointNameEditor extends GenericFunction
{
- private App _app = null;
- private JFrame _parentFrame = null;
private JDialog _dialog = null;
private DataPoint _point = null;
private JTextField _nameField = null;
/**
* Constructor
* @param inApp application object to inform of success
- * @param inParentFrame parent frame
*/
- public PointNameEditor(App inApp, JFrame inParentFrame)
+ public PointNameEditor(App inApp)
{
- _app = inApp;
- _parentFrame = inParentFrame;
+ super(inApp);
}
+ /** Get the name key */
+ public String getNameKey() {
+ return "function.editwaypointname";
+ }
/**
- * Show the edit point name dialog
- * @param inPoint point to edit
+ * Begin the function by showing the edit point name dialog
*/
- public void showDialog(DataPoint inPoint)
+ public void begin()
{
- _point = inPoint;
+ _point = _app.getTrackInfo().getCurrentPoint();
if (_dialog == null)
{
- _dialog = new JDialog(_parentFrame, I18nManager.getText("dialog.pointnameedit.title"), true);
+ _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
_dialog.setLocationRelativeTo(_parentFrame);
// Create Gui and show it
_dialog.getContentPane().add(makeDialogComponents());
--- /dev/null
+package tim.prune.function.gpsies;\r
+\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
+ * @author Vlad Patryshev\r
+ */\r
+public class FormPoster\r
+{\r
+ private URLConnection _connection;\r
+ private OutputStream _os = null;\r
+ private static final Random random = new Random();\r
+ private static final String boundary = "---------------------------"\r
+ + randomString() + randomString() + randomString();\r
+\r
+\r
+ protected void connect() throws IOException {\r
+ if (_os == null) _os = _connection.getOutputStream();\r
+ }\r
+\r
+ protected void write(char c) throws IOException {\r
+ connect();\r
+ _os.write(c);\r
+ }\r
+\r
+ protected void write(String s) throws IOException {\r
+ connect();\r
+ _os.write(s.getBytes());\r
+ }\r
+\r
+ protected void newline() throws IOException {\r
+ connect();\r
+ write("\r\n");\r
+ }\r
+\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
+ }\r
+\r
+ private void boundary() throws IOException {\r
+ write("--");\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
+ }\r
+\r
+\r
+ private void writeName(String name) throws IOException\r
+ {\r
+ newline();\r
+ write("Content-Disposition: form-data; name=\"");\r
+ write(name);\r
+ write('"');\r
+ }\r
+\r
+ /**\r
+ * adds a string parameter to the request\r
+ * @param name parameter name\r
+ * @param value parameter value\r
+ * @throws IOException\r
+ */\r
+ public void setParameter(String name, String value) throws IOException\r
+ {\r
+ boundary();\r
+ writeName(name);\r
+ newline(); newline();\r
+ writeln(value);\r
+ }\r
+\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
+ buf = null;\r
+ }\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
+ * @throws IOException\r
+ */\r
+ public void setParameter(String name, String filename, InputStream is) throws IOException\r
+ {\r
+ boundary();\r
+ writeName(name);\r
+ write("; filename=\"");\r
+ write(filename);\r
+ write('"');\r
+ newline();\r
+ write("Content-Type: ");\r
+ String type = URLConnection.guessContentTypeFromName(filename);\r
+ if (type == null) type = "application/octet-stream";\r
+ writeln(type);\r
+ newline();\r
+ pipe(is, _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
+ boundary();\r
+ writeln("--");\r
+ _os.close();\r
+ return _connection.getInputStream();\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
+ */\r
+ public static InputStream post(URL url, String name1, Object value1, String name2, Object value2,\r
+ String name3, Object value3) 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
+ }\r
+}\r
--- /dev/null
+package tim.prune.function.gpsies;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTable;
+import javax.swing.JTextArea;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.function.browser.BrowserLauncher;
+import tim.prune.load.xml.XmlFileLoader;
+import tim.prune.load.xml.ZipFileLoader;
+
+/**
+ * Function to load track information from Gpsies.com
+ * according to the currently viewed area
+ */
+public class GetGpsiesFunction extends GenericFunction implements Runnable
+{
+ /** Dialog object */
+ private JDialog _dialog = null;
+ /** list model */
+ private TrackListModel _trackListModel = null;
+ /** track table */
+ private JTable _trackTable = null;
+ /** Cancelled flag */
+ private boolean _cancelled = false;
+ /** Status label */
+ private JLabel _statusLabel = null;
+ /** Description box */
+ private JTextArea _descriptionBox = null;
+ /** Load button */
+ private JButton _loadButton = null;
+ /** Show button */
+ private JButton _showButton = null;
+ /** Number of results per page */
+ private static final int RESULTS_PER_PAGE = 20;
+ /** Maximum number of results to get */
+ private static final int MAX_RESULTS = 60;
+
+
+ /**
+ * Constructor
+ * @param inApp App object
+ */
+ public GetGpsiesFunction(App inApp)
+ {
+ super(inApp);
+ }
+
+ /**
+ * @return name key
+ */
+ public String getNameKey() {
+ return "function.getgpsies";
+ }
+
+ /**
+ * 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);
+ // add closing listener
+ _dialog.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ _cancelled = true;
+ }
+ });
+ _dialog.getContentPane().add(makeDialogComponents());
+ _dialog.pack();
+ }
+ // Clear list
+ _trackListModel.clear();
+ _loadButton.setEnabled(false);
+ _showButton.setEnabled(false);
+ _cancelled = false;
+ _descriptionBox.setText("");
+ // Start new thread to load list asynchronously
+ new Thread(this).start();
+
+ // 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());
+
+ // Status label
+ _statusLabel = new JLabel(I18nManager.getText("confirm.running"));
+ dialogPanel.add(_statusLabel, BorderLayout.NORTH);
+ // Main panel with track list
+ _trackListModel = new TrackListModel();
+ _trackTable = new JTable(_trackListModel);
+ _trackTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ public void valueChanged(ListSelectionEvent e) {
+ if (!e.getValueIsAdjusting())
+ {
+ if (_trackTable.getSelectedRow() >= 0
+ && _trackTable.getSelectedRow() < _trackListModel.getRowCount())
+ {
+ _loadButton.setEnabled(true);
+ _showButton.setEnabled(true);
+ setDescription(_trackListModel.getTrack(_trackTable.getSelectedRow()).getDescription());
+ _descriptionBox.setCaretPosition(0);
+ }
+ else {
+ _descriptionBox.setText("");
+ }
+ }
+ }
+ });
+ _trackTable.getColumnModel().getColumn(0).setPreferredWidth(300);
+ _trackTable.getColumnModel().getColumn(1).setPreferredWidth(70);
+ JScrollPane tablePane = new JScrollPane(_trackTable);
+ tablePane.setPreferredSize(new Dimension(450, 200));
+ // Panel to hold description label and box
+ JPanel descPanel = new JPanel();
+ descPanel.setLayout(new BorderLayout());
+ JLabel descLabel = new JLabel(I18nManager.getText("dialog.gpsies.description") + " :");
+ descPanel.add(descLabel, BorderLayout.NORTH);
+ _descriptionBox = new JTextArea(5, 20);
+ _descriptionBox.setEditable(false);
+ _descriptionBox.setLineWrap(true);
+ _descriptionBox.setWrapStyleWord(true);
+ JScrollPane descPane = new JScrollPane(_descriptionBox);
+ descPane.setPreferredSize(new Dimension(400, 80));
+ descPanel.add(descPane, BorderLayout.CENTER);
+ // Use split pane to split table from description
+ JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, tablePane, descPanel);
+ splitPane.setResizeWeight(1.0);
+ dialogPanel.add(splitPane, BorderLayout.CENTER);
+
+ // button panel at bottom
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+ _loadButton = new JButton(I18nManager.getText("button.load"));
+ _loadButton.setEnabled(false);
+ _loadButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ loadSelectedTrack();
+ }
+ });
+ buttonPanel.add(_loadButton);
+ _showButton = new JButton(I18nManager.getText("button.showwebpage"));
+ _showButton.setEnabled(false);
+ _showButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ showSelectedTrack();
+ }
+ });
+ buttonPanel.add(_showButton);
+ JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e)
+ {
+ _cancelled = true;
+ _dialog.dispose();
+ }
+ });
+ buttonPanel.add(cancelButton);
+ dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+ dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+ return dialogPanel;
+ }
+
+ /**
+ * Set the description in the box
+ * @param inDesc description to set, or null for no description
+ */
+ private void setDescription(String inDesc)
+ {
+ String text = inDesc;
+ if (inDesc == null || inDesc.length() < 2) {
+ text = I18nManager.getText("dialog.gpsies.nodescription");
+ }
+ _descriptionBox.setText(text);
+ }
+
+ /**
+ * Run method to call gpsies.com in separate thread
+ */
+ public void run()
+ {
+ _statusLabel.setText(I18nManager.getText("confirm.running"));
+ // Act on callback to update list and send another request if necessary
+ double[] coords = _app.getViewport().getBounds();
+ // Example http://www.gpsies.com/api.do?BBOX=10,51,12,53&limit=20&trackTypes=jogging&filetype=kml&device=Run.GPS
+ int currPage = 1;
+
+ ArrayList<GpsiesTrack> trackList = null;
+ URL url = null;
+ String descMessage = "";
+ // Loop for each page of the results
+ do
+ {
+ String urlString = "http://www.gpsies.com/api.do?BBOX=" +
+ coords[1] + "," + coords[0] + "," + coords[3] + "," + coords[2] +
+ "&limit=" + RESULTS_PER_PAGE + "&resultPage=" + currPage;
+ // System.out.println(urlString);
+ // Parse the returned XML with a special handler
+ GpsiesXmlHandler xmlHandler = new GpsiesXmlHandler();
+ try
+ {
+ url = new URL(urlString);
+ SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
+ saxParser.parse(url.openStream(), xmlHandler);
+ }
+ catch (Exception e) {
+ descMessage = e.getClass().getName() + " - " + e.getMessage();
+ }
+ // TODO: Close streams somehow? Haven't got a reference to the input stream to close it!
+ // Add track list to model
+ trackList = xmlHandler.getTrackList();
+ _trackListModel.addTracks(trackList);
+
+ // Compare number of results with results per page and call again if necessary
+ currPage++;
+ }
+ while (trackList != null && trackList.size() == RESULTS_PER_PAGE
+ && _trackListModel.getRowCount() < MAX_RESULTS && !_cancelled);
+ // Set status label according to error or "none found", leave blank if ok
+ if (descMessage.equals("") && (trackList == null || trackList.size() == 0)) {
+ descMessage = I18nManager.getText("dialog.gpsies.nonefound");
+ }
+ _statusLabel.setText(descMessage);
+ }
+
+
+ /**
+ * Load the selected track
+ */
+ private void loadSelectedTrack()
+ {
+ // Find the row selected in the table and get the corresponding track
+ int rowNum = _trackTable.getSelectedRow();
+ if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
+ {
+ String url = _trackListModel.getTrack(rowNum).getDownloadLink();
+ XmlFileLoader xmlLoader = new XmlFileLoader(_app);
+ ZipFileLoader loader = new ZipFileLoader(_app, xmlLoader);
+ try
+ {
+ loader.openStream(new URL(url).openStream());
+ }
+ catch (IOException ioe) {
+ System.err.println("IO Exception : " + ioe.getMessage());
+ }
+ }
+ // Close the dialog
+ _cancelled = true;
+ _dialog.dispose();
+ }
+
+
+ /**
+ * Show the webpage for the selected track
+ */
+ private void showSelectedTrack()
+ {
+ // Find the row selected in the table and show the corresponding url
+ int rowNum = _trackTable.getSelectedRow();
+ if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
+ {
+ String id = _trackListModel.getTrack(rowNum).getFileId();
+ BrowserLauncher.launchBrowser("http://gpsies.com/map.do?fileId=" + id);
+ }
+ // Close the dialog
+ _cancelled = true;
+ _dialog.dispose();
+ }
+}
--- /dev/null
+package tim.prune.function.gpsies;
+
+/**
+ * Class to hold a single track from Gpsies.com
+ */
+public class GpsiesTrack
+{
+ /** Track name or title */
+ private String _trackName = null;
+ /** Description */
+ private String _description = null;
+ /** File id for more details */
+ private String _fileId = null;
+ /** Track length in metres */
+ private double _trackLength = 0.0;
+ /** Download link */
+ private String _downloadLink = null;
+
+
+ /**
+ * @param inName name of track
+ */
+ public void setTrackName(String inName)
+ {
+ _trackName = inName;
+ }
+
+ /**
+ * @return track name
+ */
+ public String getTrackName()
+ {
+ return _trackName;
+ }
+
+ /**
+ * @param inDesc description
+ */
+ public void setDescription(String inDesc)
+ {
+ _description = inDesc;
+ }
+
+ /**
+ * @return track description
+ */
+ public String getDescription()
+ {
+ return _description;
+ }
+
+ /**
+ * @param inId id of track
+ */
+ public void setFileId(String inId)
+ {
+ _fileId = inId;
+ }
+
+ /**
+ * @return file id
+ */
+ public String getFileId()
+ {
+ return _fileId;
+ }
+
+ /**
+ * @param inLength length of track
+ */
+ public void setLength(double inLength)
+ {
+ _trackLength = inLength;
+ }
+
+ /**
+ * @return track length
+ */
+ public double getLength()
+ {
+ return _trackLength;
+ }
+
+ /**
+ * @param inLink link to download track
+ */
+ public void setDownloadLink(String inLink)
+ {
+ _downloadLink = inLink;
+ }
+
+ /**
+ * @return download link
+ */
+ public String getDownloadLink()
+ {
+ return _downloadLink;
+ }
+}
--- /dev/null
+package tim.prune.function.gpsies;
+
+import java.util.ArrayList;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * XML handler for dealing with XML returned from gpsies.com
+ */
+public class GpsiesXmlHandler extends DefaultHandler
+{
+ private boolean _inTracks = false;
+ private boolean _inTrack = false;
+ private boolean _inTrackName = false;
+ private boolean _inDescription = false;
+ private boolean _inFileId = false;
+ private boolean _inTrackLength = false;
+ private boolean _inLink = false;
+ private String _value = null;
+ private ArrayList<GpsiesTrack> _trackList = null;
+ private GpsiesTrack _track = null;
+
+
+ /**
+ * React to the start of an XML tag
+ */
+ public void startElement(String inUri, String inLocalName, String inTagName,
+ Attributes inAttributes) throws SAXException
+ {
+ if (inTagName.equals("tracks")) {
+ _inTracks = true;
+ _trackList = new ArrayList<GpsiesTrack>();
+ }
+ else if (_inTracks && inTagName.equals("track")) {
+ _inTrack = true;
+ _track = new GpsiesTrack();
+ }
+ else if (_inTrack && inTagName.equals("title")) {_inTrackName = true;}
+ else if (_inTrack && inTagName.equals("description")) {_inDescription = true;}
+ else if (_inTrack && inTagName.equals("fileId")) {_inFileId = true;}
+ else if (_inTrack && inTagName.equals("trackLengthM")) {_inTrackLength = true;}
+ else if (_inTrack && inTagName.equals("downloadLink")) {_inLink = true;}
+ super.startElement(inUri, inLocalName, inTagName, inAttributes);
+ }
+
+ /**
+ * React to the end of an XML tag
+ */
+ public void endElement(String inUri, String inLocalName, String inTagName)
+ throws SAXException
+ {
+ if (inTagName.equals("tracks")) {_inTracks = false;}
+ else if (_inTrack && inTagName.equals("track")) {
+ _trackList.add(_track);
+ _inTrack = false;
+ }
+ else if (_inTrackName && inTagName.equals("title")) {
+ _track.setTrackName(_value);
+ _inTrackName = false;
+ }
+ else if (_inDescription && inTagName.equals("description")) {
+ _track.setDescription(_value);
+ _inDescription = false;
+ }
+ else if (_inFileId && inTagName.equals("fileId")) {
+ _track.setFileId(_value);
+ _inFileId = false;
+ }
+ else if (_inTrackLength && inTagName.equals("trackLengthM")) {
+ try {
+ _track.setLength(Double.parseDouble(_value));
+ }
+ catch (NumberFormatException nfe) {}
+ _inTrackLength = false;
+ }
+ else if (_inLink && inTagName.equals("downloadLink")) {
+ _track.setDownloadLink(_value);
+ _inLink = false;
+ }
+ super.endElement(inUri, inLocalName, inTagName);
+ }
+
+ /**
+ * React to characters received inside tags
+ */
+ public void characters(char[] inCh, int inStart, int inLength)
+ throws SAXException
+ {
+ _value = new String(inCh, inStart, inLength);
+ // System.out.println("Value: '" + value + "'");
+ // TODO: Note, this doesn't cope well with split characters for really long descriptions etc
+ super.characters(inCh, inStart, inLength);
+ }
+
+ /**
+ * @return the list of tracks
+ */
+ public ArrayList<GpsiesTrack> getTrackList()
+ {
+ return _trackList;
+ }
+}
--- /dev/null
+package tim.prune.function.gpsies;
+
+import java.text.NumberFormat;
+import java.util.ArrayList;
+
+import javax.swing.table.AbstractTableModel;
+
+import tim.prune.Config;
+import tim.prune.I18nManager;
+import tim.prune.data.Distance;
+
+/**
+ * Model for list of tracks from gpsies.com
+ */
+public class TrackListModel extends AbstractTableModel
+{
+ /** List of tracks */
+ private ArrayList<GpsiesTrack> _trackList = null;
+ /** Column heading for track name */
+ private static final String _nameColLabel = I18nManager.getText("dialog.gpsies.column.name");
+ /** Column heading for length */
+ private static final String _lengthColLabel = I18nManager.getText("dialog.gpsies.column.length");
+ /** Formatter for distances */
+ private NumberFormat _distanceFormatter = NumberFormat.getInstance();
+
+ /**
+ * Constructor
+ */
+ public TrackListModel()
+ {
+ _distanceFormatter.setMaximumFractionDigits(1);
+ }
+
+ /**
+ * @return column count
+ */
+ public int getColumnCount()
+ {
+ return 2;
+ }
+
+ /**
+ * @return number of rows
+ */
+ public int getRowCount()
+ {
+ if (_trackList == null) return 0;
+ return _trackList.size();
+ }
+
+ /**
+ * @param inColNum column number
+ * @return column label for given column
+ */
+ public String getColumnName(int inColNum)
+ {
+ if (inColNum == 0) {return _nameColLabel;}
+ return _lengthColLabel;
+ }
+
+ /**
+ * @param inRowNum row number
+ * @param inColNum column number
+ * @return cell entry at given row and column
+ */
+ public Object getValueAt(int inRowNum, int inColNum)
+ {
+ GpsiesTrack track = _trackList.get(inRowNum);
+ if (inColNum == 0) {return track.getTrackName();}
+ double lengthM = track.getLength();
+ if (Config.getConfigBoolean(Config.KEY_METRIC_UNITS)) {
+ return _distanceFormatter.format(lengthM / 1000.0) + " " + I18nManager.getText("units.kilometres.short");
+ }
+ // must be imperial
+ return _distanceFormatter.format(Distance.convertMetresToMiles(lengthM))
+ + " " + I18nManager.getText("units.miles.short");
+ }
+
+ /**
+ * Add a list of tracks to this model
+ * @param inList list of tracks to add
+ */
+ public void addTracks(ArrayList<GpsiesTrack> inList)
+ {
+ if (_trackList == null) {_trackList = new ArrayList<GpsiesTrack>();}
+ if (inList != null && inList.size() > 0) {
+ _trackList.addAll(inList);
+ }
+ fireTableDataChanged();
+ }
+
+ /**
+ * @param inRowNum row number from 0
+ * @return track object for this row
+ */
+ public GpsiesTrack getTrack(int inRowNum)
+ {
+ return _trackList.get(inRowNum);
+ }
+
+ /**
+ * Clear the list of tracks
+ */
+ public void clear()
+ {
+ _trackList = null;
+ }
+}
private JLabel _durationLabel = null;
private JLabel _altRangeLabel = null, _updownLabel = null;
private JLabel _aveSpeedLabel = null, _aveMovingSpeedLabel = null;
+ private JLabel _paceLabel = null;
// Photo details
private JLabel _photoLabel = null;
rangeDetailsPanel.add(_aveSpeedLabel);
_aveMovingSpeedLabel = new JLabel("");
rangeDetailsPanel.add(_aveMovingSpeedLabel);
+ _paceLabel = new JLabel("");
+ rangeDetailsPanel.add(_paceLabel);
_altRangeLabel = new JLabel("");
rangeDetailsPanel.add(_altRangeLabel);
_updownLabel = new JLabel("");
lowerPanel.add(unitsLabel);
String[] distUnits = {I18nManager.getText("units.kilometres"), I18nManager.getText("units.miles")};
_distUnitsDropdown = new JComboBox(distUnits);
- if (!Config.getUseMetricUnits()) {_distUnitsDropdown.setSelectedIndex(1);}
+ if (!Config.getConfigBoolean(Config.KEY_METRIC_UNITS)) {_distUnitsDropdown.setSelectedIndex(1);}
_distUnitsDropdown.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
dataUpdated(DataSubscriber.UNITS_CHANGED);
- Config.setUseMetricUnits(_distUnitsDropdown.getSelectedIndex() == 0);
+ Config.setConfigBoolean(Config.KEY_METRIC_UNITS, _distUnitsDropdown.getSelectedIndex() == 0);
}
});
lowerPanel.add(_distUnitsDropdown);
:"");
if (currentPoint.getTimestamp().isValid())
{
- if (currentPointIndex > 0 && currentPointIndex < (_trackInfo.getTrack().getNumPoints()-1)) {
+ if (currentPointIndex > 0 && currentPointIndex < (_trackInfo.getTrack().getNumPoints()-1))
+ {
DataPoint prevPoint = _trackInfo.getTrack().getPoint(currentPointIndex - 1);
DataPoint nextPoint = _trackInfo.getTrack().getPoint(currentPointIndex + 1);
if (prevPoint.getTimestamp().isValid() && nextPoint.getTimestamp().isValid())
_updownLabel.setText("");
_aveSpeedLabel.setText("");
_aveMovingSpeedLabel.setText("");
+ _paceLabel.setText("");
}
else
{
+ (selection.getStart()+1) + " " + I18nManager.getText("details.range.to")
+ " " + (selection.getEnd()+1));
_distanceLabel.setText(LABEL_RANGE_DISTANCE + roundedNumber(selection.getDistance(distUnits)) + " " + distUnitsStr);
- _movingDistanceLabel.setText(LABEL_RANGE_MOVINGDISTANCE + roundedNumber(selection.getMovingDistance(distUnits)) + " " + distUnitsStr);
+ if (selection.getHasMultipleSegments()) {
+ _movingDistanceLabel.setText(LABEL_RANGE_MOVINGDISTANCE + roundedNumber(selection.getMovingDistance(distUnits)) + " " + distUnitsStr);
+ }
+ else {
+ _movingDistanceLabel.setText(null);
+ }
if (selection.getNumSeconds() > 0)
{
_durationLabel.setText(LABEL_RANGE_DURATION + buildDurationString(selection.getNumSeconds()));
_aveSpeedLabel.setText(I18nManager.getText("details.range.avespeed") + ": "
+ roundedNumber(selection.getDistance(distUnits)/selection.getNumSeconds()*3600.0) + " " + speedUnitsStr);
- _aveMovingSpeedLabel.setText(I18nManager.getText("details.range.avemovingspeed") + ": "
- + roundedNumber(selection.getMovingDistance(distUnits)/selection.getMovingSeconds()*3600.0) + " " + speedUnitsStr);
+ if (selection.getHasMultipleSegments()) {
+ _aveMovingSpeedLabel.setText(I18nManager.getText("details.range.avemovingspeed") + ": "
+ + roundedNumber(selection.getMovingDistance(distUnits)/selection.getMovingSeconds()*3600.0) + " " + speedUnitsStr);
+ }
+ else {
+ _aveMovingSpeedLabel.setText(null);
+ }
+ if (Config.getConfigBoolean(Config.KEY_SHOW_PACE)) {
+ _paceLabel.setText(I18nManager.getText("details.range.pace") + ": "
+ + buildDurationString((long) (selection.getNumSeconds()/selection.getDistance(distUnits)))
+ + " / " + distUnitsStr);
+ }
+ else {
+ _paceLabel.setText("");
+ }
}
else {
_durationLabel.setText("");
_aveSpeedLabel.setText("");
_aveMovingSpeedLabel.setText("");
+ _paceLabel.setText("");
}
String altUnitsLabel = getAltitudeUnitsLabel(selection.getAltitudeFormat());
IntegerRange altRange = selection.getAltitudeRange();
}
// show photo details and thumbnail
Photo currentPhoto = _trackInfo.getPhotoList().getPhoto(_trackInfo.getSelection().getCurrentPhotoIndex());
- if (_track == null || ( (currentPoint == null || currentPoint.getPhoto() == null) && currentPhoto == null))
+ if ((currentPoint == null || currentPoint.getPhoto() == null) && currentPhoto == null)
{
// no photo, hide details
_photoLabel.setText(I18nManager.getText("details.nophoto"));
{
if (currentPhoto == null) {currentPhoto = currentPoint.getPhoto();}
_photoLabel.setText(I18nManager.getText("details.photofile") + ": " + currentPhoto.getFile().getName());
- _photoLabel.setText(LABEL_POINT_TIMESTAMP + currentPhoto.getTimestamp().getText());
+ _photoTimestampLabel.setText(LABEL_POINT_TIMESTAMP + currentPhoto.getTimestamp().getText());
_photoConnectedLabel.setText(I18nManager.getText("details.photo.connected") + ": "
+ (currentPhoto.getCurrentStatus() == Photo.Status.NOT_CONNECTED ?
I18nManager.getText("dialog.about.no"):I18nManager.getText("dialog.about.yes")));
if (inNumSecs < 86400L) return "" + (inNumSecs / 60 / 60) + I18nManager.getText("display.range.time.hours")
+ " " + ((inNumSecs / 60) % 60) + I18nManager.getText("display.range.time.mins");
if (inNumSecs < 432000L) return "" + (inNumSecs / 86400L) + I18nManager.getText("display.range.time.days")
- + " " + (inNumSecs / 60 / 60) + I18nManager.getText("display.range.time.hours");
+ + " " + (inNumSecs / 60 / 60) % 24 + I18nManager.getText("display.range.time.hours");
if (inNumSecs < 8640000L) return "" + (inNumSecs / 86400L) + I18nManager.getText("display.range.time.days");
return "big";
}
--- /dev/null
+package tim.prune.gui;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import tim.prune.GenericFunction;
+
+/**
+ * Class to launch a function triggered by an action
+ */
+public class FunctionLauncher implements ActionListener
+{
+ /** Function to launch */
+ private GenericFunction _function = null;
+
+ /**
+ * Constructor
+ * @param inFunction function to launch
+ */
+ public FunctionLauncher(GenericFunction inFunction)
+ {
+ _function = inFunction;
+ }
+
+ /**
+ * React to action
+ * @param e event
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ _function.begin();
+ }
+
+}
\ No newline at end of file
/** Icon for window */
public static final String WINDOW_ICON = "window_icon.png";
+ /** Icon for scalebar button on main map display */
+ public static final String SCALEBAR_BUTTON = "scalebar.gif";
+ /** Icon for map button on main map display when selected */
+ public static final String SCALEBAR_BUTTON_ON = "scalebar_on.gif";
/** Icon for map button on main map display */
public static final String MAP_BUTTON = "map_icon.gif";
/** Icon for map button on main map display when selected */
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
+
import javax.swing.JButton;
+import javax.swing.JCheckBoxMenuItem;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke;
import tim.prune.App;
+import tim.prune.Config;
import tim.prune.DataSubscriber;
import tim.prune.FunctionLibrary;
import tim.prune.GenericFunction;
import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
import tim.prune.data.PhotoList;
import tim.prune.data.Selection;
import tim.prune.data.Track;
private JMenuItem _selectNoneItem = null;
private JMenuItem _selectStartItem = null;
private JMenuItem _selectEndItem = null;
+ private JMenuItem _findWaypointItem = null;
private JMenuItem _reverseItem = null;
private JMenuItem _addTimeOffsetItem = null;
+ private JMenuItem _addAltitudeOffsetItem = null;
private JMenuItem _mergeSegmentsItem = null;
private JMenu _rearrangeMenu = null;
private JMenuItem _cutAndMoveItem = null;
private JMenuItem _show3dItem = null;
private JMenu _browserMapMenu = null;
private JMenuItem _chartItem = null;
+ private JCheckBoxMenuItem _paceCheckbox = null;
+ private JMenuItem _getGpsiesItem = null;
private JMenuItem _distanceItem = null;
private JMenuItem _saveExifItem = null;
private JMenuItem _connectPhotoItem = null;
private JButton _selectEndButton = null;
private JButton _connectPhotoButton = null;
+ /** Array of key events */
+ private static final int[] KEY_EVENTS = {
+ KeyEvent.VK_A, KeyEvent.VK_B, KeyEvent.VK_C, KeyEvent.VK_D, KeyEvent.VK_E,
+ KeyEvent.VK_F, KeyEvent.VK_G, KeyEvent.VK_H, KeyEvent.VK_I, KeyEvent.VK_J,
+ KeyEvent.VK_K, KeyEvent.VK_L, KeyEvent.VK_M, KeyEvent.VK_N, KeyEvent.VK_O,
+ KeyEvent.VK_P, KeyEvent.VK_Q, KeyEvent.VK_R, KeyEvent.VK_S, KeyEvent.VK_T,
+ KeyEvent.VK_U, KeyEvent.VK_V, KeyEvent.VK_W, KeyEvent.VK_X, KeyEvent.VK_Y, KeyEvent.VK_Z};
+
/**
* Constructor
{
JMenuBar menubar = new JMenuBar();
JMenu fileMenu = new JMenu(I18nManager.getText("menu.file"));
+ setAltKey(fileMenu, "altkey.menu.file");
// Open file
JMenuItem openMenuItem = new JMenuItem(I18nManager.getText("menu.file.open"));
- openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK));
+ setShortcut(openMenuItem, "shortcut.menu.file.open");
_openFileAction = new ActionListener() {
public void actionPerformed(ActionEvent e)
{
fileMenu.addSeparator();
// Load from GPS
JMenuItem loadFromGpsMenuItem = makeMenuItem(FunctionLibrary.FUNCTION_GPSLOAD);
- loadFromGpsMenuItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_GPSLOAD.begin();
- }
- });
+ setShortcut(loadFromGpsMenuItem, "shortcut.menu.file.load");
fileMenu.add(loadFromGpsMenuItem);
- // Save to GPS
+ // Send to GPS
_sendGpsItem = makeMenuItem(FunctionLibrary.FUNCTION_GPSSAVE);
- _sendGpsItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_GPSSAVE.begin();
- }
- });
_sendGpsItem.setEnabled(false);
fileMenu.add(_sendGpsItem);
fileMenu.addSeparator();
// Save
_saveItem = new JMenuItem(I18nManager.getText("menu.file.save"), KeyEvent.VK_S);
+ setShortcut(_saveItem, "shortcut.menu.file.save");
_saveAction = new ActionListener() {
public void actionPerformed(ActionEvent e)
{
fileMenu.add(_saveItem);
// Export - Kml
_exportKmlItem = makeMenuItem(FunctionLibrary.FUNCTION_KMLEXPORT);
- _exportKmlItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_KMLEXPORT.begin();
- }
- });
_exportKmlItem.setEnabled(false);
fileMenu.add(_exportKmlItem);
// Gpx
_exportGpxItem = makeMenuItem(FunctionLibrary.FUNCTION_GPXEXPORT);
- _exportGpxItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_GPXEXPORT.begin();
- }
- });
_exportGpxItem.setEnabled(false);
fileMenu.add(_exportGpxItem);
// Pov
_exportPovItem = makeMenuItem(FunctionLibrary.FUNCTION_POVEXPORT);
- _exportPovItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_POVEXPORT.begin();
- }
- });
_exportPovItem.setEnabled(false);
fileMenu.add(_exportPovItem);
fileMenu.addSeparator();
menubar.add(fileMenu);
// Edit menu
JMenu editMenu = new JMenu(I18nManager.getText("menu.edit"));
- editMenu.setMnemonic(KeyEvent.VK_E);
+ setAltKey(editMenu, "altkey.menu.edit");
_undoItem = new JMenuItem(I18nManager.getText("menu.edit.undo"));
+ setShortcut(_undoItem, "shortcut.menu.edit.undo");
_undoAction = new ActionListener() {
public void actionPerformed(ActionEvent e)
{
_editPointItem.addActionListener(_editPointAction);
_editPointItem.setEnabled(false);
editMenu.add(_editPointItem);
- _editWaypointNameItem = new JMenuItem(I18nManager.getText("menu.edit.editwaypointname"));
- _editWaypointNameItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- _app.editCurrentPointName();
- }
- });
+ _editWaypointNameItem = makeMenuItem(FunctionLibrary.FUNCTION_EDIT_WAYPOINT_NAME);
_editWaypointNameItem.setEnabled(false);
editMenu.add(_editWaypointNameItem);
_deletePointItem = new JMenuItem(I18nManager.getText("menu.edit.deletepoint"));
editMenu.add(_deleteRangeItem);
editMenu.addSeparator();
_compressItem = makeMenuItem(FunctionLibrary.FUNCTION_COMPRESS);
- _compressItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_COMPRESS.begin();
- }
- });
+ setShortcut(_compressItem, "shortcut.menu.edit.compress");
_compressItem.setEnabled(false);
editMenu.add(_compressItem);
_deleteMarkedPointsItem = new JMenuItem(I18nManager.getText("menu.edit.deletemarked"));
_reverseItem.setEnabled(false);
editMenu.add(_reverseItem);
_addTimeOffsetItem = makeMenuItem(FunctionLibrary.FUNCTION_ADD_TIME_OFFSET);
- _addTimeOffsetItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_ADD_TIME_OFFSET.begin();
- }
- });
_addTimeOffsetItem.setEnabled(false);
editMenu.add(_addTimeOffsetItem);
+ _addAltitudeOffsetItem = makeMenuItem(FunctionLibrary.FUNCTION_ADD_ALTITUDE_OFFSET);
+ _addAltitudeOffsetItem.setEnabled(false);
+ editMenu.add(_addAltitudeOffsetItem);
_mergeSegmentsItem = new JMenuItem(I18nManager.getText("menu.edit.mergetracksegments"));
_mergeSegmentsItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
// Select menu
JMenu selectMenu = new JMenu(I18nManager.getText("menu.select"));
+ setAltKey(selectMenu, "altkey.menu.select");
_selectAllItem = new JMenuItem(I18nManager.getText("menu.select.all"));
+ setShortcut(_selectAllItem, "shortcut.menu.select.all");
_selectAllItem.setEnabled(false);
_selectAllItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
- _app.selectAll();
+ _selection.selectRange(0, _track.getNumPoints()-1);
}
});
selectMenu.add(_selectAllItem);
};
_selectEndItem.addActionListener(_selectEndAction);
selectMenu.add(_selectEndItem);
+ selectMenu.addSeparator();
+ _findWaypointItem = makeMenuItem(FunctionLibrary.FUNCTION_FIND_WAYPOINT);
+ _findWaypointItem.setEnabled(false);
+ selectMenu.add(_findWaypointItem);
menubar.add(selectMenu);
// Add view menu
JMenu viewMenu = new JMenu(I18nManager.getText("menu.view"));
+ setAltKey(viewMenu, "altkey.menu.view");
_show3dItem = makeMenuItem(FunctionLibrary.FUNCTION_3D);
- _show3dItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_3D.begin();
- }
- });
_show3dItem.setEnabled(false);
viewMenu.add(_show3dItem);
// browser submenu
viewMenu.add(_browserMapMenu);
// Charts
_chartItem = makeMenuItem(FunctionLibrary.FUNCTION_CHARTS);
- _chartItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_CHARTS.begin();
- }
- });
_chartItem.setEnabled(false);
viewMenu.add(_chartItem);
// Distances
_distanceItem = makeMenuItem(FunctionLibrary.FUNCTION_DISTANCES);
_distanceItem.setEnabled(false);
- _distanceItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- FunctionLibrary.FUNCTION_DISTANCES.begin();
- }
- });
viewMenu.add(_distanceItem);
- // Set the map background
- JMenuItem mapBgItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_MAP_BG);
- mapBgItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent arg0) {
- FunctionLibrary.FUNCTION_SET_MAP_BG.begin();
- }
- });
- viewMenu.add(mapBgItem);
+ // Get gpsies tracks
+ _getGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_GET_GPSIES);
+ _getGpsiesItem.setEnabled(false);
+ viewMenu.add(_getGpsiesItem);
menubar.add(viewMenu);
// Add photo menu
JMenu photoMenu = new JMenu(I18nManager.getText("menu.photo"));
+ setAltKey(photoMenu, "altkey.menu.photo");
addPhotosMenuItem = new JMenuItem(I18nManager.getText("menu.file.addphotos"));
addPhotosMenuItem.addActionListener(_addPhotoAction);
photoMenu.add(addPhotosMenuItem);
photoMenu.addSeparator();
// correlate all photos
_correlatePhotosItem = makeMenuItem(FunctionLibrary.FUNCTION_CORRELATE_PHOTOS);
- _correlatePhotosItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_CORRELATE_PHOTOS.begin();
- }
- });
_correlatePhotosItem.setEnabled(false);
photoMenu.add(_correlatePhotosItem);
menubar.add(photoMenu);
+ // Settings menu
+ JMenu settingsMenu = new JMenu(I18nManager.getText("menu.settings"));
+ setAltKey(settingsMenu, "altkey.menu.settings");
+ // Set the map background
+ JMenuItem mapBgItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_MAP_BG);
+ settingsMenu.add(mapBgItem);
+ // Turn pace display on/off
+ _paceCheckbox = new JCheckBoxMenuItem(
+ I18nManager.getText("menu.settings.showpace"), false);
+ _paceCheckbox.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ Config.setConfigBoolean(Config.KEY_SHOW_PACE, _paceCheckbox.isSelected());
+ UpdateMessageBroker.informSubscribers();
+ }
+ });
+ settingsMenu.add(_paceCheckbox);
+ // Set kmz image size
+ JMenuItem setKmzImageSizeItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_KMZ_IMAGE_SIZE);
+ settingsMenu.add(setKmzImageSizeItem);
+ // Set program paths
+ JMenuItem setPathsItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_PATHS);
+ settingsMenu.add(setPathsItem);
+ settingsMenu.addSeparator();
+ // Save configuration
+ JMenuItem saveConfigMenuItem = makeMenuItem(FunctionLibrary.FUNCTION_SAVECONFIG);
+ settingsMenu.add(saveConfigMenuItem);
+ menubar.add(settingsMenu);
+
// Help menu
JMenu helpMenu = new JMenu(I18nManager.getText("menu.help"));
+ setAltKey(helpMenu, "altkey.menu.help");
JMenuItem helpItem = makeMenuItem(FunctionLibrary.FUNCTION_HELP);
- helpItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_HELP.begin();
- }
- });
+ setShortcut(helpItem, "shortcut.menu.help.help");
helpMenu.add(helpItem);
+ JMenuItem showKeysItem = makeMenuItem(FunctionLibrary.FUNCTION_SHOW_KEYS);
+ helpMenu.add(showKeysItem);
JMenuItem aboutItem = makeMenuItem(FunctionLibrary.FUNCTION_ABOUT);
- aboutItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_ABOUT.begin();
- }
- });
helpMenu.add(aboutItem);
JMenuItem checkVersionItem = makeMenuItem(FunctionLibrary.FUNCTION_CHECK_VERSION);
- checkVersionItem.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e)
- {
- FunctionLibrary.FUNCTION_CHECK_VERSION.begin();
- }
- });
helpMenu.add(checkVersionItem);
menubar.add(helpMenu);
*/
private static JMenuItem makeMenuItem(GenericFunction inFunction)
{
- return new JMenuItem(I18nManager.getText(inFunction.getNameKey()));
+ JMenuItem item = new JMenuItem(I18nManager.getText(inFunction.getNameKey()));
+ item.addActionListener(new FunctionLauncher(inFunction));
+ return item;
+ }
+
+ /**
+ * Set the alt key for the given menu
+ * @param inMenu menu to set
+ * @param inKey key to lookup to get language-sensitive altkey
+ */
+ private static void setAltKey(JMenu inMenu, String inKey)
+ {
+ // Lookup the key in the properties
+ String altKey = I18nManager.getText(inKey);
+ if (altKey != null && altKey.length() == 1)
+ {
+ int code = altKey.charAt(0) - 'A';
+ if (code >= 0 && code < 26)
+ {
+ // Found a valid code between A and Z
+ inMenu.setMnemonic(KEY_EVENTS[code]);
+ }
+ }
+ }
+
+ /**
+ * Set the shortcut key for the given menu item
+ * @param inMenuItem menu item to set
+ * @param inKey key to lookup to get language-sensitive shortcut
+ */
+ private static void setShortcut(JMenuItem inMenuItem, String inKey)
+ {
+ // Lookup the key in the properties
+ String altKey = I18nManager.getText(inKey);
+ if (altKey != null && altKey.length() == 1)
+ {
+ int code = altKey.charAt(0) - 'A';
+ if (code >= 0 && code < 26)
+ {
+ // Found a valid code between A and Z
+ inMenuItem.setAccelerator(KeyStroke.getKeyStroke(KEY_EVENTS[code], InputEvent.CTRL_DOWN_MASK));
+ }
+ }
}
/**
_exportPovItem.setEnabled(hasData);
_compressItem.setEnabled(hasData);
_deleteMarkedPointsItem.setEnabled(hasData && _track.hasMarkedPoints());
- _rearrangeMenu.setEnabled(hasData && _track.hasMixedData());
+ _rearrangeMenu.setEnabled(hasData && _track.hasTrackPoints() && _track.hasWaypoints());
_selectAllItem.setEnabled(hasData);
_selectNoneItem.setEnabled(hasData);
_show3dItem.setEnabled(hasData);
_chartItem.setEnabled(hasData);
_browserMapMenu.setEnabled(hasData);
_distanceItem.setEnabled(hasData);
+ _getGpsiesItem.setEnabled(hasData);
+ _findWaypointItem.setEnabled(hasData && _track.hasWaypoints());
// is undo available?
boolean hasUndo = !_app.getUndoStack().isEmpty();
_undoItem.setEnabled(hasUndo);
_mergeSegmentsItem.setEnabled(hasRange);
_reverseItem.setEnabled(hasRange);
_addTimeOffsetItem.setEnabled(hasRange);
+ _addAltitudeOffsetItem.setEnabled(hasRange);
// Is the currently selected point outside the current range?
_cutAndMoveItem.setEnabled(hasRange && hasPoint &&
(_selection.getCurrentPointIndex() < _selection.getStart()
private static final int[] ALTITUDE_SCALES = {10000, 5000, 2000, 1000, 500, 200, 100, 50};
private static final Color COLOR_LINES = Color.GRAY;
private static final Color COLOR_ALT_BARS = Color.BLUE;
+ private static final Color COLOR_CURR_RANGE = Color.GREEN;
private static final Color COLOR_SELECTED = Color.RED;
private static final Color COLOR_SELECTED_BG = Color.ORANGE;
private static final Color COLOR_ALT_SCALE = Color.RED;
{
int width = getWidth();
int height = getHeight();
- AltitudeRange altitudeRange = _track.getAltitudeRange();
- int minAltitude = altitudeRange.getMinimum();
- int maxAltitude = altitudeRange.getMaximum();
// message if no altitudes in track
- if (minAltitude < 0 || maxAltitude < 0
- || minAltitude == maxAltitude)
+ if (!_track.hasAltitudeData())
{
g.setColor(COLOR_LINES);
g.drawString(I18nManager.getText("display.noaltitudes"), 50, height/2);
}
// altitude profile
+ AltitudeRange altitudeRange = _track.getAltitudeRange();
+ int minAltitude = altitudeRange.getMinimum();
+ int maxAltitude = altitudeRange.getMaximum();
int numPoints = _track.getNumPoints();
_xScaleFactor = 1.0 * (width - 2 * BORDER_WIDTH) / numPoints;
- double yScaleFactor = 1.0 * (height - 2 * BORDER_WIDTH) /
- (altitudeRange.getMaximum() - minAltitude);
+ double yScaleFactor = 1.0 * (height - 2 * BORDER_WIDTH) / (maxAltitude - minAltitude);
int barWidth = (int) (_xScaleFactor + 1.0);
int selectedPoint = _trackInfo.getSelection().getCurrentPointIndex();
+ // selection start, end
+ int selectionStart = -1, selectionEnd = -1;
+ if (_trackInfo.getSelection().hasRangeSelected()) {
+ selectionStart = _trackInfo.getSelection().getStart();
+ selectionEnd = _trackInfo.getSelection().getEnd();
+ }
// horizontal lines for scale - set to round numbers eg 500m
int lineScale = getLineScale(minAltitude, maxAltitude);
else
{
g.setColor(COLOR_ALT_BARS);
+ if (p >= selectionStart && p <= selectionEnd) {
+ g.setColor(COLOR_CURR_RANGE);
+ }
}
if (_track.getPoint(p).getAltitude().isValid())
{
{
// work out which data point is nearest and select it
int pointNum = (int) ((e.getX() - BORDER_WIDTH) / _xScaleFactor);
- _trackInfo.getSelection().selectPoint(pointNum);
+ _trackInfo.selectPoint(pointNum);
}
}
}
import tim.prune.DataSubscriber;
import tim.prune.I18nManager;
-import tim.prune.data.DataPoint;
-import tim.prune.data.Photo;
import tim.prune.data.TrackInfo;
/**
_photoList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e)
{
- if (!e.getValueIsAdjusting()) selectPhoto(_photoList.getSelectedIndex());
+ if (!e.getValueIsAdjusting()) {
+ selectPhoto(_photoList.getSelectedIndex());
+ }
}});
JPanel photoListPanel = new JPanel();
photoListPanel.setLayout(new BorderLayout());
{
if (_track != null && !_ignoreScrollEvents)
{
- _trackInfo.getSelection().selectPoint(inValue);
+ _trackInfo.selectPoint(inValue);
}
}
}
else
{
- _scroller.setMaximum(_track.getNumPoints() + SCROLLBAR_INTERVAL);
+ _scroller.setMaximum(_track.getNumPoints() -1 + SCROLLBAR_INTERVAL);
if (currentPointIndex >= 0)
_scroller.setValue(currentPointIndex);
_scroller.setEnabled(true);
_waypointList.clearSelection();
}
}
- // Do the same for the photos
- if (_photoList.getSelectedIndex() >= 0)
+ // Make sure correct photo is selected
+ if (_photoListModel.getSize() > 0)
{
- DataPoint trackPoint = _trackInfo.getCurrentPoint();
- Photo selectedPhoto = _photoListModel.getPhoto(_photoList.getSelectedIndex());
- // Get selected Photo, if it's still there
- DataPoint photoPoint = null;
- if (selectedPhoto != null) {
- photoPoint = _photoListModel.getPhoto(_photoList.getSelectedIndex()).getDataPoint();
- }
- // Compare selected photo with selected point
- if ( (photoPoint != null && (trackPoint == null || !photoPoint.equals(trackPoint)))
- || (_trackInfo.getSelection().getCurrentPhotoIndex() < 0) )
+ int photoIndex = _trackInfo.getSelection().getCurrentPhotoIndex();
+ int listSelection = _photoList.getSelectedIndex();
+ // Change listbox selection if indexes not equal
+ if (listSelection != photoIndex)
{
- // photo is selected in list but different from current point - deselect
- _photoList.clearSelection();
- _trackInfo.getSelection().deselectPhoto();
+ if (photoIndex < 0) {
+ _photoList.clearSelection();
+ }
+ else {
+ _photoList.setSelectedIndex(photoIndex);
+ }
}
}
}
--- /dev/null
+package tim.prune.gui;
+
+import tim.prune.gui.map.MapCanvas;
+import tim.prune.gui.map.MapPosition;
+import tim.prune.gui.map.MapUtils;
+
+/**
+ * Class to provide access to current viewport
+ * The point of this class is to decouple the view from the MapCanvas object
+ * so that when the GetGpsies function needs to know the area currently viewed, it doesn't
+ * need to have a direct connection to the MapCanvas. Instead it asks the App for the viewport,
+ * which is then able to get the map position from the MapCanvas.
+ * I'm still not sure whether this is ugly or not, but it's more efficient than constantly listening.
+ */
+public class Viewport
+{
+ /** Map canvas object */
+ private MapCanvas _mapCanvas = null;
+
+ /**
+ * Constructor
+ * @param inCanvas map canvas object
+ */
+ public Viewport(MapCanvas inCanvas)
+ {
+ _mapCanvas = inCanvas;
+ }
+
+ /**
+ * @return coordinate bounds of current viewport
+ */
+ public double[] getBounds()
+ {
+ int width = _mapCanvas.getWidth();
+ int height = _mapCanvas.getHeight();
+ MapPosition mapPosition = _mapCanvas.getMapPosition();
+ double minLat = MapUtils.getLatitudeFromY(mapPosition.getYFromPixels(height, height));
+ double maxLat = MapUtils.getLatitudeFromY(mapPosition.getYFromPixels(0, height));
+ double minLon = MapUtils.getLongitudeFromX(mapPosition.getXFromPixels(0, width));
+ double maxLon = MapUtils.getLongitudeFromX(mapPosition.getXFromPixels(width, width));
+ return new double[] {minLat, minLon, maxLat, maxLon};
+ }
+}
--- /dev/null
+package tim.prune.gui;
+
+import java.util.ArrayList;
+import javax.swing.AbstractListModel;
+
+import tim.prune.data.DataPoint;
+import tim.prune.data.Track;
+
+/**
+ * Class to deal with the matching of waypoint names
+ * and the representation in a list
+ */
+public class WaypointNameMatcher extends AbstractListModel
+{
+ private ArrayList<DataPoint> _waypoints = null;
+ private int _numPoints = 0;
+ private String[] _waypointNames = null;
+ private ArrayList<DataPoint> _matches = null;
+
+
+ /**
+ * Initialisation giving Track object
+ * @param inTrack Track object
+ */
+ public void init(Track inTrack)
+ {
+ // Get list of waypoints from track
+ _waypoints = new ArrayList<DataPoint>();
+ inTrack.getWaypoints(_waypoints);
+ // Initialise match flags and waypoint names
+ _numPoints = _waypoints.size();
+ _waypointNames = new String[_numPoints];
+ for (int i=0; i<_numPoints; i++) {
+ _waypointNames[i] = _waypoints.get(i).getWaypointName().toLowerCase();
+ }
+ _matches = new ArrayList<DataPoint>();
+ findMatches(null);
+ }
+
+ /**
+ * Search for the given term and collect the matches
+ * @param inSearch string to search for
+ */
+ public void findMatches(String inSearch)
+ {
+ // Reset array
+ _matches.clear();
+ // Convert search to lower case to match name array
+ String search = null;
+ if (inSearch != null && !inSearch.equals("")) {
+ search = inSearch.toLowerCase();
+ }
+ // Loop through waypoint names
+ for (int i=0; i<_numPoints; i++)
+ {
+ if (search == null || _waypointNames[i].indexOf(search) >= 0)
+ {
+ _matches.add(_waypoints.get(i));
+ }
+ }
+ fireChanged();
+ }
+
+ /**
+ * @see javax.swing.ListModel#getSize()
+ */
+ public int getSize()
+ {
+ if (_numPoints == 0) return 0;
+ return _matches.size();
+ }
+
+ /**
+ * @see javax.swing.ListModel#getElementAt(int)
+ */
+ public Object getElementAt(int inIndex)
+ {
+ return _matches.get(inIndex).getWaypointName();
+ }
+
+ /**
+ * Get the waypoint at the given index
+ * @param inIndex index number, starting at 0
+ * @return DataPoint object
+ */
+ public DataPoint getWaypoint(int inIndex)
+ {
+ return _matches.get(inIndex);
+ }
+
+ /**
+ * Fire event to notify that contents have changed
+ */
+ public void fireChanged()
+ {
+ this.fireContentsChanged(this, 0, getSize()-1);
+ }
+}
return parseValue(getText());
}
+ /**
+ * @param inValue value to set
+ */
+ public void setValue(int inValue)
+ {
+ setText("" + inValue);
+ }
+
/**
* @param inText text to parse
* @return value as integer
private App _app = null;
/** Track object */
private Track _track = null;
+ /** TrackInfo object */
+ private TrackInfo _trackInfo = null;
/** Selection object */
private Selection _selection = null;
/** Previously selected point */
private BufferedImage _mapImage = null;
/** Slider for transparency */
private JSlider _transparencySlider = null;
+ /** Checkbox for scale bar */
+ private JCheckBox _scaleCheckBox = null;
/** Checkbox for maps */
private JCheckBox _mapCheckBox = null;
/** Checkbox for autopan */
private JPanel _topPanel = null;
/** Side component panel */
private JPanel _sidePanel = null;
+ /** Scale bar */
+ private ScaleBar _scaleBar = null;
/* Data */
private DoubleRange _latRange = null, _lonRange = null;
private DoubleRange _xRange = null, _yRange = null;
public MapCanvas(App inApp, TrackInfo inTrackInfo)
{
_app = inApp;
+ _trackInfo = inTrackInfo;
_track = inTrackInfo.getTrack();
_selection = inTrackInfo.getSelection();
_mapPosition = new MapPosition();
});
_transparencySlider.setFocusable(false); // stop slider from stealing keyboard focus
_topPanel.add(_transparencySlider);
+ // Add checkbox button for enabling scale bar
+ _scaleCheckBox = new JCheckBox(IconManager.getImageIcon(IconManager.SCALEBAR_BUTTON), true);
+ _scaleCheckBox.setSelectedIcon(IconManager.getImageIcon(IconManager.SCALEBAR_BUTTON_ON));
+ _scaleCheckBox.setOpaque(false);
+ _scaleCheckBox.setToolTipText(I18nManager.getText("menu.map.showscalebar"));
+ _scaleCheckBox.addItemListener(new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ _scaleBar.setVisible(_scaleCheckBox.isSelected());
+ }
+ });
+ _scaleCheckBox.setFocusable(false); // stop button from stealing keyboard focus
+ _topPanel.add(_scaleCheckBox);
// Add checkbox button for enabling maps or not
_mapCheckBox = new JCheckBox(IconManager.getImageIcon(IconManager.MAP_BUTTON), false);
_mapCheckBox.setSelectedIcon(IconManager.getImageIcon(IconManager.MAP_BUTTON_ON));
zoomOutButton.setFocusable(false); // stop button from stealing keyboard focus
_sidePanel.add(zoomOutButton);
+ // Bottom panel for scale bar
+ _scaleBar = new ScaleBar();
+
// add control panels to this one
setLayout(new BorderLayout());
_topPanel.setVisible(false);
_sidePanel.setVisible(false);
add(_topPanel, BorderLayout.NORTH);
add(_sidePanel, BorderLayout.WEST);
+ add(_scaleBar, BorderLayout.SOUTH);
// Make popup menu
makePopup();
}
}
// Draw the mapImage if necessary
- if ((_mapImage == null || _recalculate)) {
+ if ((_mapImage == null || _recalculate))
+ {
getMapTiles();
+ _scaleBar.updateScale(_mapPosition.getZoom(), _mapPosition.getCentreTileY());
}
// Draw the prepared image onto the panel
if (_mapImage != null) {
inG.fillRect(0, 0, getWidth(), getHeight());
inG.setColor(COLOR_MESSAGES);
inG.drawString(I18nManager.getText("display.nodata"), 50, getHeight()/2);
+ _scaleBar.updateScale(-1, 0);
}
// Draw slider etc on top
paintChildren(inG);
// Make maps brighter / fainter
float[] scaleFactors = {1.0f, 1.05f, 1.1f, 1.2f, 1.6f, 2.0f};
float scaleFactor = scaleFactors[_transparencySlider.getValue()];
- if (scaleFactor > 1.0f) {
+ if (scaleFactor > 1.0f)
+ {
RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
RescaleOp op = new RescaleOp(scaleFactor, 0, hints);
_mapPosition.getXFromPixels(inE.getX(), getWidth()),
_mapPosition.getYFromPixels(inE.getY(), getHeight()),
_mapPosition.getBoundsFromPixels(CLICK_SENSITIVITY), false);
- _selection.selectPoint(pointIndex);
+ _trackInfo.selectPoint(pointIndex);
}
else
{
public void keyPressed(KeyEvent inE)
{
int code = inE.getKeyCode();
+ int currPointIndex = _selection.getCurrentPointIndex();
// Check for meta key
if (inE.isControlDown())
{
else if (code == KeyEvent.VK_DOWN)
zoomOut();
// Key nav for next/prev point
- else if (code == KeyEvent.VK_LEFT)
- _selection.selectPreviousPoint();
+ else if (code == KeyEvent.VK_LEFT && currPointIndex > 0)
+ _trackInfo.selectPoint(currPointIndex-1);
else if (code == KeyEvent.VK_RIGHT)
- _selection.selectNextPoint();
+ _trackInfo.selectPoint(currPointIndex+1);
}
else
{
rightwardsPan = -PAN_DISTANCE;
panMap(rightwardsPan, upwardsPan);
// Check for delete key to delete current point
- if (code == KeyEvent.VK_DELETE && _selection.getCurrentPointIndex() >= 0)
+ if (code == KeyEvent.VK_DELETE && currPointIndex >= 0)
{
_app.deleteCurrentPoint();
}
else if (clicks > 0)
zoomOut();
}
+
+ /**
+ * @return current map position
+ */
+ public MapPosition getMapPosition()
+ {
+ return _mapPosition;
+ }
}
private MapTileConfig _tileConfig = null;
/** Grid size */
- private static final int GRID_SIZE = 11;
+ private static final int GRID_SIZE = 15;
/** max zoom level of map tiles */
private static final int MAX_TILE_ZOOM = 18;
*/
public void centreMap(int inZoom, int inTileX, int inTileY)
{
- if (inZoom != _zoom)
+ int shift = Math.max(Math.abs(inTileX-_tileX), Math.abs(inTileY - _tileY));
+ if (shift == 0) {return;}
+ // Clear cache if either zoom has changed or map has jumped too far
+ if (inZoom != _zoom || shift > GRID_SIZE/2)
{
_zoom = inZoom;
clearAll();
*/
public MapTileConfig()
{
- _index = Config.getMapServerIndex();
- _url = fixUrl(Config.getMapServerUrl());
+ _index = Config.getConfigInt(Config.KEY_MAPSERVERINDEX);
+ _url = fixUrl(Config.getConfigString(Config.KEY_MAPSERVERURL));
// reset index wrong or if other url too short
if (_index < 0 || _index > OTHER_SERVER_NUM ||
(_index == OTHER_SERVER_NUM && (_url == null || _url.length() < 5)))
--- /dev/null
+package tim.prune.gui.map;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import javax.swing.JPanel;
+
+import tim.prune.Config;
+import tim.prune.I18nManager;
+
+/**
+ * Class to show a scale bar on the main map of Prune
+ */
+public class ScaleBar extends JPanel
+{
+ /** zoom level */
+ private int _zoomLevel = -1;
+ /** y tile number */
+ private int _yTile = -1;
+
+ // Dimensions
+ /** Offset from left side in pixels */
+ private static final int LEFT_OFFSET = 20;
+ /** Offset from top in pixels */
+ private static final int Y_OFFSET = 10;
+ /** Tick height in pixels */
+ private static final int TICK_HEIGHT = 5;
+ /** 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};
+ /** 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};
+
+
+ /**
+ * Constructor
+ */
+ public ScaleBar()
+ {
+ super();
+ setOpaque(false);
+ setPreferredSize(new Dimension(100, 20));
+ }
+
+ /**
+ * Paint method to override display
+ * @param inG graphics object
+ */
+ public void paint(Graphics inG)
+ {
+ super.paint(inG);
+ if (_zoomLevel > -1)
+ {
+ 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]);
+
+ // 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);
+ final double lat = Math.atan(Math.sinh(angle));
+ final double cosLat = Math.cos(lat);
+ rightSide = (int) (rightSide / cosLat);
+ // Adjust if scale is too large
+ while (rightSide > 300)
+ {
+ rightSide /= 2;
+ scale /= 2;
+ // Abort if scale is now less than 1 unit (shouldn't ever be)
+ if (scale < 1) {return;}
+ }
+
+ // horizontal
+ inG.setColor(Color.BLACK);
+ inG.drawLine(LEFT_OFFSET, Y_OFFSET, rightSide, Y_OFFSET);
+ inG.drawLine(LEFT_OFFSET, Y_OFFSET+1, rightSide, Y_OFFSET+1);
+ // 0 tick
+ inG.drawLine(LEFT_OFFSET, Y_OFFSET, LEFT_OFFSET, Y_OFFSET-TICK_HEIGHT);
+ inG.drawLine(LEFT_OFFSET+1, Y_OFFSET, LEFT_OFFSET+1, Y_OFFSET-TICK_HEIGHT);
+ // end tick
+ inG.drawLine(rightSide, Y_OFFSET, rightSide, Y_OFFSET-TICK_HEIGHT);
+ inG.drawLine(rightSide+1, Y_OFFSET, rightSide+1, Y_OFFSET-TICK_HEIGHT);
+ // text
+ String text = (scale>0?(""+scale):("1/"+(-scale))) + " " + I18nManager.getText(useMetric?"units.kilometres.short":"units.miles.short");
+ inG.drawString(text, rightSide+MARGIN_WIDTH, Y_OFFSET);
+ }
+ catch (ArrayIndexOutOfBoundsException ai) {}
+ }
+ }
+
+ /**
+ * Update the scale level
+ * @param inZoom new zoom level
+ */
+ public void updateScale(int inZoom, int inYtile)
+ {
+ _zoomLevel = inZoom;
+ _yTile = inYtile;
+ }
+}
--- /dev/null
+# Text entries for the Prune application
+# Afrikaans entries as extra
+
+# Menu entries
+menu.file=L\u00eaer
+menu.file.open=Open L\u00eaer
+menu.file.addphotos=Voeg Fotos By
+menu.file.save=Stoor
+menu.file.exit=Gaan Uit
+menu.edit=Redigeer
+menu.edit.undo=Herroep
+menu.edit.clearundo=Herroep Lys Skoonmaak
+menu.edit.editpoint=Redigeer Punt
+menu.edit.deletepoint=Punt Uitvee
+menu.edit.deleterange=Reeks Uitvee
+menu.edit.deletemarked=Gemerkde Punt Uitvee
+menu.edit.interpolate=Interpoleer
+menu.edit.average=Gemiddelde Seleksie
+menu.edit.reverse=Reeks Omkeer
+menu.edit.mergetracksegments=Saamvoeg van spoor segmente
+menu.edit.rearrange=Herrangskik bakens
+menu.edit.rearrange.start=Bakens na begin van l\u00eaer
+menu.edit.rearrange.end=Bakens na einde van l\u00eaer
+menu.edit.rearrange.nearest=Beweeg elk na naaste spoor punt
+menu.edit.cutandmove=Sny en skuif seleksie
+menu.select=Selekteer
+menu.select.all=Selekteer Alles
+menu.select.none=Selekteer Niks
+menu.select.start=Stel Reeks Begin
+menu.select.end=Stel Reeks Einde
+menu.photo=Foto
+menu.photo.saveexif=Stoor na EXIF
+menu.photo.connect=Las foto by huidige punt
+menu.photo.disconnect=Ontkoppel foto vanaf huidige punt
+menu.photo.delete=Verwyder foto
+menu.view=Kyk
+menu.view.browser=Kaart in werf blaaier
+menu.view.browser.google=Google Kaarte
+menu.view.browser.openstreetmap=Openstreetmap
+menu.view.browser.mapquest=Mapquest
+menu.view.browser.yahoo=Yahoo Kaarte
+menu.help=Hulp
+# Popup menu for map
+menu.map.zoomin=Zoom in
+menu.map.zoomout=Zoom uit
+menu.map.zoomfull=Zoom na vol skaal
+menu.map.newpoint=Skep nuwe punt
+menu.map.connect=Connekteer baan punte
+menu.map.autopan=Automatiese Skuif van Kyk Venster
+menu.map.showmap=Wys Kaart
+
+# Functions
+function.loadfromgps=Laai van GPS data
+function.sendtogps=Stuur van GPS data
+function.exportkml=KML Uitvoer
+function.exportgpx=GPS Uitvoer
+function.exportpov=POV Uitvoer
+function.editwaypointname=Redigeer Baken Naam
+function.compress=Kompakteer spoor
+function.addtimeoffset=Voeg tyd spruit by
+function.findwaypoint=Vind Baken
+function.charts=Grafieke
+function.show3d=3D Kyk
+function.distances=Afstande
+function.setmapbg=Stel Kaart agtergrond
+function.getgpsies=Kry GPS spore
+function.correlatephotos=Korreleer Fotos
+function.help=Hulp
+function.showkeys=Wys Kortpad sleutels
+function.about=Omtrent Prune
+function.checkversion=Kyk vir nuwe weergawe
+function.saveconfig=Stoor Stellings
+
+# Dialogs
+dialog.exit.confirm.title=Uitgaan uit Prune
+dialog.exit.confirm.text=Jou data is nie gestoor nie. Is jy seker jy wil uitgaan?
+dialog.openappend.title=Voegby tot bestaande data
+dialog.openappend.text=Voeg hierdie data by die data wat alreeds gelaai is?
+dialog.deletepoint.title=Vee punt uit
+dialog.deletepoint.deletephoto=Vee aangehegde foto van die punt uit?
+dialog.deletephoto.title=Vee foto uit
+dialog.deletephoto.deletepoint=Vee punt uit wat aan hierdie foto geheg is?
+dialog.openoptions.title=Oopmaak Opsies
+dialog.openoptions.filesnippet=Ekstrak vanuit L\u00eaer
+dialog.load.table.field=Veld
+dialog.load.table.datatype=Data Tipe
+dialog.load.table.description=Beskrywing
+dialog.delimiter.label=Veld Skeinding Karakter
+dialog.delimiter.comma=Komma ,
+dialog.delimiter.tab=Tab
+dialog.delimiter.space=Spasie
+dialog.delimiter.semicolon=Komma Punt ;
+dialog.delimiter.other=Ander
+dialog.openoptions.deliminfo.records=Rekords, met
+dialog.openoptions.deliminfo.fields=velde
+dialog.openoptions.deliminfo.norecords=Geen rekords
+dialog.openoptions.altitudeunits=Hoogte Eenhede
+dialog.jpegload.subdirectories=Sluit sub-gidse in
+dialog.jpegload.loadjpegswithoutcoords=Sluit fotos sonder koordinate in
+dialog.jpegload.loadjpegsoutsidearea=Sluit foto buitekant huidige area in
+dialog.jpegload.progress.title=Fotos Laai
+dialog.jpegload.progress=Wag asseblief terwyl fotos gesoek word
+dialog.gpsload.nogpsbabel=Geen gpsbabel program kon gevind word. Gaanvoort?
+dialog.gpsload.device=Apparaat naam
+dialog.gpsload.format=Formaat
+dialog.gpsload.getwaypoints=Laai Bakens
+dialog.gpsload.gettracks=Laai spore
+dialog.gpssend.sendwaypoints=Stuur Bakens
+dialog.gpssend.sendtracks=Stuur Spore
+dialog.gpssend.trackname=Spoor name
+dialog.saveoptions.title=Stoor L\u00eaer
+dialog.save.fieldstosave=Velde om te stoor
+dialog.save.table.field=Veld
+dialog.save.table.hasdata=Het Data
+dialog.save.table.save=Stoor
+dialog.save.headerrow=Hoof Afvoer Ry
+dialog.save.coordinateunits=Koordinaat eenhede
+dialog.save.altitudeunits=Hoogte Eenhede
+dialog.save.timestampformat=Tyd Stempel Formaat
+dialog.save.overwrite.title=L\u00eaer bestaan reeds
+dialog.save.overwrite.text=Hierdie L\u00eaer bestaan reeds. Is jy seker jy wil die l\u00eaer oorskryf?
+dialog.exportkml.text=Titel vir die data
+dialog.exportkml.altitude=Absolute hoogte (vir aviasie)
+dialog.exportkml.kmz=Kompakteer om kmz l\u00eaer te maak
+dialog.exportkml.exportimages=Voer beeld duimnaelsketse uit na kmz
+dialog.exportgpx.name=Naam
+dialog.exportgpx.desc=Beskrywing
+dialog.exportgpx.includetimestamps=Tydstempel Insluit
+dialog.exportpov.text=Steutel asseblief parameters in vir POV uitvoer
+dialog.exportpov.font=Font
+dialog.exportpov.camerax=Kamera X
+dialog.exportpov.cameray=Kamera Y
+dialog.exportpov.cameraz=Kamera Z
+dialog.exportpov.modelstyle=Model styl
+dialog.exportpov.ballsandsticks=Balle en stokkies
+dialog.exportpov.tubesandwalls=Buise en mure
+dialog.exportpov.warningtracksize=Hierdie spoor het 'n groot aantal punte, wat Java3D miskien nie kan vertoon.\nIs jy seker jy wil voortgaan?
+dialog.pointtype.desc=Stoor die volgende punt tipes
+dialog.pointtype.track=Spoor punte
+dialog.pointtype.waypoint=Bakens
+dialog.pointtype.photo=Foto punte
+dialog.confirmreversetrack.title=Bevestig omkering
+dialog.confirmreversetrack.text=Hierdie spoor bevat tydstempel informasie, wat uit sekwensie/order sal wees na omkering.\nIs jy seker jy wil die spoor omruil vir die seksie?
+dialog.confirmcutandmove.title=Bevestig sny en skuif
+dialog.confirmcutandmove.text=Hierdie spoor het tydstempel informasie, wat uit sekwensie/orde sal wees na skuif.\nIs jy seker jy wil die seksie skuif?
+dialog.interpolate.title=Interpoleer punte
+dialog.interpolate.parameter.text=Aantal punte om bytevoeg tussen geselekteerde punte.
+dialog.undo.title=Herroep aksie(s)
+dialog.undo.pretext=Selekteer asb die aksie(s) om te herroep
+dialog.undo.none.title=Kan nie herroep
+dialog.undo.none.text=Geen operasies om te herroep!
+dialog.clearundo.title=Maak Herroep lys uit skoon
+dialog.clearundo.text=Is jy seker jy wil die herroep lys skoon maak?\nAlle herroep informasie sal verlore gaan!
+dialog.pointedit.title=Redigeer punt
menu.edit.undo=Rückgängig
menu.edit.clearundo=Liste der letzten Änderungen löschen
menu.edit.editpoint=Punkt bearbeiten
-menu.edit.editwaypointname=Waypoint Name bearbeiten
menu.edit.deletepoint=Punkt löschen
menu.edit.deleterange=Bereich löschen
-menu.edit.deletemarked=Komprimierten Punkte löschen
+menu.edit.deletemarked=Komprimierte Punkte löschen
menu.edit.interpolate=Interpolieren
menu.edit.average=Durchschnitt berechnen
menu.edit.reverse=Bereich umkehren
-menu.edit.mergetracksegments=Trackteile verbinden
-menu.edit.rearrange=Waypoints reorganisieren
-menu.edit.rearrange.start=Alle Waypoints zum Anfang
-menu.edit.rearrange.end=Alle Waypoints zum Ende
-menu.edit.rearrange.nearest=Jeden Waypoint zum nächsten Trackpunkt verschieben
+menu.edit.mergetracksegments=Trackabschnitte verbinden
+menu.edit.rearrange=Wegpunkte reorganisieren
+menu.edit.rearrange.start=Alle Wegpunkte zum Anfang
+menu.edit.rearrange.end=Alle Wegpunkte ans Ende
+menu.edit.rearrange.nearest=Jeden Wegpunkt zum nächsten Trackpunkt verschieben
menu.edit.cutandmove=Schneiden und verschieben
menu.select=Markieren
menu.select.all=Alles markieren
menu.view.browser.openstreetmap=Openstreetmap
menu.view.browser.mapquest=
menu.view.browser.yahoo=
+menu.settings=Einstellungen
+menu.settings.showpace=Tempo anzeigen
menu.help=Hilfe
# Popup menu for map
menu.map.zoomin=Hineinzoomen
menu.map.zoomout=Herauszoomen
-menu.map.zoomfull=Auf Bildschirmgröße anpassen
-menu.map.newpoint=Neuen Punkt kreieren
+menu.map.zoomfull=Auf Bildschirmgröße 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
+
+# Alt keys for menus
+altkey.menu.file=D
+altkey.menu.edit=B
+altkey.menu.select=M
+altkey.menu.view=A
+altkey.menu.photo=F
+altkey.menu.settings=E
+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.edit.undo=Z
+shortcut.menu.edit.compress=K
+shortcut.menu.select.all=A
+shortcut.menu.help.help=H
# Functions
function.loadfromgps=Vom GPS laden
function.exportkml=KML exportieren
function.exportgpx=GPX exportieren
function.exportpov=POV exportieren
+function.editwaypointname=Wegpunkt Name bearbeiten
function.compress=Track komprimieren
-function.addtimeoffset=Zeitdifferenz addieren
-function.charts=Diagrammen
+function.addtimeoffset=Zeitverschiebung aufrechnen
+function.addaltitudeoffset=Höhenverschiebung aufrechnen
+function.findwaypoint=Wegpunkt finden
+function.charts=Diagramme
function.show3d=3D Ansicht
function.distances=Distanzen
function.setmapbg=Karte Hintergrund setzen
+function.setkmzimagesize=Bildgröße im KMZ setzen
+function.setpaths=Programmenpfade setzen
+function.getgpsies=Gpsies Tracks holen
function.correlatephotos=Fotos korrelieren
function.help=Hilfe
+function.showkeys=Tastenkombinationen anzeigen
function.about=Ãœber Prune
function.checkversion=Nach neuen Versionen suchen
+function.saveconfig=Einstellungen 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=an existierende Daten anhängen oder ersetzen
+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.deletephoto.title=Foto entfernen
dialog.deletephoto.deletepoint=Den zu diesem Foto gehörenden Punkt auch löschen?
dialog.openoptions.title=Öffnen
-dialog.openoptions.filesnippet=Extrakt von der Datei
+dialog.openoptions.filesnippet=Dateiausschnitt
dialog.load.table.field=Feld
dialog.load.table.datatype=Daten Typ
dialog.load.table.description=Beschreibung
dialog.jpegload.loadjpegsoutsidearea=Auch Fotos ausserhalb vom Track laden
dialog.jpegload.progress.title=Fotos werden geladen
dialog.jpegload.progress=Bitte warten während die Fotos durchgesucht werden
-dialog.gpsload.nogpsbabel=Kein gpsbabel Programm wurde gefunden. Weiter?
-dialog.gpsload.device=Device Name
+dialog.gpsload.nogpsbabel=Programm gpsbabel wurde nicht gefunden. Weiter?
+dialog.gpsload.device=Gerätename
dialog.gpsload.format=Format
-dialog.gpsload.getwaypoints=Waypoints laden
+dialog.gpsload.getwaypoints=Wegpunkte laden
dialog.gpsload.gettracks=Tracks laden
-dialog.gpssend.sendwaypoints=Waypoints schicken
-dialog.gpssend.sendtracks=Tracks schicken
+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.altitudeunits=Höhe Maßeinheiten
dialog.save.timestampformat=Zeitstempelformat
dialog.save.overwrite.title=Datei schon vorhanden
-dialog.save.overwrite.text=Diese Datei existiert schon. Wollen Sie die vorhandene Datei überschreiben?
+dialog.save.overwrite.text=Diese Datei gibt es schon. Wollen Sie die vorhandene Datei überschreiben?
dialog.exportkml.text=Titel für die Daten
-dialog.exportkml.altitude=Auch Höheninformation (für Luftfahrt)
+dialog.exportkml.altitude=Absolute Höheninformation (für Luftfahrt)
dialog.exportkml.kmz=Daten in kmz Datei komprimieren
-dialog.exportkml.exportimages=Bilder in kmz exportieren
+dialog.exportkml.exportimages=Vorschaubilder mit in kmz exportieren
dialog.exportgpx.name=Name
dialog.exportgpx.desc=Beschreibung
-dialog.exportgpx.includetimestamps=Zeitstempel exportieren
+dialog.exportgpx.includetimestamps=Zeitstempel mit exportieren
dialog.exportpov.text=Geben Sie die Parameter für den POV Export ein
dialog.exportpov.font=Font
dialog.exportpov.camerax=Kamera X
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 fortführen?
+dialog.exportpov.warningtracksize=Dieser Track hat sehr viele Punkte, die Java3D vielleicht nicht bearbeiten kann.\nMöchten Sie den Vorgang trotzdem fortsetzen?
+dialog.pointtype.desc=Folgende Punkttypen speichern:
+dialog.pointtype.track=Trackpunkte
+dialog.pointtype.waypoint=Wegpunkte
+dialog.pointtype.photo=Fotopunkte
dialog.confirmreversetrack.title=Umkehrung bestätigen
-dialog.confirmreversetrack.text=Diese Daten enthalten Zeitstempel Informationen, die bei einer Umkehrung in falscher Reihenfolge erscheinen würden.\nSind Sie sicher, dass Sie diesen Bereich umkehren wollen?
+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 Zeitstempel Informationen, die nach dem Verschieben in falscher Reihenfolge erscheinen würden.\nSind Sie sicher, dass Sie diesen Bereich verschieben wollen?
+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.interpolate.title=Punkte interpolieren
-dialog.interpolate.parameter.text=Anzahl Punkte die zwischen den gewählten Punkten eingefügt werden sollen
+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=Auswahl der Operationen die rückgängig gemacht werden sollen.
+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=Sind Sie sicher, Sie wollen die Undo-Liste löschen?\nAlle Undo Information wird veloren gehen!
dialog.pointedit.title=Punkt bearbeiten
-dialog.pointedit.text=Wählen Sie jeden Feld aus zu bearbeiten, und mit dem 'Bearbeiten' Knopf den Wert ändern
+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.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.changevalue.title=Feld bearbeiten
-dialog.pointnameedit.title=Waypoint Name bearbeiten
-dialog.pointnameedit.name=Waypoint Name
+dialog.pointnameedit.name=Wegpunkt Name
dialog.pointnameedit.uppercase=GROß geschrieben
dialog.pointnameedit.lowercase=klein geschrieben
dialog.pointnameedit.sentencecase=Gemischt geschrieben
dialog.addtimeoffset.hours=Stunde
dialog.addtimeoffset.minutes=Minute
dialog.addtimeoffset.notimestamps=Zeitdifferenz kann nicht addiert werden weil dieser Bereich keine Zeitinformation hat
+dialog.findwaypoint.intro=Geben Sie einen Teil von dem Namen ein
+dialog.findwaypoint.search=Suche
dialog.connect.title=Foto mit Punkt verbinden
-dialog.connectphoto.clonepoint=Dieser Punkt hat schon ein Foto.\nWollen Sie eine Kopie von dem Punkt machen?
+dialog.connectphoto.clonepoint=Diesem Punkt ist schon ein Foto zugeordnet.\nWollen Sie eine Kopie dieses Punktes machen?
dialog.saveexif.title=Exif speichern
-dialog.saveexif.intro=Selektieren Sie die Fotos zu speichern
-dialog.saveexif.nothingtosave=Koordinaten sind nicht modifiziert, nichts zu 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.noexiftool=Kein exiftool Programm gefunden. Trotzdem fortfahren?
dialog.saveexif.table.photoname=Foto Name
dialog.saveexif.table.status=Status
dialog.charts.svg=zur SVG Datei
dialog.charts.svgwidth=SVG Breite
dialog.charts.svgheight=SVG Höhe
-dialog.charts.needaltitudeortimes=Ohne Daten über Höhe und Zeit, kann keine Diagrammen erzeugt werden.
+dialog.charts.needaltitudeortimes=Ohne Daten über Höhe und Zeit kann kein Diagramm erzeugt werden.
dialog.charts.gnuplotpath=Gnuplot Pfad
-dialog.charts.gnuplotnotfound=Gnuplot konnte mit diesem Pfad nicht gefunden werden
-dialog.distances.intro=Distanzen per Luftlinie zwischen Punkte
+dialog.charts.gnuplotnotfound=Gnuplot konnte im angegebenen Pfad nicht gefunden werden
+dialog.distances.intro=Luftlinienentfernung zwischen Punkte
dialog.distances.column.from=Vom Punkt
dialog.distances.column.to=Zum Punkt
-dialog.distances.currentpoint=Aktuelle Punkt
-dialog.distances.toofewpoints=Diese Funktion braucht Waypoints um die Distanzen zu berechnen
+dialog.distances.currentpoint=Aktueller Punkt
+dialog.distances.toofewpoints=Diese Funktion braucht Wegpunkte um die Distanzen zu berechnen
dialog.setmapbg.mapnik=
dialog.setmapbg.osma=
dialog.setmapbg.cyclemap=Fahrradkarte
dialog.setmapbg.other=Andere
dialog.setmapbg.server=Server URL
-dialog.correlate.notimestamps=Die Punkte haben keine Zeitinformation, deswegen ist es nicht möglich die Fotos zu korrelieren.
-dialog.correlate.nouncorrelatedphotos=Alle Photos sind schon korreliert.\nWollen Sie trotzdem fortsetzen?
-dialog.correlate.photoselect.intro=Selektieren Sie einen von diesen Fotos um die Differenz zu berechnen
-dialog.correlate.photoselect.photoname=Foto Name
+dialog.gpsies.column.name=Track Name
+dialog.gpsies.column.length=Länge
+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.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.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, die Zeitdifferenz kann automatisch berechnet werden.
-dialog.correlate.options.intro=Wählen Sie die Optionen aus für die Korrelation
+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.options.offsetpanel=Zeitunterschied
dialog.correlate.options.offset=Unterschied
dialog.correlate.options.offset.hours=Stunden,
dialog.correlate.options.nodistancelimit=Keine Distanzgrenzen
dialog.correlate.options.distancelimit=Distanzgrenzen
dialog.correlate.options.correlate=Korrelieren
-dialog.correlate.alloutsiderange=Alle Fotos sind ausserhalb vom Track Zeitraum, so können nicht korreliert werden.\nVersuchen Sie mit einem anderen Offset oder verbinden Sie manuell mindestens ein Foto.
+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.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=Komische Punkte entfernen
-dialog.compress.wackypoints.paramdesc=Distanz Faktor
-dialog.compress.singletons.title=Singletons entfernen
-dialog.compress.singletons.paramdesc=Distanz Faktor
+dialog.compress.wackypoints.title=Ungewöhnliche Punkte entfernen
+dialog.compress.wackypoints.paramdesc=Distanzfaktor
+dialog.compress.singletons.title=Singletons (isolierte Punkte) entfernen
+dialog.compress.singletons.paramdesc=Distanzfaktor
dialog.compress.summarylabel=Punkte zu entfernen
dialog.help.help=Bitte sehen Sie\n http://activityworkshop.net/software/prune/\nfür weitere Information und Benutzeranleitungen.
dialog.about.version=Version
dialog.about.build=Build
-dialog.about.summarytext1=Prune ist ein Programm für das Laden, Darstellen und Editieren von Daten von GPS Geräten.
-dialog.about.summarytext2=Es ist unter den Gnu GPL zur Verfügung gestellt, für frei, gratis und offen Gebrauch und Weiterentwicklung.<br>Kopieren, Weiterverbreitung und Veränderungen sind erlaubt und willkommen<br>unter die Bedingungen in der enthaltenen <code>license.txt</code> Datei.
-dialog.about.summarytext3=Bitte sehen Sie <code style="font-weight:bold">http://activityworkshop.net/</code> für weitere Information und Benutzeranleitungen.
+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.credits.icons=Einige Bilder von
dialog.about.credits.translators=Dolmetscher
dialog.about.credits.translations=Ãœbersetzungen mit Hilfe von
-dialog.about.credits.devtools=Entwicklungsprogrammen
-dialog.about.credits.othertools=Andere Programmen
+dialog.about.credits.devtools=Entwicklungsprogramme
+dialog.about.credits.othertools=Andere Programme
dialog.about.credits.thanks=Danke an
dialog.about.readme=Liesmich
-dialog.checkversion.error=Die Versionnummer konnte nicht geprüft werden.\nBitte prüfen Sie die Internet Verbindung.
+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.newversion2=.
dialog.checkversion.releasedate1=Diese neue Version ist am
dialog.checkversion.releasedate2=veröffentlicht worden.
-dialog.checkversion.download=Um die neue Version herunterzuladen, schauen Sie nach http://activityworkshop.net/software/prune/download.html.
+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>Entf</td><td>Aktuellen Punkt entfernen</td></tr></table>
+dialog.saveconfig.desc=Die folgende Einstellungen können gespeichert werden :
+dialog.saveconfig.prune.trackdirectory=Datenverzeichnis
+dialog.saveconfig.prune.photodirectory=Fotoverzeichnis
+dialog.saveconfig.prune.languagecode=Sprachecode (DE)
+dialog.saveconfig.prune.gpsdevice=GPS Gerätename
+dialog.saveconfig.prune.gpsformat=GPS Format
+dialog.saveconfig.prune.povrayfont=Povray Font
+dialog.saveconfig.prune.metricunits=Metrische Einheiten verwenden?
+dialog.saveconfig.prune.gnuplotpath=Gnuplot Pfad
+dialog.saveconfig.prune.gpsbabelpath=Gpsbabel Pfad
+dialog.saveconfig.prune.exiftoolpath=Exiftool Pfad
+dialog.saveconfig.prune.mapserverindex=Kartenserver Index
+dialog.saveconfig.prune.mapserverurl=Kartenserver URL
+dialog.saveconfig.prune.showpace=Tempo anzeigen
+dialog.saveconfig.prune.kmzimagewidth=Bildbreite in KMZ
+dialog.saveconfig.prune.kmzimageheight=Bildhöhe in KMZ
+dialog.setpaths.intro=Sie können hier die Pfade für externe Applikationen setzen:
+dialog.addaltitude.noaltitudes=Der markierten Bereich enthält keine Höhenangaben
+dialog.addaltitude.desc=Höhenverschiebung aufzurechnen
# 3d window
dialog.3d.title=Prune 3D Ansicht
dialog.3d.altitudecap=Minimum Höhenskala
dialog.3dlines.title=Prune Gitterlinien
-dialog.3dlines.empty=Keine Linien zum anzeigen!
+dialog.3dlines.empty=Keine Linien zum Anzeigen!
dialog.3dlines.intro=Hier sind die Linien für die 3D Ansicht
# Confirm messages || These are displayed as confirmation in the status bar
confirm.deletepoint.single=Punkt wurde entfernt
confirm.deletepoint.multi=Punkte wurden entfernt
confirm.point.edit=Punkt editiert
-confirm.mergetracksegments=Trackteilen verbunden
+confirm.mergetracksegments=Trackabschnitte verbunden
confirm.reverserange=Bereich umgekehrt
-confirm.addtimeoffset=Zeitdifferenz addiert
-confirm.rearrangewaypoints=Waypoints reorganisiert
+confirm.addtimeoffset=Zeitverschiebung aufgerechnet
+confirm.addaltitudeoffset=Höhenverschiebung aufgerechnet
+confirm.rearrangewaypoints=Wegpunkte reorganisiert
confirm.cutandmove=Bereich verschoben
confirm.saveexif.ok1=Es wurden
-confirm.saveexif.ok2=Foto Dateien geschrieben
+confirm.saveexif.ok2=Fotodateien geschrieben
confirm.undo.single=Operation rückgängig gemacht
confirm.undo.multi=Operationen rückgängig gemacht
confirm.jpegload.single=Foto wurde geladen
confirm.correlate.single=Foto wurde korreliert
confirm.correlate.multi=Fotos wurden korreliert
confirm.createpoint=Punkt kreiert
+confirm.running=In Bearbeitung ...
# Buttons
button.ok=OK
button.finish=Fertig
button.cancel=Abbrechen
button.overwrite=Ãœberschreiben
-button.moveup=Aufwärts moven
-button.movedown=Abwärts moven
+button.moveup=Nach oben verschieben
+button.movedown=Nach unten verschieben
button.showlines=Linien anzeigen
button.edit=Bearbeiten
button.exit=Beenden
button.notoall=Nein für alle
button.selectall=Alle selektieren
button.selectnone=Nichts selektieren
-button.preview=Vorschauen
+button.preview=Vorschau
+button.load=Laden
button.guessfields=Felder erraten
button.showwebpage=Webseite anzeigen
-button.gnuplotpath=Gnuplot Pfad setzen
+button.check=Prüfen
# File types
filetype.txt=TXT Dateien
# Display components
display.nodata=Keine Daten geladen
-display.noaltitudes=Track enthält keine Höhe Daten
+display.noaltitudes=Track enthält keine Höhenangaben
details.trackdetails=Details vom Track
details.notrack=Kein Track geladen
details.track.points=Punkte
details.index.selected=Index
details.index.of=von
details.nopointselection=Nichts selektiert
-details.photofile=Foto Datei
-details.norangeselection=Nichts selektiert
-details.rangedetails=Details vom Bereich
+details.photofile=Fotodatei
+details.norangeselection=Kein Bereich ausgewählt
+details.rangedetails=Details der Auswahl
details.range.selected=Markiert
details.range.to=bis
details.altitude.to=bis
display.range.time.days=T
details.range.avespeed=Geschwindigkeit
details.range.avemovingspeed=Geschwindigkeit unterwegs
-details.waypointsphotos.waypoints=Waypoints
+details.range.pace=Tempo
+details.waypointsphotos.waypoints=Wegpunkte
details.waypointsphotos.photos=Fotos
-details.photodetails=Details vom Foto
-details.nophoto=Kein Foto selektiert
+details.photodetails=Fotodetails
+details.nophoto=Kein Foto ausgewählt
details.photo.loading=Laden
details.photo.connected=Verbunden
-map.overzoom=Keine Karten mit diesem Zoom verfügbar
+map.overzoom=Keine Karten für diesen Zoomfaktor verfügbar
# Field names
fieldname.latitude=Breitengrad
fieldname.custom=Custom
fieldname.prefix=Feld
fieldname.distance=Länge
-fieldname.movingdistance=Weglänge
-fieldname.duration=Zeitlänge
+fieldname.movingdistance=Wegstrecke
+fieldname.duration=Zeitdauer
fieldname.speed=Geschwindigkeit
fieldname.verticalspeed=Vertikale Geschwindigkeit
# Measurement units
units.original=Original
-units.default=Default
+units.default=Standard
units.metres=Meter
units.metres.short=
units.feet=
undo.loadphotos=Fotos laden
undo.editpoint=Punkt bearbeiten
undo.deletepoint=Punkt löschen
-undo.deletephoto=Photo entfernen
+undo.deletephoto=Foto entfernen
undo.deleterange=Bereich löschen
undo.compress=Track komprimieren
undo.insert=Punkte hinzufügen
undo.reverse=Bereich umdrehen
-undo.mergetracksegments=Trackteile verbinden
-undo.addtimeoffset=zeitdifferenz addieren
-undo.rearrangewaypoints=Waypoints reorganisieren
+undo.mergetracksegments=Trackabschnitte verbinden
+undo.addtimeoffset=Zeitverschiebung aufrechnen
+undo.addaltitudeoffset=Höhenverschiebung aufrechnen
+undo.rearrangewaypoints=Wegpunkte reorganisieren
undo.cutandmove=Bereich verschieben
undo.connectphoto=Foto verbinden
undo.disconnectphoto=Foto trennen
# Error messages
error.save.dialogtitle=Fehler beim Speichern
-error.save.nodata=Keine Daten wurden geladen
-error.save.failed=Speichern von der Datei fehlgeschlagen:
+error.save.nodata=Keine Daten zum Sichern vorhanden
+error.save.failed=Speichern von der Datei fehlgeschlagen
error.saveexif.filenotfound=Foto Datei nicht gefunden
error.saveexif.cannotoverwrite1=Foto Datei
-error.saveexif.cannotoverwrite2=ist schreib-geschützt. Speichern zu einer Kopie?
+error.saveexif.cannotoverwrite2=ist schreib-geschützt. Als Kopie speichern?
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.jpegload.nogpsfound=Keine GPS Information gefunden
error.undofailed.title=Undo fehlgeschlagen
error.undofailed.text=Operation konnte nicht rückgängig gemacht werden
-error.function.noop.title=Funktion hat nichts gemacht
-error.rearrange.noop=Waypoints Reorganisieren hatte keinen Effekt
+error.function.noop.title=Funktion hat nichts bewirkt
+error.rearrange.noop=Die Wegpunkte zu reorganisieren hatte keinen Effekt
error.function.notavailable.title=Funktion nicht verfügbar
-error.function.nojava3d=Diese Funktion braucht den Java3d Library,\nvon Sun.com erhältlich.
-error.3d=Ein Fehler ist mit der 3d Darstellung aufgetreten
+error.function.nojava3d=Diese Funktion benötigt die Java3d Library,\nvon Sun.com erhältlich.
+error.3d=Ein Fehler ist bei der 3D Darstellung aufgetreten
error.readme.notfound=Liesmich Datei nicht gefunden
-error.osmimage.dialogtitle=Laden von Karten-Bilder fehlgeschlagen
-error.osmimage.failed=Laden von Karten-Bilder fehlgeschlagen. Bitte prüfen Sie die Internet-Verbindung.
+error.osmimage.dialogtitle=Laden von Karten-Bildern fehlgeschlagen
+error.osmimage.failed=Laden von Karten-Bildern fehlgeschlagen. Bitte prüfen Sie die Internetverbindung.
# Swiss-German entries as extra
# Menu entries
-menu.file=Datei
+menu.file=File
menu.file.open=File öffne
menu.file.addphotos=Fötelis innätue
menu.file.save=Speichere
menu.edit.undo=Undo
menu.edit.clearundo=Undo-Liste lösche
menu.edit.editpoint=Punkt editiere
-menu.edit.editwaypointname=Waypoint Name editiere
menu.edit.deletepoint=Punkt lösche
menu.edit.deleterange=Beriich lösche
menu.edit.deletemarked=Komprimierte Punkte lösche
menu.view.browser.openstreetmap=
menu.view.browser.mapquest=
menu.view.browser.yahoo=
+menu.settings=Iistellige
+menu.settings.showpace=Tempo aazeige
menu.help=Hilfe
# Popup menu for map
menu.map.zoomin=Innezoome
menu.map.connect=Trackpünktli verbindä
menu.map.autopan=Autopan
menu.map.showmap=Kate zeigä
+menu.map.showscalebar=Massstab aazeige
+
+# Alt keys for menus
+altkey.menu.file=F
+altkey.menu.edit=E
+altkey.menu.select=S
+altkey.menu.view=A
+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.edit.undo=Z
+shortcut.menu.edit.compress=K
+shortcut.menu.select.all=A
+shortcut.menu.help.help=H
# Functions
function.loadfromgps=uusem GPS lade
function.exportkml=KML exportierä
function.exportgpx=GPX exportierä
function.exportpov=POV exportierä
+function.editwaypointname=Waypoint Name editiere
function.compress=Track komprimierä
function.addtimeoffset=Ziitverschiebig zutue
+function.addaltitudeoffset=Höchiverschiebig zutue
+function.findwaypoint=Waypoint findä
function.charts=Diagramme
function.show3d=Drüü-D Aasicht
function.distances=Distanze
function.setmapbg=Karte Hintegrund setzä
+function.getgpsies=Gpsies Tracks holä
function.correlatephotos=Fötelis korrelierä
+function.setkmzimagesize=Bildligrösse inem KMZ setze
+function.setpaths=Programmepfade setze
function.help=Hilfe
+function.showkeys=Tastekombinatione aazeige
function.about=Ãœber Prune
function.checkversion=Pruef nach ne noie Version
+function.saveconfig=Iistellige speichere
# Dialogs
dialog.exit.confirm.title=Prune beände
dialog.save.overwrite.title=s'File existiert scho
dialog.save.overwrite.text=s'File existiert scho. Sind Sie sicher, Sie wend s'File überschriibe?
dialog.exportkml.text=Titel für die Date
-dialog.exportkml.altitude=Au Höchiinformation (fürs Fliege)
+dialog.exportkml.altitude=Absolut Höchiinformation (fürs Fliege)
dialog.exportkml.kmz=Date ins kmz File komprimierä
dialog.exportkml.exportimages=Bildli ins Kmz exportierä
dialog.exportgpx.name=Name
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.pointtype.desc=Folgende Punkttype speichere:
+dialog.pointtype.track=Trackpunkte
+dialog.pointtype.waypoint=Waypoints
+dialog.pointtype.photo=Fötelipunkte
dialog.confirmreversetrack.title=Umdrehig bestätige
dialog.confirmreversetrack.text=Diese Daten enthalte Ziitstämpel Informatione, die bei dr Umkehrig usser Reihefolge erschiene würdi.\nSind Sie sicher, Sie wend dn Beriich umkehre?
dialog.confirmcutandmove.title=Move bestätige
dialog.pointedit.table.changed=Geändert
dialog.pointedit.changevalue.text=Gebet Sie den neuen Wert für diesen Fäld ina
dialog.pointedit.changevalue.title=Fäld editiere
-dialog.pointnameedit.title=Waypoint Name editiere
dialog.pointnameedit.name=Waypoint Name
dialog.pointnameedit.uppercase=GROSS gschriebe
dialog.pointnameedit.lowercase=chli gschriebe
dialog.addtimeoffset.hours=Schtunde
dialog.addtimeoffset.minutes=Minute
dialog.addtimeoffset.notimestamps=Ziitverschiebig nöd möglech wil dr Beriich kei Ziitinfo hät
+dialog.findwaypoint.intro=Gebet Sie en Teil vonem Namen ina
+dialog.findwaypoint.search=Sueche
dialog.connect.title=Föteli verknüpfe
dialog.connectphoto.clonepoint=Derer Punkt hät scho s Föteli.\nWend sie ne Kopie vonem Punkt machä?
dialog.saveexif.title=Exif go speicherä
dialog.setmapbg.cyclemap=Velokarte
dialog.setmapbg.other=Anderi
dialog.setmapbg.server=Server URL
+dialog.gpsies.column.name=Track Name
+dialog.gpsies.column.length=Länge
+dialog.gpsies.description=Beschriebig
+dialog.gpsies.nodescription=Kei Beschriebig
+dialog.gpsies.nonefound=Kei Tracks gfunde
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.correlate.photoselect.intro=Wählet Sie eini vo deren Föteli uus, um die Ziitdifferänz zu berächnä
dialog.correlate.photoselect.photoname=Föteli Name
dialog.correlate.photoselect.timediff=Ziitdifferänz
dialog.correlate.photoselect.photolater=Föteli spöter
dialog.checkversion.releasedate1=Die noii Version isch am
dialog.checkversion.releasedate2=ussecho.
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>Entf</td><td>Aktuelli Punkt lösche</td></tr></table>
+dialog.saveconfig.desc=Die folgendi Iinstellige könne gspeicheret werde :
+dialog.saveconfig.prune.trackdirectory=Trackverzeichnis
+dialog.saveconfig.prune.photodirectory=Föteliverzeichnis
+dialog.saveconfig.prune.languagecode=Sprochecode (DE_ch)
+dialog.saveconfig.prune.gpsdevice=GPS Gerätename
+dialog.saveconfig.prune.gpsformat=GPS Format
+dialog.saveconfig.prune.povrayfont=Povray Font
+dialog.saveconfig.prune.metricunits=Metrischi Einheite verwende?
+dialog.saveconfig.prune.gnuplotpath=Gnuplot Pfad
+dialog.saveconfig.prune.gpsbabelpath=Gpsbabel Pfad
+dialog.saveconfig.prune.exiftoolpath=Exiftool Pfad
+dialog.saveconfig.prune.mapserverindex=Kartenserver Index
+dialog.saveconfig.prune.mapserverurl=Kartenserver URL
+dialog.saveconfig.prune.showpace=Tempo aazeige
+dialog.saveconfig.prune.kmzimagewidth=Bildbreiti im KMZ
+dialog.saveconfig.prune.kmzimageheight=Bildhöchi im KMZ
+dialog.setpaths.intro=Sie könnet dann die Pfade für dia Applikatione setzä:
+dialog.addaltitude.noaltitudes=Dr seläktierte Beriich hät keini Höchiinformation
+dialog.addaltitude.desc=Höchiverschiebig zuzutue
# 3d window
dialog.3d.title=Prune Drüü-d Aasicht
confirm.mergetracksegments=Segmänte gmerged
confirm.reverserange=Beriich umgdrähet
confirm.addtimeoffset=Ziitverschiebig zutue
+confirm.addaltitudeoffset=Höchiverschiebig zutue
confirm.rearrangewaypoints=Waypoints umorganisiert
confirm.cutandmove=Beriich gmoved
confirm.saveexif.ok1=Es sin
confirm.correlate.single=Föteli isch korreliert worde
confirm.correlate.multi=Fötelis sin korreliert worde
confirm.createpoint=Punkt kreiert worde
+confirm.running=Am Laufe ...
# Buttons
button.ok=OK
button.selectall=Alli selektierä
button.selectnone=Nüüt selektierä
button.preview=Vorschauä
+button.load=Ladä
button.guessfields=Fälde erratä
button.showwebpage=Websiite aazeigä
-button.gnuplotpath=Gnuplot Pfad setzä
+button.check=Prüefa
+
# File types
filetype.txt=TXT Dateie
display.range.time.days=T
details.range.avespeed=Gschwindikeit
details.range.avemovingspeed=Gschwindikeit ufem Wäg
+details.range.pace=Tempo
details.waypointsphotos.waypoints=Waypoints
details.waypointsphotos.photos=Fötelis
details.photodetails=Details vonem Föteli
undo.reverse=Beriich umdrähie
undo.mergetracksegments=track segmänte merge
undo.addtimeoffset=ziitverschiebig zutue
+undo.addaltitudeoffset=höchiverschiebig zutue
undo.rearrangewaypoints=Waypoints reorganisierä
undo.cutandmove=Selektion movä
undo.connectphoto=Föteli verbindä
# Error messages
error.save.dialogtitle=Fähle bim Speichere
error.save.nodata=Kei Date zum speichere
-error.save.failed=Speichere vom File fehlgschlage :
+error.save.failed=Speichere vom File fehlgschlage
error.saveexif.filenotfound=Föteli File nöd gfunde
error.saveexif.cannotoverwrite1=Föteli File
error.saveexif.cannotoverwrite2=isch nöd schriibbar. Speichere na einer Kopie?
menu.edit.undo=Undo
menu.edit.clearundo=Clear undo list
menu.edit.editpoint=Edit point
-menu.edit.editwaypointname=Edit waypoint name
menu.edit.deletepoint=Delete point
menu.edit.deleterange=Delete range
menu.edit.deletemarked=Delete marked points
menu.view.browser.openstreetmap=Openstreetmap
menu.view.browser.mapquest=Mapquest
menu.view.browser.yahoo=Yahoo maps
+menu.settings=Settings
+menu.settings.showpace=Show pace in range display
menu.help=Help
# Popup menu for map
menu.map.zoomin=Zoom in
menu.map.connect=Connect track points
menu.map.autopan=Autopan
menu.map.showmap=Show map
+menu.map.showscalebar=Show scalebar
+
+# Alt keys for menus
+altkey.menu.file=F
+altkey.menu.edit=E
+altkey.menu.select=S
+altkey.menu.view=V
+altkey.menu.photo=P
+altkey.menu.settings=T
+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.edit.undo=Z
+shortcut.menu.edit.compress=C
+shortcut.menu.select.all=A
+shortcut.menu.help.help=H
# Functions
function.loadfromgps=Load data from GPS
function.exportkml=Export KML
function.exportgpx=Export GPX
function.exportpov=Export POV
+function.editwaypointname=Edit waypoint name
function.compress=Compress track
function.addtimeoffset=Add time offset
+function.addaltitudeoffset=Add altitude offset
+function.findwaypoint=Find waypoint
function.charts=Charts
function.show3d=Three-D view
function.distances=Distances
-function.setmapbg=Set map background
+function.getgpsies=Get Gpsies tracks
function.correlatephotos=Correlate photos
+function.setmapbg=Set map background
+function.setkmzimagesize=Set KMZ image size
+function.setpaths=Set program paths
function.help=Help
+function.showkeys=Show shortcut keys
function.about=About Prune
function.checkversion=Check for new version
+function.saveconfig=Save settings
# Dialogs
dialog.exit.confirm.title=Exit Prune
dialog.save.overwrite.title=File already exists
dialog.save.overwrite.text=This file already exists. Are you sure you want to overwrite the file?
dialog.exportkml.text=Title for the data
-dialog.exportkml.altitude=Include altitudes (for aviation)
+dialog.exportkml.altitude=Absolute altitudes (for aviation)
dialog.exportkml.kmz=Compress to make kmz file
dialog.exportkml.exportimages=Export image thumbnails to kmz
dialog.exportgpx.name=Name
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.pointtype.desc=Save the following point types:
+dialog.pointtype.track=Track points
+dialog.pointtype.waypoint=Waypoints
+dialog.pointtype.photo=Photo points
dialog.confirmreversetrack.title=Confirm reversal
dialog.confirmreversetrack.text=This track contains timestamp information, which will be out of sequence after a reversal.\nAre you sure you want to reverse this section?
dialog.confirmcutandmove.title=Confirm cut and move
dialog.pointedit.table.changed=Changed
dialog.pointedit.changevalue.text=Enter the new value for this field
dialog.pointedit.changevalue.title=Edit field
-dialog.pointnameedit.title=Edit waypoint name
dialog.pointnameedit.name=Waypoint name
dialog.pointnameedit.uppercase=UPPER case
dialog.pointnameedit.lowercase=lower case
dialog.addtimeoffset.hours=Hours
dialog.addtimeoffset.minutes=Minutes
dialog.addtimeoffset.notimestamps=Cannot add a time offset as this selection doesn't contain any timestamp information
+dialog.findwaypoint.intro=Enter part of the waypoint name
+dialog.findwaypoint.search=Search
dialog.connect.title=Connect photo to point
dialog.connectphoto.clonepoint=This point already has a photo.\nDo you want to make a copy of the point?
dialog.saveexif.title=Save Exif
dialog.setmapbg.cyclemap=Cyclemap
dialog.setmapbg.other=Other
dialog.setmapbg.server=Server URL
+dialog.gpsies.column.name=Track name
+dialog.gpsies.column.length=Length
+dialog.gpsies.description=Description
+dialog.gpsies.nodescription=No description
+dialog.gpsies.nonefound=No tracks found
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.releasedate1=This new version was released on
dialog.checkversion.releasedate2=.
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>Del</td><td>Delete current point</td></tr></table>
+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.saveconfig.prune.languagecode=Language code (EN)
+dialog.saveconfig.prune.gpsdevice=GPS device
+dialog.saveconfig.prune.gpsformat=GPS format
+dialog.saveconfig.prune.povrayfont=Povray font
+dialog.saveconfig.prune.metricunits=Use metric units?
+dialog.saveconfig.prune.gnuplotpath=Path to gnuplot
+dialog.saveconfig.prune.gpsbabelpath=Path to gpsbabel
+dialog.saveconfig.prune.exiftoolpath=Path to exiftool
+dialog.saveconfig.prune.mapserverindex=Index of map server
+dialog.saveconfig.prune.mapserverurl=URL of map server
+dialog.saveconfig.prune.showpace=Show pace
+dialog.saveconfig.prune.kmzimagewidth=KMZ image width
+dialog.saveconfig.prune.kmzimageheight=KMZ image height
+dialog.setpaths.intro=If you need to, you can choose the paths to the external applications:
+dialog.addaltitude.noaltitudes=The selected range does not contain altitudes
+dialog.addaltitude.desc=Altitude offset to add
# 3d window
dialog.3d.title=Prune Three-d view
confirm.mergetracksegments=Track segments merged
confirm.reverserange=Range reversed
confirm.addtimeoffset=Time offset added
+confirm.addaltitudeoffset=Altitude offset added
confirm.rearrangewaypoints=Waypoints rearranged
confirm.cutandmove=Selection moved
confirm.saveexif.ok1=Saved
confirm.correlate.single=photo was correlated
confirm.correlate.multi=photos were correlated
confirm.createpoint=point created
+confirm.running=Running ...
# Buttons
button.ok=OK
button.selectall=Select all
button.selectnone=Select none
button.preview=Preview
+button.load=Load
button.guessfields=Guess fields
button.showwebpage=Show webpage
-button.gnuplotpath=Set gnuplot path
+button.check=Check
# File types
filetype.txt=TXT files
display.range.time.days=d
details.range.avespeed=Ave speed
details.range.avemovingspeed=Moving ave
+details.range.pace=Pace
details.waypointsphotos.waypoints=Waypoints
details.waypointsphotos.photos=Photos
details.photodetails=Photo details
undo.reverse=reverse range
undo.mergetracksegments=merge track segments
undo.addtimeoffset=add time offset
+undo.addaltitudeoffset=add altitude offset
undo.rearrangewaypoints=rearrange waypoints
undo.cutandmove=move section
undo.connectphoto=connect photo
# Error messages
error.save.dialogtitle=Error saving data
error.save.nodata=No data to save
-error.save.failed=Failed to save the data to file:
+error.save.failed=Failed to save the data to file
error.saveexif.filenotfound=Failed to find photo file
error.saveexif.cannotoverwrite1=Photo file
error.saveexif.cannotoverwrite2=is read-only and can't be overwritten. Write to copy?
menu.edit.undo=Deshacer
menu.edit.clearundo=Despejar la lista de deshacer
menu.edit.editpoint=Editar punto
-menu.edit.editwaypointname=Editar nombre de waypoint
menu.edit.deletepoint=Eliminar punto
menu.edit.deleterange=Eliminar rango
-menu.edit.deletemarked=
+menu.edit.deletemarked=Eliminar puntos marcados
menu.edit.interpolate=Interpolar
menu.edit.average=Crear punto a la media del rango
menu.edit.reverse=Invertir rango
menu.edit.rearrange=Reorganizar waypoints
menu.edit.rearrange.start=Volver al comienzo
menu.edit.rearrange.end=Ir al final
-menu.edit.rearrange.nearest=Ir al más próximo
-menu.edit.cutandmove=
+menu.edit.rearrange.nearest=Ir al m\u00e1s pr\u00f3ximo
+menu.edit.cutandmove=Cortar y mover selecci\u00f3n
menu.select=Seleccionar
menu.select.all=Seleccionar todo
menu.select.none=No seleccionar nada
menu.view.browser=Mapa en un navegador
menu.view.browser.google=Google maps
menu.view.browser.openstreetmap=Openstreetmap
-menu.view.browser.mapquest=
-menu.view.browser.yahoo=
+menu.view.browser.mapquest=Mapquest
+menu.view.browser.yahoo=mapas Yahoo
+menu.settings=Preferencias
+menu.settings.showpace=
menu.help=Ayuda
# Popup menu for map
menu.map.zoomin=Ampliar zoom
menu.map.zoomfull=Mostrar todo
menu.map.newpoint=Crear uno punto nuevo
menu.map.connect=Conectar puntos de track
-menu.map.autopan=Posicionar automáticamente
+menu.map.autopan=Posicionar autom\u00e1ticamente
menu.map.showmap=Mostrar el mapa
+menu.map.showscalebar=
+
+# Alt keys for menus
+altkey.menu.file=A
+altkey.menu.edit=E
+altkey.menu.select=S
+altkey.menu.view=V
+altkey.menu.photo=F
+altkey.menu.settings=P
+altkey.menu.help=Y
+
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=A
+shortcut.menu.file.load=C
+shortcut.menu.file.save=G
+shortcut.menu.edit.undo=Z
+shortcut.menu.edit.compress=C
+shortcut.menu.select.all=T
+shortcut.menu.help.help=H
# Functions
function.loadfromgps=Cargar datos del GPS
function.exportkml=Exportar KML
function.exportgpx=Exportar GPX
function.exportpov=Exportar POV
-function.compress=Comprimir Track
-function.addtimeoffset=
+function.editwaypointname=Editar nombre de waypoint
+function.compress=Comprimir track
+function.addtimeoffset=A\u00f1adir compensar tiempo
+function.addaltitudeoffset=A\u00f1adir compensar altitud
+function.findwaypoint=Buscar waypoint
function.charts=Diagramas
function.show3d=Mostrar en 3-D
function.distances=Distancias
-function.setmapbg=Configurar fondo de mapa
+function.getgpsies=Bajar ruta de Gpsies
function.correlatephotos=Correlacionar fotos
+function.setmapbg=Configurar fondo de mapa
+function.setkmzimagesize=Configurar tama\u00f1os de las im\u00e1genes KMZ
+function.setpaths=Configurar rutas del programas
function.help=Ayuda
+function.showkeys=
function.about=Acerca de Prune
-function.checkversion=Buscar una nueva versión
+function.checkversion=Buscar una nueva versi\u00f3n
+function.saveconfig=Guardar preferencias
# Dialogs
dialog.exit.confirm.title=Salir de Prune
dialog.openoptions.filesnippet=Extraer archivo
dialog.load.table.field=Campo
dialog.load.table.datatype=Tipo de datos
-dialog.load.table.description=Descripción
+dialog.load.table.description=Descripci\u00f3n
dialog.delimiter.label=Separador de campo
dialog.delimiter.comma=Coma ,
dialog.delimiter.tab=Tabulador
dialog.openoptions.altitudeunits=Unidades altitud
dialog.jpegload.subdirectories=Incluir subdirectorios
dialog.jpegload.loadjpegswithoutcoords=Fotos sin coordenadas tambien
-dialog.jpegload.loadjpegsoutsidearea=
+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.device=
-dialog.gpsload.format=
-dialog.gpsload.getwaypoints=
-dialog.gpsload.gettracks=
+dialog.gpsload.format=Formato
+dialog.gpsload.getwaypoints=Cargar waypoints
+dialog.gpsload.gettracks=Cargar tracks
dialog.gpssend.sendwaypoints=
dialog.gpssend.sendtracks=
dialog.gpssend.trackname=Nombre del track
dialog.save.table.field=Campo
dialog.save.table.hasdata=Contiene datos
dialog.save.table.save=Guardar
-dialog.save.headerrow=TÃtulo fila
+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.overwrite.title=El archivo ya existe
dialog.save.overwrite.text=El archivo ya existe, desea sobreescribirlo?
-dialog.exportkml.text=Descripción para los datos
-dialog.exportkml.altitude=Incluir altitudes (para aviación)
+dialog.exportkml.text=Descripci\u00f3n para los datos
+dialog.exportkml.altitude=Absoluta altitudes (para aviaci\u00f3n)
dialog.exportkml.kmz=Comprimir al archivo kmz
dialog.exportkml.exportimages=Exportar fotos al kmz
dialog.exportgpx.name=Nombre
-dialog.exportgpx.desc=Descripción
+dialog.exportgpx.desc=Descripci\u00f3n
dialog.exportgpx.includetimestamps=Tiempo tambien
dialog.exportpov.text=Introdzca los Parametros para exportar
dialog.exportpov.font=Fuente
-dialog.exportpov.camerax=Cámara X
-dialog.exportpov.cameray=Cámara Y
-dialog.exportpov.cameraz=Cámara Z
-dialog.exportpov.modelstyle=
-dialog.exportpov.ballsandsticks=
-dialog.exportpov.tubesandwalls=
-dialog.exportpov.warningtracksize=Este track contiene un gran numero de puntos. Puede ser que Java3D no los pueda visualizar. Está seguro de que desea continuar?
-dialog.confirmreversetrack.title=Confirmar inversión
-dialog.confirmreversetrack.text=Este track contiene información sobre la fecha, que estará fuera de secuencia después de la inversión. Esta seguro que desea invertir esta sección?
+dialog.exportpov.camerax=C\u00e1mara X
+dialog.exportpov.cameray=C\u00e1mara Y
+dialog.exportpov.cameraz=C\u00e1mara Z
+dialog.exportpov.modelstyle=Estilo
+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.pointtype.desc=
+dialog.pointtype.track=
+dialog.pointtype.waypoint=
+dialog.pointtype.photo=
+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.confirmcutandmove.title=Confirmar ...
-dialog.confirmcutandmove.text=Este track contiene información sobre la fecha, que estará fuera de secuencia después de la .... Esta seguro que desea ... esta sección?
+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.interpolate.title=Interpolar puntos
-dialog.interpolate.parameter.text=Número de los puntos a insertar entre los puntos elegidos
+dialog.interpolate.parameter.text=N\u00famero de los puntos a insertar entre los puntos elegidos
dialog.undo.title=Deshacer
-dialog.undo.pretext=Por favor, seleccione la operación(es) a deshacer
+dialog.undo.pretext=Por favor, seleccione la operaci\u00f3n(es) a deshacer
dialog.undo.none.title=No se puede deshacer
-dialog.undo.none.text=Ninguna operación a 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á toda la información!
+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ón 'Editar' para modificar el valor
+dialog.pointedit.text=Seleccione cada campo a editar y use el bot\u00f3n 'Editar' para modificar el valor
dialog.pointedit.table.field=Campo
dialog.pointedit.table.value=Valor
dialog.pointedit.table.changed=Modificado
dialog.pointedit.changevalue.text=Introduzca el nuevo valor de campo
dialog.pointedit.changevalue.title=Editar campo
-dialog.pointnameedit.title=Editar nombre de waypoint
dialog.pointnameedit.name=Nombre de waypoint
-dialog.pointnameedit.uppercase=Mayúsculas
-dialog.pointnameedit.lowercase=minúsculas
+dialog.pointnameedit.uppercase=May\u00fasculas
+dialog.pointnameedit.lowercase=min\u00fasculas
dialog.pointnameedit.sentencecase=Mezcla
dialog.addtimeoffset.add=
dialog.addtimeoffset.subtract=
dialog.addtimeoffset.hours=Horas
dialog.addtimeoffset.minutes=Minutos
dialog.addtimeoffset.notimestamps=
+dialog.findwaypoint.intro=
+dialog.findwaypoint.search=
dialog.connect.title=Conectar foto
dialog.connectphoto.clonepoint=
dialog.saveexif.title=Guardar Exif
dialog.saveexif.overwrite=Sobreescribirlar archivos?
dialog.charts.xaxis=Eje de abscisas
dialog.charts.yaxis=Eje vertical
-dialog.charts.output=
+dialog.charts.output=Resultado
dialog.charts.screen=
dialog.charts.svg=
dialog.charts.svgwidth=
dialog.setmapbg.cyclemap=
dialog.setmapbg.other=Otro
dialog.setmapbg.server=
-dialog.correlate.notimestamps=No hay información de tiempo para los puntos, asà que no hay nada que correlacionar con las fotos.
-dialog.correlate.nouncorrelatedphotos=No hay fotos no correlacionadas.\nEstá seguro de que desea continuar?
+dialog.gpsies.column.name=Nombre
+dialog.gpsies.column.length=
+dialog.gpsies.description=Descripci\u00f3n
+dialog.gpsies.nodescription=Ning\u00fan descripci\u00f3n
+dialog.gpsies.nonefound=
+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.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.correlate.photoselect.photolater=Foto más adelante
-dialog.correlate.options.tip=Sugerencia: Correlacionando al menos una foto manualmente, el margen de tiempo se calcula automáticamente.
-dialog.correlate.options.intro=Seleccionar las opciones para correlación automática
+dialog.correlate.photoselect.photolater=Foto m\u00e1s adelante
+dialog.correlate.options.tip=Sugerencia: Correlacionando al menos una foto manualmente, el margen de tiempo se calcula autom\u00e1ticamente.
+dialog.correlate.options.intro=Seleccionar las opciones para correlaci\u00f3n autom\u00e1tica
dialog.correlate.options.offsetpanel=Margen de tiempo
dialog.correlate.options.offset=Margen
dialog.correlate.options.offset.hours=horas,
dialog.correlate.options.offset.minutes=minutos y
dialog.correlate.options.offset.seconds=segundos
-dialog.correlate.options.photolater=Foto después de punto
-dialog.correlate.options.pointlater=Punto después de foto
-dialog.correlate.options.limitspanel=LÃmites de correlación
-dialog.correlate.options.notimelimit=Sin lÃmite de tiempo
-dialog.correlate.options.timelimit=LÃmite de tiempo
-dialog.correlate.options.nodistancelimit=Sin lÃmite de distancia
-dialog.correlate.options.distancelimit=LÃmite de distancia
+dialog.correlate.options.photolater=Foto despu\u00e9s de punto
+dialog.correlate.options.pointlater=Punto despu\u00e9s de foto
+dialog.correlate.options.limitspanel=L\u00edmites de correlaci\u00f3n
+dialog.correlate.options.notimelimit=Sin l\u00edmite de tiempo
+dialog.correlate.options.timelimit=L\u00edmite de tiempo
+dialog.correlate.options.nodistancelimit=Sin l\u00edmite de distancia
+dialog.correlate.options.distancelimit=L\u00edmite de distancia
dialog.correlate.options.correlate=Correlacionar
-dialog.correlate.alloutsiderange=Todas las fotos están fuera del margen horario del track, por lo que ninguna puede ser correlada.\nIntente cambiar el margen o correle manualmente al menos una foto.
-dialog.compress.nonefound=Ningún punto eliminado
+dialog.correlate.alloutsiderange=Todas las fotos est\u00e1n fuera del margen horario del track, por lo que ninguna puede ser correlada.\nIntente cambiar el margen o correle manualmente al menos una foto.
+dialog.compress.nonefound=Ning\u00fan punto eliminado
dialog.compress.duplicates.title=Eliminar duplicados
dialog.compress.closepoints.title=
dialog.compress.closepoints.paramdesc=
dialog.compress.singletons.title=
dialog.compress.singletons.paramdesc=
dialog.compress.summarylabel=
-dialog.help.help=Por favor, ver\n http://activityworkshop.net/software/prune/\npara más información y guÃas del usuario.
-dialog.about.version=Versión
+dialog.help.help=Por favor, ver\n http://activityworkshop.net/software/prune/\npara m\u00e1s informaci\u00f3n y gu\u00edas del usuario.
+dialog.about.version=Versi\u00f3n
dialog.about.build=Construir
dialog.about.summarytext1=Prune es un programa para cargar, mostrar y editar datos de receptores GPS.
-dialog.about.summarytext2=Distribuido bajo el GNU GPL para uso libre y gratuito.<br>Se permite (y se anima) la copia, redistribución y modificación 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ás información y guÃas del usuario.
-dialog.about.languages=
-dialog.about.translatedby=Traducción al español realizada por activityworkshop y amigos muy amables!
+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.systeminfo=Informacion del sistema
dialog.about.systeminfo.os=Sistema operativo
dialog.about.systeminfo.java=Java Runtime
dialog.about.yes=Si
dialog.about.no=No
dialog.about.credits=Credits
-dialog.about.credits.code=El código de Prune fue escrito por
-dialog.about.credits.exifcode=El código Exif por
+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.translators=Traductores
-dialog.about.credits.translations=Ayuda en la traducción
+dialog.about.credits.translations=Ayuda en la traducci\u00f3n
dialog.about.credits.devtools=Herramientas de desarrollo
dialog.about.credits.othertools=Otras herramientas
dialog.about.credits.thanks=Gracias a
dialog.checkversion.releasedate1=
dialog.checkversion.releasedate2=
dialog.checkversion.download=To download the new version, go to http://activityworkshop.net/software/prune/download.html.
+dialog.keys.intro=
+dialog.keys.keylist=
+dialog.saveconfig.desc=
+dialog.saveconfig.prune.trackdirectory=
+dialog.saveconfig.prune.photodirectory=
+dialog.saveconfig.prune.languagecode=
+dialog.saveconfig.prune.gpsdevice=
+dialog.saveconfig.prune.gpsformat=
+dialog.saveconfig.prune.povrayfont=Fuente povray
+dialog.saveconfig.prune.metricunits=
+dialog.saveconfig.prune.gnuplotpath=
+dialog.saveconfig.prune.gpsbabelpath=
+dialog.saveconfig.prune.exiftoolpath=
+dialog.saveconfig.prune.mapserverindex=
+dialog.saveconfig.prune.mapserverurl=
+dialog.saveconfig.prune.showpace=
+dialog.saveconfig.prune.kmzimagewidth=
+dialog.saveconfig.prune.kmzimageheight=
+dialog.setpaths.intro=
+dialog.addaltitude.noaltitudes=
+dialog.addaltitude.desc=
# 3d window
dialog.3d.title=Prune vista 3-D
dialog.3d.altitudecap=Escala de las altitudes
-dialog.3dlines.title=CuadrÃcula Prune
-dialog.3dlines.empty=No hay ninguna cuadrÃcula!
-dialog.3dlines.intro=Información de la cuadrÃcula
+dialog.3dlines.title=Cuadr\u00edcula Prune
+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.loadfile=Dato cargado de
confirm.mergetracksegments=Segmentos unidos
confirm.reverserange=Rango invertido
confirm.addtimeoffset=
+confirm.addaltitudeoffset=
confirm.rearrangewaypoints=Waypoints reorganizados
confirm.cutandmove=
confirm.saveexif.ok1=Guardando
confirm.saveexif.ok2=fotos
-confirm.undo.single=operación no realizada
-confirm.undo.multi=operación(es) no realizada(s)
+confirm.undo.single=operaci\u00f3n no realizada
+confirm.undo.multi=operaci\u00f3n(es) no realizada(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.createpoint=
+confirm.createpoint=punto creado
+confirm.running=Trabajando ...
# Buttons
button.ok=Aceptar
button.overwrite=Sobreescribir
button.moveup=Mover hacia arriba
button.movedown=Mover hacia abajo
-button.showlines=Mostrar cuadrÃcula
+button.showlines=Mostrar cuadr\u00edcula
button.edit=Editar
button.exit=Salir
button.close=Cerrar
-button.continue=Continúe
+button.continue=Contin\u00fae
button.yes=Si
button.no=No
button.yestoall=Si por todo
button.notoall=No por todo
button.selectall=Seleccionar todo
button.selectnone=Seleccionar nada
-button.preview=Previsualización
+button.preview=Previsualizaci\u00f3n
+button.load=Cargar
button.guessfields=Adivinar campos
-button.showwebpage=
-button.gnuplotpath=
+button.showwebpage=Mostrar p\u00e1gina web
+button.check=Verificar
# File types
filetype.txt=Archivos TXT
filetype.svg=Archivos SVG
# Display components
-display.nodata=Ningún dato cargado
+display.nodata=Ning\u00fan dato cargado
display.noaltitudes=Los datos del track no incluyen altitudes
details.trackdetails=Detalles del track
-details.notrack=Ningún track cargado
+details.notrack=Ning\u00fan track cargado
details.track.points=Puntos
details.track.file=Archivo
-details.track.numfiles=Número de archivos
+details.track.numfiles=N\u00famero de archivos
details.pointdetails=Detalles del punto
details.index.selected=Indice seleccionado
details.index.of=de
-details.nopointselection=Ningún punto seleccionado
+details.nopointselection=Ning\u00fan punto seleccionado
details.photofile=Archivo de fotos
-details.norangeselection=Ningún rango seleccionado
+details.norangeselection=Ning\u00fan rango seleccionado
details.rangedetails=Detalles del rango
details.range.selected=Rango seleccionado
details.range.to=hacia
display.range.time.days=d
details.range.avespeed=Velocidad media
details.range.avemovingspeed=
+details.range.pace=
details.waypointsphotos.waypoints=Waypoints
details.waypointsphotos.photos=Fotos
details.photodetails=Detalles del Foto
fieldname.latitude=Latitud
fieldname.longitude=Longitud
fieldname.altitude=Altitud
-fieldname.timestamp=Información de tiempo
+fieldname.timestamp=Informaci\u00f3n de tiempo
fieldname.time=Tiempo
fieldname.waypointname=Nombre
fieldname.waypointtype=Tipo
fieldname.prefix=Campo
fieldname.distance=Distancia
fieldname.movingdistance=
-fieldname.duration=Duración
+fieldname.duration=Duraci\u00f3n
fieldname.speed=Velocidad
-fieldname.verticalspeed=
+fieldname.verticalspeed=Velocidad vertical
# Measurement units
units.original=Original
units.metres.short=m
units.feet=Pies
units.feet.short=ft
-units.kilometres=Kilómetros
+units.kilometres=Kil\u00f3metros
units.kilometres.short=km
units.kmh=km/h
units.miles=Millas
undo.reverse=invertir rango
undo.mergetracksegments=unir los segmentos de track
undo.addtimeoffset=
+undo.addaltitudeoffset=
undo.rearrangewaypoints=reordenar waypoints
undo.cutandmove=
undo.connectphoto=conectar foto
# Error messages
error.save.dialogtitle=Fallo al guardar datos
-error.save.nodata=Ningún dato salvado
-error.save.failed=Fallo al guardar datos al archivo:
+error.save.nodata=Ning\u00fan dato salvado
+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.load.dialogtitle=Fallo al cargar datos
error.load.noread=No se puede leer el fichero
-error.load.nopoints=Ninguna información coordenadas encontrada
+error.load.nopoints=Ninguna informaci\u00f3n coordenadas encontrada
error.load.unknownxml=Formato xml no reconocido:
-error.load.noxmlinzip=
+error.load.noxmlinzip=Ning\u00fan xml archivo encontrado
error.load.othererror=Fallo al cargar datos:
error.jpegload.dialogtitle=Error cargando fotos
-error.jpegload.nofilesfound=Ningún archivo encontrado
-error.jpegload.nojpegsfound=Ningún archivo jpeg encontrado
-error.jpegload.noexiffound=Ninguna información EXIF encontrada
-error.jpegload.nogpsfound=Ninguna información GPS encontrada
+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.undofailed.title=Fallo al deshacer
-error.undofailed.text=No ha sido posible deshacer la operación
-error.function.noop.title=La función no se ha efectuado
-error.rearrange.noop=Reordenación de waypoints no se ha efectuado
-error.function.notavailable.title=Función no disponible
-error.function.nojava3d=Esta función requiere la librerÃa Java3d, disponible en Sun.com.
-error.3d=Ha ocurrido un error con la función 3-D
+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 waypoints 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.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ón a internet.
+error.osmimage.failed=Imposible cargar el mapa. Por favor, compruebe la conexi\u00f3n a internet.
menu.file.addphotos=Ajouter photos
menu.file.save=Enregistrer
menu.file.exit=Quitter
-menu.edit=Édition
+menu.edit=\u00c9dition
menu.edit.undo=Annuler
menu.edit.clearundo=Purger la liste d'annulation
menu.edit.editpoint=Editer le point
-menu.edit.editwaypointname=Editer le nom du waypoint
menu.edit.deletepoint=Supprimer le point
-menu.edit.deleterange=Supprimer l'étendue
-menu.edit.deletemarked=Supprimer les points marqués
+menu.edit.deleterange=Supprimer l'\u00e9tendue
+menu.edit.deletemarked=Supprimer les points marqu\u00e9s
menu.edit.interpolate=Interpoler
-menu.edit.average=Créer un point pour la sélection
-menu.edit.reverse=Inverser l'étendue
+menu.edit.average=Cr\u00e9er un point pour la s\u00e9lection
+menu.edit.reverse=Inverser l'\u00e9tendue
menu.edit.mergetracksegments=Fusionner les segments de trace
-menu.edit.rearrange=Réarranger les waypoints
-menu.edit.rearrange.start=Tous au début du fichier
-menu.edit.rearrange.end=Tous à la fin du fichier
+menu.edit.rearrange=R\u00e9arranger les waypoints
+menu.edit.rearrange.start=Tous au d\u00e9but du fichier
+menu.edit.rearrange.end=Tous \u00e0 la fin du fichier
menu.edit.rearrange.nearest=Chacun au point de trace le plus proche
-menu.edit.cutandmove=Couper et bouger la sélection
-menu.select=Sélectionner
-menu.select.all=Tout sélectionner
-menu.select.none=Rien sélectionner
-menu.select.start=Définir le début de l'étendue
-menu.select.end=Définir la fin de l'étendue
+menu.edit.cutandmove=Couper et bouger la s\u00e9lection
+menu.select=S\u00e9lectionner
+menu.select.all=Tout s\u00e9lectionner
+menu.select.none=Rien s\u00e9lectionner
+menu.select.start=D\u00e9finir le d\u00e9but de l'\u00e9tendue
+menu.select.end=D\u00e9finir la fin de l'\u00e9tendue
menu.photo=Photo
menu.photo.saveexif=Enregistrer dans les Exif
menu.photo.connect=Relier au point
-menu.photo.disconnect=Détacher du point
+menu.photo.disconnect=D\u00e9tacher du point
menu.photo.delete=Retirer la photo
menu.view=Affichage
menu.view.browser=Ouvrir la carte dans le navigateur
menu.view.browser.openstreetmap=Openstreetmap
menu.view.browser.mapquest=Mapquest
menu.view.browser.yahoo=Yahoo maps
+menu.settings=Pr\u00e9f\u00e9rences
+menu.settings.showpace=Montrer allure dans les d\u00e9tails
menu.help=Aide
# Popup menu for map
menu.map.zoomin=Zoom avant
-menu.map.zoomout=Zoom arrière
-menu.map.zoomfull=Adapter à la vue
+menu.map.zoomout=Zoom arri\u00e8re
+menu.map.zoomfull=Adapter \u00e0 la vue
menu.map.newpoint=Ajouter un point
menu.map.connect=Relier les points de trace
-menu.map.autopan=Déplacement automatique
+menu.map.autopan=D\u00e9placement automatique
menu.map.showmap=Montrer la carte
+menu.map.showscalebar=Montrer l'echelle
+
+# Alt keys for menus
+altkey.menu.file=F
+altkey.menu.edit=E
+altkey.menu.select=S
+altkey.menu.view=A
+altkey.menu.photo=P
+altkey.menu.settings=R
+altkey.menu.help=I
+
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=O
+shortcut.menu.file.load=T
+shortcut.menu.file.save=E
+shortcut.menu.edit.undo=Z
+shortcut.menu.edit.compress=C
+shortcut.menu.select.all=S
+shortcut.menu.help.help=A
# Functions
-function.loadfromgps=Télécharger du GPS
+function.loadfromgps=T\u00e9l\u00e9charger du GPS
function.sendtogps=Envoyer au GPS
function.exportkml=Exporter en KML
function.exportgpx=Exporter en GPX
function.exportpov=Exporter en POV
+function.editwaypointname=Editer le nom du waypoint
function.compress=Compresser la trace
-function.addtimeoffset=Ajouter un décalage d'horaire
+function.addtimeoffset=Ajouter un d\u00e9calage d'horaire
+function.addaltitudeoffset=Ajouter un d\u00e9calage d'altitude
+function.findwaypoint=Trouver un waypoint
function.charts=Graphiques
function.show3d=Montrer en 3D
function.distances=Distances
-function.setmapbg=Définir le fond de carte
-function.correlatephotos=Corréler les photos
+function.getgpsies=R\u00e9cup\u00e9rer les traces Gpsies
+function.correlatephotos=Corr\u00e9ler les photos
+function.setmapbg=D\u00e9finir le fond de carte
+function.setkmzimagesize=D\u00e9finir la taille de l'image KMZ
+function.setpaths=D\u00e9finir les chemins des programmes
function.help=Aide
+function.showkeys=Montrer les raccourcis clavier
function.about=À propos de Prune
-function.checkversion=Chercher une mise à jour
+function.checkversion=Chercher une mise \u00e0 jour
+function.saveconfig=Enregistrer les pr\u00e9f\u00e9rences
# Dialogs
dialog.exit.confirm.title=Quitter Prune
-dialog.exit.confirm.text=Les données ont été modifiées. Souhaitez-vous quitter Prune sans les enregistrer ?
-dialog.openappend.title=Ajouter aux données existantes
-dialog.openappend.text=Ajouter aux données déjà chargées ?
+dialog.exit.confirm.text=Les donn\u00e9es ont \u00e9t\u00e9 modifi\u00e9es. Souhaitez-vous quitter Prune sans les enregistrer ?
+dialog.openappend.title=Ajouter aux donn\u00e9es existantes
+dialog.openappend.text=Ajouter aux donn\u00e9es d\u00e9j\u00e0 charg\u00e9es ?
dialog.deletepoint.title=Effacer le point
-dialog.deletepoint.deletephoto=Effacer la photo attachée à ce point ?
+dialog.deletepoint.deletephoto=Effacer la photo attach\u00e9e \u00e0 ce point ?
dialog.deletephoto.title=Effacer la photo
-dialog.deletephoto.deletepoint=Effacer le point attaché à cette photo ?
+dialog.deletephoto.deletepoint=Effacer le point attach\u00e9 \u00e0 cette photo ?
dialog.openoptions.title=Ouvrir options
dialog.openoptions.filesnippet=Extrait de fichier
dialog.load.table.field=Champ
-dialog.load.table.datatype=Type de donnée
+dialog.load.table.datatype=Type de donn\u00e9e
dialog.load.table.description=Description
-dialog.delimiter.label=Séparateur de texte
+dialog.delimiter.label=S\u00e9parateur de texte
dialog.delimiter.comma=Virgule ,
dialog.delimiter.tab=Tabulation
dialog.delimiter.space=Espace
dialog.openoptions.deliminfo.records=enregistrements, avec
dialog.openoptions.deliminfo.fields=champs
dialog.openoptions.deliminfo.norecords=Pas d'enregistrements
-dialog.openoptions.altitudeunits=Unités d'altitude
+dialog.openoptions.altitudeunits=Unit\u00e9s d'altitude
dialog.jpegload.subdirectories=Inclure les sous-dossiers
-dialog.jpegload.loadjpegswithoutcoords=Inclure les photos sans coordonnées
+dialog.jpegload.loadjpegswithoutcoords=Inclure les photos sans coordonn\u00e9es
dialog.jpegload.loadjpegsoutsidearea=Inclure des photos en dehors de l'endroit actuel
dialog.jpegload.progress.title=Chargement des photos
dialog.jpegload.progress=Veuillez patienter pendant la recherche des photos
dialog.gpsload.nogpsbabel=Gpsbabel introuvable. Continuer ?
-dialog.gpsload.device=Chemin du périphérique
+dialog.gpsload.device=Chemin du p\u00e9riph\u00e9rique
dialog.gpsload.format=Format
-dialog.gpsload.getwaypoints=Télécharger les waypoints
-dialog.gpsload.gettracks=Télécharger les traces
+dialog.gpsload.getwaypoints=T\u00e9l\u00e9charger les waypoints
+dialog.gpsload.gettracks=T\u00e9l\u00e9charger les traces
dialog.gpssend.sendwaypoints=Envoyer les waypoints
dialog.gpssend.sendtracks=Envoyer les traces
dialog.gpssend.trackname=Nom de trace
dialog.saveoptions.title=Enregistrer le fichier
-dialog.save.fieldstosave=Champs à enregistrer
+dialog.save.fieldstosave=Champs \u00e0 enregistrer
dialog.save.table.field=Champ
-dialog.save.table.hasdata=Possède une information
+dialog.save.table.hasdata=Poss\u00e8de une information
dialog.save.table.save=Enregistrer
-dialog.save.headerrow=Entêtes
-dialog.save.coordinateunits=Unités des coordonnées
-dialog.save.altitudeunits=Unités d'altitude
+dialog.save.headerrow=Ent\u00eates
+dialog.save.coordinateunits=Unit\u00e9s des coordonn\u00e9es
+dialog.save.altitudeunits=Unit\u00e9s d'altitude
dialog.save.timestampformat=Format de l'heure
-dialog.save.overwrite.title=Le fichier existe déjÃ
-dialog.save.overwrite.text=Ce fichier existe déjà . Êtes-vous sûr de vouloir écraser ce fichier ?
-dialog.exportkml.text=Titre pour les données
-dialog.exportkml.altitude=Inclure les altitudes (pour aviation)
+dialog.save.overwrite.title=Le fichier existe d\u00e9j\u00e0
+dialog.save.overwrite.text=Ce fichier existe d\u00e9j\u00e0. \u00cates-vous s\u00fbr de vouloir \u00e9craser ce fichier ?
+dialog.exportkml.text=Titre pour les donn\u00e9es
+dialog.exportkml.altitude=Absolues altitudes (pour aviation)
dialog.exportkml.kmz=Compresser au format kmz
dialog.exportkml.exportimages=Exporter les vignettes au format kmz
dialog.exportgpx.name=Nom
-dialog.exportgpx.desc=Légende
+dialog.exportgpx.desc=L\u00e9gende
dialog.exportgpx.includetimestamps=Inclure l'heure pour chaque point
-dialog.exportpov.text=Entrez les paramètres pour l'export POV
+dialog.exportpov.text=Entrez les param\u00e8tres pour l'export POV
dialog.exportpov.font=Police
-dialog.exportpov.camerax=Caméra X
-dialog.exportpov.cameray=Caméra Y
-dialog.exportpov.cameraz=Caméra Z
-dialog.exportpov.modelstyle=Style du modèle
-dialog.exportpov.ballsandsticks=Points et bâtons
+dialog.exportpov.camerax=Cam\u00e9ra X
+dialog.exportpov.cameray=Cam\u00e9ra Y
+dialog.exportpov.cameraz=Cam\u00e9ra Z
+dialog.exportpov.modelstyle=Style du mod\u00e8le
+dialog.exportpov.ballsandsticks=Points et b\u00e2tons
dialog.exportpov.tubesandwalls=Tubes et murs
-dialog.exportpov.warningtracksize=Cette trace possède un grand nombre de points, Java3D peut ne pas pouvoir l'afficher.\nÊtes-vous sûr de vouloir continuer ?
+dialog.exportpov.warningtracksize=Cette trace poss\u00e8de un grand nombre de points, Java3D peut ne pas pouvoir l'afficher.\n\u00cates-vous s\u00fbr de vouloir continuer ?
+dialog.pointtype.desc=Sauvegarder ces types de points:
+dialog.pointtype.track=Points de la trace
+dialog.pointtype.waypoint=Waypoints
+dialog.pointtype.photo=Points de photos
dialog.confirmreversetrack.title=Confirmer l'inversion
-dialog.confirmreversetrack.text=Cette trace contient des informations temporelles qui seront désordonnées après une inversion.\nÊtes-vous sûr de vouloir inverser cette section ?
-dialog.confirmcutandmove.title=Confirmer le déplacement
-dialog.confirmcutandmove.text=Cette trace contient des informations temporelles qui seront désordonnées après un déplacement.\nÊtes-vous sûr de vouloir déplacer cette section ?
+dialog.confirmreversetrack.text=Cette trace contient des informations temporelles qui seront d\u00e9sordonn\u00e9es apr\u00e8s une inversion.\n\u00cates-vous s\u00fbr de vouloir inverser cette section ?
+dialog.confirmcutandmove.title=Confirmer le d\u00e9placement
+dialog.confirmcutandmove.text=Cette trace contient des informations temporelles qui seront d\u00e9sordonn\u00e9es apr\u00e8s un d\u00e9placement.\n\u00cates-vous s\u00fbr de vouloir d\u00e9placer cette section ?
dialog.interpolate.title=Interpoler les points
-dialog.interpolate.parameter.text=Nombre de points à insérer entre les points sélectionnés
+dialog.interpolate.parameter.text=Nombre de points \u00e0 ins\u00e9rer entre les points s\u00e9lectionn\u00e9s
dialog.undo.title=Annuler les actions
-dialog.undo.pretext=Sélectionnez les actions à annuler
+dialog.undo.pretext=S\u00e9lectionnez les actions \u00e0 annuler
dialog.undo.none.title=Annulation impossible
-dialog.undo.none.text=Pas d'opération à annuler !
+dialog.undo.none.text=Pas d'op\u00e9ration \u00e0 annuler !
dialog.clearundo.title=Purger la liste d'annulation
-dialog.clearundo.text=Etes-vous sûr de vouloir effacer la liste d'annulation ?\nToutes les informations d'annulation seront perdues !
+dialog.clearundo.text=Etes-vous s\u00fbr de vouloir effacer la liste d'annulation ?\nToutes les informations d'annulation seront perdues !
dialog.pointedit.title=Editer le point
-dialog.pointedit.text=Sélectionner chaque champ à éditer et utiliser le bouton 'Editer' pour changer la valeur
+dialog.pointedit.text=S\u00e9lectionner chaque champ \u00e0 \u00e9diter et utiliser le bouton 'Editer' pour changer la valeur
dialog.pointedit.table.field=Champ
dialog.pointedit.table.value=Valeur
-dialog.pointedit.table.changed=Changé
+dialog.pointedit.table.changed=Chang\u00e9
dialog.pointedit.changevalue.text=Entrer la nouvelle valeur pour ce champ
dialog.pointedit.changevalue.title=Editer le champ
-dialog.pointnameedit.title=Editer le nom de waypoint
dialog.pointnameedit.name=Nom de waypoint
dialog.pointnameedit.uppercase=CASSE MAJUSCULES
dialog.pointnameedit.lowercase=casse minuscules
dialog.addtimeoffset.days=Jours
dialog.addtimeoffset.hours=Heures
dialog.addtimeoffset.minutes=Minutes
-dialog.addtimeoffset.notimestamps=Ne peut pas décaler l'heure; cette sélection ne contient pas de données d'heure
+dialog.addtimeoffset.notimestamps=Ne peut pas d\u00e9caler l'heure; cette s\u00e9lection ne contient pas de donn\u00e9es d'heure
+dialog.findwaypoint.intro=Entrez une partie du nom de waypoint
+dialog.findwaypoint.search=Chercher
dialog.connect.title=Lier la photo au point
-dialog.connectphoto.clonepoint=Ce point est déjà lié à une photo.\nVoulez-vous faire une copie de ce point ?
+dialog.connectphoto.clonepoint=Ce point est d\u00e9j\u00e0 li\u00e9 \u00e0 une photo.\nVoulez-vous faire une copie de ce point ?
dialog.saveexif.title=Enregistrer Exif
-dialog.saveexif.intro=Sélectionner les photos à sauver à l'aide des cases à cocher
-dialog.saveexif.nothingtosave=Coordonnées inchangées, rien à enregistrer
+dialog.saveexif.intro=S\u00e9lectionner les photos \u00e0 sauver \u00e0 l'aide des cases \u00e0 cocher
+dialog.saveexif.nothingtosave=Coordonn\u00e9es inchang\u00e9es, rien \u00e0 enregistrer
dialog.saveexif.noexiftool=Exiftool introuvable. Continuer ?
dialog.saveexif.table.photoname=Nom de la photo
dialog.saveexif.table.status=Statut
dialog.saveexif.table.save=Enregistrer
-dialog.saveexif.photostatus.connected=Connecté
-dialog.saveexif.photostatus.disconnected=Déconnecté
-dialog.saveexif.photostatus.modified=Modifié
+dialog.saveexif.photostatus.connected=Connect\u00e9
+dialog.saveexif.photostatus.disconnected=D\u00e9connect\u00e9
+dialog.saveexif.photostatus.modified=Modifi\u00e9
dialog.saveexif.overwrite=Ecraser les fichiers
dialog.charts.xaxis=Axe des x
dialog.charts.yaxis=Axe des y
dialog.charts.output=Sortie
-dialog.charts.screen=Sortie sur écran
+dialog.charts.screen=Sortie sur \u00e9cran
dialog.charts.svg=Sortie dans un fichier SVG
dialog.charts.svgwidth=Largeur de l'image SVG
dialog.charts.svgheight=Hauteur de l'image SVG
-dialog.charts.needaltitudeortimes=La trace ne peut générer des graphiques sans disposer d'altitudes ou d'indications temporelles
+dialog.charts.needaltitudeortimes=La trace ne peut g\u00e9n\u00e9rer des graphiques sans disposer d'altitudes ou d'indications temporelles
dialog.charts.gnuplotpath=Chemin gnuplot
-dialog.charts.gnuplotnotfound=Gnuplot est introuvable dans le chemin indiqué
-dialog.distances.intro=Distances à vol d'oiseau entre des points
+dialog.charts.gnuplotnotfound=Gnuplot est introuvable dans le chemin indiqu\u00e9
+dialog.distances.intro=Distances \u00e0 vol d'oiseau entre des points
dialog.distances.column.from=Du point
dialog.distances.column.to=Vers le point
dialog.distances.currentpoint=Point courant
dialog.distances.toofewpoints=Cette fonction a besoin de waypoints pour calculer les distances entre eux
-dialog.setmapbg.mapnik=Mapnik (défaut)
+dialog.setmapbg.mapnik=Mapnik (d\u00e9faut)
dialog.setmapbg.osma=Osma
dialog.setmapbg.cyclemap=Cyclemap
dialog.setmapbg.other=Autres
dialog.setmapbg.server=URL du serveur
-dialog.correlate.notimestamps=Les points n'ont pas d'indication de temps, il n'est pas possible de les corréler.
-dialog.correlate.nouncorrelatedphotos=Il n'y a pas de photos non-corrélées.\nVoulez-vous continuer ?
-dialog.correlate.photoselect.intro=Sélectionner une de ces photos corrélées pour définir le décalage de temps
+dialog.gpsies.column.name=Nom de trace
+dialog.gpsies.column.length=Distance
+dialog.gpsies.description=Description
+dialog.gpsies.nodescription=Aucune description
+dialog.gpsies.nonefound=Aucun trace trouv\u00e9
+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
dialog.correlate.photoselect.photoname=Nom de la photo
-dialog.correlate.photoselect.timediff=Différence de temps
+dialog.correlate.photoselect.timediff=Diff\u00e9rence de temps
dialog.correlate.photoselect.photolater=Photo prise plus tard
-dialog.correlate.options.tip=Astuce : En corrélant manuellement au moins une photo, le décalage de temps peut être calculé pour vous.
-dialog.correlate.options.intro=Sélectionner les options pour la corrélation automatique
-dialog.correlate.options.offsetpanel=Décalage de temps
-dialog.correlate.options.offset=Décalage
+dialog.correlate.options.tip=Astuce : En corr\u00e9lant manuellement au moins une photo, le d\u00e9calage de temps peut \u00eatre calcul\u00e9 pour vous.
+dialog.correlate.options.intro=S\u00e9lectionner les options pour la corr\u00e9lation automatique
+dialog.correlate.options.offsetpanel=D\u00e9calage de temps
+dialog.correlate.options.offset=D\u00e9calage
dialog.correlate.options.offset.hours=heures,
dialog.correlate.options.offset.minutes=minutes et
dialog.correlate.options.offset.seconds=secondes
-dialog.correlate.options.photolater=Photo postérieure au point
-dialog.correlate.options.pointlater=Point postérieur à la photo
-dialog.correlate.options.limitspanel=Limites de corrélation
+dialog.correlate.options.photolater=Photo post\u00e9rieure au point
+dialog.correlate.options.pointlater=Point post\u00e9rieur \u00e0 la photo
+dialog.correlate.options.limitspanel=Limites de corr\u00e9lation
dialog.correlate.options.notimelimit=Pas de limite de temps
dialog.correlate.options.timelimit=Limite de temps
dialog.correlate.options.nodistancelimit=Pas de limite de distance
dialog.correlate.options.distancelimit=Limite de distance
-dialog.correlate.options.correlate=Corréler
-dialog.correlate.alloutsiderange=Les photos ne correspondent pas à la plage de temps de la trace, aucune ne peut être corrélée.\nEssayez de modifier le décalage ou de corréler manuellement au moins une photo.
-dialog.compress.nonefound=Pas de données à effacer
+dialog.correlate.options.correlate=Corr\u00e9ler
+dialog.correlate.alloutsiderange=Les photos ne correspondent pas \u00e0 la plage de temps de la trace, aucune ne peut \u00eatre corr\u00e9l\u00e9e.\nEssayez de modifier le d\u00e9calage ou de corr\u00e9ler manuellement au moins une photo.
+dialog.compress.nonefound=Pas de donn\u00e9es \u00e0 effacer
dialog.compress.duplicates.title=Suppression des doublons
dialog.compress.closepoints.title=Suppression des points voisins
dialog.compress.closepoints.paramdesc=Taille du voisinage
dialog.compress.wackypoints.title=Suppression des points anormaux
dialog.compress.wackypoints.paramdesc=Distance
-dialog.compress.singletons.title=Suppression des points isolés
+dialog.compress.singletons.title=Suppression des points isol\u00e9s
dialog.compress.singletons.paramdesc=Distance
-dialog.compress.summarylabel=Points à supprimer
-dialog.help.help=Consultez la page\n http://activityworkshop.net/software/prune/\npour plus de détails et des manuels utilisateur.
+dialog.compress.summarylabel=Points \u00e0 supprimer
+dialog.help.help=Consultez la page\n http://activityworkshop.net/software/prune/\npour plus de d\u00e9tails et des manuels utilisateur.
dialog.about.version=Version
dialog.about.build=Build
-dialog.about.summarytext1=Prune est un programme pour charger, afficher et éditer des données de récepteurs GPS.
-dialog.about.summarytext2=Distribué sous license Gnu GPL pour un usage et une amélioration libres, ouverts et mondiaux.<br>La copie, la redistribution et la modification sont autorisées et encouragées<br>selon les conditions détaillées dans le fichier <code>license.txt</code> inclus.
-dialog.about.summarytext3=Consultez la page <code style="font-weight:bold">http://activityworkshop.net/</code> pour plus de détails et des manuels utilisateur.
+dialog.about.summarytext1=Prune est un programme pour charger, afficher et \u00e9diter des donn\u00e9es de r\u00e9cepteurs GPS.
+dialog.about.summarytext2=Distribu\u00e9 sous license Gnu GPL pour un usage et une am\u00e9lioration libres, ouverts et mondiaux.<br>La copie, la redistribution et la modification sont autoris\u00e9es et encourag\u00e9es<br>selon les conditions d\u00e9taill\u00e9es dans le fichier <code>license.txt</code> inclus.
+dialog.about.summarytext3=Consultez la page <code style="font-weight:bold">http://activityworkshop.net/</code> pour plus de d\u00e9tails et des manuels utilisateur.
dialog.about.languages=Langues disponibles
-dialog.about.translatedby=Texte en français par Petrovsk et theYinYeti.
-dialog.about.systeminfo=Info Système
-dialog.about.systeminfo.os=Système d'exploitation
+dialog.about.translatedby=Texte en fran\u00e7ais par Petrovsk et theYinYeti.
+dialog.about.systeminfo=Info Syst\u00e8me
+dialog.about.systeminfo.os=Syst\u00e8me d'exploitation
dialog.about.systeminfo.java=Java Runtime
-dialog.about.systeminfo.java3d=Java3d installé
-dialog.about.systeminfo.povray=Povray installé
-dialog.about.systeminfo.exiftool=Exiftool installé
-dialog.about.systeminfo.gpsbabel=Gpsbabel installé
-dialog.about.systeminfo.gnuplot=Gnuplot installé
+dialog.about.systeminfo.java3d=Java3d install\u00e9
+dialog.about.systeminfo.povray=Povray install\u00e9
+dialog.about.systeminfo.exiftool=Exiftool install\u00e9
+dialog.about.systeminfo.gpsbabel=Gpsbabel install\u00e9
+dialog.about.systeminfo.gnuplot=Gnuplot install\u00e9
dialog.about.yes=Oui
dialog.about.no=Non
-dialog.about.credits=Crédits
-dialog.about.credits.code=Code de Prune écrit par
+dialog.about.credits=Cr\u00e9dits
+dialog.about.credits.code=Code de Prune \u00e9crit par
dialog.about.credits.exifcode=Code Exif par
-dialog.about.credits.icons=Quelques icônes provenant de
-dialog.about.credits.translators=Interprètes
+dialog.about.credits.icons=Quelques ic\u00f4nes provenant de
+dialog.about.credits.translators=Interpr\u00e8tes
dialog.about.credits.translations=Traduction avec l'aide de
-dialog.about.credits.devtools=Outils de développement
+dialog.about.credits.devtools=Outils de d\u00e9veloppement
dialog.about.credits.othertools=Autre outils
-dialog.about.credits.thanks=Merci Ã
+dialog.about.credits.thanks=Merci \u00e0
dialog.about.readme=Lisez-moi
-dialog.checkversion.error=Ne peut pas vérifier la version.\nVeuillez vérifier votre connexion Internet.
-dialog.checkversion.uptodate=Vous utilisez déjà la version actuelle de Prune.
+dialog.checkversion.error=Ne peut pas v\u00e9rifier la version.\nVeuillez v\u00e9rifier votre connexion Internet.
+dialog.checkversion.uptodate=Vous utilisez d\u00e9j\u00e0 la version actuelle de Prune.
dialog.checkversion.newversion1=La version actuelle est maintenant la version
dialog.checkversion.newversion2=.
dialog.checkversion.releasedate1=La nouvelle version est sortie le
dialog.checkversion.releasedate2=.
-dialog.checkversion.download=Pour télécharger la nouvelle version, aller à http://activityworkshop.net/software/prune/download.html.
+dialog.checkversion.download=Pour t\u00e9l\u00e9charger la nouvelle version, aller \u00e0 http://activityworkshop.net/software/prune/download.html.
+dialog.keys.intro=Vous pouvez utiliser ces raccourcis clavier \u00e0 la place de la souris
+dialog.keys.keylist=<table><tr><td>Touches-fl\u00e8ches</td><td>Faire d\u00e9filer la carte horizontallement et verticallement</td></tr><tr><td>Ctrl + gauche, Ctrl + droite</td><td>Choisir le point pr\u00e9c\u00e9dent ou suivant</td></tr><tr><td>Ctrl + haut, Ctrl + bas</td><td>Zoomer, s'\u00e9loigner</td></tr><tr><td>Suppr</td><td>Effacer le point courant</td></tr></table>
+dialog.saveconfig.desc=Les param\u00e8tres suivants peuvent \u00eatre sauvegard\u00e9s dans un fichier de configuration:
+dialog.saveconfig.prune.trackdirectory=Dossier des traces
+dialog.saveconfig.prune.photodirectory=Dossier des Photos
+dialog.saveconfig.prune.languagecode=Code langue (FR)
+dialog.saveconfig.prune.gpsdevice=Chemin du p\u00e9riph\u00e9rique GPS
+dialog.saveconfig.prune.gpsformat=Format GPS
+dialog.saveconfig.prune.povrayfont=Police povray
+dialog.saveconfig.prune.metricunits=Utiliser le syst\u00e8me m\u00e9trique?
+dialog.saveconfig.prune.gnuplotpath=Chemin gnuplot
+dialog.saveconfig.prune.gpsbabelpath=Chemin gpsbabel
+dialog.saveconfig.prune.exiftoolpath=Chemin exiftool
+dialog.saveconfig.prune.mapserverindex=Index du serveur de carte
+dialog.saveconfig.prune.mapserverurl=URL du serveur de carte
+dialog.saveconfig.prune.showpace=Montrer l'allure
+dialog.saveconfig.prune.kmzimagewidth=Largeur de l'image KMZ
+dialog.saveconfig.prune.kmzimageheight=Hauteur de l'image KMZ
+dialog.setpaths.intro=Si vous le souhaitez, vous pouvez d\u00e9finir les chemins des applications externes:
+dialog.addaltitude.noaltitudes=L'\u00e9tendue s\u00e9lectionn\u00e9e de contient pas d'altitudes
+dialog.addaltitude.desc=D\u00e9callage d'altitude \u00e0 ajouter
# 3d window
dialog.3d.title=Vue 3D de Prune
dialog.3d.altitudecap=Etendue d'altitude minimale
dialog.3dlines.title=Grille de Prune
-dialog.3dlines.empty=Pas de grille à afficher !
+dialog.3dlines.empty=Pas de grille \u00e0 afficher !
dialog.3dlines.intro=Ceci est la grille pour la vue 3D
-# Confirm messages - these are displayed as confirmation in the status bar
-confirm.loadfile=Données chargées depuis le fichier
-confirm.save.ok1=Enregistrement réussi de
+# Confirm messages || These are displayed as confirmation in the status bar
+confirm.loadfile=Donn\u00e9es charg\u00e9es depuis le fichier
+confirm.save.ok1=Enregistrement r\u00e9ussi de
confirm.save.ok2=points dans le fichier
-confirm.deletepoint.single=point a été effacé
-confirm.deletepoint.multi=points ont été effacés
-confirm.point.edit=point édité
-confirm.mergetracksegments=Segments de trace ont été fusionné
-confirm.reverserange=Etendue inversée
-confirm.addtimeoffset=Décalage ajouté
-confirm.rearrangewaypoints=Waypoints réarrangés
-confirm.cutandmove=Sélection déplacée
+confirm.deletepoint.single=point a \u00e9t\u00e9 effac\u00e9
+confirm.deletepoint.multi=points ont \u00e9t\u00e9 effac\u00e9s
+confirm.point.edit=point \u00e9dit\u00e9
+confirm.mergetracksegments=Segments de trace ont \u00e9t\u00e9 fusionn\u00e9
+confirm.reverserange=Etendue invers\u00e9e
+confirm.addtimeoffset=D\u00e9calage ajout\u00e9
+confirm.addaltitudeoffset=D\u00e9calage d'altitude ajout\u00e9
+confirm.rearrangewaypoints=Waypoints r\u00e9arrang\u00e9s
+confirm.cutandmove=S\u00e9lection d\u00e9plac\u00e9e
confirm.saveexif.ok1=Enregistrement de
confirm.saveexif.ok2=fichiers photo
-confirm.undo.single=opération annulée
-confirm.undo.multi=opérations annulées
-confirm.jpegload.single=la photo a été ajoutée
-confirm.jpegload.multi=les photos ont été ajoutées
-confirm.photo.connect=photo reliée
-confirm.photo.disconnect=photo détachée
-confirm.correlate.single=photo a été corrélée
-confirm.correlate.multi=photos ont été corrélées
-confirm.createpoint=Point créé
+confirm.undo.single=op\u00e9ration annul\u00e9e
+confirm.undo.multi=op\u00e9rations annul\u00e9es
+confirm.jpegload.single=la photo a \u00e9t\u00e9 ajout\u00e9e
+confirm.jpegload.multi=les photos ont \u00e9t\u00e9 ajout\u00e9es
+confirm.photo.connect=photo reli\u00e9e
+confirm.photo.disconnect=photo d\u00e9tach\u00e9e
+confirm.correlate.single=photo a \u00e9t\u00e9 corr\u00e9l\u00e9e
+confirm.correlate.multi=photos ont \u00e9t\u00e9 corr\u00e9l\u00e9es
+confirm.createpoint=Point cr\u00e9\u00e9
+confirm.running=En cours...
# Buttons
button.ok=OK
button.next=Prochain
button.finish=Fin
button.cancel=Annuler
-button.overwrite=Écraser
+button.overwrite=\u00c9craser
button.moveup=Monter
button.movedown=Descendre
button.showlines=Montrer les lignes
-button.edit=Éditer
+button.edit=\u00c9diter
button.exit=Terminer
button.close=Fermer
button.continue=Continuer
button.no=Non
button.yestoall=Oui pour tous
button.notoall=Non pour tous
-button.selectall=Tout sélectionner
-button.selectnone=Ne rien sélectionner
-button.preview=Aperçu
+button.selectall=Tout s\u00e9lectionner
+button.selectnone=Ne rien s\u00e9lectionner
+button.preview=Aper\u00e7u
+button.load=T\u00e9l\u00e9charger
button.guessfields=Deviner les champs
button.showwebpage=Montrer page web
-button.gnuplotpath=Localiser gnuplot
+button.check=V\u00e9rifier
# File types
filetype.txt=Fichiers TXT
filetype.svg=Fichiers SVG
# Display components
-display.nodata=Pas de données chargées
+display.nodata=Pas de donn\u00e9es charg\u00e9es
display.noaltitudes=La trace ne comporte pas d'information d'altitude
-details.trackdetails=Détails de la trace
-details.notrack=Pas de trace chargée
+details.trackdetails=D\u00e9tails de la trace
+details.notrack=Pas de trace charg\u00e9e
details.track.points=Points
details.track.file=Fichier
details.track.numfiles=Nombre de fichiers
-details.pointdetails=Détails du point
+details.pointdetails=D\u00e9tails du point
details.index.selected=Index
details.index.of=sur
details.nopointselection=Aucun point choisi
details.photofile=Fichier photo
-details.norangeselection=Aucune étendue sélectionnée
-details.rangedetails=Détails sur l'étendue
-details.range.selected=Sélection des points
-details.range.to=Ã
-details.altitude.to=Ã
-details.range.climb=Montée
+details.norangeselection=Aucune \u00e9tendue s\u00e9lectionn\u00e9e
+details.rangedetails=D\u00e9tails sur l'\u00e9tendue
+details.range.selected=S\u00e9lection des points
+details.range.to=\u00e0
+details.altitude.to=\u00e0
+details.range.climb=Mont\u00e9e
details.range.descent=Descente
-details.coordformat=Format de coordonnées
-details.distanceunits=Unités de distance
+details.coordformat=Format de coordonn\u00e9es
+details.distanceunits=Unit\u00e9s de distance
display.range.time.secs=s
display.range.time.mins=m
display.range.time.hours=h
display.range.time.days=j
details.range.avespeed=Vitesse moyenne
details.range.avemovingspeed=Moyenne continue
+details.range.pace=Allure
details.waypointsphotos.waypoints=Waypoints
details.waypointsphotos.photos=Photos
-details.photodetails=Détails de la photo
+details.photodetails=D\u00e9tails de la photo
details.nophoto=Pas de photo
details.photo.loading=Chargement
-details.photo.connected=Reliée
-map.overzoom=Aucune carte disponible à ce niveau de zoom
+details.photo.connected=Reli\u00e9e
+map.overzoom=Aucune carte disponible \u00e0 ce niveau de zoom
# Field names
fieldname.latitude=Latitude
fieldname.waypointname=Nom
fieldname.waypointtype=Type
fieldname.newsegment=Segment
-fieldname.custom=Personnalisé
+fieldname.custom=Personnalis\u00e9
fieldname.prefix=Champ
fieldname.distance=Distance
fieldname.movingdistance=Distance continue
-fieldname.duration=Durée
+fieldname.duration=Dur\u00e9e
fieldname.speed=Vitesse
fieldname.verticalspeed=Vitesse verticale
# Measurement units
units.original=Original
-units.default=Défaut
-units.metres=mètres
+units.default=D\u00e9faut
+units.metres=m\u00e8tres
units.metres.short=m
units.feet=pieds
units.feet.short=p
-units.kilometres=Kilomètres
+units.kilometres=Kilom\u00e8tres
units.kilometres.short=km
units.kmh=km/h
units.miles=Miles
units.hours=heures
units.degminsec=Deg-min-sec
units.degmin=Deg-min
-units.deg=Degrés
+units.deg=Degr\u00e9s
units.iso8601=ISO 8601
# External urls
cardinal.w=O
# Undo operations
-undo.load=charger les données
+undo.load=charger les donn\u00e9es
undo.loadphotos=charger les photos
-undo.editpoint=éditer le point
+undo.editpoint=\u00e9diter le point
undo.deletepoint=effacer le point
undo.deletephoto=retirer la photo
-undo.deleterange=effacer l'étendue
+undo.deleterange=effacer l'\u00e9tendue
undo.compress=compresser la trace
-undo.insert=insérer les points
-undo.reverse=inverser l'étendue
+undo.insert=ins\u00e9rer les points
+undo.reverse=inverser l'\u00e9tendue
undo.mergetracksegments=fusionner les segments de trace
-undo.addtimeoffset=ajouter décalage d'heure
-undo.rearrangewaypoints=réarranger les waypoints
-undo.cutandmove=déplacer la sélection
+undo.addtimeoffset=ajouter d\u00e9calage d'heure
+undo.addaltitudeoffset=ajouter d\u00e9calage d'altitude
+undo.rearrangewaypoints=r\u00e9arranger les waypoints
+undo.cutandmove=d\u00e9placer la s\u00e9lection
undo.connectphoto=relier la photo
-undo.disconnectphoto=détacher la photo
-undo.correlate=corréler les photos
+undo.disconnectphoto=d\u00e9tacher la photo
+undo.correlate=corr\u00e9ler les photos
undo.createpoint=ajouter un point
# Error messages
-error.save.dialogtitle=Erreur à l'enregistrement des données
-error.save.nodata=Pas de données à enregistrer
-error.save.failed=Echec de l'enregistrement des données dans le fichier:
+error.save.dialogtitle=Erreur \u00e0 l'enregistrement des donn\u00e9es
+error.save.nodata=Pas de donn\u00e9es \u00e0 enregistrer
+error.save.failed=Echec de l'enregistrement des donn\u00e9es dans le fichier
error.saveexif.filenotfound=Fichier photo introuvable
error.saveexif.cannotoverwrite1=Le fichier photo
-error.saveexif.cannotoverwrite2=est en lecture seule et ne peut pas être écraser. Enregistrer sur une copie ?
-error.load.dialogtitle=Erreur au chargement des données
+error.saveexif.cannotoverwrite2=est en lecture seule et ne peut pas \u00eatre \u00e9craser. Enregistrer sur une copie ?
+error.load.dialogtitle=Erreur au chargement des donn\u00e9es
error.load.noread=Fichier illisible
-error.load.nopoints=Aucune coordonnée trouvée dans le fichier
+error.load.nopoints=Aucune coordonn\u00e9e trouv\u00e9e dans le fichier
error.load.unknownxml=Format xml non-reconnu :
-error.load.noxmlinzip=
-error.load.othererror=Erreur à la lecture du fichier :
+error.load.noxmlinzip=Aucune xml fichier trouv\u00e9e dans le fichier
+error.load.othererror=Erreur \u00e0 la lecture du fichier :
error.jpegload.dialogtitle=Erreur au chargement des photos
-error.jpegload.nofilesfound=Aucun fichier trouvé
-error.jpegload.nojpegsfound=Aucun fichier jpeg trouvé
-error.jpegload.noexiffound=Aucune information EXIF trouvée
-error.jpegload.nogpsfound=Aucune information GPS trouvée
+error.jpegload.nofilesfound=Aucun fichier trouv\u00e9
+error.jpegload.nojpegsfound=Aucun fichier jpeg trouv\u00e9
+error.jpegload.noexiffound=Aucune information EXIF trouv\u00e9e
+error.jpegload.nogpsfound=Aucune information GPS trouv\u00e9e
error.undofailed.title=Echec de l'annulation
-error.undofailed.text=Echec de l'opération d'annulation
+error.undofailed.text=Echec de l'op\u00e9ration d'annulation
error.function.noop.title=Fonction sans effet
-error.rearrange.noop=Réarrangement des waypoints sans effet
+error.rearrange.noop=R\u00e9arrangement des waypoints sans effet
error.function.notavailable.title=Function non-disponible
-error.function.nojava3d=Cette fonction nécessite la librairie Java3d,\ndisponible sur Sun.com.
-error.3d=Un problème est survenu avec l'affichage 3D
+error.function.nojava3d=Cette fonction n\u00e9cessite la librairie Java3d,\ndisponible sur Sun.com.
+error.3d=Un probl\u00e8me est survenu avec l'affichage 3D
error.readme.notfound=Fichier Lisez-moi introuvable
error.osmimage.dialogtitle=Erreur au chargement des portions de cartes
-error.osmimage.failed=Erreur du chargement des portions de cartes. Vérifiez votre connexion internet.
+error.osmimage.failed=Erreur du chargement des portions de cartes. V\u00e9rifiez votre connexion internet.
menu.file.exit=Keluar
menu.edit=Ubah
menu.edit.undo=Batal
-menu.edit.clearundo=
+
menu.edit.editpoint=Perbaiki titik
-menu.edit.editwaypointname=Perbaiki Nama waypoint
menu.edit.deletepoint=Hapus titik
menu.edit.deleterange=Hapus jarak
-menu.edit.deletemarked=
-menu.edit.interpolate=
-menu.edit.average=
-menu.edit.reverse=
-menu.edit.mergetracksegments=
-menu.edit.rearrange=
-menu.edit.rearrange.start=
-menu.edit.rearrange.end=
-menu.edit.rearrange.nearest=
-menu.edit.cutandmove=
menu.select=Pilih
menu.select.all=Pilih semua
menu.select.none=Tidak memilih
-menu.select.start=
-menu.select.end=
menu.photo=Foto
menu.photo.saveexif=Simpan ke Exif
menu.photo.connect=Hubungkan ke titik
menu.photo.disconnect=Putuskan dari titik
-menu.photo.delete=
+menu.photo.delete=Menghapus foto
menu.view=Lihat
-menu.view.browser=
-menu.view.browser.google=
-menu.view.browser.openstreetmap=
-menu.view.browser.mapquest=
-menu.view.browser.yahoo=
+menu.settings=Pengaturan
+menu.view.browser=Peta di browser
menu.help=Bantuan
# Popup menu for map
menu.map.zoomin=Perbesar
menu.map.zoomout=Perkecil
-menu.map.zoomfull=
menu.map.newpoint=Buat titik baru
menu.map.connect=Hubungkan titik jalur
-menu.map.autopan=
menu.map.showmap=Tampilkan peta
+# Alt keys for menus
+altkey.menu.file=B
+altkey.menu.edit=U
+altkey.menu.select=P
+altkey.menu.view=L
+altkey.menu.photo=F
+altkey.menu.settings=G
+altkey.menu.help=N
+
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=B
+shortcut.menu.file.load=M
+shortcut.menu.file.save=S
+shortcut.menu.edit.undo=Z
+shortcut.menu.edit.compress=P
+shortcut.menu.select.all=-
+shortcut.menu.help.help=-
+
# Functions
function.loadfromgps=Muat data dari GPS
function.sendtogps=Kirim data ke GPS
function.exportkml=Ekspor KML
function.exportgpx=Ekspor GPX
function.exportpov=Ekspor POV
+function.editwaypointname=Perbaiki Nama waypoint
function.compress=Padatkan jalur
-function.addtimeoffset=
+
+function.findwaypoint=Menemukan waypoint
function.charts=Grafik
function.show3d=Lihat tiga-D
-function.distances=
-function.setmapbg=
+function.distances=Jarak
+
function.correlatephotos=Korelasikan foto
function.help=Bantuan
function.about=Tentang Prune
-function.checkversion=
+function.saveconfig=Simpan pengaturan
# Dialogs
-dialog.exit.confirm.title=
-dialog.exit.confirm.text=
-dialog.openappend.title=
-dialog.openappend.text=
-dialog.deletepoint.title=
-dialog.deletepoint.deletephoto=
-dialog.deletephoto.title=
-dialog.deletephoto.deletepoint=
-dialog.openoptions.title=
-dialog.openoptions.filesnippet=
-dialog.load.table.field=
dialog.load.table.datatype=Jenis
dialog.load.table.description=Keterangan
-dialog.delimiter.label=
-dialog.delimiter.comma=
-dialog.delimiter.tab=
-dialog.delimiter.space=
-dialog.delimiter.semicolon=
-dialog.delimiter.other=
-dialog.openoptions.deliminfo.records=
-dialog.openoptions.deliminfo.fields=
-dialog.openoptions.deliminfo.norecords=
-dialog.openoptions.altitudeunits=
-dialog.jpegload.subdirectories=
-dialog.jpegload.loadjpegswithoutcoords=
-dialog.jpegload.loadjpegsoutsidearea=
-dialog.jpegload.progress.title=
-dialog.jpegload.progress=
-dialog.gpsload.nogpsbabel=
-dialog.gpsload.device=
-dialog.gpsload.format=
-dialog.gpsload.getwaypoints=
-dialog.gpsload.gettracks=
-dialog.gpssend.sendwaypoints=
-dialog.gpssend.sendtracks=
-dialog.gpssend.trackname=
-dialog.saveoptions.title=
-dialog.save.fieldstosave=
-dialog.save.table.field=
-dialog.save.table.hasdata=
-dialog.save.table.save=
-dialog.save.headerrow=
-dialog.save.coordinateunits=
-dialog.save.altitudeunits=
-dialog.save.timestampformat=
-dialog.save.overwrite.title=
-dialog.save.overwrite.text=
-dialog.exportkml.text=
-dialog.exportkml.altitude=
-dialog.exportkml.kmz=
-dialog.exportkml.exportimages=
-dialog.exportgpx.name=
-dialog.exportgpx.desc=
-dialog.exportgpx.includetimestamps=
-dialog.exportpov.text=
-dialog.exportpov.font=
-dialog.exportpov.camerax=
-dialog.exportpov.cameray=
-dialog.exportpov.cameraz=
-dialog.exportpov.modelstyle=
-dialog.exportpov.ballsandsticks=
-dialog.exportpov.tubesandwalls=
-dialog.exportpov.warningtracksize=
-dialog.confirmreversetrack.title=
-dialog.confirmreversetrack.text=
-dialog.confirmcutandmove.title=
-dialog.confirmcutandmove.text=
-dialog.interpolate.title=
-dialog.interpolate.parameter.text=
-dialog.undo.title=
-dialog.undo.pretext=
-dialog.undo.none.title=
-dialog.undo.none.text=
-dialog.clearundo.title=
-dialog.clearundo.text=
-dialog.pointedit.title=
-dialog.pointedit.text=
-dialog.pointedit.table.field=
-dialog.pointedit.table.value=
-dialog.pointedit.table.changed=
-dialog.pointedit.changevalue.text=
-dialog.pointedit.changevalue.title=
-dialog.pointnameedit.title=
dialog.pointnameedit.name=Nama
-dialog.pointnameedit.uppercase=
-dialog.pointnameedit.lowercase=
-dialog.pointnameedit.sentencecase=
-dialog.addtimeoffset.add=
-dialog.addtimeoffset.subtract=
-dialog.addtimeoffset.days=
-dialog.addtimeoffset.hours=
-dialog.addtimeoffset.minutes=
-dialog.addtimeoffset.notimestamps=
-dialog.connect.title=
-dialog.connectphoto.clonepoint=
-dialog.saveexif.title=
-dialog.saveexif.intro=
-dialog.saveexif.nothingtosave=
-dialog.saveexif.noexiftool=
-dialog.saveexif.table.photoname=
-dialog.saveexif.table.status=
-dialog.saveexif.table.save=
-dialog.saveexif.photostatus.connected=
-dialog.saveexif.photostatus.disconnected=
-dialog.saveexif.photostatus.modified=
-dialog.saveexif.overwrite=
-dialog.charts.xaxis=
-dialog.charts.yaxis=
-dialog.charts.output=
-dialog.charts.screen=
-dialog.charts.svg=
-dialog.charts.svgwidth=
-dialog.charts.svgheight=
-dialog.charts.needaltitudeortimes=
-dialog.charts.gnuplotpath=
-dialog.charts.gnuplotnotfound=
-dialog.distances.intro=
dialog.distances.column.from=Awal
dialog.distances.column.to=Akhir
-dialog.distances.currentpoint=
-dialog.distances.toofewpoints=
-dialog.setmapbg.mapnik=
-dialog.setmapbg.osma=
-dialog.setmapbg.cyclemap=
-dialog.setmapbg.other=
-dialog.setmapbg.server=
-dialog.correlate.notimestamps=
-dialog.correlate.nouncorrelatedphotos=
-dialog.correlate.photoselect.intro=
-dialog.correlate.photoselect.photoname=
-dialog.correlate.photoselect.timediff=
-dialog.correlate.photoselect.photolater=
-dialog.correlate.options.tip=
-dialog.correlate.options.intro=
-dialog.correlate.options.offsetpanel=
-dialog.correlate.options.offset=
-dialog.correlate.options.offset.hours=
-dialog.correlate.options.offset.minutes=
-dialog.correlate.options.offset.seconds=
-dialog.correlate.options.photolater=
-dialog.correlate.options.pointlater=
-dialog.correlate.options.limitspanel=
-dialog.correlate.options.notimelimit=
-dialog.correlate.options.timelimit=
-dialog.correlate.options.nodistancelimit=
-dialog.correlate.options.distancelimit=
-dialog.correlate.options.correlate=
-dialog.correlate.alloutsiderange=
-dialog.compress.nonefound=
-dialog.compress.duplicates.title=
-dialog.compress.closepoints.title=
-dialog.compress.closepoints.paramdesc=
-dialog.compress.wackypoints.title=
-dialog.compress.wackypoints.paramdesc=
-dialog.compress.singletons.title=
-dialog.compress.singletons.paramdesc=
-dialog.compress.summarylabel=
-dialog.help.help=
-dialog.about.version=
-dialog.about.build=
-dialog.about.summarytext1=
-dialog.about.summarytext2=
-dialog.about.summarytext3=
dialog.about.languages=Bahasa
-dialog.about.translatedby=
-dialog.about.systeminfo=
-dialog.about.systeminfo.os=
-dialog.about.systeminfo.java=
-dialog.about.systeminfo.java3d=
-dialog.about.systeminfo.povray=
-dialog.about.systeminfo.exiftool=
-dialog.about.systeminfo.gpsbabel=
-dialog.about.systeminfo.gnuplot=
dialog.about.yes=Ya
dialog.about.no=Tidak
-dialog.about.credits=
-dialog.about.credits.code=
-dialog.about.credits.exifcode=
-dialog.about.credits.icons=
-dialog.about.credits.translators=
-dialog.about.credits.translations=
-dialog.about.credits.devtools=
-dialog.about.credits.othertools=
-dialog.about.credits.thanks=
-dialog.about.readme=
-dialog.checkversion.error=
-dialog.checkversion.uptodate=
-dialog.checkversion.newversion1=
-dialog.checkversion.newversion2=
-dialog.checkversion.releasedate1=
-dialog.checkversion.releasedate2=
-dialog.checkversion.download=
-
-# 3d window
-dialog.3d.title=
-dialog.3d.altitudecap=
-dialog.3dlines.title=
-dialog.3dlines.empty=
-dialog.3dlines.intro=
-
-# Confirm messages || These are displayed as confirmation in the status bar
-confirm.loadfile=
-confirm.save.ok1=
-confirm.save.ok2=
-confirm.deletepoint.single=
-confirm.deletepoint.multi=
-confirm.point.edit=
-confirm.mergetracksegments=
-confirm.reverserange=
-confirm.addtimeoffset=
-confirm.rearrangewaypoints=
-confirm.cutandmove=
-confirm.saveexif.ok1=
-confirm.saveexif.ok2=
-confirm.undo.single=
-confirm.undo.multi=
-confirm.jpegload.single=
-confirm.jpegload.multi=
-confirm.photo.connect=
-confirm.photo.disconnect=
-confirm.correlate.single=
-confirm.correlate.multi=
-confirm.createpoint=
# Buttons
-button.ok=
button.back=Sebelumnya
button.next=Lanjut
-button.finish=
-button.cancel=
-button.overwrite=
-button.moveup=
-button.movedown=
-button.showlines=
-button.edit=
-button.exit=
button.close=Tutup
-button.continue=
button.yes=Ya
button.no=Tidak
-button.yestoall=
-button.notoall=
-button.selectall=
-button.selectnone=
-button.preview=
button.guessfields=Deteksi otomatis
-button.showwebpage=
-button.gnuplotpath=
# File types
filetype.txt=Berkas teks
filetype.svg=Berkas SVG
# Display components
-display.nodata=
-display.noaltitudes=
-details.trackdetails=
-details.notrack=
-details.track.points=
-details.track.file=
-details.track.numfiles=
-details.pointdetails=
-details.index.selected=
-details.index.of=
-details.nopointselection=
-details.photofile=
-details.norangeselection=
-details.rangedetails=
-details.range.selected=
-details.range.to=
-details.altitude.to=
-details.range.climb=
-details.range.descent=
-details.coordformat=
-details.distanceunits=
-display.range.time.secs=
-display.range.time.mins=
-display.range.time.hours=
-display.range.time.days=
-details.range.avespeed=
-details.range.avemovingspeed=
-details.waypointsphotos.waypoints=
-details.waypointsphotos.photos=
-details.photodetails=
-details.nophoto=
+display.nodata=Tidak ada data
+details.trackdetails=Rincian track
+details.notrack=Tidak ada track
+details.pointdetails=Rincian titik
+details.nopointselection=Tidak ada titik
+details.norangeselection=Tidak ada jangkauan
+details.rangedetails=Rincian jangkauan
+details.waypointsphotos.photos=Foto
+details.photodetails=Rincian foto
+details.nophoto=Tidak ada foto
details.photo.loading=Membuka
-details.photo.connected=
-map.overzoom=
-
-# Field names
-fieldname.latitude=
-fieldname.longitude=
-fieldname.altitude=
-fieldname.timestamp=
-fieldname.time=
-fieldname.waypointname=
-fieldname.waypointtype=
-fieldname.newsegment=
-fieldname.custom=
-fieldname.prefix=
-fieldname.distance=
-fieldname.movingdistance=
-fieldname.duration=
-fieldname.speed=
-fieldname.verticalspeed=
-
-# Measurement units
-units.original=
-units.default=
-units.metres=
-units.metres.short=
-units.feet=
-units.feet.short=
-units.kilometres=
-units.kilometres.short=
-units.kmh=
-units.miles=
-units.miles.short=
-units.mph=
-units.metrespersec=
-units.feetpersec=
-units.hours=
-units.degminsec=
-units.degmin=
-units.deg=
-units.iso8601=
-
-# External urls
-url.googlemaps=
-
-# Cardinals for 3d plots
-cardinal.n=
-cardinal.s=
-cardinal.e=
-cardinal.w=
-
-# Undo operations
-undo.load=
-undo.loadphotos=
-undo.editpoint=
-undo.deletepoint=
-undo.deletephoto=
-undo.deleterange=
-undo.compress=
-undo.insert=
-undo.reverse=
-undo.mergetracksegments=
-undo.addtimeoffset=
-undo.rearrangewaypoints=
-undo.cutandmove=
-undo.connectphoto=
-undo.disconnectphoto=
-undo.correlate=
-undo.createpoint=
-
-# Error messages
-error.save.dialogtitle=
-error.save.nodata=
-error.save.failed=
-error.saveexif.filenotfound=
-error.saveexif.cannotoverwrite1=
-error.saveexif.cannotoverwrite2=
-error.load.dialogtitle=
-error.load.noread=
-error.load.nopoints=
-error.load.unknownxml=
-error.load.noxmlinzip=
-error.load.othererror=
-error.jpegload.dialogtitle=
-error.jpegload.nofilesfound=
-error.jpegload.nojpegsfound=
-error.jpegload.noexiffound=
-error.jpegload.nogpsfound=
-error.undofailed.title=
-error.undofailed.text=
-error.function.noop.title=
-error.rearrange.noop=
-error.function.notavailable.title=
-error.function.nojava3d=
-error.3d=
-error.readme.notfound=
-error.osmimage.dialogtitle=
-error.osmimage.failed=
menu.edit.undo=Annulla
menu.edit.clearundo=Cancella lista ultime modifiche
menu.edit.editpoint=Edita punto
-menu.edit.editwaypointname=Edita nome waypoint
menu.edit.deletepoint=Cancella punto
menu.edit.deleterange=Cancella la serie
menu.edit.deletemarked=Cancella punti marcati
menu.edit.rearrange=Riorganizza waypoint
menu.edit.rearrange.start=Tutti all'inizio del file
menu.edit.rearrange.end=Tutti alla fine del file
-menu.edit.rearrange.nearest=Sul punto più vicino
+menu.edit.rearrange.nearest=Sul punto pi\u00f9 vicino
menu.edit.cutandmove=Taglia e muovi la selezione
menu.select=Seleziona
menu.select.all=Seleziona tutto
menu.view.browser.openstreetmap=Openstreetmap
menu.view.browser.mapquest=Mapquest
menu.view.browser.yahoo=mappe Yahoo
+menu.settings=Preferenze
+menu.settings.showpace=
menu.help=Aiuto
# Popup menu for map
menu.map.zoomin=Zoom +
menu.map.connect=Aggancia ai punti
menu.map.autopan=Autopan
menu.map.showmap=Mostra sulla mappa
+menu.map.showscalebar=
+
+# Alt keys for menus
+altkey.menu.file=F
+altkey.menu.edit=E
+altkey.menu.select=S
+altkey.menu.view=V
+altkey.menu.photo=O
+altkey.menu.settings=P
+altkey.menu.help=A
+
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=A
+shortcut.menu.file.load=C
+shortcut.menu.file.save=S
+shortcut.menu.edit.undo=Z
+shortcut.menu.edit.compress=C
+shortcut.menu.select.all=T
+shortcut.menu.help.help=H
# Functions
function.loadfromgps=Carica dati da GPS
function.exportkml=Esporta in KML
function.exportgpx=Esporta in GPX
function.exportpov=Esporta in POV
+function.editwaypointname=Edita nome waypoint
function.compress=Comprimi la traccia
function.addtimeoffset=Aggiungi uno scarto temporale
+function.addaltitudeoffset=
+function.findwaypoint=
function.charts=Diagrammi
function.show3d=Mostra in 3D
function.distances=Mostra distanze
-function.setmapbg=Configura sfondo mappa
+function.getgpsies=
function.correlatephotos=Correla le foto
+function.setmapbg=Configura sfondo mappa
+function.setkmzimagesize=
+function.setpaths=
function.help=Aiuto
+function.showkeys=
function.about=Informazioni su Prune
function.checkversion=Controlla gli aggiornamenti
+function.saveconfig=
# Dialogs
dialog.exit.confirm.title=Esci da Prune
dialog.exit.confirm.text=Le modifiche non sono state salvate. Sei sicuro di voler uscire?
dialog.openappend.title=Aggiungi ai dati esistenti
-dialog.openappend.text=Aggiungi questi dati a quelli già caricati?
+dialog.openappend.text=Aggiungi questi dati a quelli gi\u00e0 caricati?
dialog.deletepoint.title=Cancella Punto
dialog.deletepoint.deletephoto=Cancella la foto collegata a questo punto?
dialog.deletephoto.title=Cancella Foto
dialog.openoptions.deliminfo.records=registra, con
dialog.openoptions.deliminfo.fields=campi
dialog.openoptions.deliminfo.norecords=Nessun record
-dialog.openoptions.altitudeunits=Unità di misura altitudine
+dialog.openoptions.altitudeunits=Unit\u00e0 di misura altitudine
dialog.jpegload.subdirectories=Includi sottocartelle
dialog.jpegload.loadjpegswithoutcoords=Includi foto senza coordinate
dialog.jpegload.loadjpegsoutsidearea=Includi foto fuori dall'area corrente
dialog.save.table.hasdata=Ha dati
dialog.save.table.save=Salva
dialog.save.headerrow=Regista l'intestazione delle righe
-dialog.save.coordinateunits=Unità di misura coordinate
-dialog.save.altitudeunits=Unità di misura altitudine
+dialog.save.coordinateunits=Unit\u00e0 di misura coordinate
+dialog.save.altitudeunits=Unit\u00e0 di misura altitudine
dialog.save.timestampformat=Formato della data
-dialog.save.overwrite.title=File già esistente
-dialog.save.overwrite.text=Questo file esiste già . Sei sicuro di volerlo sovrascrivere?
+dialog.save.overwrite.title=File gi\u00e0 esistente
+dialog.save.overwrite.text=Questo file esiste gi\u00e0. Sei sicuro di volerlo sovrascrivere?
dialog.exportkml.text=Titolo dei dati
dialog.exportkml.altitude=Includi altitudine (per aviazione)
dialog.exportkml.kmz=Comprimi per file kmz
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ò non essere in grado di visualizzarli.\nSei sicuro di voler continuare?
+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.pointtype.desc=
+dialog.pointtype.track=
+dialog.pointtype.waypoint=
+dialog.pointtype.photo=
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.interpolate.parameter.text=Numero di punti da inserire tra i punti selezionati
dialog.undo.title=Annulla l'azione(i)
dialog.undo.pretext=Per favore seleziona l'azione(i) da annullare
-dialog.undo.none.title=Non è possibile annullare
+dialog.undo.none.title=Non \u00e8 possibile annullare
dialog.undo.none.text=Nessuna operazione da annullare!
dialog.clearundo.title=Cancella la lista annulla
dialog.clearundo.text=Sei sicuro di voler cancellare la lista annulla?\nTutte le informazioni saranno perse!
dialog.pointedit.table.changed=Cambiato
dialog.pointedit.changevalue.text=Inserisci il nuovo valore di questo campo
dialog.pointedit.changevalue.title=Edita il campo
-dialog.pointnameedit.title=Edita il nome del waypoint
dialog.pointnameedit.name=Nome del waypoint
dialog.pointnameedit.uppercase=MAIUSCOLE
dialog.pointnameedit.lowercase=minuscole
dialog.addtimeoffset.days=Giorni
dialog.addtimeoffset.hours=Ore
dialog.addtimeoffset.minutes=Minuti
-dialog.addtimeoffset.notimestamps=Non posso aggiungere uno scarto temporale a questa selezione perché non contiene informazioni temporali
+dialog.addtimeoffset.notimestamps=Non posso aggiungere uno scarto temporale a questa selezione perch\u00e9 non contiene informazioni temporali
+dialog.findwaypoint.intro=
+dialog.findwaypoint.search=
dialog.connect.title=Collega la foto al punto
-dialog.connectphoto.clonepoint=Questo punto ha già una foto collegata.\nVuoi fare una copia del punto?
+dialog.connectphoto.clonepoint=Questo punto ha gi\u00e0 una foto collegata.\nVuoi fare una copia del punto?
dialog.saveexif.title=Salva Exif
dialog.saveexif.intro=Seleziona le foto da salvare usando le caselle di spunta
dialog.saveexif.nothingtosave=Le coordinate non sono cambiate, niente da registrare
dialog.setmapbg.cyclemap=Mappa ciclistica
dialog.setmapbg.other=Altro
dialog.setmapbg.server=URL server
-dialog.correlate.notimestamps=Non ci sono informazioni temporali tra i dati dei punti, non c'è niente per collegarli con le foto.
+dialog.gpsies.column.name=
+dialog.gpsies.column.length=
+dialog.gpsies.description=
+dialog.gpsies.nodescription=
+dialog.gpsies.nonefound=
+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.photoselect.photoname=Nome della foto
dialog.correlate.options.nodistancelimit=Nessun limite di distanza
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ò essere correlata.\nProva a cambiare lo scarto o correla manualmente almeno una foto.
+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.compress.nonefound=Nessun punto rimosso
dialog.compress.duplicates.title=Cancella duplicati
dialog.compress.closepoints.title=Cancella punti vicini
dialog.compress.singletons.title=Cancella solitari
dialog.compress.singletons.paramdesc=Fattore distanza
dialog.compress.summarylabel=Punti da cancellare
-dialog.help.help=Per favore vedi\n http://activityworkshop.net/software/prune/\nper maggiori informazioni e per la guida utente.
+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.summarytext1=Prune è un programma per il caricamento, la visione e l'edit di dati provenienti da un GPS.
-dialog.about.summarytext2=È rilasciato sotto la licenza Gnu GPL per l'uso gratuito e aperto ed il suo miglioramento, con validità mondiale.<br>La copia, la ridistribuzione sono permesse e incoraggiate<br>in accordo con i termini inclusi nel file <code>license.txt</code>.
+dialog.about.summarytext1=Prune \u00e8 un programma per il caricamento, la visione e l'edit di dati provenienti da un GPS.
+dialog.about.summarytext2=\u00c8 rilasciato sotto la licenza Gnu GPL per l'uso gratuito e aperto ed il suo miglioramento, con validit\u00e0 mondiale.<br>La copia, la ridistribuzione sono permesse e incoraggiate<br>in accordo con i termini inclusi nel file <code>license.txt</code>.
dialog.about.summarytext3=Per favore vedi <code style="font-weight:bold">http://activityworkshop.net/</code> per maggiori informazioni e per la guida utente.
dialog.about.languages=Lingue disponibili
dialog.about.translatedby=Testo italiano di Giovanni Sartor + altro
dialog.about.systeminfo.exiftool=Exiftool installato
dialog.about.systeminfo.gpsbabel=Gpsbabel installato
dialog.about.systeminfo.gnuplot=Gnuplot installato
-dialog.about.yes=Sì
+dialog.about.yes=S\u00ec
dialog.about.no=No
dialog.about.credits=Crediti
-dialog.about.credits.code=Il codice Prune code è scritto da
-dialog.about.credits.exifcode=Il codice Exif è scritto da
+dialog.about.credits.code=Il codice Prune code \u00e8 scritto da
+dialog.about.credits.exifcode=Il codice Exif \u00e8 scritto da
dialog.about.credits.icons=Alcune icone prese da
dialog.about.credits.translators=Traduttori
dialog.about.credits.translations=Aiuto nella traduzione da
dialog.about.readme=Leggimi
dialog.checkversion.error=Non posso verificare l'aggiornamento.\nPer favore controlla la connessione internet.
dialog.checkversion.uptodate=Stai usando l'ultima versione di Prune
-dialog.checkversion.newversion1=Una nuova versione di Prune è disponibile! L'ultima versione è ora la versione
+dialog.checkversion.newversion1=Una nuova versione di Prune \u00e8 disponibile! L'ultima versione \u00e8 ora la versione
dialog.checkversion.newversion2=.
-dialog.checkversion.releasedate1=Questa nuova versione è stata rilasciata il
+dialog.checkversion.releasedate1=Questa nuova versione \u00e8 stata rilasciata il
dialog.checkversion.releasedate2=.
dialog.checkversion.download=Per scaricare la nuova versione vai a http://activityworkshop.net/software/prune/download.html.
+dialog.keys.intro=
+dialog.keys.keylist=
+dialog.saveconfig.desc=
+dialog.saveconfig.prune.trackdirectory=
+dialog.saveconfig.prune.photodirectory=
+dialog.saveconfig.prune.languagecode=
+dialog.saveconfig.prune.gpsdevice=Nome del Dispositivo GPS
+dialog.saveconfig.prune.gpsformat=Formato GPS
+dialog.saveconfig.prune.povrayfont=Font povray
+dialog.saveconfig.prune.metricunits=
+dialog.saveconfig.prune.gnuplotpath=Path gnuplot
+dialog.saveconfig.prune.gpsbabelpath=Path gpsbabel
+dialog.saveconfig.prune.exiftoolpath=Path exiftool
+dialog.saveconfig.prune.mapserverindex=
+dialog.saveconfig.prune.mapserverurl=
+dialog.saveconfig.prune.showpace=
+dialog.saveconfig.prune.kmzimagewidth=
+dialog.saveconfig.prune.kmzimageheight=
+dialog.setpaths.intro=
+dialog.addaltitude.noaltitudes=
+dialog.addaltitude.desc=
# 3d window
dialog.3d.title=Visione Prune in 3D
confirm.loadfile=Dati caricati da file
confirm.save.ok1=Salvati con successo
confirm.save.ok2=punti nel file
-confirm.deletepoint.single=punto è stato rimosso
+confirm.deletepoint.single=punto \u00e8 stato rimosso
confirm.deletepoint.multi=punti sono stati rimossi
confirm.point.edit=punto editato
confirm.mergetracksegments=segmeni di traccia uniti
confirm.reverserange=Intervallo invertito
confirm.addtimeoffset=Scarto temporale aggiunto
+confirm.addaltitudeoffset=
confirm.rearrangewaypoints=Waypoint riorganizzati
confirm.cutandmove=Selezione spostata
confirm.saveexif.ok1=Salvato
confirm.saveexif.ok2=foto
confirm.undo.single=operazione annullate
confirm.undo.multi=operazioni annullate
-confirm.jpegload.single=foto è stata aggiunta
+confirm.jpegload.single=foto \u00e8 stata aggiunta
confirm.jpegload.multi=foto sono state aggiunte
confirm.photo.connect=foto collegata
confirm.photo.disconnect=foto scollegata
confirm.correlate.single=foto era correlata
confirm.correlate.multi=foto erano correlate
confirm.createpoint=punto creato
+confirm.running=
# Buttons
button.ok=OK
button.exit=Esci
button.close=Chiudi
button.continue=Continuare
-button.yes=Sì
+button.yes=S\u00ec
button.no=No
button.yestoall=Si a tutto
button.notoall=No a tutto
button.selectall=Seleziona tutto
button.selectnone=Deseleziona tutto
button.preview=Anteprima
+button.load=Carica
button.guessfields=Campi soluzione
button.showwebpage=Mostra pagina
-button.gnuplotpath=Fissa path gnuplot
+button.check=
# File types
filetype.txt=File TXT
details.range.climb=Salita
details.range.descent=Discesa
details.coordformat=Formato coordinate
-details.distanceunits=Unità di misura distanze
+details.distanceunits=Unit\u00e0 di misura distanze
display.range.time.secs=s
display.range.time.mins=m
display.range.time.hours=h
display.range.time.days=g
-details.range.avespeed=Velocità media
-details.range.avemovingspeed=Velocità media in movimento
+details.range.avespeed=Velocit\u00e0 media
+details.range.avemovingspeed=Velocit\u00e0 media in movimento
+details.range.pace=
details.waypointsphotos.waypoints=Waypoint
details.waypointsphotos.photos=Foto
details.photodetails=Dettagli foto
fieldname.distance=Distanza
fieldname.movingdistance=Distanza in movimento
fieldname.duration=Durata
-fieldname.speed=VelocitÃ
-fieldname.verticalspeed=Velocità verticale
+fieldname.speed=Velocit\u00e0
+fieldname.verticalspeed=Velocit\u00e0 verticale
# Measurement units
units.original=Originale
undo.reverse=inverti l'intervallo
undo.mergetracksegments=unisci segmenti traccia
undo.addtimeoffset=aggiungi scarto temporale
+undo.addaltitudeoffset=
undo.rearrangewaypoints=riorganizza waypoint
undo.cutandmove=muovi selezione
undo.connectphoto=collega foto
# Error messages
error.save.dialogtitle=Errore nel salvataggio dati
error.save.nodata=Nessun dato da salvare
-error.save.failed=Fallito il tentativo di salvare i dati nel file:
+error.save.failed=Fallito il tentativo di salvare i dati nel file
error.saveexif.filenotfound=Non trovato un file di foto
error.saveexif.cannotoverwrite1=File di foto
-error.saveexif.cannotoverwrite2=è in sola lettura e non può essere sovrascritto. Creo una copia?
+error.saveexif.cannotoverwrite2=\u00e8 in sola lettura e non pu\u00f2 essere sovrascritto. Creo una copia?
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.rearrange.noop=La riorganizzazione dei waypoint 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=È avvenuto un errore nella visualizzazione 3D
+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.osmimage.failed=Impossibile caricare le immagini della mappa. Per favore verifica la connessione a internet.
\ No newline at end of file
# Menu entries
menu.file=Plik
-menu.file.open=Otw\u00F3rz
+menu.file.open=Otw\u00f3rz
menu.file.addphotos=Dodaj zdj\u0119cia
menu.file.save=Zapisz
menu.file.exit=Zako\u0144cz
menu.edit=Edycja
menu.edit.undo=Cofnij
-menu.edit.clearundo=Wyczy\u015B\u0107 list\u0119 zmian
+menu.edit.clearundo=Wyczy\u015b\u0107 list\u0119 zmian
menu.edit.editpoint=Edytuj punkt
-menu.edit.editwaypointname=Zmie\u0144 nazw\u0119 punktu po\u015Bredniego
menu.edit.deletepoint=Usu\u0144 punkt
menu.edit.deleterange=Usu\u0144 zakres
menu.edit.deletemarked=Usu\u0144 zaznaczone punkty
-menu.edit.interpolate=Interpoluj punkty
-menu.edit.average=U\u015Brednij zaznaczenie
-menu.edit.reverse=Odwr\u00F3\u0107 zakres
-menu.edit.mergetracksegments=Po\u0142\u0105cz fragmenty \u015Bcie\u017Cek
-menu.edit.rearrange=Zmie\u0144 kolejno\u015B\u0107 punkt\u00F3w po\u015Brednich
-menu.edit.rearrange.start=Wszystkie na pocz\u0105tek \u015Bcie\u017Cki
-menu.edit.rearrange.end=Wszystkie na koniec \u015Bcie\u017Cki
-menu.edit.rearrange.nearest=Do najbli\u017Cszego punktu
+menu.edit.interpolate=Wstaw pomi\u0119dzy
+menu.edit.average=U\u015brednij zaznaczenie
+menu.edit.reverse=Odwr\u00f3\u0107 zakres
+menu.edit.mergetracksegments=Po\u0142\u0105cz fragmenty \u015bcie\u017cek
+menu.edit.rearrange=Zmie\u0144 kolejno\u015b\u0107 punkt\u00f3w po\u015brednich
+menu.edit.rearrange.start=Wszystkie na pocz\u0105tek \u015bcie\u017cki
+menu.edit.rearrange.end=Wszystkie na koniec \u015bcie\u017cki
+menu.edit.rearrange.nearest=Do najbli\u017cszego punktu
menu.edit.cutandmove=Wytnij i przesu\u0144 zaznaczenie
menu.select=Zaznacz
menu.select.all=Zaznacz wszystko
menu.view.browser.openstreetmap=Openstreetmap
menu.view.browser.mapquest=Mapquest
menu.view.browser.yahoo=Mapy Yahoo
+menu.settings=Ustawienia
+menu.settings.showpace=Poka\u017c tempo przy wy\u015bwietlaniu zakresu
menu.help=Pomoc
# Popup menu for map
menu.map.zoomin=Powi\u0119ksz
-menu.map.zoomout=Zmniejsz
+menu.map.zoomout=Pomniejsz
menu.map.zoomfull=Dostosuj powi\u0119kszenie
-menu.map.newpoint=Stw\u00F3rz nowy punkt
-menu.map.connect=Po\u0142\u0105cz punkty \u015Bcie\u017Cki
+menu.map.newpoint=Stw\u00f3rz nowy punkt
+menu.map.connect=Po\u0142\u0105cz punkty \u015bcie\u017cki
menu.map.autopan=Przesuwanie mapy
-menu.map.showmap=Poka\u017C map\u0119
+menu.map.showmap=Poka\u017c map\u0119
+menu.map.showscalebar=Poka\u017c skal\u0119
+
+# Alt keys for menus
+altkey.menu.file=P
+altkey.menu.edit=E
+altkey.menu.select=A
+altkey.menu.view=W
+altkey.menu.photo=Z
+altkey.menu.settings=T
+altkey.menu.help=M
+
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=O
+shortcut.menu.file.load=L
+shortcut.menu.file.save=S
+shortcut.menu.edit.undo=Z
+shortcut.menu.edit.compress=C
+shortcut.menu.select.all=A
+shortcut.menu.help.help=H
# Functions
function.loadfromgps=\u0141aduj z GPS
-function.sendtogps=Wy\u015Blij dane do urz\u0105dzenia GPS
+function.sendtogps=Wy\u015blij dane do urz\u0105dzenia GPS
function.exportkml=Eksportuj KML
function.exportgpx=Eksportuj jako GPX
function.exportpov=Eksportuj jako POV
-function.compress=Skompresuj \u015Bcie\u017Ck\u0119
+function.editwaypointname=Zmie\u0144 nazw\u0119 punktu po\u015bredniego
+function.compress=Kompresuj \u015bcie\u017ck\u0119
function.addtimeoffset=Dodaj przesuni\u0119cie czasu
+function.addaltitudeoffset=Dodaj przesuni\u0119cie wysoko\u015bci
+function.findwaypoint=Znajd\u017a punkt po\u015bredni
function.charts=Wykres
-function.show3d=Poka\u017C model 3D
-function.distances=Odleg\u0142o\u015Bci
+function.show3d=Poka\u017c model 3D
+function.distances=Odleg\u0142o\u015bci
+function.getgpsies=Pobierz \u015bcie\u017cki z Gpsies
+function.correlatephotos=Powi\u0105\u017c zdj\u0119cia
function.setmapbg=Wybierz map\u0119
-function.correlatephotos=Powi\u0105\u017C zdj\u0119cia
+function.setkmzimagesize=Ustaw rozmiar zdj\u0119\u0107 w KMZ
+function.setpaths=Ustaw \u015bcie\u017cki do program\u00f3w
function.help=Pomoc
+function.showkeys=Poka\u017c klawisze skr\u00f3tu
function.about=O Prune
-function.checkversion=Sprawd\u017A czy jest nowa wersja
+function.checkversion=Sprawd\u017a czy jest nowa wersja
+function.saveconfig=Zapisz ustawienia
# Dialogs
dialog.exit.confirm.title=Zako\u0144cz Prune
-dialog.exit.confirm.text=Dane nie s\u0105 zapisane. Czy na pewno chcesz wyj\u015B\u0107?
+dialog.exit.confirm.text=Dane nie s\u0105 zapisane. Czy na pewno chcesz wyj\u015b\u0107?
dialog.openappend.title=Dodaj do istniej\u0105cych danych
-dialog.openappend.text=Doda\u0107 te dane do ju\u017C za\u0142adowanych?
+dialog.openappend.text=Doda\u0107 dane do ju\u017c za\u0142adowanych?
dialog.deletepoint.title=Usu\u0144 punkt
dialog.deletepoint.deletephoto=Usun\u0105\u0107 zdj\u0119cie do\u0142\u0105czone do tego punktu?
dialog.deletephoto.title=Usu\u0144 zdj\u0119cie
dialog.deletephoto.deletepoint=Usun\u0105\u0107 punkt do\u0142\u0105czony do tego zdj\u0119cia?
-dialog.openoptions.title=Otw\u00F3rz opcje
+dialog.openoptions.title=Otw\u00f3rz opcje
dialog.openoptions.filesnippet=Fragment z pliku
dialog.load.table.field=Pole
dialog.load.table.datatype=Typ danych
dialog.delimiter.comma=Przecinek ,
dialog.delimiter.tab=Tabulator
dialog.delimiter.space=Spacja
-dialog.delimiter.semicolon=\u015Arednik ;
+dialog.delimiter.semicolon=\u015arednik ;
dialog.delimiter.other=Inne
dialog.openoptions.deliminfo.records=rekordy, z
dialog.openoptions.deliminfo.fields=pola
-dialog.openoptions.deliminfo.norecords=Brak rekord\u00F3w
-dialog.openoptions.altitudeunits=Jednostki wysoko\u015Bci
+dialog.openoptions.deliminfo.norecords=Brak rekord\u00f3w
+dialog.openoptions.altitudeunits=Jednostki wysoko\u015bci
dialog.jpegload.subdirectories=Do\u0142\u0105cz podkatalogi
-dialog.jpegload.loadjpegswithoutcoords=Do\u0142\u0105cz zdj\u0119cia bez wsp\u00F3\u0142rz\u0119dnych
-dialog.jpegload.loadjpegsoutsidearea=Do\u0142\u0105cz zdj\u0119cia spoza bie\u017C\u0105cego obszaru
+dialog.jpegload.loadjpegswithoutcoords=Do\u0142\u0105cz zdj\u0119cia bez wsp\u00f3\u0142rz\u0119dnych
+dialog.jpegload.loadjpegsoutsidearea=Do\u0142\u0105cz zdj\u0119cia spoza bie\u017c\u0105cego obszaru
dialog.jpegload.progress.title=\u0141aduj\u0119 zdj\u0119cia
dialog.jpegload.progress=Czekaj, szukam zdj\u0119\u0107
-dialog.gpsload.nogpsbabel=Nie znalezionio programu gpsbabel. Kontynuowa\u0107?
+dialog.gpsload.nogpsbabel=Nie znaleziono programu gpsbabel. Kontynuowa\u0107?
dialog.gpsload.device=Nazwa urz\u0105dzenia
dialog.gpsload.format=Format
-dialog.gpsload.getwaypoints=\u0141aduj punkty po\u015Brednie
-dialog.gpsload.gettracks=\u0141aduj \u015Bcie\u017Cki
-dialog.gpssend.sendwaypoints=Wy\u015Blij punkty po\u015Brednie
-dialog.gpssend.sendtracks=Wy\u015Blij \u015Bcie\u017Cki
-dialog.gpssend.trackname=Nazwa \u015Bcie\u017Cki
+dialog.gpsload.getwaypoints=\u0141aduj punkty po\u015brednie
+dialog.gpsload.gettracks=\u0141aduj \u015bcie\u017cki
+dialog.gpssend.sendwaypoints=Wy\u015blij punkty po\u015brednie
+dialog.gpssend.sendtracks=Wy\u015blij \u015bcie\u017cki
+dialog.gpssend.trackname=Nazwa \u015bcie\u017cki
dialog.saveoptions.title=Zapisz plik
dialog.save.fieldstosave=Pola do zapisu
dialog.save.table.field=Pole
-dialog.save.table.hasdata=je\u015Bli s\u0105 dane
+dialog.save.table.hasdata=je\u015bli s\u0105 dane
dialog.save.table.save=Zapisz
-dialog.save.headerrow=Dodaj wiersz nag\u0142\u00F3wka
-dialog.save.coordinateunits=Jednostki wsp\u00F3\u0142rz\u0119dnych
-dialog.save.altitudeunits=Jednostki wysoko\u015Bci
+dialog.save.headerrow=Dodaj wiersz nag\u0142\u00f3wka
+dialog.save.coordinateunits=Jednostki wsp\u00f3\u0142rz\u0119dnych
+dialog.save.altitudeunits=Jednostki wysoko\u015bci
dialog.save.timestampformat=Format znacznika czasu
-dialog.save.overwrite.title=Plik ju\u017C istnieje
-dialog.save.overwrite.text=Ten plik ju\u017C istnieje. Czy na pewno chcesz go nadpisa\u0107?
+dialog.save.overwrite.title=Plik ju\u017c istnieje
+dialog.save.overwrite.text=Ten plik ju\u017c istnieje. Czy na pewno chcesz go nadpisa\u0107?
dialog.exportkml.text=Tytu\u0142 dla danych
-dialog.exportkml.altitude=Do\u0142\u0105cz wysoko\u015Bci (dla cel\u00F3w lotniczych)
+dialog.exportkml.altitude=Do\u0142\u0105cz wysoko\u015bci (dla cel\u00f3w lotniczych)
dialog.exportkml.kmz=Skompresuj do pliku KMZ
dialog.exportkml.exportimages=Eksportuj miniaturki zdj\u0119\u0107 do KMZ
dialog.exportgpx.name=Nazwa
dialog.exportgpx.desc=Opis
dialog.exportgpx.includetimestamps=Do\u0142\u0105cz znaczniki czasu
-dialog.exportpov.text=Wprowad\u017A dodatkowe parametry eksportu do formatu POV
+dialog.exportpov.text=Wprowad\u017a dodatkowe parametry eksportu do formatu POV
dialog.exportpov.font=Czcionka
dialog.exportpov.camerax=Kamera X
dialog.exportpov.cameray=Kamera Y
dialog.exportpov.cameraz=Kamera Z
dialog.exportpov.modelstyle=Styl modelu
dialog.exportpov.ballsandsticks=Kule i pa\u0142ki
-dialog.exportpov.tubesandwalls=Rurki i \u015Bciany
-dialog.exportpov.warningtracksize=Ta \u015Bcie\u017Cka ma bardzo wiele punkt\u00F3w, kt\u00F3rych Java3D mo\u017Ce nie wy\u015Bwietli\u0107.\nCzy chcesz kontynuowa\u0107?
-dialog.confirmreversetrack.title=Potwierd\u017A odwr\u00F3cenie
-dialog.confirmreversetrack.text=Ta \u015Bcie\u017Cka zawiera znaczniki czasu, kt\u00F3re po odwr\u00F3ceniu nie b\u0119d\u0105 ustawione w kolejno\u015Bci.\nCzy na pewno chcesz odwr\u00F3ci\u0107 ten fragment?
-dialog.confirmcutandmove.title=Potwierd\u017A wytnij i przesu\u0144
-dialog.confirmcutandmove.text=Ta \u015Bcie\u017Cka zawiera znaczniki czasu, kt\u00F3re po przesuni\u0119ciu nie b\u0119d\u0105 ustawione w kolejno\u015Bci.\nCzy na pewno chcesz przesun\u0105\u0107 ten fragment?
+dialog.exportpov.tubesandwalls=Rurki i \u015bciany
+dialog.exportpov.warningtracksize=Ta \u015bcie\u017cka ma bardzo wiele punkt\u00f3w, kt\u00f3rych Java3D mo\u017ce nie wy\u015bwietli\u0107.\nCzy chcesz kontynuowa\u0107?
+dialog.pointtype.desc=Zapisz punkty nast\u0119puj\u0105cych typ\u00f3w:
+dialog.pointtype.track=punkty \u015bcie\u017cki
+dialog.pointtype.waypoint=punkty po\u015brednie
+dialog.pointtype.photo=punkty zdj\u0119\u0107
+dialog.confirmreversetrack.title=Potwierd\u017a odwr\u00f3cenie
+dialog.confirmreversetrack.text=Ta \u015bcie\u017cka zawiera znaczniki czasu, kt\u00f3re po odwr\u00f3ceniu nie b\u0119d\u0105 ustawione w kolejno\u015bci.\nCzy na pewno chcesz odwr\u00f3ci\u0107 ten fragment?
+dialog.confirmcutandmove.title=Potwierd\u017a wytnij i przesu\u0144
+dialog.confirmcutandmove.text=Ta \u015bcie\u017cka zawiera znaczniki czasu, kt\u00f3re po przesuni\u0119ciu nie b\u0119d\u0105 ustawione w kolejno\u015bci.\nCzy na pewno chcesz przesun\u0105\u0107 ten fragment?
dialog.interpolate.title=Interpoluj punkty
-dialog.interpolate.parameter.text=Ilo\u015B\u0107 punkt\u00F3w do wstawienia pomi\u0119dzy wybrane punkty
-dialog.undo.title=Potwierd\u017A akcje
-dialog.undo.pretext=Wybierz akcje kt\u00F3re chcesz cofn\u0105\u0107
-dialog.undo.none.title=Nie mo\u017Cna cofn\u0105\u0107
+dialog.interpolate.parameter.text=Ilo\u015b\u0107 punkt\u00f3w do wstawienia pomi\u0119dzy wybrane punkty
+dialog.undo.title=Potwierd\u017a akcje
+dialog.undo.pretext=Wybierz akcje kt\u00f3re chcesz cofn\u0105\u0107
+dialog.undo.none.title=Nie mo\u017cna cofn\u0105\u0107
dialog.undo.none.text=Brak zmian do cofni\u0119cia
-dialog.clearundo.title=Wyczy\u015B\u0107 list\u0119 zmian
-dialog.clearundo.text=Czy na pewno chcesz wyczy\u015Bci\u0107 list\u0119 zmian?\nWszystkie informacje o zmianach b\u0119d\u0105 utracone!
+dialog.clearundo.title=Wyczy\u015b\u0107 list\u0119 zmian
+dialog.clearundo.text=Czy na pewno chcesz wyczy\u015bci\u0107 list\u0119 zmian?\nWszystkie informacje o zmianach b\u0119d\u0105 utracone!
dialog.pointedit.title=Edytuj punkt
-dialog.pointedit.text=Zaznacz wszystkie pola do edycji i u\u017Cyj przycisku 'Edytuj' by zmieni\u0107 warto\u015Bci
+dialog.pointedit.text=Zaznacz wszystkie pola do edycji i u\u017cyj przycisku 'Edytuj' by zmieni\u0107 warto\u015bci
dialog.pointedit.table.field=Pole
-dialog.pointedit.table.value=Warto\u015B\u0107
+dialog.pointedit.table.value=Warto\u015b\u0107
dialog.pointedit.table.changed=Zmieniony
-dialog.pointedit.changevalue.text=Wprowad\u017A now\u0105 warto\u015B\u0107 tego pola
+dialog.pointedit.changevalue.text=Wprowad\u017a now\u0105 warto\u015b\u0107 tego pola
dialog.pointedit.changevalue.title=Edytuj pole
-dialog.pointnameedit.title=Zmie\u0144 nazw\u0119 punktu po\u015Bredniego
-dialog.pointnameedit.name=Nazwa punktu po\u015Bredniego
+dialog.pointnameedit.name=Nazwa punktu po\u015bredniego
dialog.pointnameedit.uppercase=WIELKIE litery
dialog.pointnameedit.lowercase=ma\u0142e litery
dialog.pointnameedit.sentencecase=Jak W Zdaniu
dialog.addtimeoffset.days=Dni
dialog.addtimeoffset.hours=Godziny
dialog.addtimeoffset.minutes=Minuty
-dialog.addtimeoffset.notimestamps=Nie mo\u017Cna przesun\u0105\u0107 czasu, poniewa\u017C zaznaczenie nie zawiera znacznik\u00F3w czasu
+dialog.addtimeoffset.notimestamps=Nie mo\u017cna przesun\u0105\u0107 czasu, poniewa\u017c zaznaczenie nie zawiera znacznik\u00f3w czasu
+dialog.findwaypoint.intro=
+dialog.findwaypoint.search=
dialog.connect.title=Po\u0142\u0105cz zdj\u0119cie do punktu
-dialog.connectphoto.clonepoint=Ten punkt ju\u017C ma zdj\u0119cie.\nCzy chcesz zrobi\u0107 kopi\u0119 tego punktu?
+dialog.connectphoto.clonepoint=Ten punkt po\u0142\u0105czono ju\u017c ze zdj\u0119ciem.\nCzy chcesz zrobi\u0107 kopi\u0119 tego punktu?
dialog.saveexif.title=Zapisz Exif
-dialog.saveexif.intro=Zaznacz zdj\u0119cia do zapisu u\u017Cywaj\u0105c p\u00F3l opcji
-dialog.saveexif.nothingtosave=Wsp\u00F3\u0142rz\u0119dne s\u0105 nie zmienione, Nie ma nic do zapisu
+dialog.saveexif.intro=Zaznacz zdj\u0119cia do zapisu u\u017cywaj\u0105c znacznik\u00f3w
+dialog.saveexif.nothingtosave=Wsp\u00f3\u0142rz\u0119dne nie zosta\u0142y zmienione, nie ma nic do zapisu
dialog.saveexif.noexiftool=Nie znaleziono programu exiftool. Kontynuowa\u0107?
dialog.saveexif.table.photoname=Nazwa zdj\u0119cia
dialog.saveexif.table.status=Status
dialog.saveexif.photostatus.disconnected=Roz\u0142\u0105czony
dialog.saveexif.photostatus.modified=Zmodyfikowany
dialog.saveexif.overwrite=Nadpisz pliki
-dialog.charts.xaxis=O\u015B X
-dialog.charts.yaxis=O\u015B Y
+dialog.charts.xaxis=O\u015b X
+dialog.charts.yaxis=O\u015b Y
dialog.charts.output=Wykres
-dialog.charts.screen=Wy\u015Bwietl na ekranie
+dialog.charts.screen=Wy\u015bwietl na ekranie
dialog.charts.svg=Zapisz do pliku SVG
-dialog.charts.svgwidth=szeroko\u015B\u0107 SVG
-dialog.charts.svgheight=wysoko\u015B\u0107 SVG
-dialog.charts.needaltitudeortimes=\u015Acie\u017Cka musi posiada\u0107 zapisane wysoko\u015Bci lub znaczniki czasu aby mo\u017Cliwe by\u0142o utworzenie wykres\u00F3w
-dialog.charts.gnuplotpath=\u015Acie\u017Cka do programu gnuplot
+dialog.charts.svgwidth=szeroko\u015b\u0107 SVG
+dialog.charts.svgheight=wysoko\u015b\u0107 SVG
+dialog.charts.needaltitudeortimes=\u015acie\u017cka musi posiada\u0107 zapisane wysoko\u015bci lub znaczniki czasu aby mo\u017cliwe by\u0142o utworzenie wykres\u00f3w
+dialog.charts.gnuplotpath=\u015acie\u017cka do programu gnuplot
dialog.charts.gnuplotnotfound=Nie znalaz\u0142em programu gnuplot
-dialog.distances.intro=Odleg\u0142o\u015B\u0107 mi\u0119dzy punktami w linii prostej
+dialog.distances.intro=Odleg\u0142o\u015b\u0107 mi\u0119dzy punktami w linii prostej
dialog.distances.column.from=Z punktu
dialog.distances.column.to=Do punktu
dialog.distances.currentpoint=Wybrany punkt
-dialog.distances.toofewpoints=Ta funkcja wymaga przynajmniej dw\u00F3ch punkt\u00F3w po\u015Brednich aby obliczy\u0107 odleg\u0142o\u015Bci
-dialog.setmapbg.mapnik=Mapnik (domy\u015Blny)
+dialog.distances.toofewpoints=Ta funkcja wymaga przynajmniej dw\u00f3ch punkt\u00f3w po\u015brednich, aby mo\u017cna by\u0142o obliczy\u0107 odleg\u0142o\u015bci
+dialog.setmapbg.mapnik=Mapnik (domy\u015blny)
dialog.setmapbg.osma=Osma
dialog.setmapbg.cyclemap=Cyclemap
dialog.setmapbg.other=Inne
dialog.setmapbg.server=Adres URL serwera
-dialog.correlate.notimestamps=Punkty nie maj\u0105 znacznik\u00F3w czasu, nie mo\u017Cna ich powi\u0105za\u0107 ze zdj\u0119ciami.
+dialog.gpsies.column.name=Nazwa \u015bcie\u017cki
+dialog.gpsies.column.length=D\u0142ugo\u015b\u0107
+dialog.gpsies.description=Opis
+dialog.gpsies.nodescription=Brak opisu
+dialog.gpsies.nonefound=
+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
+dialog.correlate.photoselect.intro=Wybierz jedno z powi\u0105zanych zdj\u0119\u0107 i u\u017cyj go jako wzorca do przesuni\u0119cia czasu
dialog.correlate.photoselect.photoname=Nazwa zdj\u0119cia
-dialog.correlate.photoselect.timediff=R\u00F3\u017Cnica czasowa
-dialog.correlate.photoselect.photolater=P\u00F3\u017Aniejsze zdj\u0119cie
-dialog.correlate.options.tip=Porada: Gdy powi\u0105\u017Cesz r\u0119cznie przynajmniej jedno zdj\u0119cie, r\u00F3\u017Cnica czasowa zostanie policzona automatycznie.
+dialog.correlate.photoselect.timediff=R\u00f3\u017cnica czasowa
+dialog.correlate.photoselect.photolater=P\u00f3\u017aniejsze zdj\u0119cie
+dialog.correlate.options.tip=Porada: Gdy powi\u0105\u017cesz r\u0119cznie przynajmniej jedno zdj\u0119cie, r\u00f3\u017cnica czasowa zostanie policzona automatycznie.
dialog.correlate.options.intro=Wybierz opcje dla automatycznej korelacji
dialog.correlate.options.offsetpanel=Przesuni\u0119cie czasowe
dialog.correlate.options.offset=Przesuni\u0119cie
dialog.correlate.options.offset.hours=godzin,
dialog.correlate.options.offset.minutes=minut i
dialog.correlate.options.offset.seconds=sekund
-dialog.correlate.options.photolater=Zdj\u0119cie p\u00F3\u017Aniejsze ni\u017C punkt
-dialog.correlate.options.pointlater=Punkt p\u00F3\u017Aniejszy ni\u017C zdj\u0119cie
+dialog.correlate.options.photolater=Zdj\u0119cie p\u00f3\u017aniejsze ni\u017c punkt
+dialog.correlate.options.pointlater=Punkt p\u00f3\u017aniejszy ni\u017c zdj\u0119cie
dialog.correlate.options.limitspanel=Ograniczenia korelacji
dialog.correlate.options.notimelimit=Bez limitu czasu
dialog.correlate.options.timelimit=Limit czasu
-dialog.correlate.options.nodistancelimit=Bez limitu odleg\u0142o\u015Bci
-dialog.correlate.options.distancelimit=Limit odleg\u0142o\u015Bci
-dialog.correlate.options.correlate=Powi\u0105\u017C ze sob\u0105
-dialog.correlate.alloutsiderange=Wszystkie zdj\u0119cia s\u0105 poza zakresem czasu \u015Bcie\u017Cki, tak \u017Ce \u017Cadne nie mo\u017Ce zosta\u0107 z ni\u0105 skorelowane.\nSpr\u00F3buj zmieni\u0107 przesuni\u0119cie lub r\u0119cznie skoreluj przynajmniej jedno zdj\u0119cie.
-dialog.compress.nonefound=Nie mo\u017Cna usun\u0105\u0107 \u017Cadnych punkt\u00F3w
-dialog.compress.duplicates.title=Usuwanie duplikat\u00F3w
-dialog.compress.closepoints.title=Usuwanie bliskich sobie punkt\u00F3w
-dialog.compress.closepoints.paramdesc=Wsp\u00F3\u0142czynnik rozpi\u0119to\u015Bci
-dialog.compress.wackypoints.title=Usuwanie dziwacznych punkt\u00F3w
-dialog.compress.wackypoints.paramdesc=Wsp\u00F3\u0142czynnik odleg\u0142o\u015Bci
-dialog.compress.singletons.title=Usuwanie odosobnionych punkt\u00F3w
-dialog.compress.singletons.paramdesc=Wsp\u00F3\u0142czynnik odleg\u0142o\u015Bci
+dialog.correlate.options.nodistancelimit=Bez limitu odleg\u0142o\u015bci
+dialog.correlate.options.distancelimit=Limit odleg\u0142o\u015bci
+dialog.correlate.options.correlate=Powi\u0105\u017c ze sob\u0105
+dialog.correlate.alloutsiderange=Wszystkie zdj\u0119cia s\u0105 poza zakresem czasu \u015bcie\u017cki, tak \u017ce \u017cadne nie mo\u017ce zosta\u0107 z ni\u0105 skorelowane.\nSpr\u00f3buj zmieni\u0107 przesuni\u0119cie lub r\u0119cznie skoreluj przynajmniej jedno zdj\u0119cie.
+dialog.compress.nonefound=Nie mo\u017cna usun\u0105\u0107 \u017cadnych punkt\u00f3w
+dialog.compress.duplicates.title=Usuwanie duplikat\u00f3w
+dialog.compress.closepoints.title=Usuwanie punkt\u00f3w bliskich sobie
+dialog.compress.closepoints.paramdesc=Wsp\u00f3\u0142czynnik rozpi\u0119to\u015bci
+dialog.compress.wackypoints.title=Usuwanie dziwacznych punkt\u00f3w
+dialog.compress.wackypoints.paramdesc=Wsp\u00f3\u0142czynnik odleg\u0142o\u015bci
+dialog.compress.singletons.title=Usuwanie odosobnionych punkt\u00f3w
+dialog.compress.singletons.paramdesc=Wsp\u00f3\u0142czynnik odleg\u0142o\u015bci
dialog.compress.summarylabel=Punkty do usuni\u0119cia
-dialog.help.help=Na stronie\n http://activityworkshop.net/software/prune/ \nznajdziesz wi\u0119cej informacji oraz podr\u0119cznik u\u017Cytkownika
+dialog.help.help=Na stronie\n http://activityworkshop.net/software/prune/ \nznajdziesz wi\u0119cej informacji oraz podr\u0119cznik u\u017cytkownika
dialog.about.version=Wersja
dialog.about.build=Build
-dialog.about.summarytext1=Prune s\u0142u\u017Cy do pobierania, wy\u015Bwietlania i edycji danych z odbiornik\u00F3w GPS.
-dialog.about.summarytext2=Ten program zosta\u0142 udost\u0119pniony na podstawie licencji GNU pozwalaj\u0105cej<br>na jego wolne, nieograniczone i og\u00F3lno\u015Bwiatowe u\u017Cytkowanie i rozszerzanie. <br>Kopiowanie, rozprowadzanie i modyfikowanie s\u0105 dozwolone i zalecane<br>zgodnie z warunkami zawartymi w do\u0142\u0105czonym pliku<code>license.txt</code>
-dialog.about.summarytext3=Na stronie <code style="font-weight:bold">http://activityworkshop.net/</code> znajdziesz wi\u0119cej informacji oraz podr\u0119cznik u\u017Cytkownika.
+dialog.about.summarytext1=Prune s\u0142u\u017cy do pobierania, wy\u015bwietlania i edycji danych z odbiornik\u00f3w GPS.
+dialog.about.summarytext2=Ten program zosta\u0142 udost\u0119pniony na podstawie licencji GNU pozwalaj\u0105cej<br>na jego wolne, nieograniczone i og\u00f3lno\u015bwiatowe u\u017cytkowanie i rozszerzanie. <br>Kopiowanie, rozprowadzanie i modyfikowanie s\u0105 dozwolone i zalecane<br>zgodnie z warunkami zawartymi w do\u0142\u0105czonym pliku<code>license.txt</code>
+dialog.about.summarytext3=Na stronie <code style="font-weight:bold">http://activityworkshop.net/</code> znajdziesz wi\u0119cej informacji oraz podr\u0119cznik u\u017cytkownika.
dialog.about.languages=Dost\u0119pne j\u0119zyki
dialog.about.translatedby=Tekst po polsku: Piotr, Weehal
dialog.about.systeminfo=Informacje o systemie
dialog.about.credits=Podzi\u0119kowania
dialog.about.credits.code=Kod Prune napisany przez
dialog.about.credits.exifcode=Kod Exif przez
-dialog.about.credits.icons=Niekt\u00F3re ikony z
+dialog.about.credits.icons=Niekt\u00f3re ikony z
dialog.about.credits.translators=T\u0142umacze
dialog.about.credits.translations=Pomoc w t\u0142umaczeniu
dialog.about.credits.devtools=Narz\u0119dzia deweloperskie
dialog.about.credits.othertools=Inne narz\u0119dzia
dialog.about.credits.thanks=Podzi\u0119kowania dla
-dialog.about.readme=Czytaj To
-dialog.checkversion.error=Nie mo\u017Cna sprawdzi\u0107 numeru wersji.\nSprawd\u017A po\u0142\u0105czenie z internetem.
-dialog.checkversion.uptodate=U\u017Cywasz najnowszej wersji Prune.
+dialog.about.readme=Czytaj to
+dialog.checkversion.error=Nie mo\u017cna sprawdzi\u0107 numeru wersji.\nSprawd\u017a po\u0142\u0105czenie z internetem.
+dialog.checkversion.uptodate=U\u017cywasz najnowszej wersji Prune.
dialog.checkversion.newversion1=Dost\u0119pna jest nowa wersja Prune! Najnowsz\u0105 wersj\u0105 jest wersja
dialog.checkversion.newversion2=.
dialog.checkversion.releasedate1=Nowa wersja zosta\u0142a opublikowana
dialog.checkversion.releasedate2=.
-dialog.checkversion.download=Aby \u015Bci\u0105gn\u0105\u0107 now\u0105 wersj\u0119 przejd\u017A na http://activityworkshop.net/software/prune/download.html.
+dialog.checkversion.download=Aby \u015bci\u0105gn\u0105\u0107 now\u0105 wersj\u0119 przejd\u017a na http://activityworkshop.net/software/prune/download.html.
+dialog.keys.intro=U\u017cuwaj nast\u0119puj\u0105cych klawiszy skr\u00f3t\u00f3w zamiast myszki
+dialog.keys.keylist=<table><tr><td>klawisze strza\u0142ek</td><td>Przesuwa map\u0119 w lewo, w prawo, w g\u00f3r\u0119, w d\u00f3\u0142</td></tr><tr><td>Ctrl + lewa, prawa strza\u0142ka</td><td>Wybierz punkt poprzedni lub nast\u0119pny</td></tr><tr><td>Ctrl + strza\u0142ka w g\u00f3r\u0119, w d\u00f3\u0142</td><td>Powi\u0119ksz, pomniejsz</td></tr><tr><td>Del</td><td>Usun bie\u017c\u0105cy punkt</td></tr></table>
+dialog.saveconfig.desc=Nast\u0119puj\u0105ce ustawienia mog\u0105 zosta\u0107 zapisane w pliku konfiguracyjnym:
+dialog.saveconfig.prune.trackdirectory=Katalog ze \u015bcie\u017ckami
+dialog.saveconfig.prune.photodirectory=Katalog ze zdj\u0119ciami
+dialog.saveconfig.prune.languagecode=Kod j\u0119zyka (PL)
+dialog.saveconfig.prune.gpsdevice=Urz\u0105dzenie GPS
+dialog.saveconfig.prune.gpsformat=Format pliku GPS
+dialog.saveconfig.prune.povrayfont=czcionka dla Povray-a
+dialog.saveconfig.prune.metricunits=U\u017cywaj jednostek metrycznych?
+dialog.saveconfig.prune.gnuplotpath=\u015bcie\u017cka do gnuplot
+dialog.saveconfig.prune.gpsbabelpath=\u015bcie\u017cka do gpsbabel
+dialog.saveconfig.prune.exiftoolpath=\u015bcie\u017cka do exiftool
+dialog.saveconfig.prune.mapserverindex=kolejny numer serwera map
+dialog.saveconfig.prune.mapserverurl=URL serwera map
+dialog.saveconfig.prune.showpace=Pokazuj tempo
+dialog.saveconfig.prune.kmzimagewidth=szeroko\u015b\u0107 obrazka w KMZ
+dialog.saveconfig.prune.kmzimageheight=wysoko\u015b\u0107 obrazka w KMZ
+dialog.setpaths.intro=Je\u015bli zachodzi tak potrzeba, mo\u017cesz wybra\u0107 \u015bcie\u017cki do aplikacji zewn\u0119trznych
+dialog.addaltitude.noaltitudes=Wybrany zakres nie zawiera danych o wysoko\u015bciach
+dialog.addaltitude.desc=Warto\u015b\u0107 przesuni\u0119cia wysoko\u015bci
# 3d window
-dialog.3d.title=Prune widok tr\u00F3jwymiarowy
-dialog.3d.altitudecap=Minimalny zakres wysoko\u015Bci
+dialog.3d.title=Prune widok tr\u00f3jwymiarowy
+dialog.3d.altitudecap=Minimalny zakres wysoko\u015bci
dialog.3dlines.title=Linie siatki
-dialog.3dlines.empty=Brak siatki do wy\u015Bwietlenia!
+dialog.3dlines.empty=Brak siatki do wy\u015bwietlenia!
dialog.3dlines.intro=Linie siatki w widoku 3D
# Confirm messages || These are displayed as confirmation in the status bar
confirm.loadfile=Za\u0142adowano dane z pliku
-confirm.save.ok1=Zapisano pomy\u015Blnie
-confirm.save.ok2=punkt\u00F3w do pliku
+confirm.save.ok1=Zapisano pomy\u015blnie
+confirm.save.ok2=punkt\u00f3w do pliku
confirm.deletepoint.single=usuni\u0119to punkt
-confirm.deletepoint.multi=punkt\u00F3w usuni\u0119to
+confirm.deletepoint.multi=punkt\u00f3w usuni\u0119to
confirm.point.edit=zmieniono punkt
-confirm.mergetracksegments=Po\u0142\u0105czono fragmenty \u015Bcie\u017Cki
-confirm.reverserange=Odwr\u00F3cono zakres
+confirm.mergetracksegments=Po\u0142\u0105czono fragmenty \u015bcie\u017cki
+confirm.reverserange=Odwr\u00f3cono zakres
confirm.addtimeoffset=Dodano przesuni\u0119cie czasowe
-confirm.rearrangewaypoints=Przestawiono punkty po\u015Brednie
+confirm.addaltitudeoffset=Dodano przesuni\u0119cie wysoko\u015bci
+confirm.rearrangewaypoints=Przestawiono punkty po\u015brednie
confirm.cutandmove=Przesuni\u0119to zaznaczenie
confirm.saveexif.ok1=Zapisano
confirm.saveexif.ok2=pliki zdj\u0119\u0107
confirm.correlate.single=zdj\u0119cie zosta\u0142o po\u0142\u0105czone
confirm.correlate.multi=zdj\u0119cia zosta\u0142y po\u0142\u0105czone
confirm.createpoint=stworzono punkt
+confirm.running=Przetwarzam dane ...
# Buttons
button.ok=OK
button.finish=Koniec
button.cancel=Anuluj
button.overwrite=Nadpisz
-button.moveup=Do g\u00F3ry
-button.movedown=Do d\u00F3\u0142
-button.showlines=Poka\u017C linie
+button.moveup=Do g\u00f3ry
+button.movedown=Na d\u00f3\u0142
+button.showlines=Poka\u017c linie
button.edit=Edycja
button.exit=Zako\u0144cz
button.close=Zamknij
button.selectall=Zaznacz wszystko
button.selectnone=Odznacz
button.preview=Podgl\u0105d
+button.load=\u0141aduj
button.guessfields=Zgadnij pola
-button.showwebpage=Poka\u017C stron\u0119 web
-button.gnuplotpath=Podaj \u015Bcie\u017Ck\u0119 do gnuplot
+button.showwebpage=Poka\u017c stron\u0119 web
+button.check=Sprawd\u017a
# File types
filetype.txt=Pliki TXT
# Display components
display.nodata=Nie za\u0142adowano danych
-display.noaltitudes=\u015Acie\u017Cki nie zawieraj\u0105 informacji o wysoko\u015Bci
-details.trackdetails=Szczeg\u00F3\u0142y \u015Bcie\u017Cki
-details.notrack=Brak za\u0142adowanych \u015Bcie\u017Cek
+display.noaltitudes=\u015acie\u017cki nie zawieraj\u0105 informacji o wysoko\u015bci
+details.trackdetails=Szczeg\u00f3\u0142y \u015bcie\u017cki
+details.notrack=Brak za\u0142adowanych \u015bcie\u017cek
details.track.points=Punkty
details.track.file=Plik
-details.track.numfiles=Ilo\u015B\u0107 plik\u00F3w
-details.pointdetails=Szczeg\u00F3\u0142y punktu
+details.track.numfiles=Ilo\u015b\u0107 plik\u00f3w
+details.pointdetails=Szczeg\u00f3\u0142y punktu
details.index.selected=Indeks
details.index.of=z
-details.nopointselection=\u017Baden punkt nie jest zaznaczony
+details.nopointselection=\u017baden punkt nie jest zaznaczony
details.photofile=Plik zdj\u0119cia
details.norangeselection=Brak zakresu zaznaczenia
-details.rangedetails=Szczeg\u00F3\u0142y zakresu
+details.rangedetails=Szczeg\u00f3\u0142y zakresu
details.range.selected=Wybrany
details.range.to=do
details.altitude.to=do
details.range.climb=Wzniesienie
details.range.descent=Zst\u0105pienie
details.coordformat=Format wsp\u00f3\u0142rz\u0119dnych
-details.distanceunits=Jednostki odleg\u0142o\u015Bci
+details.distanceunits=Jednostki odleg\u0142o\u015bci
display.range.time.secs=s
display.range.time.mins=m
display.range.time.hours=h
display.range.time.days=d
-details.range.avespeed=\u015Arednia pr\u0119dko\u015B\u0107
-details.range.avemovingspeed=\u015Arednie przesuni\u0119cie
-details.waypointsphotos.waypoints=Punkty po\u015Brednie
+details.range.avespeed=\u015arednia pr\u0119dko\u015b\u0107
+details.range.avemovingspeed=\u015arednie przesuni\u0119cie
+details.range.pace=Tempo
+details.waypointsphotos.waypoints=Punkty po\u015brednie
details.waypointsphotos.photos=Zdj\u0119cia
-details.photodetails=Szczeg\u00F3\u0142y zdj\u0119cia
+details.photodetails=Szczeg\u00f3\u0142y zdj\u0119cia
details.nophoto=Brak zaznaczonego zdj\u0119cia
details.photo.loading=Wczytywanie
details.photo.connected=Pod\u0142\u0105czony
map.overzoom=Brak map dla danego powi\u0119kszenia
# Field names
-fieldname.latitude=Szeroko\u015B\u0107
-fieldname.longitude=D\u0142ugo\u015B\u0107
-fieldname.altitude=Wysoko\u015B\u0107
+fieldname.latitude=Szeroko\u015b\u0107
+fieldname.longitude=D\u0142ugo\u015b\u0107
+fieldname.altitude=Wysoko\u015b\u0107
fieldname.timestamp=Czas
fieldname.time=Czas
fieldname.waypointname=Nazwa
fieldname.waypointtype=Typ
fieldname.newsegment=Odcinek
-fieldname.custom=U\u017Cytkownika
+fieldname.custom=U\u017cytkownika
fieldname.prefix=Pole
-fieldname.distance=Odleg\u0142o\u015B\u0107
-fieldname.movingdistance=Odleg\u0142o\u015B\u0107 przesuni\u0119cia
+fieldname.distance=Odleg\u0142o\u015b\u0107
+fieldname.movingdistance=Odleg\u0142o\u015b\u0107 przesuni\u0119cia
fieldname.duration=Czas trwania
-fieldname.speed=Pr\u0119dko\u015B\u0107
-fieldname.verticalspeed=Pr\u0119dko\u015B\u0107 pionowa
+fieldname.speed=Pr\u0119dko\u015b\u0107
+fieldname.verticalspeed=Pr\u0119dko\u015b\u0107 pionowa
# Measurement units
units.original=Oryginalny
-units.default=Domy\u015Blny
+units.default=Domy\u015blny
units.metres=Metry
units.metres.short=m
units.feet=Stopy
undo.deletepoint=usu\u0144 punkt
undo.deletephoto=usu\u0144 zdj\u0119cie (nie z dysku)
undo.deleterange=usu\u0144 zakres
-undo.compress=skompresuj \u015Bcie\u017Ck\u0119
+undo.compress=skompresuj \u015bcie\u017ck\u0119
undo.insert=wstaw punkty
-undo.reverse=odwr\u00F3\u0107 zakres
-undo.mergetracksegments=po\u0142\u0105cz fragmenty \u015Bcie\u017Cki
+undo.reverse=odwr\u00f3\u0107 zakres
+undo.mergetracksegments=po\u0142\u0105cz fragmenty \u015bcie\u017cki
undo.addtimeoffset=dodaj przesuni\u0119cie czasowe
-undo.rearrangewaypoints=przestaw punkty po\u015Brednie
+undo.addaltitudeoffset=dodaj przeuni\u0119cie wysoko\u015bci
+undo.rearrangewaypoints=przestaw punkty po\u015brednie
undo.cutandmove=przesu\u0144 fragment
undo.connectphoto=do\u0142\u0105cz zdj\u0119cie
undo.disconnectphoto=od\u0142\u0105cz zdj\u0119cie
undo.correlate=po\u0142\u0105cz ze zdj\u0119ciami
-undo.createpoint=stw\u00F3rz punkt
+undo.createpoint=stw\u00f3rz punkt
# Error messages
error.save.dialogtitle=B\u0142\u0105d zapisu danych
error.save.nodata=Brak danych do zapisu
-error.save.failed=Nie powi\u00F3d\u0142 si\u0119 zapis danych do pliku:
+error.save.failed=Nie powi\u00f3d\u0142 si\u0119 zapis danych do pliku:
error.saveexif.filenotfound=Nie znaleziono pliku zdj\u0119cia
error.saveexif.cannotoverwrite1=Plik ze zdj\u0119ciem
-error.saveexif.cannotoverwrite2=jest w trybie tylko do odczytu i nie mo\u017Ce zosta\u0107 nadpisany. Zapisa\u0107 do kopii?
+error.saveexif.cannotoverwrite2=jest w trybie tylko do odczytu i nie mo\u017ce zosta\u0107 nadpisany. Zapisa\u0107 do kopii?
error.load.dialogtitle=B\u0142\u0105d \u0142adowania danych
-error.load.noread=Nie mo\u017Cna przeczyta\u0107 pliku
-error.load.nopoints=Nie znaleziono informacji o wsp\u00F3\u0142rz\u0119dnych w pliku
+error.load.noread=Nie mo\u017cna przeczyta\u0107 pliku
+error.load.nopoints=Nie znaleziono informacji o wsp\u00f3\u0142rz\u0119dnych w pliku
error.load.unknownxml=Nieznany format xml:
error.load.noxmlinzip=Nie znaleziono pliku xml w pliku zip
error.load.othererror=B\u0142\u0105d czytania pliku:
error.jpegload.dialogtitle=B\u0142\u0105d \u0142adowania zdj\u0119cia
-error.jpegload.nofilesfound=Nie znaleziono plik\u00F3w
-error.jpegload.nojpegsfound=Nie znaleziono plik\u00F3w jpeg
+error.jpegload.nofilesfound=Nie znaleziono plik\u00f3w
+error.jpegload.nojpegsfound=Nie znaleziono plik\u00f3w jpeg
error.jpegload.noexiffound=Nie znaleziono informacji EXIF
error.jpegload.nogpsfound=Nie znaleziono informacji GPS
error.undofailed.title=Cofnij nie powiod\u0142o si\u0119
-error.undofailed.text=Nie mo\u017Cna cofn\u0105\u0107
+error.undofailed.text=Nie mo\u017cna cofn\u0105\u0107
error.function.noop.title=Funkcja nie ma skutku
-error.rearrange.noop=Przestawienie punkt\u00F3w po\u015Brednich nie przyniesie skutku
+error.rearrange.noop=Przestawienie punkt\u00f3w po\u015brednich nie przyniesie skutku
error.function.notavailable.title=Funkcja nie dost\u0119pna
error.function.nojava3d=Ta funkcja wymaga biblioteki Java3d,\ndost\u0119pnej na Sun.com.
-error.3d=Nast\u0105pi\u0142 b\u0142\u0105d z wy\u015Bwietlaniem 3D
+error.3d=Nast\u0105pi\u0142 b\u0142\u0105d z wy\u015bwietlaniem 3D
error.readme.notfound=Nie znaleziono pliku Readme
-error.osmimage.dialogtitle=B\u0142\u0105d przy \u0142adowaniu obraz\u00F3w map
-error.osmimage.failed=B\u0142\u0105d przy \u0142adowaniu obraz\u00F3w map. Sprawd\u017A po\u0142\u0105czenie z internetem.
+error.osmimage.dialogtitle=B\u0142\u0105d przy \u0142adowaniu obraz\u00f3w map
+error.osmimage.failed=B\u0142\u0105d przy \u0142adowaniu obraz\u00f3w map. Sprawd\u017a po\u0142\u0105czenie z internetem.
\ No newline at end of file
# Menu entries
menu.file=Arquivo
menu.file.open=Abrir
-menu.file.addphotos=
menu.file.save=Salvar
menu.file.exit=Sair
menu.edit=Editar
menu.edit.undo=Desfazer
-menu.edit.clearundo=
menu.edit.editpoint=Editar ponto
-menu.edit.editwaypointname=Editar nome do waypoint
-menu.edit.deletepoint=
-menu.edit.deleterange=
-menu.edit.deletemarked=
-menu.edit.interpolate=
-menu.edit.average=
-menu.edit.reverse=
-menu.edit.mergetracksegments=
-menu.edit.rearrange=
-menu.edit.rearrange.start=
-menu.edit.rearrange.end=
-menu.edit.rearrange.nearest=
-menu.edit.cutandmove=
menu.select=Selecionar
menu.select.all=Selectionar tudo
menu.select.none=Não selecionar nenhuns
-menu.select.start=
-menu.select.end=
menu.photo=Foto
menu.photo.saveexif=Salvar exif
-menu.photo.connect=
-menu.photo.disconnect=
menu.photo.delete=Remover Foto
menu.view=Exibir
-menu.view.browser=
-menu.view.browser.google=
-menu.view.browser.openstreetmap=
-menu.view.browser.mapquest=
-menu.view.browser.yahoo=
menu.help=Ajuda
# Popup menu for map
menu.map.zoomin=Ampliar zoom
menu.map.zoomout=Reduzir zoom
-menu.map.zoomfull=
-menu.map.newpoint=
-menu.map.connect=
-menu.map.autopan=
menu.map.showmap=Mostrar o mapa
+# Alt keys for menus
+altkey.menu.file=A
+altkey.menu.edit=E
+altkey.menu.select=S
+altkey.menu.view=X
+altkey.menu.photo=F
+altkey.menu.help=A
+
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=A
+shortcut.menu.file.save=S
+shortcut.menu.edit.undo=Z
+shortcut.menu.select.all=T
+shortcut.menu.help.help=H
+
# Functions
-function.loadfromgps=
-function.sendtogps=
function.exportkml=Exportar KML
function.exportgpx=Exportar GPX
function.exportpov=Exportar POV
-function.compress=
-function.addtimeoffset=
+function.editwaypointname=Editar nome do waypoint
function.charts=Diagramas
function.show3d=Visualizar 3d
function.distances=Distâncias
-function.setmapbg=
-function.correlatephotos=
function.help=Ajuda
function.about=Sobre o Prune
-function.checkversion=
# Dialogs
-dialog.exit.confirm.title=
-dialog.exit.confirm.text=
-dialog.openappend.title=
-dialog.openappend.text=
-dialog.deletepoint.title=
-dialog.deletepoint.deletephoto=
-dialog.deletephoto.title=
-dialog.deletephoto.deletepoint=
-dialog.openoptions.title=
-dialog.openoptions.filesnippet=
-dialog.load.table.field=
-dialog.load.table.datatype=
-dialog.load.table.description=
-dialog.delimiter.label=
-dialog.delimiter.comma=
-dialog.delimiter.tab=
-dialog.delimiter.space=
-dialog.delimiter.semicolon=
-dialog.delimiter.other=
-dialog.openoptions.deliminfo.records=
-dialog.openoptions.deliminfo.fields=
-dialog.openoptions.deliminfo.norecords=
-dialog.openoptions.altitudeunits=
-dialog.jpegload.subdirectories=
-dialog.jpegload.loadjpegswithoutcoords=
-dialog.jpegload.loadjpegsoutsidearea=
-dialog.jpegload.progress.title=
-dialog.jpegload.progress=
-dialog.gpsload.nogpsbabel=
-dialog.gpsload.device=
-dialog.gpsload.format=
-dialog.gpsload.getwaypoints=
-dialog.gpsload.gettracks=
-dialog.gpssend.sendwaypoints=
-dialog.gpssend.sendtracks=
-dialog.gpssend.trackname=
-dialog.saveoptions.title=
-dialog.save.fieldstosave=
-dialog.save.table.field=
-dialog.save.table.hasdata=
-dialog.save.table.save=
-dialog.save.headerrow=
-dialog.save.coordinateunits=
-dialog.save.altitudeunits=
-dialog.save.timestampformat=
-dialog.save.overwrite.title=
-dialog.save.overwrite.text=
-dialog.exportkml.text=
-dialog.exportkml.altitude=
-dialog.exportkml.kmz=
-dialog.exportkml.exportimages=
-dialog.exportgpx.name=
-dialog.exportgpx.desc=
-dialog.exportgpx.includetimestamps=
-dialog.exportpov.text=
-dialog.exportpov.font=
-dialog.exportpov.camerax=
-dialog.exportpov.cameray=
-dialog.exportpov.cameraz=
-dialog.exportpov.modelstyle=
-dialog.exportpov.ballsandsticks=
-dialog.exportpov.tubesandwalls=
-dialog.exportpov.warningtracksize=
-dialog.confirmreversetrack.title=
-dialog.confirmreversetrack.text=
-dialog.confirmcutandmove.title=
-dialog.confirmcutandmove.text=
-dialog.interpolate.title=
-dialog.interpolate.parameter.text=
-dialog.undo.title=
-dialog.undo.pretext=
-dialog.undo.none.title=
-dialog.undo.none.text=
-dialog.clearundo.title=
-dialog.clearundo.text=
-dialog.pointedit.title=
-dialog.pointedit.text=
-dialog.pointedit.table.field=
-dialog.pointedit.table.value=
-dialog.pointedit.table.changed=
-dialog.pointedit.changevalue.text=
-dialog.pointedit.changevalue.title=
-dialog.pointnameedit.title=
-dialog.pointnameedit.name=
-dialog.pointnameedit.uppercase=
-dialog.pointnameedit.lowercase=
-dialog.pointnameedit.sentencecase=
-dialog.addtimeoffset.add=
-dialog.addtimeoffset.subtract=
-dialog.addtimeoffset.days=
-dialog.addtimeoffset.hours=
-dialog.addtimeoffset.minutes=
-dialog.addtimeoffset.notimestamps=
-dialog.connect.title=
-dialog.connectphoto.clonepoint=
-dialog.saveexif.title=
-dialog.saveexif.intro=
-dialog.saveexif.nothingtosave=
-dialog.saveexif.noexiftool=
-dialog.saveexif.table.photoname=
-dialog.saveexif.table.status=
-dialog.saveexif.table.save=
-dialog.saveexif.photostatus.connected=
-dialog.saveexif.photostatus.disconnected=
-dialog.saveexif.photostatus.modified=
-dialog.saveexif.overwrite=
-dialog.charts.xaxis=
-dialog.charts.yaxis=
-dialog.charts.output=
-dialog.charts.screen=
-dialog.charts.svg=
-dialog.charts.svgwidth=
-dialog.charts.svgheight=
-dialog.charts.needaltitudeortimes=
-dialog.charts.gnuplotpath=
-dialog.charts.gnuplotnotfound=
-dialog.distances.intro=
-dialog.distances.column.from=
-dialog.distances.column.to=
-dialog.distances.currentpoint=
-dialog.distances.toofewpoints=
-dialog.setmapbg.mapnik=
-dialog.setmapbg.osma=
-dialog.setmapbg.cyclemap=
-dialog.setmapbg.other=
-dialog.setmapbg.server=
-dialog.correlate.notimestamps=
-dialog.correlate.nouncorrelatedphotos=
-dialog.correlate.photoselect.intro=
-dialog.correlate.photoselect.photoname=
-dialog.correlate.photoselect.timediff=
-dialog.correlate.photoselect.photolater=
-dialog.correlate.options.tip=
-dialog.correlate.options.intro=
-dialog.correlate.options.offsetpanel=
-dialog.correlate.options.offset=
-dialog.correlate.options.offset.hours=
-dialog.correlate.options.offset.minutes=
-dialog.correlate.options.offset.seconds=
-dialog.correlate.options.photolater=
-dialog.correlate.options.pointlater=
-dialog.correlate.options.limitspanel=
-dialog.correlate.options.notimelimit=
-dialog.correlate.options.timelimit=
-dialog.correlate.options.nodistancelimit=
-dialog.correlate.options.distancelimit=
-dialog.correlate.options.correlate=
-dialog.correlate.alloutsiderange=
-dialog.compress.nonefound=
-dialog.compress.duplicates.title=
-dialog.compress.closepoints.title=
-dialog.compress.closepoints.paramdesc=
-dialog.compress.wackypoints.title=
-dialog.compress.wackypoints.paramdesc=
-dialog.compress.singletons.title=
-dialog.compress.singletons.paramdesc=
-dialog.compress.summarylabel=
-dialog.help.help=
-dialog.about.version=
-dialog.about.build=
-dialog.about.summarytext1=
-dialog.about.summarytext2=
-dialog.about.summarytext3=
-dialog.about.languages=
-dialog.about.translatedby=
-dialog.about.systeminfo=
-dialog.about.systeminfo.os=
-dialog.about.systeminfo.java=
-dialog.about.systeminfo.java3d=
-dialog.about.systeminfo.povray=
-dialog.about.systeminfo.exiftool=
-dialog.about.systeminfo.gpsbabel=
-dialog.about.systeminfo.gnuplot=
dialog.about.yes=Sim
dialog.about.no=Não
-dialog.about.credits=
-dialog.about.credits.code=
-dialog.about.credits.exifcode=
-dialog.about.credits.icons=
-dialog.about.credits.translators=
-dialog.about.credits.translations=
-dialog.about.credits.devtools=
-dialog.about.credits.othertools=
-dialog.about.credits.thanks=
-dialog.about.readme=
-dialog.checkversion.error=
-dialog.checkversion.uptodate=
-dialog.checkversion.newversion1=
-dialog.checkversion.newversion2=
-dialog.checkversion.releasedate1=
-dialog.checkversion.releasedate2=
-dialog.checkversion.download=
-
-# 3d window
-dialog.3d.title=
-dialog.3d.altitudecap=
-dialog.3dlines.title=
-dialog.3dlines.empty=
-dialog.3dlines.intro=
-
-# Confirm messages || These are displayed as confirmation in the status bar
-confirm.loadfile=
-confirm.save.ok1=
-confirm.save.ok2=
-confirm.deletepoint.single=
-confirm.deletepoint.multi=
-confirm.point.edit=
-confirm.mergetracksegments=
-confirm.reverserange=
-confirm.addtimeoffset=
-confirm.rearrangewaypoints=
-confirm.cutandmove=
-confirm.saveexif.ok1=
-confirm.saveexif.ok2=
-confirm.undo.single=
-confirm.undo.multi=
-confirm.jpegload.single=
-confirm.jpegload.multi=
-confirm.photo.connect=
-confirm.photo.disconnect=
-confirm.correlate.single=
-confirm.correlate.multi=
-confirm.createpoint=
# Buttons
-button.ok=
-button.back=
-button.next=
-button.finish=
button.cancel=Cancelar
-button.overwrite=
-button.moveup=
-button.movedown=
-button.showlines=
button.edit=Editar
button.exit=Sair
button.close=Fechar
-button.continue=
button.yes=Sim
button.no=Não
-button.yestoall=
-button.notoall=
-button.selectall=
-button.selectnone=
-button.preview=
-button.guessfields=
-button.showwebpage=
-button.gnuplotpath=
-
-# File types
-filetype.txt=
-filetype.jpeg=
-filetype.kmlkmz=
-filetype.kml=
-filetype.kmz=
-filetype.gpx=
-filetype.pov=
-filetype.svg=
# Display components
display.nodata=Nenhum dados foi carregado
-display.noaltitudes=
details.trackdetails=Detalhes da track
-details.notrack=
details.track.points=Pontos
details.track.file=Arquivo
details.track.numfiles=Número de arquivos
details.pointdetails=Detalhes da ponto
-details.index.selected=
details.index.of=de
-details.nopointselection=
-details.photofile=
-details.norangeselection=
details.rangedetails=Detalhes da range
details.range.selected=Selecionado
details.range.to=a
details.altitude.to=a
-details.range.climb=
-details.range.descent=
-details.coordformat=
-details.distanceunits=
-display.range.time.secs=
-display.range.time.mins=
-display.range.time.hours=
-display.range.time.days=
-details.range.avespeed=
-details.range.avemovingspeed=
-details.waypointsphotos.waypoints=
details.waypointsphotos.photos=Fotos
details.photodetails=Detalhes da foto
-details.nophoto=
details.photo.loading=Carregando
-details.photo.connected=
-map.overzoom=
# Field names
fieldname.latitude=Latitude
fieldname.longitude=Longitude
fieldname.altitude=Altura
-fieldname.timestamp=
fieldname.time=Tempo
-fieldname.waypointname=
-fieldname.waypointtype=
-fieldname.newsegment=
-fieldname.custom=
-fieldname.prefix=
fieldname.distance=Distância
-fieldname.movingdistance=
-fieldname.duration=
fieldname.speed=Velocidade
-fieldname.verticalspeed=
-
-# Measurement units
-units.original=
-units.default=
-units.metres=
-units.metres.short=
-units.feet=
-units.feet.short=
-units.kilometres=
-units.kilometres.short=
-units.kmh=
-units.miles=
-units.miles.short=
-units.mph=
-units.metrespersec=
-units.feetpersec=
-units.hours=
-units.degminsec=
-units.degmin=
-units.deg=
-units.iso8601=
# External urls
url.googlemaps=maps.google.pt
-
-# Cardinals for 3d plots
-cardinal.n=
-cardinal.s=
-cardinal.e=
-cardinal.w=
-
-# Undo operations
-undo.load=
-undo.loadphotos=
-undo.editpoint=
-undo.deletepoint=
-undo.deletephoto=
-undo.deleterange=
-undo.compress=
-undo.insert=
-undo.reverse=
-undo.mergetracksegments=
-undo.addtimeoffset=
-undo.rearrangewaypoints=
-undo.cutandmove=
-undo.connectphoto=
-undo.disconnectphoto=
-undo.correlate=
-undo.createpoint=
-
-# Error messages
-error.save.dialogtitle=
-error.save.nodata=
-error.save.failed=
-error.saveexif.filenotfound=
-error.saveexif.cannotoverwrite1=
-error.saveexif.cannotoverwrite2=
-error.load.dialogtitle=
-error.load.noread=
-error.load.nopoints=
-error.load.unknownxml=
-error.load.noxmlinzip=
-error.load.othererror=
-error.jpegload.dialogtitle=
-error.jpegload.nofilesfound=
-error.jpegload.nojpegsfound=
-error.jpegload.noexiffound=
-error.jpegload.nogpsfound=
-error.undofailed.title=
-error.undofailed.text=
-error.function.noop.title=
-error.rearrange.noop=
-error.function.notavailable.title=
-error.function.nojava3d=
-error.3d=
-error.readme.notfound=
-error.osmimage.dialogtitle=
-error.osmimage.failed=
# Romanian entries as extra
# Menu entries
-menu.file=Fisier
-menu.file.open=Deschidere fisier
+menu.file=Fi\u015Fier
+menu.file.open=Deschidere fi\u015Fier
menu.file.addphotos=Adaugare foto
menu.file.save=Salvare
menu.file.exit=Iesire
menu.edit=Editare
menu.edit.undo=Anulare
-menu.edit.clearundo=Stergere lista de anulari
+menu.edit.clearundo=\u015Etergere lista de anulari
menu.edit.editpoint=Editare punct
-menu.edit.editwaypointname=Editare nume waypoint
-menu.edit.deletepoint=Stergere punct
-menu.edit.deleterange=Stergere gama
-menu.edit.deletemarked=Stergere puncte marcate
+menu.edit.deletepoint=\u015Etergere punct
+menu.edit.deleterange=\u015Etergere gama
+menu.edit.deletemarked=\u015Etergere puncte marcate
menu.edit.interpolate=Interpolare
menu.edit.average=Mediere selectie
menu.edit.reverse=Inversare selectie
menu.view.browser.yahoo=Harti Yahoo
menu.help=Ajutor
# Popup menu for map
-menu.map.zoomin=
-menu.map.zoomout=
-menu.map.zoomfull=
-menu.map.newpoint=
-menu.map.connect=
-menu.map.autopan=
-menu.map.showmap=
+menu.map.zoomin=Apropie in
+menu.map.zoomout=Apropie out
+menu.map.newpoint=Adaug\u0103 punct
+menu.map.connect=Traseaz\u0103 linii între puncte
-# Functions
-function.loadfromgps=
-function.sendtogps=
-function.exportkml=
-function.exportgpx=
-function.exportpov=
-function.compress=
-function.addtimeoffset=
-function.charts=
-function.show3d=
-function.distances=
-function.setmapbg=
-function.correlatephotos=
-function.help=
-function.about=
-function.checkversion=
+# Alt keys for menus
+altkey.menu.file=F
+altkey.menu.edit=E
+altkey.menu.select=S
+altkey.menu.view=V
+altkey.menu.photo=O
+altkey.menu.help=A
-# Dialogs
-dialog.exit.confirm.title=
-dialog.exit.confirm.text=
-dialog.openappend.title=
-dialog.openappend.text=
-dialog.deletepoint.title=
-dialog.deletepoint.deletephoto=
-dialog.deletephoto.title=
-dialog.deletephoto.deletepoint=
-dialog.openoptions.title=
-dialog.openoptions.filesnippet=
-dialog.load.table.field=
-dialog.load.table.datatype=
-dialog.load.table.description=
-dialog.delimiter.label=
-dialog.delimiter.comma=
-dialog.delimiter.tab=
-dialog.delimiter.space=
-dialog.delimiter.semicolon=
-dialog.delimiter.other=
-dialog.openoptions.deliminfo.records=
-dialog.openoptions.deliminfo.fields=
-dialog.openoptions.deliminfo.norecords=
-dialog.openoptions.altitudeunits=
-dialog.jpegload.subdirectories=
-dialog.jpegload.loadjpegswithoutcoords=
-dialog.jpegload.loadjpegsoutsidearea=
-dialog.jpegload.progress.title=
-dialog.jpegload.progress=
-dialog.gpsload.nogpsbabel=
-dialog.gpsload.device=
-dialog.gpsload.format=
-dialog.gpsload.getwaypoints=
-dialog.gpsload.gettracks=
-dialog.gpssend.sendwaypoints=
-dialog.gpssend.sendtracks=
-dialog.gpssend.trackname=
-dialog.saveoptions.title=
-dialog.save.fieldstosave=
-dialog.save.table.field=
-dialog.save.table.hasdata=
-dialog.save.table.save=
-dialog.save.headerrow=
-dialog.save.coordinateunits=
-dialog.save.altitudeunits=
-dialog.save.timestampformat=
-dialog.save.overwrite.title=
-dialog.save.overwrite.text=
-dialog.exportkml.text=
-dialog.exportkml.altitude=
-dialog.exportkml.kmz=
-dialog.exportkml.exportimages=
-dialog.exportgpx.name=
-dialog.exportgpx.desc=
-dialog.exportgpx.includetimestamps=
-dialog.exportpov.text=
-dialog.exportpov.font=
-dialog.exportpov.camerax=
-dialog.exportpov.cameray=
-dialog.exportpov.cameraz=
-dialog.exportpov.modelstyle=
-dialog.exportpov.ballsandsticks=
-dialog.exportpov.tubesandwalls=
-dialog.exportpov.warningtracksize=
-dialog.confirmreversetrack.title=
-dialog.confirmreversetrack.text=
-dialog.confirmcutandmove.title=
-dialog.confirmcutandmove.text=
-dialog.interpolate.title=
-dialog.interpolate.parameter.text=
-dialog.undo.title=
-dialog.undo.pretext=
-dialog.undo.none.title=
-dialog.undo.none.text=
-dialog.clearundo.title=
-dialog.clearundo.text=
-dialog.pointedit.title=
-dialog.pointedit.text=
-dialog.pointedit.table.field=
-dialog.pointedit.table.value=
-dialog.pointedit.table.changed=
-dialog.pointedit.changevalue.text=
-dialog.pointedit.changevalue.title=
-dialog.pointnameedit.title=
-dialog.pointnameedit.name=
-dialog.pointnameedit.uppercase=
-dialog.pointnameedit.lowercase=
-dialog.pointnameedit.sentencecase=
-dialog.addtimeoffset.add=
-dialog.addtimeoffset.subtract=
-dialog.addtimeoffset.days=
-dialog.addtimeoffset.hours=
-dialog.addtimeoffset.minutes=
-dialog.addtimeoffset.notimestamps=
-dialog.connect.title=
-dialog.connectphoto.clonepoint=
-dialog.saveexif.title=
-dialog.saveexif.intro=
-dialog.saveexif.nothingtosave=
-dialog.saveexif.noexiftool=
-dialog.saveexif.table.photoname=
-dialog.saveexif.table.status=
-dialog.saveexif.table.save=
-dialog.saveexif.photostatus.connected=
-dialog.saveexif.photostatus.disconnected=
-dialog.saveexif.photostatus.modified=
-dialog.saveexif.overwrite=
-dialog.charts.xaxis=
-dialog.charts.yaxis=
-dialog.charts.output=
-dialog.charts.screen=
-dialog.charts.svg=
-dialog.charts.svgwidth=
-dialog.charts.svgheight=
-dialog.charts.needaltitudeortimes=
-dialog.charts.gnuplotpath=
-dialog.charts.gnuplotnotfound=
-dialog.distances.intro=
-dialog.distances.column.from=
-dialog.distances.column.to=
-dialog.distances.currentpoint=
-dialog.distances.toofewpoints=
-dialog.setmapbg.mapnik=
-dialog.setmapbg.osma=
-dialog.setmapbg.cyclemap=
-dialog.setmapbg.other=
-dialog.setmapbg.server=
-dialog.correlate.notimestamps=
-dialog.correlate.nouncorrelatedphotos=
-dialog.correlate.photoselect.intro=
-dialog.correlate.photoselect.photoname=
-dialog.correlate.photoselect.timediff=
-dialog.correlate.photoselect.photolater=
-dialog.correlate.options.tip=
-dialog.correlate.options.intro=
-dialog.correlate.options.offsetpanel=
-dialog.correlate.options.offset=
-dialog.correlate.options.offset.hours=
-dialog.correlate.options.offset.minutes=
-dialog.correlate.options.offset.seconds=
-dialog.correlate.options.photolater=
-dialog.correlate.options.pointlater=
-dialog.correlate.options.limitspanel=
-dialog.correlate.options.notimelimit=
-dialog.correlate.options.timelimit=
-dialog.correlate.options.nodistancelimit=
-dialog.correlate.options.distancelimit=
-dialog.correlate.options.correlate=
-dialog.correlate.alloutsiderange=
-dialog.compress.nonefound=
-dialog.compress.duplicates.title=
-dialog.compress.closepoints.title=
-dialog.compress.closepoints.paramdesc=
-dialog.compress.wackypoints.title=
-dialog.compress.wackypoints.paramdesc=
-dialog.compress.singletons.title=
-dialog.compress.singletons.paramdesc=
-dialog.compress.summarylabel=
-dialog.help.help=
-dialog.about.version=
-dialog.about.build=
-dialog.about.summarytext1=
-dialog.about.summarytext2=
-dialog.about.summarytext3=
-dialog.about.languages=
-dialog.about.translatedby=
-dialog.about.systeminfo=
-dialog.about.systeminfo.os=
-dialog.about.systeminfo.java=
-dialog.about.systeminfo.java3d=
-dialog.about.systeminfo.povray=
-dialog.about.systeminfo.exiftool=
-dialog.about.systeminfo.gpsbabel=
-dialog.about.systeminfo.gnuplot=
-dialog.about.yes=
-dialog.about.no=
-dialog.about.credits=
-dialog.about.credits.code=
-dialog.about.credits.exifcode=
-dialog.about.credits.icons=
-dialog.about.credits.translators=
-dialog.about.credits.translations=
-dialog.about.credits.devtools=
-dialog.about.credits.othertools=
-dialog.about.credits.thanks=
-dialog.about.readme=
-dialog.checkversion.error=
-dialog.checkversion.uptodate=
-dialog.checkversion.newversion1=
-dialog.checkversion.newversion2=
-dialog.checkversion.releasedate1=
-dialog.checkversion.releasedate2=
-dialog.checkversion.download=
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=D
+shortcut.menu.file.save=S
+shortcut.menu.edit.undo=Z
+shortcut.menu.select.all=T
-# 3d window
-dialog.3d.title=
-dialog.3d.altitudecap=
-dialog.3dlines.title=
-dialog.3dlines.empty=
-dialog.3dlines.intro=
+# Functions
+function.exportkml=Export\u0103 într-un fi\u015Fier KML
+function.exportgpx=Export\u0103 într-un fi\u015Fier GPX
+function.exportpov=Export\u0103 într-un fi\u015Fier POV
+function.editwaypointname=Editare nume waypoint
+function.help=Ajutor
+function.about=Despre Prune
-# Confirm messages || These are displayed as confirmation in the status bar
-confirm.loadfile=
-confirm.save.ok1=
-confirm.save.ok2=
-confirm.deletepoint.single=
-confirm.deletepoint.multi=
-confirm.point.edit=
-confirm.mergetracksegments=
-confirm.reverserange=
-confirm.addtimeoffset=
-confirm.rearrangewaypoints=
-confirm.cutandmove=
-confirm.saveexif.ok1=
-confirm.saveexif.ok2=
-confirm.undo.single=
-confirm.undo.multi=
-confirm.jpegload.single=
-confirm.jpegload.multi=
-confirm.photo.connect=
-confirm.photo.disconnect=
-confirm.correlate.single=
-confirm.correlate.multi=
-confirm.createpoint=
+# Dialogs
+dialog.save.overwrite.text=Fi\u015Fierul exist\u0103. ÃŽl suprascriu?
+dialog.pointedit.text=V\u0103 rog selecta\u0163i rândul care va fi editat
+dialog.pointedit.table.value=Valoare
+dialog.findwaypoint.search=C\u0103utare
+dialog.setmapbg.mapnik=Mapnik (implicit)
+dialog.setmapbg.server=Adres\u0103 server
+dialog.correlate.options.tip=Indiciu: By manually correlating at least one photo, the time offset can be calculated for you.
+dialog.about.version=Versiunea
+dialog.about.readme=Cite\u015Fte-m\u0103
# Buttons
-button.ok=
-button.back=
-button.next=
-button.finish=
-button.cancel=
-button.overwrite=
-button.moveup=
-button.movedown=
-button.showlines=
-button.edit=
-button.exit=
-button.close=
-button.continue=
-button.yes=
-button.no=
-button.yestoall=
-button.notoall=
-button.selectall=
-button.selectnone=
-button.preview=
-button.guessfields=
-button.showwebpage=
-button.gnuplotpath=
+button.ok=OK
+button.cancel=Renun\u0163\u0103
+button.edit=Editare
+button.exit=Iesire
# File types
-filetype.txt=
-filetype.jpeg=
-filetype.kmlkmz=
-filetype.kml=
-filetype.kmz=
-filetype.gpx=
-filetype.pov=
-filetype.svg=
+filetype.jpeg=Imagine JPEG (*.jpg)
# Display components
-display.nodata=
-display.noaltitudes=
-details.trackdetails=
-details.notrack=
-details.track.points=
-details.track.file=
-details.track.numfiles=
-details.pointdetails=
-details.index.selected=
-details.index.of=
-details.nopointselection=
-details.photofile=
-details.norangeselection=
-details.rangedetails=
-details.range.selected=
-details.range.to=
-details.altitude.to=
-details.range.climb=
-details.range.descent=
-details.coordformat=
-details.distanceunits=
-display.range.time.secs=
-display.range.time.mins=
-display.range.time.hours=
-display.range.time.days=
-details.range.avespeed=
-details.range.avemovingspeed=
-details.waypointsphotos.waypoints=
-details.waypointsphotos.photos=
-details.photodetails=
-details.nophoto=
-details.photo.loading=
-details.photo.connected=
-map.overzoom=
+details.track.points=Puncte
+details.pointdetails=Punct
+details.range.selected=Selectat
+details.range.to=la
+details.altitude.to=la
# Field names
-fieldname.latitude=
-fieldname.longitude=
-fieldname.altitude=
-fieldname.timestamp=
-fieldname.time=
-fieldname.waypointname=
-fieldname.waypointtype=
-fieldname.newsegment=
-fieldname.custom=
-fieldname.prefix=
-fieldname.distance=
-fieldname.movingdistance=
-fieldname.duration=
-fieldname.speed=
-fieldname.verticalspeed=
+fieldname.waypointname=Nume
# Measurement units
-units.original=
-units.default=
-units.metres=
-units.metres.short=
-units.feet=
-units.feet.short=
-units.kilometres=
-units.kilometres.short=
-units.kmh=
-units.miles=
-units.miles.short=
-units.mph=
-units.metrespersec=
-units.feetpersec=
-units.hours=
-units.degminsec=
-units.degmin=
-units.deg=
-units.iso8601=
-
-# External urls
-url.googlemaps=
-
-# Cardinals for 3d plots
-cardinal.n=
-cardinal.s=
-cardinal.e=
-cardinal.w=
-
-# Undo operations
-undo.load=
-undo.loadphotos=
-undo.editpoint=
-undo.deletepoint=
-undo.deletephoto=
-undo.deleterange=
-undo.compress=
-undo.insert=
-undo.reverse=
-undo.mergetracksegments=
-undo.addtimeoffset=
-undo.rearrangewaypoints=
-undo.cutandmove=
-undo.connectphoto=
-undo.disconnectphoto=
-undo.correlate=
-undo.createpoint=
-
-# Error messages
-error.save.dialogtitle=
-error.save.nodata=
-error.save.failed=
-error.saveexif.filenotfound=
-error.saveexif.cannotoverwrite1=
-error.saveexif.cannotoverwrite2=
-error.load.dialogtitle=
-error.load.noread=
-error.load.nopoints=
-error.load.unknownxml=
-error.load.noxmlinzip=
-error.load.othererror=
-error.jpegload.dialogtitle=
-error.jpegload.nofilesfound=
-error.jpegload.nojpegsfound=
-error.jpegload.noexiffound=
-error.jpegload.nogpsfound=
-error.undofailed.title=
-error.undofailed.text=
-error.function.noop.title=
-error.rearrange.noop=
-error.function.notavailable.title=
-error.function.nojava3d=
-error.3d=
-error.readme.notfound=
-error.osmimage.dialogtitle=
-error.osmimage.failed=
+units.default=Implicit
--- /dev/null
+# Text entries for the Prune application
+# Chinese entries as extra
+
+# Menu entries
+menu.file=\u6587\u4ef6
+menu.file.open=\u6253\u5f00
+menu.file.addphotos=\u6dfb\u52a0\u76f8\u7247
+menu.file.save=\u4fdd\u5b58
+menu.file.exit=\u9000\u51fa
+menu.edit=\u7f16\u8f91
+menu.edit.undo=\u64a4\u9500
+menu.edit.clearundo=\u6e05\u9664\u64a4\u9500\u6e05\u5355
+menu.edit.editpoint=\u7f16\u8f91\u8f68\u8ff9\u70b9
+menu.edit.deletepoint=\u5220\u9664\u8f68\u8ff9\u70b9
+menu.edit.deleterange=\u5220\u9664\u8f68\u8ff9\u70b9\u6bb5
+menu.edit.deletemarked=\u5220\u9664\u5df2\u6807\u793a\u8f68\u8ff9\u70b9
+menu.edit.interpolate=\u63d2\u5165\u8f68\u8ff9\u70b9
+menu.edit.average=\u8bbe\u7f6e\u5e73\u5747\u8f68\u8ff9\u70b9
+menu.edit.reverse=\u8f68\u8ff9\u70b9\u53cd\u5411
+menu.edit.mergetracksegments=\u5408\u5e76\u8f68\u8ff9\u6bb5
+menu.edit.rearrange=\u822a\u70b9\u91cd\u7f6e
+menu.edit.rearrange.start=\u81f3\u8d77\u59cb\u4f4d\u7f6e
+menu.edit.rearrange.end=\u81f3\u672b\u4f4d\u7f6e
+menu.edit.rearrange.nearest=\u81f3\u6700\u8fd1\u8f68\u8ff9\u70b9
+menu.edit.cutandmove=\u79fb\u52a8
+menu.select=\u9009\u62e9
+menu.select.all=\u5168\u9009
+menu.select.none=\u64a4\u9500\u9009\u62e9
+menu.select.start=\u8bbe\u7f6e\u8d77\u70b9
+menu.select.end=\u8bbe\u7f6e\u672b\u70b9
+menu.photo=\u76f8\u7247
+menu.photo.saveexif=\u5750\u6807\u4fdd\u5b58\u81f3Exif
+menu.photo.connect=\u94fe\u63a5\u76f8\u7247
+menu.photo.disconnect=\u64a4\u9500\u94fe\u63a5
+menu.photo.delete=\u5220\u9664\u7167\u7247
+menu.view=\u67e5\u770b
+menu.view.browser=\u5728\u6d4f\u89c8\u5668\u4e2d\u6253\u5f00\u5730\u56fe
+menu.view.browser.google=Google\u5730\u56fe
+menu.view.browser.openstreetmap=Openstreet\u5730\u56fe
+menu.view.browser.mapquest=Mapquest\u5730\u56fe
+menu.view.browser.yahoo=Yahoo\u5730\u56fe
+menu.settings=\u8bbe\u7f6e
+menu.settings.showpace=\u663e\u793a\u6b65\u901f
+menu.help=\u5e2e\u52a9
+# Popup menu for map
+menu.map.zoomin=\u653e\u5927
+menu.map.zoomout=\u7f29\u5c0f
+menu.map.zoomfull=\u539f\u5c3a\u5bf8
+menu.map.newpoint=\u65b0\u5efa\u8f68\u8ff9\u70b9
+menu.map.connect=\u8fde\u63a5\u8f68\u8ff9\u70b9
+menu.map.autopan=\u81ea\u52a8\u7f29\u653e
+menu.map.showmap=\u663e\u793a\u5730\u56fe
+menu.map.showscalebar=\u663e\u793a\u6bd4\u4f8b\u5c3a
+
+# Alt keys for menus
+altkey.menu.file=
+altkey.menu.edit=
+altkey.menu.select=
+altkey.menu.view=
+altkey.menu.photo=
+altkey.menu.settings=
+altkey.menu.help=
+
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=
+shortcut.menu.file.load=
+shortcut.menu.file.save=
+shortcut.menu.edit.undo=
+shortcut.menu.edit.compress=
+shortcut.menu.select.all=
+shortcut.menu.help.help=
+
+# Functions
+function.loadfromgps=\u4eceGPS\u5bfc\u5165
+function.sendtogps=\u53d1\u9001\u81f3GPS
+function.exportkml=\u8f93\u51faKML\u6587\u4ef6
+function.exportgpx=\u8f93\u51faGPX\u6587\u4ef6
+function.exportpov=\u8f93\u51faPOV\u6587\u4ef6
+function.editwaypointname=\u7f16\u8f91\u822a\u70b9\u540d
+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.findwaypoint=\u67e5\u627e\u822a\u70b9
+function.charts=\u9ad8\u5ea6\u901f\u5ea6\u56fe\u8868
+function.show3d=3-D\u89c6\u56fe
+function.distances=\u8ddd\u79bb
+function.getgpsies=Gpsies\u8f68\u8ff9
+function.correlatephotos=\u94fe\u63a5\u76f8\u7247
+function.setmapbg=\u80cc\u666f\u5730\u56fe
+function.setkmzimagesize=
+function.setpaths=\u8bbe\u7f6e\u7a0b\u5e8f\u8def\u5f84
+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
+
+# Dialogs
+dialog.exit.confirm.title=\u9000\u51fa
+dialog.exit.confirm.text=\u6570\u636e\u672a\u4fdd\u5b58\uff0c\u662f\u5426\u9000\u51fa\uff1f
+dialog.openappend.title=\u9644\u52a0\u81f3\u5df2\u5bfc\u5165\u6570\u636e
+dialog.openappend.text=\u9644\u52a0\u73b0\u6709\u6570\u636e\u81f3\u5df2\u5bfc\u5165\u6570\u636e
+dialog.deletepoint.title=\u5220\u9664\u8f68\u8ff9\u70b9
+dialog.deletepoint.deletephoto=\u5220\u9664\u8f68\u8ff9\u70b9\u94fe\u63a5\u7684\u76f8\u7247\uff1f
+dialog.deletephoto.title=\u5220\u9664\u76f8\u7247
+dialog.deletephoto.deletepoint=\u5220\u9664\u76f8\u7247\u94fe\u63a5\u7684\u8f68\u8ff9\u70b9\uff1f
+dialog.openoptions.title=\u6253\u5f00\u9009\u9879
+dialog.openoptions.filesnippet=\u6587\u4ef6\u683c\u5f0f
+dialog.load.table.field=\u6570\u636e\u6bb5
+dialog.load.table.datatype=\u6570\u636e\u7c7b\u578b
+dialog.load.table.description=\u63cf\u8ff0
+dialog.delimiter.label=\u6570\u636e\u6bb5\u5206\u9694\u7b26
+dialog.delimiter.comma=\u9017\u53f7
+dialog.delimiter.tab=Tab
+dialog.delimiter.space=\u7a7a\u683c
+dialog.delimiter.semicolon=\u5206\u53f7
+dialog.delimiter.other=\u5176\u4ed6
+dialog.openoptions.deliminfo.records=\u6761\u8bb0\u5f55\uff0c
+dialog.openoptions.deliminfo.fields=\u6570\u636e\u6bb5
+dialog.openoptions.deliminfo.norecords=\u65e0\u7eaa\u5f55
+dialog.openoptions.altitudeunits=\u9ad8\u5ea6\u5355\u4f4d
+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.jpegload.progress.title=\u5bfc\u5165\u76f8\u7247
+dialog.jpegload.progress=\u8bf7\u7b49\u5f85\uff0c\u6b63\u641c\u7d22\u76f8\u7247
+dialog.gpsload.nogpsbabel=\u627e\u4e0d\u5230Gpsbabel,\u7ee7\u7eed\uff1f
+dialog.gpsload.device=GPS\u7aef\u53e3\u540d\u79f0
+dialog.gpsload.format=GPS\u6587\u4ef6\u683c\u5f0f
+dialog.gpsload.getwaypoints=\u5bfc\u5165\u822a\u70b9
+dialog.gpsload.gettracks=\u5bfc\u5165\u8f68\u8ff9
+dialog.gpssend.sendwaypoints=\u53d1\u9001\u822a\u70b9
+dialog.gpssend.sendtracks=\u53d1\u9001\u8f68\u8ff9
+dialog.gpssend.trackname=\u8f68\u8ff9\u540d
+dialog.saveoptions.title=\u4fdd\u5b58
+dialog.save.fieldstosave=\u4fdd\u5b58\u6570\u636e\u6bb5
+dialog.save.table.field=\u6570\u636e\u6bb5
+dialog.save.table.hasdata=\u6709\u6570\u636e
+dialog.save.table.save=\u4fdd\u5b58
+dialog.save.headerrow=\u8f93\u51fa\u5934\u884c
+dialog.save.coordinateunits=\u5750\u6807\u5355\u4f4d
+dialog.save.altitudeunits=\u9ad8\u5ea6\u5355\u4f4d
+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.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.exportgpx.name=\u540d\u79f0
+dialog.exportgpx.desc=\u63cf\u8ff0
+dialog.exportgpx.includetimestamps=\u5305\u542b\u65f6\u95f4
+dialog.exportpov.text=\u8bf7\u8f93\u5165POV\u53c2\u6570
+dialog.exportpov.font=\u5b57\u4f53
+dialog.exportpov.camerax=X\u76f8\u673a
+dialog.exportpov.cameray=Y\u76f8\u673a
+dialog.exportpov.cameraz=Z\u76f8\u673a
+dialog.exportpov.modelstyle=\u6a21\u578b\u7c7b\u578b
+dialog.exportpov.ballsandsticks=\u7403\u548c\u6746
+dialog.exportpov.tubesandwalls=\u7ba1\u548c\u5899
+dialog.exportpov.warningtracksize=\u8f68\u8ff9\u542b\u6709\u592a\u591a\u822a\u70b9\uff0cJAVA3D\u53ef\u80fd\u65e0\u6cd5\u663e\u793a\n\u662f\u5426\u7ee7\u7eed\uff1f
+dialog.pointtype.desc=\u4fdd\u5b58\u4e0b\u5217\u70b9\uff1a
+dialog.pointtype.track=\u8f68\u8ff9\u70b9
+dialog.pointtype.waypoint=\u822a\u70b9
+dialog.pointtype.photo=\u76f8\u7247\u70b9
+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.confirmcutandmove.text=\u8f68\u8ff9\u5305\u542b\u65f6\u95f4\u4fe1\u606f\uff0c\u79fb\u52a8\u540e\u53ef\u80fd\u4e22\u5931\n\u662f\u5426\u7ee7\u7eed\uff1f
+dialog.interpolate.title=\u91cd\u53e0\u8f68\u8ff9\u70b9
+dialog.interpolate.parameter.text=\u6240\u9009\u4e24\u70b9\u4e2d\u63d2\u5165\u70b9\u7684\u4e2a\u6570
+dialog.undo.title=\u64a4\u9500\u52a8\u4f5c
+dialog.undo.pretext=\u8bf7\u9009\u62e9\u8981\u64a4\u9500\u7684\u52a8\u4f5c
+dialog.undo.none.title=\u4e0d\u80fd\u64a4\u9500
+dialog.undo.none.text=\u65e0\u52a8\u4f5c\u53ef\u64a4\u9500
+dialog.clearundo.title=\u6e05\u9664\u64a4\u9500\u6e05\u5355
+dialog.clearundo.text=\u662f\u5426\u786e\u5b9e\u8981\u6e05\u9664\u64a4\u9500\u6e05\u5355\uff1f\n\u64a4\u9500\u4fe1\u606f\u4f1a\u4e22\u5931
+dialog.pointedit.title=\u7f16\u8f91\u8f68\u8ff9\u70b9
+dialog.pointedit.text=\u9009\u62e9\u8981\u7f16\u8f91\u7684\u533a\u57df\u5e76\u7528\u201c\u7f16\u8f91\u201d\u952e\u6539\u53d8\u6570\u503c
+dialog.pointedit.table.field=\u6570\u636e\u6bb5
+dialog.pointedit.table.value=\u6570\u503c
+dialog.pointedit.table.changed=\u6539\u53d8
+dialog.pointedit.changevalue.text=\u8f93\u5165\u65b0\u6570\u503c
+dialog.pointedit.changevalue.title=\u7f16\u8f91\u6570\u636e\u6bb5
+dialog.pointnameedit.name=\u822a\u70b9\u540d\u79f0
+dialog.pointnameedit.uppercase=\u4e0a\u6863\u952e
+dialog.pointnameedit.lowercase=\u4e0b\u6863\u952e
+dialog.pointnameedit.sentencecase=\u6807\u9898\u952e
+dialog.addtimeoffset.add=\u5ef6\u540e\u65f6\u95f4
+dialog.addtimeoffset.subtract=\u63d0\u524d\u65f6\u95f4
+dialog.addtimeoffset.days=\u5929\u6570
+dialog.addtimeoffset.hours=\u5c0f\u65f6
+dialog.addtimeoffset.minutes=\u5206\u949f
+dialog.addtimeoffset.notimestamps=\u4e0d\u80fd\u6dfb\u52a0\u65f6\u95f4\u56e0\u4e3a\u6b64\u6bb5\u4e0d\u542b\u65f6\u95f4\u4fe1\u606f
+dialog.findwaypoint.intro=\u8f93\u5165\u90e8\u5206\u822a\u70b9\u540d
+dialog.findwaypoint.search=\u641c\u7d22
+dialog.connect.title=\u94fe\u63a5\u7167\u7247\u548c\u822a\u70b9
+dialog.connectphoto.clonepoint=\u6b64\u8f68\u8ff9\u70b9\u5df2\u6709\u50cf\u7247\n\u662f\u5426\u590d\u5236\u822a\u70b9\uff1f
+dialog.saveexif.title=\u4fdd\u5b58Exif
+dialog.saveexif.intro=\u9009\u62e9\u8981\u4fdd\u5b58\u7684\u76f8\u7247
+dialog.saveexif.nothingtosave=\u5750\u6807\u672a\u6539\u53d8\uff0c\u65e0\u4fdd\u5b58\u5185\u5bb9
+dialog.saveexif.noexiftool=\u672a\u627e\u5230Exif \u5de5\u5177\uff0c\u7ee7\u7eed\uff1f
+dialog.saveexif.table.photoname=\u76f8\u7247\u540d
+dialog.saveexif.table.status=\u72b6\u6001
+dialog.saveexif.table.save=\u4fdd\u5b58
+dialog.saveexif.photostatus.connected=\u5df2\u94fe\u63a5
+dialog.saveexif.photostatus.disconnected=\u672a\u94fe\u63a5
+dialog.saveexif.photostatus.modified=\u5df2\u6539\u53d8
+dialog.saveexif.overwrite=\u8986\u76d6\u6587\u4ef6
+dialog.charts.xaxis=X\u8f74
+dialog.charts.yaxis=Y\u8f74
+dialog.charts.output=\u8f93\u51fa
+dialog.charts.screen=\u8f93\u51fa\u81f3\u5c4f\u5e55
+dialog.charts.svg=\u8f93\u51fa\u81f3SVG\u6587\u4ef6
+dialog.charts.svgwidth=SVG\u5bbd\u5ea6
+dialog.charts.svgheight=SVG\u9ad8\u5ea6
+dialog.charts.needaltitudeortimes=\u8f68\u8ff9\u5fc5\u987b\u542b\u6709\u9ad8\u5ea6\u6216\u65f6\u95f4\u4fe1\u606f
+dialog.charts.gnuplotpath=gnuplot\u8def\u5f84
+dialog.charts.gnuplotnotfound=\u8def\u5f84\u9519\u8bef\uff0c\u65e0\u6cd5\u627e\u5230gnuplot
+dialog.distances.intro=\u822a\u70b9\u4e4b\u95f4\u76f4\u7ebf\u8ddd\u79bb
+dialog.distances.column.from=\u4ece\u6b64\u70b9
+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.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=
+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.photoselect.photoname=\u76f8\u7247\u540d
+dialog.correlate.photoselect.timediff=\u65f6\u95f4\u5dee
+dialog.correlate.photoselect.photolater=\u76f8\u7247\u5ef6\u540e
+dialog.correlate.options.tip=\u63d0\u793a\uff1a\u624b\u52a8\u94fe\u63a5\u81f3\u5c11\u4e00\u5f20\u76f8\u7247\uff0c\u53ef\u81ea\u52a8\u8ba1\u7b97\u65f6\u95f4\u504f\u79fb
+dialog.correlate.options.intro=\u9009\u62e9\u81ea\u52a8\u94fe\u63a5\u8bbe\u7f6e
+dialog.correlate.options.offsetpanel=\u65f6\u95f4\u504f\u79fb
+dialog.correlate.options.offset=\u504f\u79fb
+dialog.correlate.options.offset.hours=\u5c0f\u65f6
+dialog.correlate.options.offset.minutes=\u5206\u949f
+dialog.correlate.options.offset.seconds=\u79d2
+dialog.correlate.options.photolater=\u76f8\u7247\u6ede\u540e\u4e8e\u8f68\u8ff9\u70b9
+dialog.correlate.options.pointlater=\u8f68\u8ff9\u70b9\u6ede\u540e\u4e8e\u76f8\u7247
+dialog.correlate.options.limitspanel=\u94fe\u63a5\u9650\u5236
+dialog.correlate.options.notimelimit=\u65e0\u65f6\u95f4\u9650\u5236
+dialog.correlate.options.timelimit=\u65f6\u95f4\u9650\u5236
+dialog.correlate.options.nodistancelimit=\u65e0\u8ddd\u79bb\u9650\u5236
+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.compress.nonefound=\u65e0\u6cd5\u5220\u9664\u6570\u636e\u70b9
+dialog.compress.duplicates.title=\u91cd\u590d\u70b9\u5220\u9664
+dialog.compress.closepoints.title=\u90bb\u8fd1\u70b9\u5220\u9664
+dialog.compress.closepoints.paramdesc=\u8303\u56f4\u7cfb\u6570
+dialog.compress.wackypoints.title=\u5f02\u5e38\u70b9\u5220\u9664
+dialog.compress.wackypoints.paramdesc=\u8ddd\u79bb\u7cfb\u6570
+dialog.compress.singletons.title=\u79bb\u6563\u70b9\u5220\u9664
+dialog.compress.singletons.paramdesc=\u8ddd\u79bb\u7cfb\u6570
+dialog.compress.summarylabel=\u8981\u5220\u9664\u7684\u70b9
+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.summarytext1=Prune\u662f\u4e00\u4e2a\u4eceGPS\u4e2d\u5bfc\u5165\u6570\u636e\uff0c\u663e\u793a\u6570\u636e\u548c\u7f16\u8f91\u6570\u636e\u7684\u8f6f\u4ef6
+dialog.about.summarytext2=\u5b83\u7684\u53d1\u884c\u662f\u57fa\u4e8eGnu GPL\u89c4\u5219\uff0c\u662f\u514d\u8d39\u7684\uff0c\u5f00\u653e\u5f0f\u7684\uff0c\u5168\u4e16\u754c\u5171\u7528\u5e76\u6539\u5584\u589e\u5f3a\u5176\u529f\u80fd\n\u5728\u7b26\u5408"license.txt"\u6761\u4ef6\u4e0b\uff0c\u5bb9\u8bb8\u5e76\u9f13\u52b1\u590d\u5236\uff0c\u5206\u53d1\u53ca\u4fee\u6539\u3002
+dialog.about.summarytext3=\u66f4\u591a\u4fe1\u606f\u53ca\u7528\u6cd5\u6307\u5357\uff0c\u8bf7\u53c2\u8003\u7f51\u7ad9\uff1a\nhttp:activityworkshop.net/
+dialog.about.languages=\u652f\u6301\u8bed\u8a00
+dialog.about.translatedby=\u4e2d\u6587\u7ffb\u8bd1\uff1a\u9ed1\u8001\u9648 (Sam Chen)
+dialog.about.systeminfo=\u7cfb\u7edf\u4fe1\u606f
+dialog.about.systeminfo.os=\u64cd\u4f5c\u7cfb\u7edf
+dialog.about.systeminfo.java=Java Runtime
+dialog.about.systeminfo.java3d=Java 3D \u662f\u5426\u5b89\u88c5
+dialog.about.systeminfo.povray=Povray \u662f\u5426\u5b89\u88c5
+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.yes=\u662f
+dialog.about.no=\u5426
+dialog.about.credits=\u81f4\u8c22
+dialog.about.credits.code=Prune \u539f\u7801\u7f16\u5199
+dialog.about.credits.exifcode=Exif \u539f\u7801\u7f16\u5199
+dialog.about.credits.icons=\u56fe\u6807\u6765\u81ea\u4e8e
+dialog.about.credits.translators=\u8bd1\u8005
+dialog.about.credits.translations=\u7ffb\u8bd1\u52a9\u7406
+dialog.about.credits.devtools=\u5f00\u53d1\u5de5\u5177
+dialog.about.credits.othertools=\u5176\u4ed6\u5de5\u5177
+dialog.about.credits.thanks=\u81f3\u8c22
+dialog.about.readme=\u7248\u672c\u4fe1\u606f
+dialog.checkversion.error=\u65e0\u6cd5\u68c0\u6d4b\u7248\u672c\u66f4\u65b0\n\u8bf7\u68c0\u67e5\u7f51\u7edc\u8fde\u63a5
+dialog.checkversion.uptodate=\u4f60\u4f7f\u7528\u7684\u5df2\u662f\u6700\u65b0\u7248\u672c
+dialog.checkversion.newversion1=\u65b0\u7248\u672c\u5b58\u5728\uff0c \u6700\u65b0\u7248\u672c\u53f7\u662f\uff1a
+dialog.checkversion.newversion2=
+dialog.checkversion.releasedate1=\u65b0\u7248\u672c\u53d1\u884c\u4e8e
+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=
+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.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.metricunits=\u4f7f\u7528\u516c\u5236\uff1f
+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.showpace=\u663e\u793a\u6b65\u901f
+dialog.saveconfig.prune.kmzimagewidth=
+dialog.saveconfig.prune.kmzimageheight=
+dialog.setpaths.intro=\u82e5\u9700\u8981\uff0c\u53ef\u8bbe\u5b9a\u5916\u6302\u7a0b\u5e8f\u8def\u5f84
+dialog.addaltitude.noaltitudes=\u8f68\u8ff9\u4e0d\u542b\u9ad8\u5ea6\u4fe1\u606f
+dialog.addaltitude.desc=\u9ad8\u5ea6\u504f\u79fb
+
+# 3d window
+dialog.3d.title=Prune 3D \u663e\u793a
+dialog.3d.altitudecap=\u9ad8\u5ea6\u6bd4\u4f8b
+dialog.3dlines.title=Prune \u7f51\u683c\u7ebf
+dialog.3dlines.empty=\u65e0\u6cd5\u663e\u793a\u7f51\u683c\u7ebf
+dialog.3dlines.intro=3D \u7f51\u683c\u7ebf
+
+# Confirm messages || These are displayed as confirmation in the status bar
+confirm.loadfile=\u6570\u636e\u5df2\u4ece\u6587\u4ef6\u5bfc\u5165
+confirm.save.ok1=\u4fdd\u5b58\u6210\u529f
+confirm.save.ok2=\u5df2\u4fdd\u5b58\u7684\u8f68\u8ff9\u70b9
+confirm.deletepoint.single=\u5df1\u5220\u9664\u7684\u8f68\u8ff9\u70b9
+confirm.deletepoint.multi=\u5df2\u5220\u9664\u7684\u8f68\u8ff9\u70b9
+confirm.point.edit=\u5df2\u7f16\u8f91\u7684\u8f68\u8ff9\u70b9
+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=
+confirm.rearrangewaypoints=\u91cd\u65b0\u914d\u7f6e\u7684\u822a\u70b9
+confirm.cutandmove=\u5df2\u79fb\u52a8\u7684\u8f68\u8ff9\u6bb5
+confirm.saveexif.ok1=\u5df2\u4fdd\u5b58
+confirm.saveexif.ok2=\u76f8\u7247\u6587\u4ef6
+confirm.undo.single=\u5df2\u64a4\u9500\u7684\u64cd\u4f5c
+confirm.undo.multi=\u5df2\u64a4\u9500\u7684\u64cd\u4f5c
+confirm.jpegload.single=\u5df2\u52a0\u5165\u76f8\u7247
+confirm.jpegload.multi=\u5df2\u52a0\u5165\u76f8\u7247
+confirm.photo.connect=\u76f8\u7247\u5df2\u94fe\u63a5
+confirm.photo.disconnect=\u76f8\u7247\u672a\u94fe\u63a5
+confirm.correlate.single=\u76f8\u7247\u5df2\u94fe\u63a5
+confirm.correlate.multi=\u76f8\u7247\u5df2\u94fe\u63a5
+confirm.createpoint=\u5df2\u521b\u5efa\u70b9
+confirm.running=\u8bf7\u7a0d\u7b49...
+
+# Buttons
+button.ok=\u786e\u5b9a
+button.back=\u8fd4\u56de
+button.next=\u4e0b\u4e00\u6b65
+button.finish=\u5b8c\u6210
+button.cancel=\u53d6\u6d88
+button.overwrite=\u8986\u76d6
+button.moveup=\u4e0a\u79fb
+button.movedown=\u4e0b\u79fb
+button.showlines=\u663e\u793a\u7ebf\u6761
+button.edit=\u7f16\u8f91
+button.exit=\u9000\u51fa
+button.close=\u5173\u95ed
+button.continue=\u7ee7\u7eed
+button.yes=\u662f
+button.no=\u5426
+button.yestoall=\u5168\u90e8\u662f
+button.notoall=\u5168\u90e8\u5426
+button.selectall=\u5168\u9009
+button.selectnone=\u5168\u4e0d\u9009
+button.preview=\u9884\u89c8
+button.load=\u5bfc\u5165
+button.guessfields=\u731c\u4f30\u533a\u57df\u5185\u5bb9
+button.showwebpage=\u663e\u793a\u7f51\u9875
+button.check=\u68c0\u67e5
+
+# File types
+filetype.txt=TXT\u6587\u4ef6
+filetype.jpeg=JPG\u6587\u4ef6
+filetype.kmlkmz=KML,KMZ\u6587\u4ef6
+filetype.kml=KML\u6587\u4ef6
+filetype.kmz=KMZ\u6587\u4ef6
+filetype.gpx=GPX\u6587\u4ef6
+filetype.pov=POV\u6587\u4ef6
+filetype.svg=SVG\u6587\u4ef6
+
+# Display components
+display.nodata=\u65e0\u6570\u636e
+display.noaltitudes=\u8f68\u8ff9\u6570\u636e\u4e0d\u542b\u9ad8\u5ea6\u4fe1\u606f
+details.trackdetails=\u8f68\u8ff9\u4fe1\u606f
+details.notrack=\u65e0\u8f68\u8ff9
+details.track.points=\u8f68\u8ff9\u70b9
+details.track.file=\u6587\u4ef6
+details.track.numfiles=\u6587\u4ef6\u6570
+details.pointdetails=\u8f68\u8ff9\u70b9\u4fe1\u606f
+details.index.selected=\u7b2c
+details.index.of=\u70b9\u53d6\u81ea
+details.nopointselection=\u6ca1\u6709\u9009\u62e9\u70b9
+details.photofile=\u76f8\u7247\u6587\u4ef6
+details.norangeselection=\u6ca1\u6709\u9009\u62e9\u8f68\u8ff9/\u822a\u70b9\u6bb5
+details.rangedetails=\u8f68\u8ff9/\u822a\u70b9\u6bb5\u4fe1\u606f
+details.range.selected=\u9009\u4e2d
+details.range.to=\u81f3
+details.altitude.to=\u81f3
+details.range.climb=\u7d2f\u8ba1\u722c\u5347
+details.range.descent=\u7d2f\u8ba1\u4e0b\u964d
+details.coordformat=\u5750\u6807\u683c\u5f0f
+details.distanceunits=\u8ddd\u79bb\u5355\u4f4d
+display.range.time.secs=\u79d2
+display.range.time.mins=\u5206
+display.range.time.hours=\u5c0f\u65f6
+display.range.time.days=\u5929
+details.range.avespeed=\u5e73\u5747\u901f\u5ea6
+details.range.avemovingspeed=\u5e73\u5747\u79fb\u52a8
+details.range.pace=\u6b65\u901f
+details.waypointsphotos.waypoints=\u822a\u70b9
+details.waypointsphotos.photos=\u76f8\u7247
+details.photodetails=\u76f8\u7247\u4fe1\u606f
+details.nophoto=\u65e0\u76f8\u7247\u88ab\u9009\u4e2d
+details.photo.loading=\u6b63\u5bfc\u5165
+details.photo.connected=\u5df2\u94fe\u63a5
+map.overzoom=\u5728\u6b64\u653e\u5927\u5c3a\u5bf8\u4e0b\u65e0\u5730\u56fe\u8d44\u6599
+
+# Field names
+fieldname.latitude=\u7eac\u5ea6
+fieldname.longitude=\u7ecf\u5ea6
+fieldname.altitude=\u9ad8\u5ea6
+fieldname.timestamp=\u65f6\u95f4
+fieldname.time=\u65f6\u95f4
+fieldname.waypointname=\u540d\u79f0
+fieldname.waypointtype=\u7c7b\u578b
+fieldname.newsegment=\u6bb5
+fieldname.custom=\u7528\u6237
+fieldname.prefix=\u6570\u636e\u6bb5
+fieldname.distance=\u8ddd\u79bb
+fieldname.movingdistance=\u79fb\u52a8\u8ddd\u79bb
+fieldname.duration=\u65f6\u957f
+fieldname.speed=\u901f\u5ea6
+fieldname.verticalspeed=\u5782\u76f4\u901f\u5ea6
+
+# Measurement units
+units.original=\u539f\u59cb
+units.default=\u7f3a\u7701
+units.metres=\u7c73
+units.metres.short=\u7c73
+units.feet=\u82f1\u5c3a
+units.feet.short=\u82f1\u5c3a
+units.kilometres=\u5343\u7c73
+units.kilometres.short=\u5343\u7c73
+units.kmh=\u5343\u7c73/\u65f6
+units.miles=\u82f1\u91cc
+units.miles.short=\u82f1\u91cc
+units.mph=\u82f1\u91cc/\u65f6
+units.metrespersec=\u7c73/\u79d2
+units.feetpersec=\u82f1\u5c3a/\u79d2
+units.hours=\u5c0f\u65f6
+units.degminsec=\u5ea6-\u5206-\u79d2
+units.degmin=\u5ea6-\u5206
+units.deg=\u5ea6
+units.iso8601=ISO 8601
+
+# External urls
+url.googlemaps=ditu.google.cn
+
+# Cardinals for 3d plots
+cardinal.n=N
+cardinal.s=S
+cardinal.e=E
+cardinal.w=W
+
+# Undo operations
+undo.load=\u5bfc\u5165\u6570\u636e
+undo.loadphotos=\u5bfc\u5165\u76f8\u7247
+undo.editpoint=\u7f16\u8f91\u8f68\u8ff9\u70b9
+undo.deletepoint=\u5220\u9664\u8f68\u8ff9\u70b9
+undo.deletephoto=\u5220\u9664\u76f8\u7247
+undo.deleterange=\u5220\u9664\u6bb5
+undo.compress=\u538b\u7f29\u8f68\u8ff9
+undo.insert=\u63d2\u5165\u822a\u70b9
+undo.reverse=\u53cd\u5411\u6bb5
+undo.mergetracksegments=\u5408\u5e76\u6bb5
+undo.addtimeoffset=\u6dfb\u52a0\u65f6\u95f4\u504f\u79fb
+undo.addaltitudeoffset=\u52a0\u5165\u9ad8\u5ea6\u504f\u79fb
+undo.rearrangewaypoints=\u91cd\u65b0\u914d\u7f6e\u822a\u70b9
+undo.cutandmove=\u79fb\u52a8\u6bb5
+undo.connectphoto=\u94fe\u63a5\u76f8\u7247
+undo.disconnectphoto=\u65ad\u5f00\u94fe\u63a5
+undo.correlate=\u94fe\u63a5\u76f8\u7247
+undo.createpoint=\u521b\u5efa\u8f68\u8ff9\u70b9
+
+# Error messages
+error.save.dialogtitle=\u4fdd\u5b58\u6570\u636e\u9519\u8bef
+error.save.nodata=\u65e0\u6570\u636e\u4fdd\u5b58
+error.save.failed=\u5411\u6587\u4ef6\u4fdd\u5b58\u6570\u636e\u5931\u8d25
+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.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.load.unknownxml=XML\u683c\u5f0f\u9519\u8bef
+error.load.noxmlinzip=Zip\u6587\u4ef6\u4e2d\u65e0\u6cd5\u627e\u5230XML
+error.load.othererror=\u8bfb\u6587\u4ef6\u9519\u8bef
+error.jpegload.dialogtitle=\u5bfc\u5165\u76f8\u7247\u9519\u8bef
+error.jpegload.nofilesfound=\u627e\u4e0d\u5230\u6587\u4ef6
+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.undofailed.title=\u64a4\u9500\u5931\u8d25
+error.undofailed.text=\u64a4\u9500\u64cd\u4f5c\u5931\u8d25
+error.function.noop.title=\u529f\u80fd\u65e0\u6548
+error.rearrange.noop=\u91cd\u65b0\u914d\u7f6e\u822a\u70b9\u65e0\u6548
+error.function.notavailable.title=\u65e0\u6b64\u529f\u80fd
+error.function.nojava3d=\u6b64\u529f\u80fd\u9700\u8981 Java 3D\n\u53ef\u4eceSun.com\u83b7\u5f97
+error.3d=3D \u663e\u793a\u65f6\u51fa\u73b0\u4e00\u4e2a\u9519\u8bef
+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
*/
public class FileCacher
{
+ /** File to cache */
private File _file = null;
+ /** Array to hold lines of file */
private String[] _contentArray = null;
package tim.prune.load;
import java.io.File;
-
+import java.util.ArrayList;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
private JFileChooser _fileChooser = null;
private JFrame _parentFrame;
private TextFileLoader _textFileLoader = null;
+ private NmeaFileLoader _nmeaFileLoader = null;
private XmlFileLoader _xmlFileLoader = null;
private ZipFileLoader _zipFileLoader = null;
_app = inApp;
_parentFrame = inParentFrame;
_textFileLoader = new TextFileLoader(inApp, inParentFrame);
+ _nmeaFileLoader = new NmeaFileLoader(inApp);
_xmlFileLoader = new XmlFileLoader(inApp);
_zipFileLoader = new ZipFileLoader(inApp, _xmlFileLoader);
}
_fileChooser.addChoosableFileFilter(new GenericFileFilter("filetype.kmz", new String[] {"kmz"}));
_fileChooser.setAcceptAllFileFilterUsed(true);
// start from directory in config if already set (by load jpegs)
- File configDir = Config.getWorkingDirectory();
- if (configDir != null) {_fileChooser.setCurrentDirectory(configDir);}
+ String configDir = Config.getConfigString(Config.KEY_TRACK_DIR);
+ if (configDir == null) {configDir = Config.getConfigString(Config.KEY_PHOTO_DIR);}
+ if (configDir != null) {_fileChooser.setCurrentDirectory(new File(configDir));}
+ _fileChooser.setMultiSelectionEnabled(true); // Allow multiple selections
}
// Show the open dialog
if (_fileChooser.showOpenDialog(_parentFrame) == JFileChooser.APPROVE_OPTION)
{
- File file = _fileChooser.getSelectedFile();
- // Check file exists and is readable
- if (file != null && file.exists() && file.canRead())
+ File[] files = _fileChooser.getSelectedFiles();
+ // Loop through files looking for files which exist and are readable
+ ArrayList<File> dataFiles = new ArrayList<File>();
+ if (files != null)
{
- // Store directory in config for later
- Config.setWorkingDirectory(file.getParentFile());
- // Check file type to see if it's xml or just normal text
- String fileExtension = file.getName().toLowerCase();
- if (fileExtension.length() > 4)
- {fileExtension = fileExtension.substring(fileExtension.length() - 4);}
- if (fileExtension.equals(".kml") || fileExtension.equals(".gpx")
- || fileExtension.equals(".xml"))
- {
- // Use xml loader for kml, gpx and xml filenames
- _xmlFileLoader.openFile(file);
- }
- else if (fileExtension.equals(".kmz") || fileExtension.equals(".zip"))
- {
- // Use zip loader for zipped kml (or zipped gpx)
- _zipFileLoader.openFile(file);
- }
- else
+ for (int i=0; i<files.length; i++)
{
- // Use text loader for everything else
- _textFileLoader.openFile(file);
+ File file = files[i];
+ if (file.exists() && file.isFile() && file.canRead())
+ {
+ dataFiles.add(file);
+ }
}
}
+ if (dataFiles.size() > 0) {
+ _app.loadDataFiles(dataFiles);
+ }
else
{
- // couldn't read file - show error message
+ // couldn't find any files to load - show error message
_app.showErrorMessage("error.load.dialogtitle", "error.load.noread");
}
}
}
+ /**
+ * Open the selected input file
+ * @param inFile file to open
+ */
+ public void openFile(File inFile)
+ {
+ // Store directory in config for later
+ File parent = inFile.getParentFile();
+ if (parent != null) {
+ Config.setConfigString(Config.KEY_TRACK_DIR, parent.getAbsolutePath());
+ }
+ // Check file type to see if it's xml or just normal text
+ String fileExtension = inFile.getName().toLowerCase();
+ if (fileExtension.length() > 4)
+ {fileExtension = fileExtension.substring(fileExtension.length() - 4);}
+ if (fileExtension.equals(".kml") || fileExtension.equals(".gpx")
+ || fileExtension.equals(".xml"))
+ {
+ // Use xml loader for kml, gpx and xml filenames
+ _xmlFileLoader.openFile(inFile);
+ }
+ else if (fileExtension.equals(".kmz") || fileExtension.equals(".zip"))
+ {
+ // Use zip loader for zipped kml (or zipped gpx)
+ _zipFileLoader.openFile(inFile);
+ }
+ else if (fileExtension.equals("nmea"))
+ {
+ _nmeaFileLoader.openFile(inFile);
+ }
+ else
+ {
+ // Use text loader for everything else
+ _textFileLoader.openFile(inFile);
+ }
+ }
+
/**
* @return the last delimiter character used for a text file load
*/
if (_cacher == null) return null;
String[] contents = _cacher.getContents();
if (contents == null || contents.length == 0) return null;
- String delimStr = "" + inDelim;
+ String delimStr = checkDelimiter(inDelim);
// Count non-blank rows and max field count
_numRows = 0;
int maxFields = 0;
result[i] = new String[maxFields];
if (contents[i] != null)
{
- String wholeLine = contents[i].trim();
- if (!wholeLine.equals(""))
+ String wholeLine = contents[i];
+ if (!wholeLine.trim().equals(""))
{
+ // Don't use trimmed string here because you'll lose empty fields at beginning
+ // if separated by spaces or tabs
String[] splitLine = wholeLine.split(delimStr);
if (splitLine != null)
{
// Should probably trap out of range values
return !_columnStates[inColumnNum];
}
+
+ /**
+ * Check the delimiter for proper regular expression matching
+ * @param inDelim character selected as delimiter
+ * @return regular expression for splitting
+ */
+ private static String checkDelimiter(char inDelim)
+ {
+ String result = "" + inDelim;
+ // Don't pass asterisks or dots without escaping them for RE
+ if (inDelim == '*' || inDelim == '.') {
+ result = "\\" + result;
+ }
+ return result;
+ }
}
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public void begin()
{
// Check if gpsbabel looks like it's installed
- if (_gpsBabelChecked || ExternalTools.isGpsbabelInstalled()
+ if (_gpsBabelChecked || ExternalTools.isToolInstalled(ExternalTools.TOOL_GPSBABEL)
|| JOptionPane.showConfirmDialog(_dialog,
I18nManager.getText("dialog.gpsload.nogpsbabel"),
I18nManager.getText(getNameKey()),
JLabel deviceLabel = new JLabel(I18nManager.getText("dialog.gpsload.device"));
deviceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
gridPanel.add(deviceLabel);
- _deviceField = new JTextField(Config.getGpsDevice(), 12);
+ _deviceField = new JTextField(Config.getConfigString(Config.KEY_GPS_DEVICE), 12);
+ _deviceField.addKeyListener(new KeyAdapter() {
+ public void keyReleased(KeyEvent e)
+ {
+ // close dialog if escape pressed
+ if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+ _dialog.dispose();
+ }
+ }
+ });
gridPanel.add(_deviceField);
JLabel formatLabel = new JLabel(I18nManager.getText("dialog.gpsload.format"));
formatLabel.setHorizontalAlignment(SwingConstants.RIGHT);
gridPanel.add(formatLabel);
- _formatField = new JTextField(Config.getGpsFormat(), 12);
+ _formatField = new JTextField(Config.getConfigString(Config.KEY_GPS_FORMAT), 12);
gridPanel.add(_formatField);
gridPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
gridPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 20));
{
// Set up command to call gpsbabel
String[] commands = null;
+ final String device = _deviceField.getText().trim();
+ final String format = _formatField.getText().trim();
+ final String command = Config.getConfigString(Config.KEY_GPSBABEL_PATH);
if (inWaypoints && inTracks) {
// Both waypoints and track points selected
- commands = new String[] {"gpsbabel", "-w", "-t", "-i", _formatField.getText(),
- "-f", _deviceField.getText(), "-o", "gpx", "-F", "-"};
+ commands = new String[] {command, "-w", "-t", "-i", format,
+ "-f", device, "-o", "gpx", "-F", "-"};
}
else
{
// Only waypoints OR track points selected
- commands = new String[] {"gpsbabel", "-w", "-i", _formatField.getText(),
- "-f", _deviceField.getText(), "-o", "gpx", "-F", "-"};
+ commands = new String[] {command, "-w", "-i", format,
+ "-f", device, "-o", "gpx", "-F", "-"};
if (inTracks) {
commands[1] = "-t";
}
}
+ // Save GPS settings in config
+ Config.setConfigString(Config.KEY_GPS_DEVICE, device);
+ Config.setConfigString(Config.KEY_GPS_FORMAT, format);
String errorMessage = "";
XmlHandler handler = null;
panel.add(_outsideAreaCheckbox);
_fileChooser.setAccessory(panel);
// start from directory in config if already set by other operations
- File configDir = Config.getWorkingDirectory();
- if (configDir != null) {_fileChooser.setCurrentDirectory(configDir);}
+ String configDir = Config.getConfigString(Config.KEY_PHOTO_DIR);
+ if (configDir == null) {configDir = Config.getConfigString(Config.KEY_TRACK_DIR);}
+ if (configDir != null) {_fileChooser.setCurrentDirectory(new File(configDir));}
}
// enable/disable track checkbox
_trackRectangle = inRectangle;
{
// Store first directory in config for later
if (i == 0 && inFirstDir) {
- Config.setWorkingDirectory(file.isDirectory()?file:file.getParentFile());
+ File workingDir = file.isDirectory()?file:file.getParentFile();
+ Config.setConfigString(Config.KEY_PHOTO_DIR, workingDir.getAbsolutePath());
}
// Check whether it's a file or a directory
if (file.isFile())
--- /dev/null
+package tim.prune.load;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import tim.prune.App;
+import tim.prune.data.Altitude;
+import tim.prune.data.Field;
+
+/**
+ * Class to handle the loading of Nmea files
+ */
+public class NmeaFileLoader
+{
+ /** App for callback of file loading */
+ private App _app = null;
+
+ /**
+ * Constructor
+ * @param inApp App object
+ */
+ public NmeaFileLoader(App inApp)
+ {
+ _app = inApp;
+ }
+
+ /**
+ * Open the selected file
+ * @param inFile File to open
+ */
+ public void openFile(File inFile)
+ {
+ BufferedReader reader = null;
+ ArrayList<NmeaMessage> messages = new ArrayList<NmeaMessage>();
+ try
+ {
+ reader = new BufferedReader(new FileReader(inFile));
+ String currLine = reader.readLine();
+ boolean newSegment = true;
+ while (currLine != null)
+ {
+ // Try to make an NmeaMessage object for each line of file
+ if (currLine.trim().length() > 0)
+ {
+ NmeaMessage message = processLine(currLine);
+ if (message != null)
+ {
+ if (message.hasFix()) {
+ message.setSegment(newSegment);
+ // add message to list
+ messages.add(message);
+ }
+ // Start a new segment if fix lost
+ newSegment = !message.hasFix();
+ }
+ }
+ // Read next line, if any
+ currLine = reader.readLine();
+ }
+ }
+ catch (IOException ioe) {
+ _app.showErrorMessage("error.load.dialogtitle", "error.load.noread");
+ }
+ finally
+ {
+ // close file ignoring errors
+ try
+ {
+ if (reader != null) reader.close();
+ }
+ catch (Exception e) {}
+ }
+ if (messages.size() > 0)
+ {
+ _app.informDataLoaded(getFieldArray(), makeDataArray(messages),
+ Altitude.Format.METRES, inFile.getName());
+ }
+ }
+
+ /**
+ * Process the given NMEA line and return the message
+ * @param inLine line to process
+ * @return message object
+ */
+ private static NmeaMessage processLine(String inLine)
+ {
+ // Only consider lines which are long enough and begin with the GPS position sentence
+ if (inLine == null || inLine.length() < 20 || !inLine.startsWith("$GPGGA")) {
+ return null;
+ }
+ // TODO: May be possible to pull date out of GPRMC messages, but then need to back-populate
+ // Assume comma delimiter, split into array
+ String[] splitLine = inLine.split(",");
+ if (splitLine != null && splitLine.length >= 10)
+ {
+ return new NmeaMessage(splitLine[2] + splitLine[3], // latitude
+ splitLine[4] + splitLine[5], // longitude
+ splitLine[9], // altitude
+ splitLine[1], // timestamp
+ splitLine[6]); // fix
+ }
+ // Couldn't parse it, return null
+ return null;
+ }
+
+ /**
+ * Make an object array from the data list
+ * @param inList list of messages
+ * @return object array for loading
+ */
+ private static Object[][] makeDataArray(ArrayList<NmeaMessage> inList)
+ {
+ Object[][] result = new Object[inList.size()][];
+ for (int i=0; i<inList.size(); i++) {
+ result[i] = inList.get(i).getStrings();
+ }
+ return result;
+ }
+
+ /**
+ * @see tim.prune.load.xml.XmlHandler#getFieldArray()
+ */
+ public Field[] getFieldArray()
+ {
+ final Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.ALTITUDE,
+ Field.TIMESTAMP, Field.NEW_SEGMENT};
+ return fields;
+ }
+}
--- /dev/null
+package tim.prune.load;
+
+import java.util.Calendar;
+
+/**
+ * Class to hold a single NMEA message
+ */
+public class NmeaMessage
+{
+ private String _latitude = null;
+ private String _longitude = null;
+ private String _altitude = null;
+ private String _timestamp = null;
+ private boolean _fix = false;
+ private boolean _segment = false;
+
+ /**
+ * Constructor
+ * @param inLatitude latitude
+ * @param inLongitude longitude
+ * @param inAltitude altitude
+ * @param inTimestamp timestamp
+ * @param inFix fix = 0, 1 or 2
+ */
+ public NmeaMessage(String inLatitude, String inLongitude,
+ String inAltitude, String inTimestamp, String inFix)
+ {
+ _latitude = inLatitude;
+ _longitude = inLongitude;
+ _altitude = inAltitude;
+ _timestamp = inTimestamp;
+ _fix = (inFix != null && !inFix.equals("0"));
+ }
+
+ /**
+ * @return true if message has a fix
+ */
+ public boolean hasFix() {
+ return _fix;
+ }
+
+ /**
+ * @param inSegment segment flag
+ */
+ public void setSegment(boolean inSegment)
+ {
+ _segment = inSegment;
+ }
+
+ /**
+ * @return String array for loading
+ */
+ public String[] getStrings()
+ {
+ String[] results = new String[] {modify(_latitude), modify(_longitude), _altitude,
+ getTimestamp(), (_segment?"1":"")};
+ return results;
+ }
+
+ /**
+ * Insert a separator between degrees and minutes
+ * @param inCoordinate NMEA coordinate string
+ * @return modified string or input string if format wasn't what was expected
+ */
+ private static String modify(String inCoordinate)
+ {
+ if (inCoordinate != null && inCoordinate.length() > 6)
+ {
+ int dotPos = inCoordinate.indexOf('.');
+ if (dotPos > 0) {
+ return inCoordinate.substring(0, dotPos-2) + "d" + inCoordinate.substring(dotPos-2);
+ }
+ }
+ return inCoordinate;
+ }
+
+ /**
+ * Use time from NMEA message, and today's date (as date isn't given in GPGGA messages)
+ * @return Timestamp in parseable format
+ */
+ private String getTimestamp()
+ {
+ try
+ {
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(_timestamp.substring(0, 2)));
+ cal.set(Calendar.MINUTE, Integer.parseInt(_timestamp.substring(2, 4)));
+ cal.set(Calendar.SECOND, Integer.parseInt(_timestamp.substring(4, 6)));
+ cal.set(Calendar.MILLISECOND, 0);
+ // Return time as number of milliseconds
+ return "" + cal.getTimeInMillis();
+ }
+ catch (Exception e) {} // ignore parsing errors, just have no timestamp
+ return null;
+ }
+}
else {
// Didn't pass pre-check
_app.showErrorMessage("error.load.dialogtitle", "error.load.noread");
+ _app.informNoDataLoaded();
}
}
public void actionPerformed(ActionEvent e)
{
_dialog.dispose();
+ _app.informNoDataLoaded();
}
});
buttonPanel.add(cancelButton);
private boolean _insideName = false;
private boolean _insideElevation = false;
private boolean _insideTime = false;
+// private boolean _insideType = false;
private boolean _startSegment = true;
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[]>();
+ // FIXME: Read waypoint type too
/**
* Receive the start of a tag
{
_insideTime = true;
}
+// else if (qName.equalsIgnoreCase("type"))
+// {
+// _insideType = true;
+// }
else if (qName.equalsIgnoreCase("trkseg"))
{
_startSegment = true;
private void processPlacemark()
{
if (_coordinates == null) return;
- String allCoords = _coordinates.toString();
+ String allCoords = _coordinates.toString().trim();
String[] coordArray = allCoords.split("[ \n]");
int numPoints = coordArray.length;
if (numPoints == 1)
if (coordArray[p] != null && coordArray[p].trim().length()>3)
{
String[] pointArray = makeStringArray(coordArray[p], null);
- if (firstPoint) {pointArray[4] = "1";}
+ if (firstPoint) {pointArray[4] = "1";} // start of segment flag
firstPoint = false;
_pointList.add(pointArray);
}
package tim.prune.load.xml;
import java.io.File;
+import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
}
/**
- * Open the selected file and show the GUI dialog to select load options
+ * Open the selected file and select appropriate xml loader
* @param inFile File to open
*/
public void openFile(File inFile)
}
}
catch (Exception e) {
- System.err.println("Error: " + e.getMessage());
+ System.err.println("Error: " + e.getClass().getName() + " -message= " + e.getMessage());
}
}
+ /**
+ * Use the given stream to access a remote zip file
+ * @param inStream stream to use to access file
+ */
+ public void openStream(InputStream inStream)
+ {
+ try
+ {
+ ZipInputStream zis = new ZipInputStream(inStream);
+ boolean xmlFound = false;
+ while (!xmlFound && 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(".kml") || suffix.equals(".gpx") || suffix.equals(".xml"))
+ {
+ _xmlLoader.reset();
+ SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
+ saxParser.parse(zis, _xmlLoader);
+ XmlHandler handler = _xmlLoader.getHandler();
+ if (handler == null) {
+ _app.showErrorMessage("error.load.dialogtitle", "error.load.othererror");
+ }
+ else {
+ // Send back to app
+ _app.informDataLoaded(handler.getFieldArray(), handler.getDataArray(),
+ Altitude.Format.METRES, "gpsies");
+ xmlFound = true;
+ }
+ }
+ }
+ }
+ // Check whether there was an xml file inside
+ if (!xmlFound) {
+ _app.showErrorMessage("error.load.dialogtitle", "error.load.noxmlinzip");
+ }
+ }
+ catch (Exception e) {
+ System.err.println("Error: " + e.getClass().getName() + " -message= " + e.getMessage());
+ }
+ }
}
-Prune version 7
+Prune version 8
===============
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_07.jar
+ java -jar prune_08.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_07.jar --lang=DE
+ java -jar prune_08.jar --lang=DE
+New with version 8
+==================
+
+The following features were added since version 7:
+ - Loading of NMEA files (with suffix .nmea)
+ - Loading of nearby tracks from gpsies.com
+ - Function for finding waypoints by name
+ - Language-sensitive keyboard shortcuts
+ - Scale bar
+ - Display of pace (time per km or time per mile)
+ - Ability to display and save configuration settings
+ - Configurable program paths and KMZ image sizes
+ - Chinese language thanks to generous user input
New with version 7
==================
import javax.swing.JScrollPane;
import javax.swing.JTable;
+import tim.prune.Config;
import tim.prune.ExternalTools;
import tim.prune.I18nManager;
import tim.prune.UpdateMessageBroker;
public boolean saveExifInformation(PhotoList inPhotoList)
{
// Check if external exif tool can be called
- boolean exifToolInstalled = ExternalTools.isExiftoolInstalled();
+ boolean exifToolInstalled = ExternalTools.isToolInstalled(ExternalTools.TOOL_EXIFTOOL);
if (!exifToolInstalled)
{
// show warning
{
// Make a string array to construct the command and its parameters
String[] result = new String[inOverwrite?5:4];
- result[0] = "exiftool";
+ result[0] = Config.getConfigString(Config.KEY_EXIFTOOL_PATH);
result[1] = "-P";
if (inOverwrite) {result[2] = " -overwrite_original_in_place";}
// remove all gps tags
{
// Make a string array to construct the command and its parameters
String[] result = new String[inOverwrite?10:9];
- result[0] = "exiftool";
+ result[0] = Config.getConfigString(Config.KEY_EXIFTOOL_PATH);
result[1] = "-P";
if (inOverwrite) {result[2] = "-overwrite_original_in_place";}
int paramOffset = inOverwrite?3:2;
private JRadioButton[] _delimiterRadios = null;
private JTextField _otherDelimiterText = null;
private JCheckBox _headerRowCheckbox = null;
+ private PointTypeSelector _pointTypeSelector = null;
private JRadioButton[] _coordUnitsRadios = null;
private JRadioButton[] _altitudeUnitsRadios = null;
private JRadioButton[] _timestampUnitsRadios = null;
+
private static final int[] FORMAT_COORDS = {Coordinate.FORMAT_NONE, Coordinate.FORMAT_DEG_MIN_SEC,
Coordinate.FORMAT_DEG_MIN, Coordinate.FORMAT_DEG};
private static final Altitude.Format[] FORMAT_ALTS = {Altitude.Format.NO_FORMAT, Altitude.Format.METRES, Altitude.Format.FEET};
firstCard.add(Box.createRigidArea(new Dimension(0,10)));
_headerRowCheckbox = new JCheckBox(I18nManager.getText("dialog.save.headerrow"), true);
firstCard.add(_headerRowCheckbox);
-
_cards.add(firstCard, "card1");
+ // Second card
JPanel secondCard = new JPanel();
secondCard.setLayout(new BorderLayout());
JPanel secondCardHolder = new JPanel();
secondCardHolder.setLayout(new BoxLayout(secondCardHolder, BoxLayout.Y_AXIS));
+ // point type selector
+ secondCardHolder.add(Box.createRigidArea(new Dimension(0,10)));
+ _pointTypeSelector = new PointTypeSelector();
+ _pointTypeSelector.setAlignmentX(JLabel.LEFT_ALIGNMENT);
+ secondCardHolder.add(_pointTypeSelector);
JLabel coordLabel = new JLabel(I18nManager.getText("dialog.save.coordinateunits"));
coordLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
secondCardHolder.add(coordLabel);
}
coordsUnitsPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
secondCardHolder.add(coordsUnitsPanel);
- secondCardHolder.add(Box.createRigidArea(new Dimension(0,10)));
+ secondCardHolder.add(Box.createRigidArea(new Dimension(0,7)));
// altitude units
JLabel altUnitsLabel = new JLabel(I18nManager.getText("dialog.save.altitudeunits"));
altUnitsLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
}
altUnitsPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT);
secondCardHolder.add(altUnitsPanel);
- secondCardHolder.add(Box.createRigidArea(new Dimension(0,10)));
+ secondCardHolder.add(Box.createRigidArea(new Dimension(0,7)));
// Selection of format of timestamps
JLabel timestampLabel = new JLabel(I18nManager.getText("dialog.save.timestampformat"));
timestampLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT);
default : _delimiterRadios[4].setSelected(true);
_otherDelimiterText.setText("" + inDefaultDelimiter);
}
+ _pointTypeSelector.init(_app.getTrackInfo());
// set card and enable buttons
CardLayout cl = (CardLayout) _cards.getLayout();
cl.first(_cards);
*/
private boolean saveToFile()
{
+ // TODO: Shorten method
+ if (!_pointTypeSelector.getAnythingSelected()) {return false;}
boolean saveOK = true;
FileWriter writer = null;
if (_fileChooser == null)
_fileChooser.addChoosableFileFilter(new GenericFileFilter("filetype.kml", new String[] {"kml"}));
_fileChooser.setAcceptAllFileFilterUsed(true);
// start from directory in config which should be set
- File configDir = Config.getWorkingDirectory();
- if (configDir != null) {_fileChooser.setCurrentDirectory(configDir);}
+ String configDir = Config.getConfigString(Config.KEY_TRACK_DIR);
+ if (configDir == null) {configDir = Config.getConfigString(Config.KEY_PHOTO_DIR);}
+ if (configDir != null) {_fileChooser.setCurrentDirectory(new File(configDir));}
}
if (_fileChooser.showSaveDialog(_parentFrame) == JFileChooser.APPROVE_OPTION)
{
}
// Loop over points outputting each in turn to buffer
- int numPoints = _track.getNumPoints();
+ final int numPoints = _track.getNumPoints();
+ int numSaved = 0;
for (int p=0; p<numPoints; p++)
{
DataPoint point = _track.getPoint(p);
+ boolean savePoint = ((point.isWaypoint() && _pointTypeSelector.getWaypointsSelected())
+ || (!point.isWaypoint() && point.getPhoto()==null && _pointTypeSelector.getTrackpointsSelected())
+ || (!point.isWaypoint() && point.getPhoto()!=null && _pointTypeSelector.getPhotopointsSelected()));
+ if (!savePoint) {continue;}
+ numSaved++;
firstField = true;
buffer = new StringBuffer();
for (int f=0; f<numFields; f++)
writer.write(lineSeparator);
}
// Store directory in config for later
- Config.setWorkingDirectory(saveFile.getParentFile());
+ Config.setConfigString(Config.KEY_TRACK_DIR, saveFile.getParentFile().getAbsolutePath());
// Save successful
UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.save.ok1")
- + " " + numPoints + " " + I18nManager.getText("confirm.save.ok2")
+ + " " + numSaved + " " + I18nManager.getText("confirm.save.ok2")
+ " " + saveFile.getAbsolutePath());
_app.informDataSaved();
}
finally
{
// try to close file if it's open
- try
- {
- if (writer != null)
- {
+ try {
+ if (writer != null) {
writer.close();
}
}
public void begin()
{
// Check if gpsbabel looks like it's installed
- if (_gpsBabelChecked || ExternalTools.isGpsbabelInstalled()
+ if (_gpsBabelChecked || ExternalTools.isToolInstalled(ExternalTools.TOOL_GPSBABEL)
|| JOptionPane.showConfirmDialog(_dialog,
I18nManager.getText("dialog.gpsload.nogpsbabel"),
I18nManager.getText(getNameKey()),
JLabel deviceLabel = new JLabel(I18nManager.getText("dialog.gpsload.device"));
deviceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
gridPanel.add(deviceLabel);
- _deviceField = new JTextField(Config.getGpsDevice(), 12);
+ _deviceField = new JTextField(Config.getConfigString(Config.KEY_GPS_DEVICE), 12);
gridPanel.add(_deviceField);
JLabel formatLabel = new JLabel(I18nManager.getText("dialog.gpsload.format"));
formatLabel.setHorizontalAlignment(SwingConstants.RIGHT);
gridPanel.add(formatLabel);
- _formatField = new JTextField(Config.getGpsFormat(), 12);
+ _formatField = new JTextField(Config.getConfigString(Config.KEY_GPS_FORMAT), 12);
gridPanel.add(_formatField);
JLabel nameLabel = new JLabel(I18nManager.getText("dialog.gpssend.trackname"));
nameLabel.setHorizontalAlignment(SwingConstants.RIGHT);
private void callGpsBabel() throws Exception
{
// Set up command to call gpsbabel
+ final String command = Config.getConfigString(Config.KEY_GPSBABEL_PATH);
String[] commands = null;
+ final String device = _deviceField.getText().trim();
+ final String format = _formatField.getText().trim();
if (_waypointCheckbox.isSelected() && _trackCheckbox.isSelected()) {
// Both waypoints and track points selected
- commands = new String[] {"gpsbabel", "-w", "-t", "-i", "gpx", "-f", "-", "-o", _formatField.getText(),
- "-F", _deviceField.getText()};
+ commands = new String[] {command, "-w", "-t", "-i", "gpx", "-f", "-", "-o", format,
+ "-F", device};
}
else
{
// Only waypoints OR trackpoints selected
- commands = new String[] {"gpsbabel", "-w", "-i", "gpx", "-f", "-", "-o", _formatField.getText(),
- "-F", _deviceField.getText()};
+ commands = new String[] {command, "-w", "-i", "gpx", "-f", "-", "-o", format,
+ "-F", device};
if (_trackCheckbox.isSelected()) {
commands[1] = "-t";
}
}
+ // Save GPS settings in config
+ Config.setConfigString(Config.KEY_GPS_DEVICE, device);
+ Config.setConfigString(Config.KEY_GPS_FORMAT, format);
String errorMessage = "";
Process process = Runtime.getRuntime().exec(commands);
if (trackName == null || trackName.equals("")) {trackName = "prune";}
// Generate the GPX file and send to the GPS
OutputStreamWriter writer = new OutputStreamWriter(process.getOutputStream());
- GpxExporter.exportData(writer, _app.getTrackInfo().getTrack(), trackName, null, true);
+ boolean[] saveFlags = {true, true, true, true}; // export everything
+ GpxExporter.exportData(writer, _app.getTrackInfo().getTrack(), trackName, null, saveFlags);
writer.close();
// Read the error stream to see if there's a better error message there
private JDialog _dialog = null;
private JTextField _nameField = null;
private JTextField _descriptionField = null;
+ private PointTypeSelector _pointTypeSelector = null;
private JCheckBox _timestampsCheckbox = null;
private JFileChooser _fileChooser = null;
private File _exportFile = null;
_dialog.getContentPane().add(makeDialogComponents());
_dialog.pack();
}
+ _pointTypeSelector.init(_app.getTrackInfo());
_dialog.setVisible(true);
}
_descriptionField = new JTextField(10);
descPanel.add(_descriptionField);
mainPanel.add(descPanel);
+ // point type selection (track points, waypoints, photo points)
+ _pointTypeSelector = new PointTypeSelector();
+ mainPanel.add(_pointTypeSelector);
// checkbox for timestamps
_timestampsCheckbox = new JCheckBox(I18nManager.getText("dialog.exportgpx.includetimestamps"));
_timestampsCheckbox.setSelected(true);
*/
private void startExport()
{
- // OK pressed, so choose output file
+ // OK pressed, so check selections
+ if (!_pointTypeSelector.getAnythingSelected()) {
+ return;
+ }
+ // Choose output file
if (_fileChooser == null)
{
_fileChooser = new JFileChooser();
_fileChooser.setFileFilter(new GenericFileFilter("filetype.gpx", new String[] {"gpx"}));
_fileChooser.setAcceptAllFileFilterUsed(false);
// start from directory in config which should be set
- File configDir = Config.getWorkingDirectory();
- if (configDir != null) {_fileChooser.setCurrentDirectory(configDir);}
+ 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;
{
// normal writing to file
writer = new OutputStreamWriter(new FileOutputStream(_exportFile));
+ boolean[] saveFlags = {_pointTypeSelector.getTrackpointsSelected(), _pointTypeSelector.getWaypointsSelected(),
+ _pointTypeSelector.getPhotopointsSelected(), _timestampsCheckbox.isSelected()};
// write file
- int numPoints = exportData(writer, _track, _nameField.getText(),
- _descriptionField.getText(), _timestampsCheckbox.isSelected());
+ final int numPoints = exportData(writer, _track, _nameField.getText(),
+ _descriptionField.getText(), saveFlags);
// close file
writer.close();
// Store directory in config for later
- Config.setWorkingDirectory(_exportFile.getParentFile());
+ Config.setConfigString(Config.KEY_TRACK_DIR, _exportFile.getParentFile().getAbsolutePath());
// Show confirmation
UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.save.ok1")
+ " " + numPoints + " " + I18nManager.getText("confirm.save.ok2")
* @param inTrack track object containing data
* @param inName name of track (optional)
* @param inDesc description of track (optional)
- * @param inTimestamps true to export timestamps
+ * @param inSaveFlags array of booleans to export tracks, waypoints, photos, timestamps
* @return number of points written
* @throws IOException if io errors occur on write
*/
public static int exportData(OutputStreamWriter inWriter, Track inTrack, String inName,
- String inDesc, boolean inTimestamps) throws IOException
+ String inDesc, boolean[] inSaveFlags) throws IOException
{
inWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gpx version=\"");
inWriter.write(GPX_VERSION_NUMBER);
int i = 0;
DataPoint point = null;
boolean hasTrackpoints = false;
+ final boolean exportTrackpoints = inSaveFlags[0];
+ final boolean exportWaypoints = inSaveFlags[1];
+ final boolean exportPhotos = inSaveFlags[2];
+ final boolean exportTimestamps = inSaveFlags[3];
// Loop over waypoints
- int numPoints = inTrack.getNumPoints();
+ final int numPoints = inTrack.getNumPoints();
+ int numSaved = 0;
for (i=0; i<numPoints; i++)
{
point = inTrack.getPoint(i);
// Make a wpt element for each waypoint
if (point.isWaypoint())
{
- exportWaypoint(point, inWriter, inTimestamps);
+ if (exportWaypoints) {
+ exportWaypoint(point, inWriter, exportTimestamps);
+ numSaved++;
+ }
}
else
{
if (point.getSegmentStart() && !firstPoint) {
inWriter.write("\t</trkseg>\n\t<trkseg>\n");
}
- if (!point.isWaypoint()) {
- // export the track point
- exportTrackpoint(point, inWriter, inTimestamps);
- firstPoint = false;
+ if (!point.isWaypoint())
+ {
+ if ((point.getPhoto()==null && exportTrackpoints) || (point.getPhoto()!=null && exportPhotos))
+ {
+ // export the point
+ exportTrackpoint(point, inWriter, exportTimestamps);
+ numSaved++;
+ firstPoint = false;
+ }
}
}
inWriter.write("\t</trkseg></trk>\n");
}
inWriter.write("</gpx>\n");
- return numPoints;
+ return numSaved;
}
-
/**
* Export the specified waypoint into the file
* @param inPoint waypoint to export
private Track _track = null;
private JDialog _dialog = null;
private JTextField _descriptionField = null;
+ private PointTypeSelector _pointTypeSelector = null;
private JCheckBox _altitudesCheckbox = null;
private JCheckBox _kmzCheckbox = null;
private JCheckBox _exportImagesCheckbox = null;
+ private JLabel _progressLabel = null;
private JProgressBar _progressBar = null;
private JFileChooser _fileChooser = null;
private File _exportFile = null;
+ private JButton _okButton = null;
+ private boolean _cancelPressed = false;
// Filename of Kml file within zip archive
private static final String KML_FILENAME_IN_KMZ = "doc.kml";
- // Width and height of thumbnail images in Kmz
- private static final int THUMBNAIL_WIDTH = 240;
- private static final int THUMBNAIL_HEIGHT = 180;
+ // Default width and height of thumbnail images in Kmz
+ private static final int DEFAULT_THUMBNAIL_WIDTH = 240;
+ private static final int DEFAULT_THUMBNAIL_HEIGHT = 180;
+ // Actual selected width and height of thumbnail images in Kmz
+ private static int THUMBNAIL_WIDTH = 0;
+ private static int THUMBNAIL_HEIGHT = 0;
/**
_dialog.pack();
}
enableCheckboxes();
+ _descriptionField.setEnabled(true);
+ _okButton.setEnabled(true);
+ _progressLabel.setText("");
_progressBar.setVisible(false);
_dialog.setVisible(true);
}
private Component makeDialogComponents()
{
JPanel dialogPanel = new JPanel();
- dialogPanel.setLayout(new BorderLayout());
+ dialogPanel.setLayout(new BorderLayout(0, 5));
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
// Make a central panel with the text box and checkboxes
descPanel.add(new JLabel(I18nManager.getText("dialog.exportkml.text")));
_descriptionField = new JTextField(20);
descPanel.add(_descriptionField);
+ descPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(descPanel);
dialogPanel.add(mainPanel, BorderLayout.CENTER);
+ // point type selection
+ _pointTypeSelector = new PointTypeSelector();
+ _pointTypeSelector.setAlignmentX(Component.CENTER_ALIGNMENT);
+ mainPanel.add(_pointTypeSelector);
// Checkbox for altitude export
_altitudesCheckbox = new JCheckBox(I18nManager.getText("dialog.exportkml.altitude"));
_altitudesCheckbox.setHorizontalTextPosition(SwingConstants.LEFT);
+ _altitudesCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(_altitudesCheckbox);
// Checkboxes for kmz export and image export
_kmzCheckbox = new JCheckBox(I18nManager.getText("dialog.exportkml.kmz"));
_kmzCheckbox.setHorizontalTextPosition(SwingConstants.LEFT);
+ _kmzCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
_kmzCheckbox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
mainPanel.add(_kmzCheckbox);
_exportImagesCheckbox = new JCheckBox(I18nManager.getText("dialog.exportkml.exportimages"));
_exportImagesCheckbox.setHorizontalTextPosition(SwingConstants.LEFT);
+ _exportImagesCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(_exportImagesCheckbox);
mainPanel.add(Box.createVerticalStrut(10));
+ _progressLabel = new JLabel("...");
+ _progressLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
+ mainPanel.add(_progressLabel);
_progressBar = new JProgressBar(0, 100);
_progressBar.setVisible(false);
+ _progressBar.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(_progressBar);
mainPanel.add(Box.createVerticalStrut(10));
// button panel at bottom
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
- JButton okButton = new JButton(I18nManager.getText("button.ok"));
+ _okButton = new JButton(I18nManager.getText("button.ok"));
ActionListener okListener = new ActionListener() {
public void actionPerformed(ActionEvent e)
{
startExport();
}
};
- okButton.addActionListener(okListener);
+ _okButton.addActionListener(okListener);
_descriptionField.addActionListener(okListener);
- buttonPanel.add(okButton);
+ buttonPanel.add(_okButton);
JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
+ _cancelPressed = true;
_dialog.dispose();
}
});
*/
private void enableCheckboxes()
{
+ _pointTypeSelector.init(_trackInfo);
boolean hasAltitudes = _track.hasData(Field.ALTITUDE);
if (!hasAltitudes) {_altitudesCheckbox.setSelected(false);}
boolean hasPhotos = _trackInfo.getPhotoList() != null && _trackInfo.getPhotoList().getNumPhotos() > 0;
*/
private void startExport()
{
- // OK pressed, so choose output file
+ // OK pressed, now validate selection checkboxes
+ if (!_pointTypeSelector.getAnythingSelected()) {
+ return;
+ }
+ // Choose output file
if (_fileChooser == null)
{
_fileChooser = new JFileChooser();
_fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
_fileChooser.setFileFilter(new GenericFileFilter("filetype.kmlkmz", new String[] {"kml", "kmz"}));
// start from directory in config which should be set
- File configDir = Config.getWorkingDirectory();
- if (configDir != null) {_fileChooser.setCurrentDirectory(configDir);}
+ String configDir = Config.getConfigString(Config.KEY_TRACK_DIR);
+ if (configDir != null) {_fileChooser.setCurrentDirectory(new File(configDir));}
}
String requiredExtension = null, otherExtension = null;
if (_kmzCheckbox.isSelected())
{
// New file or overwrite confirmed, so initiate export in separate thread
_exportFile = file;
+ _cancelPressed = false;
new Thread(this).start();
}
else
*/
public void run()
{
- // Initialise progress bar
+ // Disable ok button to stop second go
+ _okButton.setEnabled(false);
+ _descriptionField.setEnabled(false);
+ // Initialise progress indicators
+ _progressLabel.setText(I18nManager.getText("confirm.running"));
_progressBar.setVisible(true);
_progressBar.setValue(0);
boolean exportToKmz = _kmzCheckbox.isSelected();
boolean exportImages = exportToKmz && _exportImagesCheckbox.isSelected();
_progressBar.setMaximum(exportImages?getNumPhotosToExport():1);
+
+ // Determine photo thumbnail size from config
+ THUMBNAIL_WIDTH = Config.getConfigInt(Config.KEY_KMZ_IMAGE_WIDTH);
+ if (THUMBNAIL_WIDTH < DEFAULT_THUMBNAIL_WIDTH) {THUMBNAIL_WIDTH = DEFAULT_THUMBNAIL_WIDTH;}
+ THUMBNAIL_HEIGHT = Config.getConfigInt(Config.KEY_KMZ_IMAGE_HEIGHT);
+ if (THUMBNAIL_HEIGHT < DEFAULT_THUMBNAIL_HEIGHT) {THUMBNAIL_HEIGHT = DEFAULT_THUMBNAIL_HEIGHT;}
+
OutputStreamWriter writer = null;
ZipOutputStream zipOutputStream = null;
try
{
// kmz requested - need zip output stream
zipOutputStream = new ZipOutputStream(new FileOutputStream(_exportFile));
+ // Export images into zip file too if requested
+ if (exportImages)
+ {
+ // Create thumbnails of each photo in turn and add to zip as images/image<n>.jpg
+ // This is done first so that photo sizes are known for later
+ exportThumbnails(zipOutputStream);
+ }
writer = new OutputStreamWriter(zipOutputStream);
// Make an entry in the zip file for the kml file
ZipEntry kmlEntry = new ZipEntry(KML_FILENAME_IN_KMZ);
zipOutputStream.putNextEntry(kmlEntry);
}
// write file
- int numPoints = exportData(writer, exportImages);
+ final int numPoints = exportData(writer, exportImages);
// update progress bar
_progressBar.setValue(1);
writer.flush();
// Close off this entry in the zip file
zipOutputStream.closeEntry();
- // Export images into zip file too if requested
- if (exportImages)
- {
- // Create thumbnails of each photo in turn and add to zip as images/image<n>.jpg
- exportThumbnails(zipOutputStream);
- }
}
// close file
writer.close();
// Store directory in config for later
- Config.setWorkingDirectory(_exportFile.getParentFile());
+ Config.setConfigString(Config.KEY_TRACK_DIR, _exportFile.getParentFile().getAbsolutePath());
// show confirmation
UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.save.ok1")
+ " " + numPoints + " " + I18nManager.getText("confirm.save.ok2")
private int exportData(OutputStreamWriter inWriter, boolean inExportImages)
throws IOException
{
+ boolean writeTrack = _pointTypeSelector.getTrackpointsSelected();
+ boolean writeWaypoints = _pointTypeSelector.getWaypointsSelected();
+ boolean writePhotos = _pointTypeSelector.getPhotopointsSelected();
inWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://earth.google.com/kml/2.1\">\n<Folder>\n");
inWriter.write("\t<name>");
if (_descriptionField != null && _descriptionField.getText() != null && !_descriptionField.getText().equals(""))
}
inWriter.write("</name>\n");
- boolean exportAltitudes = _altitudesCheckbox.isSelected();
+ boolean absoluteAltitudes = _altitudesCheckbox.isSelected();
int i = 0;
DataPoint point = null;
boolean hasTrackpoints = false;
- // Loop over waypoints
+ // Loop over waypoints (if any)
boolean writtenPhotoHeader = false;
- int numPoints = _track.getNumPoints();
+ final int numPoints = _track.getNumPoints();
+ int numSaved = 0;
int photoNum = 0;
+ // Loop over waypoints
for (i=0; i<numPoints; i++)
{
point = _track.getPoint(i);
// Make a blob for each waypoint
if (point.isWaypoint())
{
- exportWaypoint(point, inWriter, exportAltitudes);
+ if (writeWaypoints) {
+ exportWaypoint(point, inWriter, absoluteAltitudes);
+ numSaved++;
+ }
}
else if (point.getPhoto() == null)
{
hasTrackpoints = true;
}
// Make a blob with description for each photo
- if (point.getPhoto() != null)
+ // Photos have already been written so picture sizes already known
+ if (point.getPhoto() != null && writePhotos)
{
if (!writtenPhotoHeader)
{
writtenPhotoHeader = true;
}
photoNum++;
- exportPhotoPoint(point, inWriter, inExportImages, photoNum, exportAltitudes);
+ exportPhotoPoint(point, inWriter, inExportImages, photoNum, absoluteAltitudes);
+ numSaved++;
}
}
// Make a line for the track, if there is one
- if (hasTrackpoints)
+ if (hasTrackpoints && writeTrack)
{
// Set up strings for start and end of track segment
String trackStart = "\t<Placemark>\n\t\t<name>track</name>\n\t\t<Style>\n\t\t\t<LineStyle>\n"
+ "\t\t\t\t<color>cc0000cc</color>\n\t\t\t\t<width>4</width>\n\t\t\t</LineStyle>\n"
+ "\t\t\t<PolyStyle><color>33cc0000</color></PolyStyle>\n"
+ "\t\t</Style>\n\t\t<LineString>\n";
- if (exportAltitudes) {
+ if (absoluteAltitudes) {
trackStart += "\t\t\t<extrude>1</extrude>\n\t\t\t<altitudeMode>absolute</altitudeMode>\n";
}
+ else {
+ trackStart += "\t\t\t<altitudeMode>clampToGround</altitudeMode>\n";
+ }
trackStart += "\t\t\t<coordinates>";
String trackEnd = "\t\t\t</coordinates>\n\t\t</LineString>\n\t</Placemark>";
}
if (!point.isWaypoint() && point.getPhoto() == null)
{
- exportTrackpoint(point, inWriter, exportAltitudes);
+ exportTrackpoint(point, inWriter);
+ numSaved++;
firstTrackpoint = false;
}
}
inWriter.write(trackEnd);
}
inWriter.write("</Folder>\n</kml>");
- return numPoints;
+ return numSaved;
}
* Export the specified waypoint into the file
* @param inPoint waypoint to export
* @param inWriter writer object
- * @param inExportAltitude true to include altitude
+ * @param inAbsoluteAltitude true for absolute altitude
* @throws IOException on write failure
*/
- private void exportWaypoint(DataPoint inPoint, Writer inWriter, boolean inExportAltitude) throws IOException
+ private void exportWaypoint(DataPoint inPoint, Writer inWriter, boolean inAbsoluteAltitude) throws IOException
{
inWriter.write("\t<Placemark>\n\t\t<name>");
inWriter.write(inPoint.getWaypointName().trim());
inWriter.write("</name>\n");
inWriter.write("\t\t<Point>\n");
- if (inExportAltitude && inPoint.hasAltitude()) {
+ if (inAbsoluteAltitude && inPoint.hasAltitude()) {
inWriter.write("\t\t\t<altitudeMode>absolute</altitudeMode>\n");
}
+ else {
+ inWriter.write("\t\t\t<altitudeMode>clampToGround</altitudeMode>\n");
+ }
inWriter.write("\t\t\t<coordinates>");
inWriter.write(inPoint.getLongitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
inWriter.write(',');
inWriter.write(inPoint.getLatitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
inWriter.write(",");
- if (inExportAltitude && inPoint.hasAltitude()) {
+ if (inPoint.hasAltitude()) {
inWriter.write("" + inPoint.getAltitude().getStringValue(Altitude.Format.METRES));
}
else {
* @param inWriter writer object
* @param inImageLink flag to set whether to export image links or not
* @param inImageNumber number of image for filename
- * @param inExportAltitude true to include altitude
+ * @param inAbsoluteAltitude true for absolute altitudes
* @throws IOException on write failure
*/
private void exportPhotoPoint(DataPoint inPoint, Writer inWriter, boolean inImageLink,
- int inImageNumber, boolean inExportAltitude)
+ int inImageNumber, boolean inAbsoluteAltitude)
throws IOException
{
inWriter.write("\t<Placemark>\n\t\t<name>");
}
inWriter.write("<styleUrl>#camera_icon</styleUrl>\n");
inWriter.write("\t\t<Point>\n");
- if (inExportAltitude && inPoint.hasAltitude()) {
+ if (inAbsoluteAltitude && inPoint.hasAltitude()) {
inWriter.write("\t\t\t<altitudeMode>absolute</altitudeMode>\n");
}
+ else {
+ inWriter.write("\t\t\t<altitudeMode>clampToGround</altitudeMode>\n");
+ }
inWriter.write("\t\t\t<coordinates>");
inWriter.write(inPoint.getLongitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
inWriter.write(',');
inWriter.write(inPoint.getLatitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
inWriter.write(",");
- if (inExportAltitude && inPoint.hasAltitude()) {
+ // Altitude if point has one
+ if (inPoint.hasAltitude()) {
inWriter.write("" + inPoint.getAltitude().getStringValue(Altitude.Format.METRES));
}
else {
* Export the specified trackpoint into the file
* @param inPoint trackpoint to export
* @param inWriter writer object
- * @param inExportAltitude true to include altitude
*/
- private void exportTrackpoint(DataPoint inPoint, Writer inWriter, boolean inExportAltitude) throws IOException
+ private void exportTrackpoint(DataPoint inPoint, Writer inWriter) throws IOException
{
inWriter.write(inPoint.getLongitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
inWriter.write(',');
inWriter.write(inPoint.getLatitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
- // Altitude either absolute or locked to ground by Google Earth
+ // Altitude if point has one
inWriter.write(",");
- if (inExportAltitude && inPoint.hasAltitude()) {
+ if (inPoint.hasAltitude()) {
inWriter.write("" + inPoint.getAltitude().getStringValue(Altitude.Format.METRES));
}
else {
DataPoint point = null;
int photoNum = 0;
// Loop over all points in track
- for (int i=0; i<numPoints; i++)
+ for (int i=0; i<numPoints && !_cancelPressed; i++)
{
point = _track.getPoint(i);
if (point.getPhoto() != null)
for (int i=0; i<numPoints; i++)
{
point = _track.getPoint(i);
- if (point.getPhoto() != null)
- {
+ if (point.getPhoto() != null) {
numPhotos++;
}
}
--- /dev/null
+package tim.prune.save;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+
+import javax.swing.BorderFactory;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.EtchedBorder;
+
+import tim.prune.I18nManager;
+import tim.prune.data.TrackInfo;
+
+/**
+ * GUI element to allow the selection of point types for saving,
+ * including three checkboxes for track points, waypoints, photo points
+ */
+public class PointTypeSelector extends JPanel
+{
+ /** Array of three checkboxes */
+ private JCheckBox[] _checkboxes = new JCheckBox[3];
+
+
+ /**
+ * Constructor
+ */
+ public PointTypeSelector()
+ {
+ createComponents();
+ setBorder(BorderFactory.createCompoundBorder(
+ BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(4, 4, 4, 4))
+ );
+ }
+
+ /**
+ * Create the GUI components
+ */
+ private void createComponents()
+ {
+ setLayout(new BorderLayout());
+ // Need JLabel to explain what it is
+ add(new JLabel(I18nManager.getText("dialog.pointtype.desc")), BorderLayout.NORTH);
+ // panel for the checkboxes
+ JPanel gridPanel = new JPanel();
+ gridPanel.setLayout(new GridLayout(1, 3, 15, 3));
+ final String[] keys = {"track", "waypoint", "photo"};
+ for (int i=0; i<3; i++)
+ {
+ _checkboxes[i] = new JCheckBox(I18nManager.getText("dialog.pointtype." + keys[i]));
+ _checkboxes[i].setEnabled(true);
+ _checkboxes[i].setSelected(true);
+ gridPanel.add(_checkboxes[i]);
+ }
+ add(gridPanel, BorderLayout.CENTER);
+ }
+
+ /**
+ * Initialize the checkboxes from the given data
+ * @param inTrackInfo TrackInfo object
+ */
+ public void init(TrackInfo inTrackInfo)
+ {
+ // Get whether track has track points, waypoints, photos
+ boolean[] flags = {inTrackInfo.getTrack().hasTrackPoints(),
+ inTrackInfo.getTrack().hasWaypoints(),
+ inTrackInfo.getPhotoList().getNumPhotos() > 0
+ };
+ // Enable or disable checkboxes according to data present
+ for (int i=0; i<3; i++)
+ {
+ if (flags[i]) {
+ _checkboxes[i].setEnabled(true);
+ }
+ else {
+ _checkboxes[i].setSelected(false);
+ _checkboxes[i].setEnabled(false);
+ }
+ }
+ }
+
+ /**
+ * @return true if trackpoints selected
+ */
+ public boolean getTrackpointsSelected()
+ {
+ return _checkboxes[0].isSelected();
+ }
+
+ /**
+ * @return true if waypoints selected
+ */
+ public boolean getWaypointsSelected()
+ {
+ return _checkboxes[1].isSelected();
+ }
+
+ /**
+ * @return true if photo points selected
+ */
+ public boolean getPhotopointsSelected()
+ {
+ return _checkboxes[2].isSelected();
+ }
+
+ /**
+ * @return true if at least one type selected
+ */
+ public boolean getAnythingSelected()
+ {
+ return getTrackpointsSelected() || getWaypointsSelected()
+ || getPhotopointsSelected();
+ }
+}
JLabel fontLabel = new JLabel(I18nManager.getText("dialog.exportpov.font"));
fontLabel.setHorizontalAlignment(SwingConstants.TRAILING);
centralPanel.add(fontLabel);
- String defaultFont = Config.getPovrayFont();
+ String defaultFont = Config.getConfigString(Config.KEY_POVRAY_FONT);
if (defaultFont == null || defaultFont.equals("")) {
defaultFont = DEFAULT_FONT_FILE;
}
_fileChooser.setFileFilter(new GenericFileFilter("filetype.pov", new String[] {"pov"}));
_fileChooser.setAcceptAllFileFilterUsed(false);
// start from directory in config which should be set
- File configDir = Config.getWorkingDirectory();
- if (configDir != null) {_fileChooser.setCurrentDirectory(configDir);}
+ 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
{
// file saved
// Store directory in config for later
- Config.setWorkingDirectory(file.getParentFile());
+ Config.setConfigString(Config.KEY_TRACK_DIR, file.getParentFile().getAbsolutePath());
}
else
{
}
catch (IOException ioe)
{
- JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.save.failed") + ioe.getMessage(),
+ JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.save.failed") + " : " + ioe.getMessage(),
I18nManager.getText("error.save.dialogtitle"), JOptionPane.ERROR_MESSAGE);
}
finally
{
fontPath = DEFAULT_FONT_FILE;
}
+ else {
+ Config.setConfigString(Config.KEY_POVRAY_FONT, fontPath);
+ }
// Set up output
String[] outputLines = {
"global_settings { ambient_light rgb <4, 4, 4> }", "",
" open",
" pigment { color rgb <0.5 0.5 0.5> }",
" }", "",
- // TODO: Export rods to POV? How to store in data?
+ // MAYBE: Export rods to POV? How to store in data?
"#declare waypoint_sphere =",
" sphere {",
" <0, 0, 0>, 0.4",
" pigment { color rgb <1 1 1> }",
" translate <-" + (inModelSize * 1.03) + ", 0.2, 0>",
"}", "",
- // TODO: Light positions should relate to model size
+ // MAYBE: Light positions should relate to model size
"// lights",
"light_source { <-1, 9, -4> color rgb <0.5 0.5 0.5>}",
"light_source { <1, 6, -14> color rgb <0.6 0.6 0.6>}",
private static Group createWaypoint(Point3d inPointPos)
{
Material mat = getWaypointMaterial();
- // TODO: sort symbol scaling
+ // MAYBE: sort symbol scaling
Sphere dot = new Sphere(0.35f); // * symbolScaling / 100f);
return createBall(inPointPos, dot, mat);
}
private static Group createTrackpoint(Point3d inPointPos, byte inHeightCode)
{
Material mat = getTrackpointMaterial(inHeightCode);
- // TODO: sort symbol scaling
+ // MAYBE: sort symbol scaling
Sphere dot = new Sphere(0.2f); // * symbolScaling / 100f);
return createBall(inPointPos, dot, mat);
}
private int _altitudeCap = -1;
private double _scaleFactor = 1.0;
private double _altFactor = 1.0;
- // TODO: How to store rods (lifts) in data?
+ // MAYBE: How to store rods (lifts) in data?
private byte[] _pointTypes = null;
private byte[] _pointHeights = null;
--- /dev/null
+package tim.prune.undo;
+
+import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
+import tim.prune.data.Altitude;
+import tim.prune.data.TrackInfo;
+
+/**
+ * Undo addition/subtraction of an altitude offset
+ */
+public class UndoAddAltitudeOffset implements UndoOperation
+{
+ /** Start index of section */
+ private int _startIndex;
+ /** altitude values before operation */
+ private Altitude[] _altitudes;
+
+
+ /**
+ * Constructor
+ * @param inTrackInfo track info object
+ */
+ public UndoAddAltitudeOffset(TrackInfo inTrackInfo)
+ {
+ _startIndex = inTrackInfo.getSelection().getStart();
+ final int endIndex = inTrackInfo.getSelection().getEnd();
+ final int numPoints = endIndex - _startIndex + 1;
+ // Make array of cloned altitude objects
+ _altitudes = new Altitude[numPoints];
+ for (int i=0; i<numPoints; i++) {
+ Altitude a = inTrackInfo.getTrack().getPoint(_startIndex+i).getAltitude();
+ if (a != null && a.isValid()) {
+ _altitudes[i] = a.clone();
+ }
+ }
+ }
+
+
+ /**
+ * @return description of operation including number of points adjusted
+ */
+ public String getDescription()
+ {
+ return I18nManager.getText("undo.addaltitudeoffset") + " (" + (_altitudes.length) + ")";
+ }
+
+
+ /**
+ * Perform the undo operation on the given Track
+ * @param inTrackInfo TrackInfo object on which to perform the operation
+ */
+ public void performUndo(TrackInfo inTrackInfo) throws UndoException
+ {
+ // 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]);
+ }
+ _altitudes = null;
+ UpdateMessageBroker.informSubscribers();
+ }
+}
if (nextPoint != null) {nextPoint.setSegmentStart(_segmentFlag);}\r
}\r
// reset selection\r
- inTrackInfo.getSelection().select(_startPosition-1, _startPosition-1, _startPosition);\r
+ inTrackInfo.getSelection().clearAll();\r
}\r
}
\ No newline at end of file