]> gitweb.fperrin.net Git - GpsPrune.git/commitdiff
Version 8, September 2009
authoractivityworkshop <mail@activityworkshop.net>
Sat, 14 Feb 2015 14:22:56 +0000 (15:22 +0100)
committeractivityworkshop <mail@activityworkshop.net>
Sat, 14 Feb 2015 14:22:56 +0000 (15:22 +0100)
91 files changed:
tim/prune/App.java
tim/prune/Config.java
tim/prune/ExternalTools.java
tim/prune/FunctionLibrary.java
tim/prune/GpsPruner.java
tim/prune/I18nManager.java
tim/prune/configuration.txt [deleted file]
tim/prune/correlate/PhotoCorrelator.java
tim/prune/correlate/PhotoSelectionTableModel.java
tim/prune/data/Altitude.java
tim/prune/data/Coordinate.java
tim/prune/data/DataPoint.java
tim/prune/data/Distance.java
tim/prune/data/Field.java
tim/prune/data/FieldList.java
tim/prune/data/LatLonRectangle.java
tim/prune/data/NumberUtils.java [new file with mode: 0644]
tim/prune/data/Photo.java
tim/prune/data/Selection.java
tim/prune/data/Track.java
tim/prune/data/TrackInfo.java
tim/prune/function/AboutScreen.java
tim/prune/function/AddAltitudeOffset.java [new file with mode: 0644]
tim/prune/function/AddTimeOffset.java
tim/prune/function/FindWaypoint.java [new file with mode: 0644]
tim/prune/function/SaveConfig.java [new file with mode: 0644]
tim/prune/function/SetKmzImageSize.java [new file with mode: 0644]
tim/prune/function/SetMapBgFunction.java
tim/prune/function/SetPathsFunction.java [new file with mode: 0644]
tim/prune/function/ShowKeysScreen.java [new file with mode: 0644]
tim/prune/function/browser/BrowserLauncher.java
tim/prune/function/charts/Charter.java
tim/prune/function/compress/CompressTrackFunction.java
tim/prune/function/compress/DuplicatePointAlgorithm.java
tim/prune/function/distance/DistanceTableModel.java
tim/prune/function/edit/PointNameEditor.java
tim/prune/function/gpsies/FormPoster.java [new file with mode: 0644]
tim/prune/function/gpsies/GetGpsiesFunction.java [new file with mode: 0644]
tim/prune/function/gpsies/GpsiesTrack.java [new file with mode: 0644]
tim/prune/function/gpsies/GpsiesXmlHandler.java [new file with mode: 0644]
tim/prune/function/gpsies/TrackListModel.java [new file with mode: 0644]
tim/prune/gui/DetailsDisplay.java
tim/prune/gui/FunctionLauncher.java [new file with mode: 0644]
tim/prune/gui/IconManager.java
tim/prune/gui/MenuManager.java
tim/prune/gui/ProfileChart.java
tim/prune/gui/SelectorDisplay.java
tim/prune/gui/Viewport.java [new file with mode: 0644]
tim/prune/gui/WaypointNameMatcher.java [new file with mode: 0644]
tim/prune/gui/WholeNumberField.java
tim/prune/gui/images/scalebar.gif [new file with mode: 0644]
tim/prune/gui/images/scalebar_on.gif [new file with mode: 0644]
tim/prune/gui/map/MapCanvas.java
tim/prune/gui/map/MapTileCacher.java
tim/prune/gui/map/MapTileConfig.java
tim/prune/gui/map/ScaleBar.java [new file with mode: 0644]
tim/prune/lang/prune-texts_af.properties [new file with mode: 0644]
tim/prune/lang/prune-texts_de.properties
tim/prune/lang/prune-texts_de_CH.properties
tim/prune/lang/prune-texts_en.properties
tim/prune/lang/prune-texts_es.properties
tim/prune/lang/prune-texts_fr.properties
tim/prune/lang/prune-texts_in.properties
tim/prune/lang/prune-texts_it.properties
tim/prune/lang/prune-texts_pl.properties
tim/prune/lang/prune-texts_pt.properties
tim/prune/lang/prune-texts_ro.properties
tim/prune/lang/prune-texts_zh.properties [new file with mode: 0644]
tim/prune/load/FileCacher.java
tim/prune/load/FileLoader.java
tim/prune/load/FileSplitter.java
tim/prune/load/GpsLoader.java
tim/prune/load/JpegLoader.java
tim/prune/load/NmeaFileLoader.java [new file with mode: 0644]
tim/prune/load/NmeaMessage.java [new file with mode: 0644]
tim/prune/load/TextFileLoader.java
tim/prune/load/xml/GpxHandler.java
tim/prune/load/xml/KmlHandler.java
tim/prune/load/xml/ZipFileLoader.java
tim/prune/readme.txt
tim/prune/save/ExifSaver.java
tim/prune/save/FileSaver.java
tim/prune/save/GpsSaver.java
tim/prune/save/GpxExporter.java
tim/prune/save/KmlExporter.java
tim/prune/save/PointTypeSelector.java [new file with mode: 0644]
tim/prune/save/PovExporter.java
tim/prune/threedee/Java3DWindow.java
tim/prune/threedee/ThreeDModel.java
tim/prune/undo/UndoAddAltitudeOffset.java [new file with mode: 0644]
tim/prune/undo/UndoInsert.java

index ced255ae111cc194eac8fb0d1db64b2f2b019b36..091a37cb4a70bb1e8f149c1cb286a9098c7f26f3 100644 (file)
@@ -1,8 +1,10 @@
 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;
@@ -14,6 +16,7 @@ import tim.prune.data.Field;
 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;
@@ -22,31 +25,14 @@ import tim.prune.function.browser.BrowserLauncher;
 import tim.prune.function.browser.UrlGenerator;
 import tim.prune.function.edit.FieldEditList;
 import tim.prune.function.edit.PointEditor;
-import tim.prune.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.*;
 
 
 /**
@@ -65,6 +51,10 @@ public class App
        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
@@ -114,6 +104,27 @@ public class App
                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
@@ -238,24 +249,6 @@ public class App
        }
 
 
-       /**
-        * 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
         */
@@ -465,6 +458,39 @@ public class App
        }
 
 
+       /**
+        * 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
         */
@@ -480,7 +506,7 @@ public class App
                        // 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"));
                        }
@@ -542,7 +568,7 @@ public class App
                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
@@ -582,22 +608,13 @@ public class App
 
                                // 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
         */
@@ -608,7 +625,6 @@ public class App
                _track.clearDeletionMarkers();
        }
 
-
        /**
         * Receive loaded data and optionally merge with current Track
         * @param inFieldArray array of fields
@@ -625,16 +641,25 @@ public class App
                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
@@ -683,6 +708,38 @@ public class App
                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();
+               }
        }
 
 
@@ -710,7 +767,7 @@ public class App
                        {
                                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();
@@ -964,4 +1021,20 @@ public class App
                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;
+       }
 }
index aa36c158930cc07e0d15a21ec98363cc1988030c..befbaccc1b4819216576f8d6a3c653ad7baca9dd 100644 (file)
@@ -9,67 +9,46 @@ import java.util.Properties;
  */
 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
@@ -110,19 +89,8 @@ public abstract class Config
                        }
                        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();
                }
@@ -140,6 +108,12 @@ public abstract class Config
                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;
        }
 
@@ -157,81 +131,98 @@ public abstract class Config
                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));
        }
 }
index 22291fb122968331a6f1a52b28d4f9fc56782cb7..a2d3e56b6f75c2315832f8c89809a3d442fd6159 100644 (file)
@@ -8,42 +8,55 @@ import java.io.IOException;
  */
 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;
        }
 
        /**
@@ -52,6 +65,7 @@ public abstract class ExternalTools
         */
        private static boolean check(String inCommand)
        {
+               // System.out.println("Checking tool '" + inCommand + "'");
                try
                {
                        Runtime.getRuntime().exec(inCommand);
index 3227c31653d65b96b97758b784c861fc9ee522bb..1a2518c4008b4d4a13e8751bd23ac7ee45bc93c3 100644 (file)
@@ -2,15 +2,23 @@ package tim.prune;
 
 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;
@@ -27,15 +35,23 @@ public abstract class FunctionLibrary
        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;
 
@@ -51,15 +67,23 @@ public abstract class FunctionLibrary
                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);
        }
index f8e36ad06650109bec383bfee6824e04555ce293..29f7eb592681131438714de9122b7c7caea0a601 100644 (file)
@@ -4,7 +4,9 @@ import java.awt.event.WindowAdapter;
 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;
@@ -16,6 +18,7 @@ import tim.prune.gui.MenuManager;
 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;
 
 /**
@@ -26,9 +29,9 @@ 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;
 
@@ -40,19 +43,23 @@ public class GpsPruner
        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="))
                        {
@@ -62,12 +69,20 @@ public class GpsPruner
                        {
                                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) {
@@ -89,18 +104,29 @@ public class GpsPruner
                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);
        }
 
 
@@ -127,8 +153,9 @@ public class GpsPruner
 
        /**
         * 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);
@@ -148,6 +175,8 @@ public class GpsPruner
                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();
@@ -187,5 +216,8 @@ public class GpsPruner
                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);
        }
 }
index 80be52b44f60aa795dbe80039f279334baae7a69..b9ce3cc0e59e07888f7bd2cbfef679dcc065fea8 100644 (file)
@@ -2,6 +2,7 @@ package tim.prune;
 
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.Locale;
 import java.util.MissingResourceException;
@@ -35,14 +36,19 @@ public abstract class I18nManager
                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
                }
        }
 
@@ -50,21 +56,26 @@ public abstract class I18nManager
        /**
         * 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();
        }
 
 
diff --git a/tim/prune/configuration.txt b/tim/prune/configuration.txt
deleted file mode 100644 (file)
index 2955efc..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-
-== 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/
index 6c47d0042621e44e2c38d36f867d569533af9663..d60e905f09d048d84d13c63fc7d893c8efb3265a 100644 (file)
@@ -69,10 +69,6 @@ public class PhotoCorrelator extends GenericFunction
        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();
        }
 
 
@@ -86,6 +82,14 @@ public class PhotoCorrelator extends GenericFunction
         */
        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))
                {
@@ -378,7 +382,7 @@ public class PhotoCorrelator extends GenericFunction
                _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
index dbd9d8e572dcdd21b70acb154125c5c2a12c5e9c..4472e6b9a11756657d204a147c189ccf5c4faa63 100644 (file)
@@ -65,7 +65,7 @@ public class PhotoSelectionTableModel extends AbstractTableModel
         */
        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();
index 495e84491746f4c1c011cb4b0d64cb1c7b0bde91..3328817fa6cccdb0dfb88e36c228412c0239fa33 100644 (file)
@@ -61,6 +61,24 @@ public class Altitude
                _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
@@ -114,7 +132,9 @@ public class Altitude
        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);
@@ -155,4 +175,30 @@ public class Altitude
                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);
+       }
 }
index 19a1688ed45cc0d0f99385c0b02ba22d50041259..8b7904910b96e5da13445c7daa0aa352f15cdf41 100644 (file)
@@ -76,7 +76,7 @@ public abstract class Coordinate
                        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
@@ -97,10 +97,8 @@ public abstract class Coordinate
                                        else
                                        {
                                                inNumeric = false;
-                                               // Remember second delimiter
-                                               if (numFields == 2) {
-                                                       secondDelim += currChar;
-                                               }
+                                               // Remember delimiters
+                                               if (currChar != ',' && currChar != '.') {otherDelims[numFields] = true;}
                                        }
                                }
                                _valid = (numFields > 0);
@@ -116,16 +114,28 @@ public abstract class Coordinate
                        _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;
@@ -265,7 +275,7 @@ public abstract class Coordinate
                                {
                                        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));
@@ -274,13 +284,13 @@ public abstract class Coordinate
                                }
                                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;
                                }
index 2d60ce7e5021916a77390c1d2e875a7062014bc0..966b5606b7d2bdfcd2c608a4c36136acd28a3f77 100644 (file)
@@ -155,7 +155,7 @@ public class DataPoint
                }
                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);
                }
        }
 
index 9909df7edad664841826e842d6287c25e05ec500..d12d98817d5c7fce86d687f12f566940a03dbbd7 100644 (file)
@@ -57,4 +57,14 @@ public abstract class Distance
                // 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;
+       }
 }
index 089d8cdc2d1a623b89f0d7b7e4615b6524fb128e..5d0adc4563d25fd5465465226958eb59ebded0ca 100644 (file)
@@ -21,6 +21,8 @@ public class Field
        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)
index e4baecc97524e6b5b61ac37da47b8fe95ec9ff0e..1542f09eab32e593ef1522f49d518e4ac87e2dcc 100644 (file)
@@ -6,6 +6,7 @@ package tim.prune.data;
  */
 public class FieldList
 {
+       /** Array of Field objects making the list */
        private Field[] _fieldArray;
 
 
@@ -62,8 +63,7 @@ public class FieldList
 
 
        /**
-        * 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
         */
index 74c9855f2045c4403c037d83fba9467c765c1764..0aeb1c8565ab1d2bc9a483dd24e190a4629d23e6 100644 (file)
@@ -19,7 +19,7 @@ public class LatLonRectangle
        {
                _latRange = inLatRange;
                _lonRange = inLonRange;
-               // TODO: Expand range by certain percentage
+               // MAYBE: Expand range by certain percentage
        }
 
        /**
diff --git a/tim/prune/data/NumberUtils.java b/tim/prune/data/NumberUtils.java
new file mode 100644 (file)
index 0000000..0c76981
--- /dev/null
@@ -0,0 +1,55 @@
+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
index 805e22ea6254b8f88f78ca9b766d6d6c699590eb..4fdb61261b64dbc21beb3ed060b28894903e479d 100644 (file)
@@ -182,6 +182,14 @@ public class Photo
                _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
         */
index c07c1a91e3aea422e5b469bef027afe4b2db3247..6924d133abca3c541a44d5bf257955a7e1bd3440 100644 (file)
@@ -19,6 +19,7 @@ public class Selection
        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;
 
 
        /**
@@ -32,60 +33,14 @@ public class Selection
 
 
        /**
-        * 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
         */
@@ -110,6 +65,7 @@ public class Selection
        private void recalculate()
        {
                _altitudeFormat = Altitude.Format.NO_FORMAT;
+               _multipleSegments = false;
                if (_track.getNumPoints() > 0 && hasRangeSelected())
                {
                        _altitudeRange = new IntegerRange();
@@ -164,7 +120,10 @@ public class Selection
                                        {
                                                double radians = DataPoint.calculateRadiansBetween(lastPoint, currPoint);
                                                _angDistance += radians;
-                                               if (!currPoint.getSegmentStart()) {
+                                               if (currPoint.getSegmentStart()) {
+                                                       _multipleSegments = true;
+                                               }
+                                               else {
                                                        _angMovingDistance += radians;
                                                }
                                        }
@@ -273,23 +232,35 @@ public class Selection
        }
 
        /**
-        * 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();
        }
 
@@ -307,7 +278,7 @@ public class Selection
         * 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)
                {
@@ -322,7 +293,7 @@ public class Selection
                                _endIndex = _track.getNumPoints() - 1;
                        }
                }
-               reset();
+               markInvalid();
                UpdateMessageBroker.informSubscribers();
        }
 
@@ -350,12 +321,11 @@ public class Selection
                {
                        _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();
        }
 
@@ -393,22 +363,12 @@ public class Selection
                        _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
@@ -417,16 +377,8 @@ public class Selection
        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();
        }
 
 
index df51e8f27e3c8963189b664adefc7534861188ea..08168d1fb6c348a43cc97eff367021b9c7241ab8 100644 (file)
@@ -22,7 +22,8 @@ public class Track
        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
@@ -154,8 +155,8 @@ public class Track
                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++;
@@ -297,32 +298,42 @@ public class Track
                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
@@ -445,8 +456,9 @@ public class Track
         */
        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
@@ -457,30 +469,34 @@ public class Track
                        {
                                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;
@@ -533,7 +549,7 @@ public class Track
                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++)
                {
@@ -605,6 +621,7 @@ public class Track
                if (!_scaled) scalePoints();
                return _altitudeRange;
        }
+
        /**
         * @return the number of (valid) points in the track
         */
@@ -684,6 +701,8 @@ public class 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);
        }
 
@@ -713,14 +732,30 @@ public class Track
                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;
        }
 
        /**
@@ -809,7 +844,7 @@ public class Track
                _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);
@@ -822,12 +857,11 @@ public class Track
                                        _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()];
@@ -1099,10 +1133,15 @@ public class Track
                        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)
index d58cc167d6353239983e846a4e41969d250e7c89..eddea09468c58f7f0cfda69772ce88c690462d7e 100644 (file)
@@ -249,6 +249,31 @@ public class TrackInfo
                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
@@ -273,7 +298,7 @@ public class TrackInfo
        {
                boolean success = _track.average(_selection.getStart(), _selection.getEnd());
                if (success) {
-                       _selection.selectPoint(_selection.getEnd()+1);
+                       selectPoint(_selection.getEnd()+1);
                }
                return success;
        }
@@ -285,10 +310,38 @@ public class TrackInfo
         */
        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);
        }
 
        /**
@@ -297,19 +350,36 @@ public class TrackInfo
         */
        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
+                       }
                }
        }
 }
index 0f20ba00778064254a86ddbf2a1d0681f5d1aeb2..2835d410c787dca4c4a77fc31f58e33fad27c8b0 100644 (file)
@@ -90,8 +90,8 @@ public class AboutScreen extends GenericFunction
                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));
@@ -122,7 +122,7 @@ public class AboutScreen extends GenericFunction
                        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("...");
@@ -132,21 +132,17 @@ public class AboutScreen extends GenericFunction
                        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
@@ -178,10 +174,10 @@ public class AboutScreen extends GenericFunction
                        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") + " : "),
@@ -315,9 +311,9 @@ public class AboutScreen extends GenericFunction
                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);
+               }
        }
 }
diff --git a/tim/prune/function/AddAltitudeOffset.java b/tim/prune/function/AddAltitudeOffset.java
new file mode 100644 (file)
index 0000000..14adb83
--- /dev/null
@@ -0,0 +1,181 @@
+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();
+       }
+}
index 8b5d4a82dd548c1472fd7220c3b5d6b2353a2bc2..bbfda5ed699ea88d32e60d6683fffa7b08eaca09 100644 (file)
@@ -178,8 +178,8 @@ public class AddTimeOffset extends GenericFunction
        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;
        }
diff --git a/tim/prune/function/FindWaypoint.java b/tim/prune/function/FindWaypoint.java
new file mode 100644 (file)
index 0000000..8b6beea
--- /dev/null
@@ -0,0 +1,156 @@
+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();
+       }
+}
diff --git a/tim/prune/function/SaveConfig.java b/tim/prune/function/SaveConfig.java
new file mode 100644 (file)
index 0000000..0f2339f
--- /dev/null
@@ -0,0 +1,150 @@
+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;
+       }
+}
diff --git a/tim/prune/function/SetKmzImageSize.java b/tim/prune/function/SetKmzImageSize.java
new file mode 100644 (file)
index 0000000..1677e54
--- /dev/null
@@ -0,0 +1,159 @@
+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();
+               }
+       }
+}
index 7c5df3a3c1ed2085a5e2c68058f882ca42bf91a2..a683634383d30767fe17edf7638dbd3b3624dff2 100644 (file)
@@ -144,10 +144,10 @@ public class SetMapBgFunction extends GenericFunction
        {
                // 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) {
@@ -194,8 +194,8 @@ public class SetMapBgFunction extends GenericFunction
        {
                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();
        }
diff --git a/tim/prune/function/SetPathsFunction.java b/tim/prune/function/SetPathsFunction.java
new file mode 100644 (file)
index 0000000..65c3c41
--- /dev/null
@@ -0,0 +1,167 @@
+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
diff --git a/tim/prune/function/ShowKeysScreen.java b/tim/prune/function/ShowKeysScreen.java
new file mode 100644 (file)
index 0000000..98a9fdd
--- /dev/null
@@ -0,0 +1,106 @@
+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;
+       }
+}
index 1decbc3f586de321d7208dad537804af297d4da6..ecfd83f9b7bea07814dbcff564dcb78b63c2af09 100644 (file)
@@ -36,7 +36,9 @@ public abstract class BrowserLauncher
                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};
index a3348c8ce0e35e8da11c4aa39062b9b18abdab28..01bf16c48d27a6f6b5b22bfc1ed4a080dcd9c55e 100644 (file)
@@ -87,6 +87,12 @@ public class Charter extends GenericFunction
         */
        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)
                {
@@ -183,14 +189,6 @@ public class Charter extends GenericFunction
                // 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() {
@@ -277,7 +275,8 @@ public class Charter extends GenericFunction
                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)
                        {
@@ -439,7 +438,7 @@ public class Charter extends GenericFunction
         */
        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);
        }
 
@@ -462,7 +461,7 @@ public class Charter extends GenericFunction
                        {
                                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));
@@ -507,7 +506,7 @@ public class Charter extends GenericFunction
        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));
@@ -542,7 +541,7 @@ public class Charter extends GenericFunction
                                        + 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);
@@ -561,7 +560,7 @@ public class Charter extends GenericFunction
        {
                // 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
@@ -614,7 +613,7 @@ public class Charter extends GenericFunction
 
        /**
         * Select a file to write for the SVG output
-        * @return
+        * @return selected File object or null if cancelled
         */
        private File selectSvgFile()
        {
@@ -625,8 +624,8 @@ public class Charter extends GenericFunction
                        _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)
@@ -650,9 +649,7 @@ public class Charter extends GenericFunction
                                {
                                        return file;
                                }
-                               else {
-                                       chooseAgain = true;
-                               }
+                               chooseAgain = true;
                        }
                }
                // Cancel pressed so no file selected
@@ -671,27 +668,4 @@ public class Charter extends GenericFunction
                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");
-                               }
-                       }
-               }
-       }
 }
index 865faeb4f4ae6a576aa2dfd80dd2a8e81e5c9c15..62bf1f14a4802d41b40355b4a67250f0fc0cda95 100644 (file)
@@ -172,7 +172,7 @@ public class CompressTrackFunction extends GenericFunction
                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
index 3fd2233fc3edee0dce42abe151736c57fb3e0f42..c5ea99174894de82c675b8b27ca4d9dd0f172f5c 100644 (file)
@@ -41,8 +41,8 @@ public class DuplicatePointAlgorithm extends CompressionAlgorithm
                        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++)
index 8adbf6915150a4f5e9875ef394def5d756596dce..8dadc3a12bc06cc2bf804631eb8e145b0c47c5e6 100644 (file)
@@ -69,7 +69,7 @@ public class DistanceTableModel extends GenericTableModel
        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();
index 19edfbb80ba37c3f35ae291089a22079f0040693..3fc630e2b96506789f36ad0ee7878d13fee8bb0d 100644 (file)
@@ -11,23 +11,21 @@ import java.awt.event.KeyEvent;
 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;
@@ -37,25 +35,26 @@ public class PointNameEditor
        /**
         * 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());
diff --git a/tim/prune/function/gpsies/FormPoster.java b/tim/prune/function/gpsies/FormPoster.java
new file mode 100644 (file)
index 0000000..9f9edc4
--- /dev/null
@@ -0,0 +1,326 @@
+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
diff --git a/tim/prune/function/gpsies/GetGpsiesFunction.java b/tim/prune/function/gpsies/GetGpsiesFunction.java
new file mode 100644 (file)
index 0000000..493aedf
--- /dev/null
@@ -0,0 +1,308 @@
+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();
+       }
+}
diff --git a/tim/prune/function/gpsies/GpsiesTrack.java b/tim/prune/function/gpsies/GpsiesTrack.java
new file mode 100644 (file)
index 0000000..7441195
--- /dev/null
@@ -0,0 +1,99 @@
+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;
+       }
+}
diff --git a/tim/prune/function/gpsies/GpsiesXmlHandler.java b/tim/prune/function/gpsies/GpsiesXmlHandler.java
new file mode 100644 (file)
index 0000000..e639160
--- /dev/null
@@ -0,0 +1,104 @@
+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;
+       }
+}
diff --git a/tim/prune/function/gpsies/TrackListModel.java b/tim/prune/function/gpsies/TrackListModel.java
new file mode 100644 (file)
index 0000000..275ae83
--- /dev/null
@@ -0,0 +1,108 @@
+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;
+       }
+}
index 2703c1b0c8924d168546b399f0b94067f8ee2fd2..c40f8c2b4891360144bfe60d55dfd4817fd9a456 100644 (file)
@@ -46,6 +46,7 @@ public class DetailsDisplay extends GenericDisplay
        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;
@@ -138,6 +139,8 @@ public class DetailsDisplay extends GenericDisplay
                rangeDetailsPanel.add(_aveSpeedLabel);
                _aveMovingSpeedLabel = new JLabel("");
                rangeDetailsPanel.add(_aveMovingSpeedLabel);
+               _paceLabel = new JLabel("");
+               rangeDetailsPanel.add(_paceLabel);
                _altRangeLabel = new JLabel("");
                rangeDetailsPanel.add(_altRangeLabel);
                _updownLabel = new JLabel("");
@@ -196,12 +199,12 @@ public class DetailsDisplay extends GenericDisplay
                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);
@@ -245,7 +248,8 @@ public class DetailsDisplay extends GenericDisplay
                                :"");
                        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())
@@ -286,6 +290,7 @@ public class DetailsDisplay extends GenericDisplay
                        _updownLabel.setText("");
                        _aveSpeedLabel.setText("");
                        _aveMovingSpeedLabel.setText("");
+                       _paceLabel.setText("");
                }
                else
                {
@@ -293,19 +298,38 @@ public class DetailsDisplay extends GenericDisplay
                                + (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();
@@ -326,7 +350,7 @@ public class DetailsDisplay extends GenericDisplay
                }
                // 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"));
@@ -338,7 +362,7 @@ public class DetailsDisplay extends GenericDisplay
                {
                        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")));
@@ -403,7 +427,7 @@ public class DetailsDisplay extends GenericDisplay
                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";
        }
diff --git a/tim/prune/gui/FunctionLauncher.java b/tim/prune/gui/FunctionLauncher.java
new file mode 100644 (file)
index 0000000..e846412
--- /dev/null
@@ -0,0 +1,33 @@
+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
index 8930d68445bff8c7f59820afbca1406ecda0bbeb..85a182a87cf23022de0114718d1c9b2f08c17b83 100644 (file)
@@ -12,6 +12,10 @@ public abstract class IconManager
        /** 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 */
index 7b256ba74248463e8877f3fa7218fdd2dd9135f5..cbf25af7df581e91940ff1a64b76da3fbc487b83 100644 (file)
@@ -4,7 +4,9 @@ import java.awt.event.ActionEvent;
 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;
@@ -12,10 +14,12 @@ import javax.swing.JToolBar;
 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;
@@ -54,14 +58,18 @@ public class MenuManager implements DataSubscriber
        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;
@@ -91,6 +99,14 @@ public class MenuManager implements DataSubscriber
        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
@@ -114,9 +130,10 @@ public class MenuManager implements DataSubscriber
        {
                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)
                        {
@@ -138,26 +155,16 @@ public class MenuManager implements DataSubscriber
                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)
                        {
@@ -169,32 +176,14 @@ public class MenuManager implements DataSubscriber
                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();
@@ -209,8 +198,9 @@ public class MenuManager implements DataSubscriber
                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)
                        {
@@ -240,13 +230,7 @@ public class MenuManager implements DataSubscriber
                _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"));
@@ -271,12 +255,7 @@ public class MenuManager implements DataSubscriber
                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"));
@@ -317,14 +296,11 @@ public class MenuManager implements DataSubscriber
                _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)
@@ -378,12 +354,14 @@ public class MenuManager implements DataSubscriber
 
                // 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);
@@ -417,17 +395,16 @@ public class MenuManager implements DataSubscriber
                };
                _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
@@ -468,35 +445,21 @@ public class MenuManager implements DataSubscriber
                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);
@@ -542,41 +505,49 @@ public class MenuManager implements DataSubscriber
                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);
 
@@ -590,7 +561,49 @@ public class MenuManager implements DataSubscriber
         */
        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));
+                       }
+               }
        }
 
        /**
@@ -691,13 +704,15 @@ public class MenuManager implements DataSubscriber
                _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);
@@ -738,6 +753,7 @@ public class MenuManager implements DataSubscriber
                _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()
index a0adfdbe33b74424ce6432eb8be2e20c052f1cf3..f7ae105cfae85665f848287d37fc85ec0f59c7d1 100644 (file)
@@ -20,6 +20,7 @@ public class ProfileChart extends GenericChart
        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;
@@ -48,13 +49,9 @@ public class ProfileChart extends GenericChart
                {
                        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);
@@ -62,12 +59,20 @@ public class ProfileChart extends GenericChart
                        }
 
                        // 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);
@@ -103,6 +108,9 @@ public class ProfileChart extends GenericChart
                                        else
                                        {
                                                g.setColor(COLOR_ALT_BARS);
+                                               if (p >= selectionStart && p <= selectionEnd) {
+                                                       g.setColor(COLOR_CURR_RANGE);
+                                               }
                                        }
                                        if (_track.getPoint(p).getAltitude().isValid())
                                        {
@@ -209,7 +217,7 @@ public class ProfileChart extends GenericChart
                        {
                                // 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);
                        }
                }
        }
index 28e0a95b14a2dc6e3915a6f1f62d9e50d422a7f7..48a5ac4967a95229f7cad5d94665022872636128 100644 (file)
@@ -22,8 +22,6 @@ import javax.swing.event.ListSelectionListener;
 
 import tim.prune.DataSubscriber;
 import tim.prune.I18nManager;
-import tim.prune.data.DataPoint;
-import tim.prune.data.Photo;
 import tim.prune.data.TrackInfo;
 
 /**
@@ -117,7 +115,9 @@ public class SelectorDisplay extends GenericDisplay
                _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());
@@ -149,7 +149,7 @@ public class SelectorDisplay extends GenericDisplay
        {
                if (_track != null && !_ignoreScrollEvents)
                {
-                       _trackInfo.getSelection().selectPoint(inValue);
+                       _trackInfo.selectPoint(inValue);
                }
        }
 
@@ -217,7 +217,7 @@ public class SelectorDisplay extends GenericDisplay
                }
                else
                {
-                       _scroller.setMaximum(_track.getNumPoints() + SCROLLBAR_INTERVAL);
+                       _scroller.setMaximum(_track.getNumPoints() -1 + SCROLLBAR_INTERVAL);
                        if (currentPointIndex >= 0)
                                _scroller.setValue(currentPointIndex);
                        _scroller.setEnabled(true);
@@ -246,23 +246,20 @@ public class SelectorDisplay extends GenericDisplay
                                _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);
+                               }
                        }
                }
        }
diff --git a/tim/prune/gui/Viewport.java b/tim/prune/gui/Viewport.java
new file mode 100644 (file)
index 0000000..25eba2f
--- /dev/null
@@ -0,0 +1,43 @@
+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};
+       }
+}
diff --git a/tim/prune/gui/WaypointNameMatcher.java b/tim/prune/gui/WaypointNameMatcher.java
new file mode 100644 (file)
index 0000000..db0f827
--- /dev/null
@@ -0,0 +1,98 @@
+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);
+       }
+}
index 9a352800e95dfa3a37131167b89eff871601555c..09f676d7e90caac0c119922b3b0bcf894798c9cc 100644 (file)
@@ -69,6 +69,14 @@ public class WholeNumberField extends JTextField
                return parseValue(getText());
        }
 
+       /**
+        * @param inValue value to set
+        */
+       public void setValue(int inValue)
+       {
+               setText("" + inValue);
+       }
+
        /**
         * @param inText text to parse
         * @return value as integer
diff --git a/tim/prune/gui/images/scalebar.gif b/tim/prune/gui/images/scalebar.gif
new file mode 100644 (file)
index 0000000..99b74f4
Binary files /dev/null and b/tim/prune/gui/images/scalebar.gif differ
diff --git a/tim/prune/gui/images/scalebar_on.gif b/tim/prune/gui/images/scalebar_on.gif
new file mode 100644 (file)
index 0000000..6ae799e
Binary files /dev/null and b/tim/prune/gui/images/scalebar_on.gif differ
index a8df86efec37aedd2cfa77074ad23ddd7876e27b..2af4ae8e6a9a53c4561b89c62614debb9e9b718e 100644 (file)
@@ -53,6 +53,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        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 */
@@ -63,6 +65,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        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 */
@@ -75,6 +79,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        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;
@@ -126,6 +132,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        public MapCanvas(App inApp, TrackInfo inTrackInfo)
        {
                _app = inApp;
+               _trackInfo = inTrackInfo;
                _track = inTrackInfo.getTrack();
                _selection = inTrackInfo.getSelection();
                _mapPosition = new MapPosition();
@@ -169,6 +176,18 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                });
                _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));
@@ -223,12 +242,16 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                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();
        }
@@ -347,8 +370,10 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        }
 
                        // 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) {
@@ -370,6 +395,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        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);
@@ -430,7 +456,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                // 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);
@@ -740,7 +767,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                         _mapPosition.getXFromPixels(inE.getX(), getWidth()),
                                         _mapPosition.getYFromPixels(inE.getY(), getHeight()),
                                         _mapPosition.getBoundsFromPixels(CLICK_SENSITIVITY), false);
-                               _selection.selectPoint(pointIndex);
+                               _trackInfo.selectPoint(pointIndex);
                        }
                        else
                        {
@@ -876,6 +903,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        public void keyPressed(KeyEvent inE)
        {
                int code = inE.getKeyCode();
+               int currPointIndex = _selection.getCurrentPointIndex();
                // Check for meta key
                if (inE.isControlDown())
                {
@@ -885,10 +913,10 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        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
                {
@@ -905,7 +933,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                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();
                        }
@@ -939,4 +967,12 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                else if (clicks > 0)
                        zoomOut();
        }
+
+       /**
+        * @return current map position
+        */
+       public MapPosition getMapPosition()
+       {
+               return _mapPosition;
+       }
 }
index ea5b6fb769813d7e3c0b4700fc55698454dec2db..366e1ad3b055731efd5487746aac66ea5b978f3d 100644 (file)
@@ -30,7 +30,7 @@ public class MapTileCacher implements ImageObserver
        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;
 
@@ -52,7 +52,10 @@ public class MapTileCacher implements ImageObserver
         */
        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();
index 762baf424f1066fb84e5a4466577fad61476c345..1f9c3872e2e12de84cb60a22d083a7493e1f38b7 100644 (file)
@@ -31,8 +31,8 @@ public class MapTileConfig
         */
        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)))
diff --git a/tim/prune/gui/map/ScaleBar.java b/tim/prune/gui/map/ScaleBar.java
new file mode 100644 (file)
index 0000000..0f65db9
--- /dev/null
@@ -0,0 +1,111 @@
+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;
+       }
+}
diff --git a/tim/prune/lang/prune-texts_af.properties b/tim/prune/lang/prune-texts_af.properties
new file mode 100644 (file)
index 0000000..42875f6
--- /dev/null
@@ -0,0 +1,154 @@
+# 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
index 81b2b78410e4fa670ea8ebf0b65d58b3085ae6c8..daf49fefcea82f2bd7ed36220fd23fde94797ba8 100644 (file)
@@ -11,18 +11,17 @@ menu.edit=Bearbeiten
 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
@@ -40,15 +39,36 @@ menu.view.browser.google=Google Maps
 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
@@ -56,28 +76,36 @@ function.sendtogps=zum GPS schicken
 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
@@ -96,13 +124,13 @@ dialog.jpegload.loadjpegswithoutcoords=Auch Fotos ohne Koordinaten laden
 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
@@ -114,14 +142,14 @@ dialog.save.coordinateunits=Koordinaten Ma
 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
@@ -130,28 +158,31 @@ dialog.exportpov.cameraz=Kamera Z
 dialog.exportpov.modelstyle=Modellstil
 dialog.exportpov.ballsandsticks=Bälle und Stangen
 dialog.exportpov.tubesandwalls=Röhren und Wände
-dialog.exportpov.warningtracksize=Dieser Track hat sehr viele Punkte, die Java3D vielleicht nicht bearbeiten kann.\nMöchten Sie den Vorgang trotzdem 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
@@ -161,11 +192,13 @@ dialog.addtimeoffset.days=Tage
 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
@@ -181,27 +214,32 @@ dialog.charts.screen=zum Bildschirm
 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,
@@ -215,22 +253,22 @@ dialog.correlate.options.timelimit=Zeitgrenzen
 dialog.correlate.options.nodistancelimit=Keine Distanzgrenzen
 dialog.correlate.options.distancelimit=Distanzgrenzen
 dialog.correlate.options.correlate=Korrelieren
-dialog.correlate.alloutsiderange=Alle Fotos sind 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
@@ -249,23 +287,44 @@ dialog.about.credits.exifcode=Exif Code von
 dialog.about.credits.icons=Einige Bilder von
 dialog.about.credits.translators=Dolmetscher
 dialog.about.credits.translations=Ãœbersetzungen mit Hilfe von
-dialog.about.credits.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
@@ -275,13 +334,14 @@ confirm.save.ok2=Punkte gespeichert nach
 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
@@ -291,6 +351,7 @@ confirm.photo.disconnect=Foto getrennt
 confirm.correlate.single=Foto wurde korreliert
 confirm.correlate.multi=Fotos wurden korreliert
 confirm.createpoint=Punkt kreiert
+confirm.running=In Bearbeitung ...
 
 # Buttons
 button.ok=OK
@@ -299,8 +360,8 @@ button.next=Vorw
 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
@@ -312,10 +373,11 @@ button.yestoall=Ja f
 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
@@ -329,7 +391,7 @@ filetype.svg=SVG 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
@@ -339,9 +401,9 @@ details.pointdetails=Details vom Punkt
 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
@@ -355,13 +417,14 @@ display.range.time.hours=h
 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
@@ -375,14 +438,14 @@ fieldname.newsegment=Segment
 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=
@@ -415,14 +478,15 @@ undo.load=Daten laden
 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
@@ -431,11 +495,11 @@ undo.createpoint=Punkt kreieren
 
 # 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
@@ -449,11 +513,11 @@ error.jpegload.noexiffound=Keine EXIF Information 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.
index 5cbeed6469ed81e0b866a242052808b8400a223d..b00f39dc9d901bb4eda5dce93dcd6c39fb86dbd4 100644 (file)
@@ -2,7 +2,7 @@
 # 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
@@ -11,7 +11,6 @@ menu.edit=Editiere
 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
@@ -40,6 +39,8 @@ menu.view.browser.google=
 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
@@ -49,6 +50,25 @@ menu.map.newpoint=Noii Punkt
 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
@@ -56,16 +76,24 @@ function.sendtogps=zum GPS schicke
 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
@@ -116,7 +144,7 @@ dialog.save.timestampformat=Ziitst
 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
@@ -131,6 +159,10 @@ dialog.exportpov.modelstyle=Modellstil
 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
@@ -150,7 +182,6 @@ dialog.pointedit.table.value=Wert
 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
@@ -161,6 +192,8 @@ dialog.addtimeoffset.days=Tage
 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ä
@@ -194,9 +227,14 @@ dialog.setmapbg.osma=
 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
@@ -260,6 +298,27 @@ dialog.checkversion.newversion2=.
 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
@@ -278,6 +337,7 @@ confirm.point.edit=Punkt editiert
 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
@@ -291,6 +351,7 @@ confirm.photo.disconnect=F
 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
@@ -313,9 +374,11 @@ button.notoall=Nei f
 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
@@ -355,6 +418,7 @@ display.range.time.hours=Std
 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
@@ -422,6 +486,7 @@ undo.insert=Punkte inn
 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ä
@@ -432,7 +497,7 @@ undo.createpoint=Punkt kreier
 # 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?
index f76bd364b467ce44c22994ac6d9b58860244b225..85f4024aab364c33ac36e795607fb991c3a9aa51 100644 (file)
@@ -11,7 +11,6 @@ menu.edit=Edit
 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
@@ -40,6 +39,8 @@ menu.view.browser.google=Google maps
 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
@@ -49,6 +50,25 @@ menu.map.newpoint=Create new point
 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
@@ -56,16 +76,24 @@ function.sendtogps=Send data to 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
@@ -116,7 +144,7 @@ dialog.save.timestampformat=Timestamp format
 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
@@ -131,6 +159,10 @@ dialog.exportpov.modelstyle=Model style
 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
@@ -150,7 +182,6 @@ dialog.pointedit.table.value=Value
 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
@@ -161,6 +192,8 @@ dialog.addtimeoffset.days=Days
 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
@@ -194,6 +227,11 @@ dialog.setmapbg.osma=Osma
 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
@@ -260,6 +298,27 @@ dialog.checkversion.newversion2=.
 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
@@ -278,6 +337,7 @@ confirm.point.edit=point edited
 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
@@ -291,6 +351,7 @@ confirm.photo.disconnect=photo disconnected
 confirm.correlate.single=photo was correlated
 confirm.correlate.multi=photos were correlated
 confirm.createpoint=point created
+confirm.running=Running ...
 
 # Buttons
 button.ok=OK
@@ -313,9 +374,10 @@ button.notoall=No to all
 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
@@ -355,6 +417,7 @@ display.range.time.hours=h
 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
@@ -422,6 +485,7 @@ undo.insert=insert points
 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
@@ -432,7 +496,7 @@ undo.createpoint=create point
 # 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?
index 6dbaddbbef35d0dfe10685adddf10b1f0186b9b1..b8baa470d7e2c1a423fb39dad9c76bd03026ffd2 100644 (file)
@@ -11,10 +11,9 @@ menu.edit=Editar
 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
@@ -22,8 +21,8 @@ menu.edit.mergetracksegments=Unir los segmentos de track
 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
@@ -38,8 +37,10 @@ menu.view=Ver
 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
@@ -47,8 +48,27 @@ menu.map.zoomout=Reducir 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
@@ -56,16 +76,24 @@ function.sendtogps=Enviar datos al 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
@@ -80,7 +108,7 @@ dialog.openoptions.title=Opciones de abrir
 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
@@ -93,14 +121,14 @@ dialog.openoptions.deliminfo.norecords=Ningun dato
 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
@@ -109,51 +137,54 @@ dialog.save.fieldstosave=Campos a guardar
 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=
@@ -161,6 +192,8 @@ dialog.addtimeoffset.days=Dias
 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
@@ -176,7 +209,7 @@ dialog.saveexif.photostatus.modified=Modificada
 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=
@@ -194,29 +227,34 @@ dialog.setmapbg.osma=
 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=
@@ -225,14 +263,14 @@ dialog.compress.wackypoints.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
@@ -244,11 +282,11 @@ dialog.about.systeminfo.gnuplot=Gnuplot instalado
 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
@@ -260,13 +298,34 @@ dialog.checkversion.newversion2=
 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
@@ -278,19 +337,21 @@ confirm.point.edit=Punto editado
 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
@@ -301,21 +362,22 @@ button.cancel=Cancelar
 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
@@ -328,19 +390,19 @@ filetype.pov=Archivos POV
 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
@@ -355,6 +417,7 @@ display.range.time.hours=h
 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
@@ -367,7 +430,7 @@ map.overzoom=
 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
@@ -376,9 +439,9 @@ fieldname.custom=Personalizado
 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
@@ -387,7 +450,7 @@ units.metres=Metros
 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
@@ -422,6 +485,7 @@ undo.insert=insertar puntos
 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
@@ -431,29 +495,29 @@ undo.createpoint=crear punto
 
 # 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.
index c76eb66ce48243cde2db31cbfe56a004ac8ff803..a3e16ec22b9ff921320bb681a8ce642e2b39ec0f 100644 (file)
@@ -7,32 +7,31 @@ menu.file.open=Ouvrir fichier
 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
@@ -40,48 +39,77 @@ menu.view.browser.google=Google maps
 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
@@ -90,67 +118,70 @@ dialog.delimiter.other=Autres
 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
@@ -160,137 +191,167 @@ dialog.addtimeoffset.subtract=Avancer l'heure
 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
@@ -298,11 +359,11 @@ button.back=Retour
 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
@@ -310,12 +371,13 @@ button.yes=Oui
 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
@@ -328,40 +390,41 @@ filetype.pov=Fichiers POV
 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
@@ -372,22 +435,22 @@ fieldname.time=Temps
 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
@@ -398,7 +461,7 @@ units.feetpersec=ft/s
 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
@@ -411,49 +474,50 @@ cardinal.e=E
 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.
index e1daaf69657e5fce15a492419a2e81b0aaf1d68f..d31df3fa5366b4b774d1be8a55da7705b8c3684e 100644 (file)
@@ -9,313 +9,83 @@ menu.file.save=Simpan
 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
@@ -328,132 +98,14 @@ filetype.pov=Berkas POV
 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=
index 628f09db585fa3c17bf97ca1010b7ac500ebce51..a219fabd062228c9c6ef6bffa3d1753b1885e681 100644 (file)
@@ -11,7 +11,6 @@ menu.edit=Edita
 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
@@ -22,7 +21,7 @@ menu.edit.mergetracksegments=Unisci segmenti traccia
 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
@@ -40,6 +39,8 @@ menu.view.browser.google=Google maps
 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 +
@@ -49,6 +50,25 @@ menu.map.newpoint=Crea punto nuovo
 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
@@ -56,22 +76,30 @@ function.sendtogps=Invia dati al 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
@@ -90,7 +118,7 @@ dialog.delimiter.other=Altro
 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
@@ -110,11 +138,11 @@ dialog.save.table.field=Campo
 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
@@ -130,7 +158,11 @@ dialog.exportpov.cameraz=Camera Z
 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
@@ -139,7 +171,7 @@ dialog.interpolate.title=Interpola i punti
 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!
@@ -150,7 +182,6 @@ dialog.pointedit.table.value=Valore
 dialog.pointedit.table.changed=Cambiato
 dialog.pointedit.changevalue.text=Inserisci il nuovo valore di questo campo
 dialog.pointedit.changevalue.title=Edita il campo
-dialog.pointnameedit.title=Edita il nome del waypoint
 dialog.pointnameedit.name=Nome del waypoint
 dialog.pointnameedit.uppercase=MAIUSCOLE
 dialog.pointnameedit.lowercase=minuscole
@@ -160,9 +191,11 @@ dialog.addtimeoffset.subtract=Scarto in sottrazione
 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
@@ -194,7 +227,12 @@ dialog.setmapbg.osma=Osma
 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
@@ -215,7 +253,7 @@ dialog.correlate.options.timelimit=Limite di tempo
 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
@@ -225,11 +263,11 @@ dialog.compress.wackypoints.paramdesc=Fattore distanza
 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
@@ -241,11 +279,11 @@ dialog.about.systeminfo.povray=Povray installato
 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
@@ -255,11 +293,32 @@ dialog.about.credits.thanks=Grazie a
 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
@@ -272,25 +331,27 @@ dialog.3dlines.intro=Queste sono le linee della griglia per la visione 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
@@ -306,16 +367,17 @@ button.edit=Modifica
 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
@@ -348,13 +410,14 @@ details.altitude.to=a
 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
@@ -377,8 +440,8 @@ fieldname.prefix=Campo
 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
@@ -422,6 +485,7 @@ undo.insert=inserisci punti
 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
@@ -432,10 +496,10 @@ undo.createpoint=crea punto
 # 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
@@ -453,7 +517,7 @@ error.function.noop.title=La funzione non ha avuto effetto
 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
index 5478bd1a38979cbe872bf64b4354d7cc93d3ab24..8e05b67d816ce7262ad973953bfc356f69117ffd 100644 (file)
@@ -3,26 +3,25 @@
 
 # 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
@@ -40,43 +39,72 @@ menu.view.browser.google=Mapy Google
 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
@@ -85,73 +113,76 @@ dialog.delimiter.label=Pole separatora
 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
@@ -160,12 +191,14 @@ dialog.addtimeoffset.subtract=Odejmij czas
 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
@@ -174,63 +207,68 @@ dialog.saveexif.photostatus.connected=Po\u0142\u0105czony
 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
@@ -246,39 +284,61 @@ dialog.about.no=Nie
 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
@@ -291,6 +351,7 @@ confirm.photo.disconnect=od\u0142\u0105czono zdj\u0119cie
 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
@@ -299,9 +360,9 @@ button.next=Nast\u0119pny
 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
@@ -313,9 +374,10 @@ button.notoall=Nie na wszystko
 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
@@ -329,60 +391,61 @@ filetype.svg=Pliki SVG
 
 # 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
@@ -417,43 +480,44 @@ undo.editpoint=edycja punktu
 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
index 3944ed23e2898d85553be1705ce363fdcdb3cd74..53e0142d1d36bf310aa707c7aeeac64926274c8c 100644 (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=
index 95c1df050f1fc62229fe4a9ae1f655bbb3f5c49d..9e9b22e5e0ae4e09bb59e60f88c37bd26120390f 100644 (file)
@@ -2,19 +2,18 @@
 # 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
@@ -42,418 +41,62 @@ menu.view.browser.mapquest=Mapquest
 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
diff --git a/tim/prune/lang/prune-texts_zh.properties b/tim/prune/lang/prune-texts_zh.properties
new file mode 100644 (file)
index 0000000..d91fea7
--- /dev/null
@@ -0,0 +1,523 @@
+# 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
index de1e7caea8d6b2bd909943f6ad59f34661815096..1d12397dd61514a904faae91b0d32902c341afe2 100644 (file)
@@ -12,7 +12,9 @@ import java.util.ArrayList;
  */
 public class FileCacher
 {
+       /** File to cache */
        private File _file = null;
+       /** Array to hold lines of file */
        private String[] _contentArray = null;
 
 
index b3c03b435926411f67f6ab02d164e074d6616fa2..889f1d7933a6ec2357b07fd6c3b9b3ac3affebb9 100644 (file)
@@ -1,7 +1,7 @@
 package tim.prune.load;
 
 import java.io.File;
-
+import java.util.ArrayList;
 import javax.swing.JFileChooser;
 import javax.swing.JFrame;
 
@@ -21,6 +21,7 @@ public class FileLoader
        private JFileChooser _fileChooser = null;
        private JFrame _parentFrame;
        private TextFileLoader _textFileLoader = null;
+       private NmeaFileLoader _nmeaFileLoader = null;
        private XmlFileLoader _xmlFileLoader = null;
        private ZipFileLoader _zipFileLoader = null;
 
@@ -35,6 +36,7 @@ public class FileLoader
                _app = inApp;
                _parentFrame = inParentFrame;
                _textFileLoader = new TextFileLoader(inApp, inParentFrame);
+               _nmeaFileLoader = new NmeaFileLoader(inApp);
                _xmlFileLoader = new XmlFileLoader(inApp);
                _zipFileLoader = new ZipFileLoader(inApp, _xmlFileLoader);
        }
@@ -56,47 +58,76 @@ public class FileLoader
                        _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
         */
index 99464f705c44000054cc3b48b92b1cbcb7508c3d..60c2c5dbcf5e429e21d4d3d76a18460d273b0525 100644 (file)
@@ -33,7 +33,7 @@ public class FileSplitter
                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;
@@ -61,9 +61,11 @@ public class FileSplitter
                        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)
                                        {
@@ -120,4 +122,19 @@ public class FileSplitter
                // 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;
+       }
 }
index 0d3d8f4dce06b697ba72088040c2470d314ae5fd..3ec3c6bcfddc217d5c77684727bebb6f971eaa09 100644 (file)
@@ -6,6 +6,8 @@ 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.io.BufferedReader;
 import java.io.InputStreamReader;
 
@@ -68,7 +70,7 @@ public class GpsLoader extends GenericFunction implements Runnable
        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()),
@@ -109,12 +111,21 @@ public class GpsLoader extends GenericFunction implements Runnable
                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));
@@ -230,20 +241,26 @@ public class GpsLoader extends GenericFunction implements Runnable
        {
                // 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;
index 7939f1b0080310f28076c6dceff6b317e22d2644..194f2b7f08b83a09d2a11b72fb2ac4e48f77038c 100644 (file)
@@ -92,8 +92,9 @@ public class JpegLoader implements Runnable
                        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;
@@ -311,7 +312,8 @@ public class JpegLoader implements Runnable
                                {
                                        // 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())
diff --git a/tim/prune/load/NmeaFileLoader.java b/tim/prune/load/NmeaFileLoader.java
new file mode 100644 (file)
index 0000000..ad01789
--- /dev/null
@@ -0,0 +1,132 @@
+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;
+       }
+}
diff --git a/tim/prune/load/NmeaMessage.java b/tim/prune/load/NmeaMessage.java
new file mode 100644 (file)
index 0000000..e524e39
--- /dev/null
@@ -0,0 +1,96 @@
+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;
+       }
+}
index d4a9aa648bdd31df94288e68d15d6cb286be672f..64c9ebadff0e1955fa372a10ddf1e1868c446c82 100644 (file)
@@ -127,6 +127,7 @@ public class TextFileLoader
                else {
                        // Didn't pass pre-check
                        _app.showErrorMessage("error.load.dialogtitle", "error.load.noread");
+                       _app.informNoDataLoaded();
                }
        }
 
@@ -255,6 +256,7 @@ public class TextFileLoader
                        public void actionPerformed(ActionEvent e)
                        {
                                _dialog.dispose();
+                               _app.informNoDataLoaded();
                        }
                });
                buttonPanel.add(cancelButton);
index 3bdfb3ebbcc892e8a494f8fa3d665eb822a506c8..8ab3e17978b878dca0221d8c80c9156fa9b5d1d4 100644 (file)
@@ -17,12 +17,15 @@ public class GpxHandler extends XmlHandler
        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
@@ -58,6 +61,10 @@ public class GpxHandler extends XmlHandler
                {
                        _insideTime = true;
                }
+//             else if (qName.equalsIgnoreCase("type"))
+//             {
+//                     _insideType = true;
+//             }
                else if (qName.equalsIgnoreCase("trkseg"))
                {
                        _startSegment = true;
index bed877479aa231c5d2a1ae8ef702c5557b27aa26..787dd0bd1cfc8d1df08cdd3caeb74c471a497bcb 100644 (file)
@@ -86,7 +86,7 @@ public class KmlHandler extends XmlHandler
        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)
@@ -103,7 +103,7 @@ public class KmlHandler extends XmlHandler
                                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);
                                }
index cf3801c3053fd34f8b7322b35f764a9add4e73c3..ba9407c8063c9ea9beb44c213c3da53a099af6dd 100644 (file)
@@ -1,9 +1,11 @@
 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;
@@ -33,7 +35,7 @@ public class ZipFileLoader
        }
 
        /**
-        * 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)
@@ -75,8 +77,52 @@ public class ZipFileLoader
                        }
                }
                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());
+               }
+       }
 }
index 660750a38e579641190d00249c84fbbbcd598ada..51d9cc777da1fee7b8ee3de257bb9303bb8c0535 100644 (file)
@@ -1,4 +1,4 @@
-Prune version 7
+Prune version 8
 ===============
 
 Prune is an application for viewing, editing and managing coordinate data from GPS systems,
@@ -17,7 +17,7 @@ Running
 =======
 
 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
@@ -25,8 +25,21 @@ in a file manager window to execute it.  A shortcut, menu item, alias, desktop i
 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
 ==================
index 6533fcbed0e39f3043bde1bca12cf22c762374f2..f8e04de67a5a1308ca6d5706ed0f3ab505de1fec 100644 (file)
@@ -19,6 +19,7 @@ import javax.swing.JProgressBar;
 import javax.swing.JScrollPane;
 import javax.swing.JTable;
 
+import tim.prune.Config;
 import tim.prune.ExternalTools;
 import tim.prune.I18nManager;
 import tim.prune.UpdateMessageBroker;
@@ -79,7 +80,7 @@ public class ExifSaver implements Runnable
        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
@@ -331,7 +332,7 @@ public class ExifSaver implements Runnable
        {
                // 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
@@ -353,7 +354,7 @@ public class ExifSaver implements Runnable
        {
                // 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;
index ea4efb87087f0ca33309b1edb2454ba7564018c7..3ea60db55961c093a826e659aab5a6a0ef79c88c 100644 (file)
@@ -65,9 +65,11 @@ public class FileSaver
        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};
@@ -224,13 +226,18 @@ public class FileSaver
                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);
@@ -251,7 +258,7 @@ public class FileSaver
                }
                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);
@@ -272,7 +279,7 @@ public class FileSaver
                }
                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);
@@ -367,6 +374,7 @@ public class FileSaver
                        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);
@@ -381,6 +389,8 @@ public class FileSaver
         */
        private boolean saveToFile()
        {
+               // TODO: Shorten method
+               if (!_pointTypeSelector.getAnythingSelected()) {return false;}
                boolean saveOK = true;
                FileWriter writer = null;
                if (_fileChooser == null)
@@ -392,8 +402,9 @@ public class FileSaver
                        _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)
                {
@@ -466,10 +477,16 @@ public class FileSaver
                                        }
 
                                        // 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++)
@@ -530,10 +547,10 @@ public class FileSaver
                                                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();
                                }
@@ -546,10 +563,8 @@ public class FileSaver
                                finally
                                {
                                        // try to close file if it's open
-                                       try
-                                       {
-                                               if (writer != null)
-                                               {
+                                       try {
+                                               if (writer != null) {
                                                        writer.close();
                                                }
                                        }
index e3777a23e88d28c9ef5739e9e0a2593dd479c9d0..a9c59a8ce1e169adeb5d2c64fb9eb329023b2869 100644 (file)
@@ -65,7 +65,7 @@ public class GpsSaver extends GenericFunction implements Runnable
        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()),
@@ -106,12 +106,12 @@ public class GpsSaver extends GenericFunction implements Runnable
                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);
@@ -228,21 +228,27 @@ public class GpsSaver extends GenericFunction implements Runnable
        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);
@@ -251,7 +257,8 @@ public class GpsSaver extends GenericFunction implements Runnable
                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
index 89d40ef2efcb2ca2bc8b8e5ab1a78e9277584878..0bd93d2f0926ad09b6cdc73b637b464f006a6011 100644 (file)
@@ -46,6 +46,7 @@ public class GpxExporter extends GenericFunction implements Runnable
        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;
@@ -85,6 +86,7 @@ public class GpxExporter extends GenericFunction implements Runnable
                        _dialog.getContentPane().add(makeDialogComponents());
                        _dialog.pack();
                }
+               _pointTypeSelector.init(_app.getTrackInfo());
                _dialog.setVisible(true);
        }
 
@@ -109,6 +111,9 @@ public class GpxExporter extends GenericFunction implements Runnable
                _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);
@@ -147,7 +152,11 @@ public class GpxExporter extends GenericFunction implements Runnable
         */
        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();
@@ -155,8 +164,8 @@ public class GpxExporter extends GenericFunction implements Runnable
                        _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;
@@ -203,14 +212,16 @@ public class GpxExporter extends GenericFunction implements Runnable
                {
                        // 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")
@@ -241,12 +252,12 @@ public class GpxExporter extends GenericFunction implements Runnable
         * @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);
@@ -278,15 +289,23 @@ public class GpxExporter extends GenericFunction implements Runnable
                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
                        {
@@ -306,19 +325,23 @@ public class GpxExporter extends GenericFunction implements Runnable
                                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
index 67ad261f62a5883583c2697ba4937dee7746aabf..42ba748ff242b06a84b1bb3dccaa22ee479f0d2f 100644 (file)
@@ -56,18 +56,25 @@ public class KmlExporter extends GenericFunction implements Runnable
        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;
 
 
        /**
@@ -101,6 +108,9 @@ public class KmlExporter extends GenericFunction implements Runnable
                        _dialog.pack();
                }
                enableCheckboxes();
+               _descriptionField.setEnabled(true);
+               _okButton.setEnabled(true);
+               _progressLabel.setText("");
                _progressBar.setVisible(false);
                _dialog.setVisible(true);
        }
@@ -113,7 +123,7 @@ public class KmlExporter extends GenericFunction implements Runnable
        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
@@ -122,15 +132,22 @@ public class KmlExporter extends GenericFunction implements Runnable
                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)
                        {
@@ -141,29 +158,35 @@ public class KmlExporter extends GenericFunction implements Runnable
                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();
                        }
                });
@@ -178,6 +201,7 @@ public class KmlExporter extends GenericFunction implements Runnable
         */
        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;
@@ -191,15 +215,19 @@ public class KmlExporter extends GenericFunction implements Runnable
         */
        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())
@@ -239,6 +267,7 @@ public class KmlExporter extends GenericFunction implements Runnable
                                {
                                        // New file or overwrite confirmed, so initiate export in separate thread
                                        _exportFile = file;
+                                       _cancelPressed = false;
                                        new Thread(this).start();
                                }
                                else
@@ -255,12 +284,23 @@ public class KmlExporter extends GenericFunction implements Runnable
         */
        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
@@ -275,13 +315,20 @@ public class KmlExporter extends GenericFunction implements Runnable
                        {
                                // 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);
 
@@ -292,18 +339,12 @@ public class KmlExporter extends GenericFunction implements Runnable
                                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")
@@ -337,6 +378,9 @@ public class KmlExporter extends GenericFunction implements Runnable
        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(""))
@@ -349,28 +393,34 @@ public class KmlExporter extends GenericFunction implements Runnable
                }
                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)
                                {
@@ -378,20 +428,24 @@ public class KmlExporter extends GenericFunction implements Runnable
                                        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>";
 
@@ -409,7 +463,8 @@ public class KmlExporter extends GenericFunction implements Runnable
                                }
                                if (!point.isWaypoint() && point.getPhoto() == null)
                                {
-                                       exportTrackpoint(point, inWriter, exportAltitudes);
+                                       exportTrackpoint(point, inWriter);
+                                       numSaved++;
                                        firstTrackpoint = false;
                                }
                        }
@@ -417,7 +472,7 @@ public class KmlExporter extends GenericFunction implements Runnable
                        inWriter.write(trackEnd);
                }
                inWriter.write("</Folder>\n</kml>");
-               return numPoints;
+               return numSaved;
        }
 
 
@@ -425,24 +480,27 @@ public class KmlExporter extends GenericFunction implements Runnable
         * 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 {
@@ -458,11 +516,11 @@ public class KmlExporter extends GenericFunction implements Runnable
         * @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>");
@@ -480,15 +538,19 @@ public class KmlExporter extends GenericFunction implements Runnable
                }
                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 {
@@ -502,16 +564,15 @@ public class KmlExporter extends GenericFunction implements Runnable
         * 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 {
@@ -539,7 +600,7 @@ public class KmlExporter extends GenericFunction implements Runnable
                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)
@@ -580,8 +641,7 @@ public class KmlExporter extends GenericFunction implements Runnable
                for (int i=0; i<numPoints; i++)
                {
                        point = _track.getPoint(i);
-                       if (point.getPhoto() != null)
-                       {
+                       if (point.getPhoto() != null) {
                                numPhotos++;
                        }
                }
diff --git a/tim/prune/save/PointTypeSelector.java b/tim/prune/save/PointTypeSelector.java
new file mode 100644 (file)
index 0000000..6dcd1ea
--- /dev/null
@@ -0,0 +1,114 @@
+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();
+       }
+}
index c96d744dbcfc0c35f6886d5e75fbe752cccc7b7a..654aac6d4c8ed83baadb8ddc099f11527c466596 100644 (file)
@@ -167,7 +167,7 @@ public class PovExporter extends GenericFunction
                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;
                }
@@ -265,8 +265,8 @@ public class PovExporter extends GenericFunction
                        _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
@@ -295,7 +295,7 @@ public class PovExporter extends GenericFunction
                                        {
                                                // file saved
                                                // Store directory in config for later
-                                               Config.setWorkingDirectory(file.getParentFile());
+                                               Config.setConfigString(Config.KEY_TRACK_DIR, file.getParentFile().getAbsolutePath());
                                        }
                                        else
                                        {
@@ -359,7 +359,7 @@ public class PovExporter extends GenericFunction
                }
                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
@@ -394,6 +394,9 @@ public class PovExporter extends GenericFunction
                {
                        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> }", "",
@@ -428,7 +431,7 @@ public class PovExporter extends GenericFunction
                  "   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",
@@ -514,7 +517,7 @@ public class PovExporter extends GenericFunction
                  "  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>}",
index e3531f08d6acb3f4914e632c6236a0ef2121fd9d..0bde564c373fe45199aca872bdbcf49f18cf97de 100644 (file)
@@ -465,7 +465,7 @@ public class Java3DWindow implements ThreeDWindow
        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);
        }
@@ -485,7 +485,7 @@ public class Java3DWindow implements ThreeDWindow
        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);
        }
index 929659bcd8ee92704bd0949b29d951f5579946a9..65f1152e913861555bd10a8f5786415bbe9ce15e 100644 (file)
@@ -18,7 +18,7 @@ public class ThreeDModel
        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;
 
diff --git a/tim/prune/undo/UndoAddAltitudeOffset.java b/tim/prune/undo/UndoAddAltitudeOffset.java
new file mode 100644 (file)
index 0000000..4dbdd08
--- /dev/null
@@ -0,0 +1,62 @@
+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();
+       }
+}
index 1b3f3ef9077746e51ad3d723cc442dc36ad373a3..39676af411d0eaa374aae01070bd2139cd01505a 100644 (file)
@@ -76,6 +76,6 @@ public class UndoInsert implements UndoOperation
                        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