]> gitweb.fperrin.net Git - GpsPrune.git/commitdiff
Version 14, October 2012
authoractivityworkshop <mail@activityworkshop.net>
Sun, 15 Feb 2015 10:15:00 +0000 (11:15 +0100)
committeractivityworkshop <mail@activityworkshop.net>
Sun, 15 Feb 2015 10:15:00 +0000 (11:15 +0100)
125 files changed:
tim/prune/App.java
tim/prune/FunctionLibrary.java
tim/prune/GpsPrune.java
tim/prune/config/Config.java
tim/prune/copyright.txt
tim/prune/correlate/Correlator.java
tim/prune/correlate/MediaPreviewTableModel.java
tim/prune/correlate/MediaPreviewTableRow.java
tim/prune/correlate/MediaSelectionTableModel.java
tim/prune/data/Altitude.java
tim/prune/data/AltitudeRange.java
tim/prune/data/DataPoint.java
tim/prune/data/Distance.java
tim/prune/data/Field.java
tim/prune/data/MediaList.java
tim/prune/data/MediaObject.java
tim/prune/data/MidpointData.java [new file with mode: 0644]
tim/prune/data/PointScaler.java
tim/prune/data/RecentFile.java
tim/prune/data/Selection.java
tim/prune/data/SpeedCalculator.java [new file with mode: 0644]
tim/prune/data/SpeedValue.java [new file with mode: 0644]
tim/prune/data/Timestamp.java
tim/prune/data/Track.java
tim/prune/data/TrackInfo.java
tim/prune/data/Unit.java [new file with mode: 0644]
tim/prune/data/UnitSet.java [new file with mode: 0644]
tim/prune/data/UnitSetLibrary.java [new file with mode: 0644]
tim/prune/function/AddAltitudeOffset.java
tim/prune/function/CropToSelection.java [new file with mode: 0644]
tim/prune/function/DeleteBitOfTrackFunction.java [new file with mode: 0644]
tim/prune/function/DeleteSelectedRangeFunction.java [new file with mode: 0644]
tim/prune/function/DiskCacheConfig.java
tim/prune/function/FullRangeDetails.java
tim/prune/function/GetWikipediaFunction.java
tim/prune/function/InterpolateFunction.java [new file with mode: 0644]
tim/prune/function/PasteCoordinates.java
tim/prune/function/PhotoComparer.java [new file with mode: 0644]
tim/prune/function/PhotoPopupFunction.java
tim/prune/function/PlayAudioFunction.java
tim/prune/function/RearrangePhotosFunction.java
tim/prune/function/SearchWikipediaNames.java
tim/prune/function/cache/ManageCacheFunction.java
tim/prune/function/cache/RowInfo.java
tim/prune/function/charts/Charter.java
tim/prune/function/compress/CompressTrackFunction.java
tim/prune/function/compress/CompressionAlgorithm.java
tim/prune/function/compress/MarkPointsInRectangleFunction.java [new file with mode: 0644]
tim/prune/function/distance/DistanceFunction.java
tim/prune/function/distance/DistanceTableModel.java
tim/prune/function/edit/PointNameEditor.java
tim/prune/function/gpsies/GenericDownloaderFunction.java
tim/prune/function/gpsies/GetGpsiesFunction.java
tim/prune/function/gpsies/TrackListModel.java
tim/prune/function/gpsies/UploadGpsiesFunction.java
tim/prune/gui/DetailsDisplay.java
tim/prune/gui/IconManager.java
tim/prune/gui/ImageUtils.java
tim/prune/gui/MenuManager.java
tim/prune/gui/SelectorDisplay.java
tim/prune/gui/images/add_photo_icon.png [changed mode: 0755->0644]
tim/prune/gui/images/add_textfile_icon.png [changed mode: 0755->0644]
tim/prune/gui/images/autopan.gif
tim/prune/gui/images/connect_photo_icon.png [deleted file]
tim/prune/gui/images/cut_and_move.gif
tim/prune/gui/images/drag_points_icon.gif [new file with mode: 0644]
tim/prune/gui/images/drag_points_icon_on.gif [new file with mode: 0644]
tim/prune/gui/images/scalebar.gif
tim/prune/gui/map/CloudmadeMapSource.java
tim/prune/gui/map/DiskTileCacher.java
tim/prune/gui/map/MapCanvas.java
tim/prune/gui/map/MapPosition.java
tim/prune/gui/map/MapSource.java
tim/prune/gui/map/MapSourceLibrary.java
tim/prune/gui/map/MapTileManager.java
tim/prune/gui/map/MapUtils.java
tim/prune/gui/map/MemTileCacher.java
tim/prune/gui/map/OsmMapSource.java
tim/prune/gui/map/ScaleBar.java
tim/prune/gui/map/TileDownloader.java [new file with mode: 0644]
tim/prune/gui/profile/AltitudeData.java
tim/prune/gui/profile/ProfileChart.java
tim/prune/gui/profile/ProfileData.java
tim/prune/gui/profile/SpeedData.java
tim/prune/gui/profile/VerticalSpeedData.java [new file with mode: 0644]
tim/prune/lang/prune-texts_af.properties
tim/prune/lang/prune-texts_cz.properties
tim/prune/lang/prune-texts_da.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_fa.properties
tim/prune/lang/prune-texts_fr.properties
tim/prune/lang/prune-texts_hu.properties
tim/prune/lang/prune-texts_in.properties
tim/prune/lang/prune-texts_it.properties
tim/prune/lang/prune-texts_ja.properties
tim/prune/lang/prune-texts_ko.properties
tim/prune/lang/prune-texts_nl.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_ru.properties
tim/prune/lang/prune-texts_tr.properties
tim/prune/lang/prune-texts_zh.properties
tim/prune/load/MediaHelper.java
tim/prune/load/NmeaFileLoader.java
tim/prune/load/TextFileLoader.java
tim/prune/readme.txt
tim/prune/save/FileSaver.java
tim/prune/save/GpsSaver.java
tim/prune/save/GpxExporter.java
tim/prune/save/PovExporter.java
tim/prune/threedee/Java3DWindow.java
tim/prune/threedee/ThreeDModel.java
tim/prune/undo/UndoAddAltitudeOffset.java
tim/prune/undo/UndoDeleteMarked.java [moved from tim/prune/undo/UndoCompress.java with 81% similarity]
tim/prune/undo/UndoDeletePoint.java
tim/prune/undo/UndoDeleteRange.java
tim/prune/undo/UndoEditPoint.java
tim/prune/undo/UndoInsert.java
tim/prune/undo/UndoInterpolate.java [new file with mode: 0644]
tim/prune/undo/UndoLoadPhotos.java
tim/prune/undo/UndoLookupSrtm.java

index 770fd2089aaac23518ecd687bec0f0d8878ee738..205d88ae11c74165c23bd6aa7ef1fab275af4485 100644 (file)
@@ -62,8 +62,12 @@ public class App
        private boolean _mangleTimestampsConfirmed = false;
        private Viewport _viewport = null;
        private ArrayList<File> _dataFiles = null;
        private boolean _mangleTimestampsConfirmed = false;
        private Viewport _viewport = null;
        private ArrayList<File> _dataFiles = null;
-       private boolean _firstDataFile = true;
+       private boolean _autoAppendNextFile = false;
        private boolean _busyLoading = false;
        private boolean _busyLoading = false;
+       private AppMode _appMode = AppMode.NORMAL;
+
+       /** Enum for the app mode - currently only two options but may expand later */
+       public enum AppMode {NORMAL, DRAWRECT};
 
 
        /**
 
 
        /**
@@ -123,14 +127,15 @@ public class App
                if (inDataFiles == null || inDataFiles.size() == 0) {
                        _dataFiles = null;
                }
                if (inDataFiles == null || inDataFiles.size() == 0) {
                        _dataFiles = null;
                }
-               else {
+               else
+               {
                        _dataFiles = inDataFiles;
                        File f = _dataFiles.get(0);
                        _dataFiles.remove(0);
                        // Start load of specified file
                        if (_fileLoader == null)
                                _fileLoader = new FileLoader(this, _frame);
                        _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;
+                       _autoAppendNextFile = false; // prompt for append
                        _fileLoader.openFile(f);
                }
        }
                        _fileLoader.openFile(f);
                }
        }
@@ -144,6 +149,7 @@ public class App
        {
                _undoStack.add(inUndo);
                UpdateMessageBroker.informSubscribers(inConfirmText);
        {
                _undoStack.add(inUndo);
                UpdateMessageBroker.informSubscribers(inConfirmText);
+               setCurrentMode(AppMode.NORMAL);
        }
 
        /**
        }
 
        /**
@@ -272,6 +278,7 @@ public class App
                DataPoint currentPoint = _trackInfo.getCurrentPoint();
                if (currentPoint != null)
                {
                DataPoint currentPoint = _trackInfo.getCurrentPoint();
                if (currentPoint != null)
                {
+                       // Check for photo
                        boolean deletePhoto = false;
                        Photo currentPhoto = currentPoint.getPhoto();
                        if (currentPhoto != null)
                        boolean deletePhoto = false;
                        Photo currentPhoto = currentPoint.getPhoto();
                        if (currentPhoto != null)
@@ -291,10 +298,11 @@ public class App
                        // store necessary information to undo it later
                        int pointIndex = _trackInfo.getSelection().getCurrentPointIndex();
                        int photoIndex = _trackInfo.getPhotoList().getPhotoIndex(currentPhoto);
                        // store necessary information to undo it later
                        int pointIndex = _trackInfo.getSelection().getCurrentPointIndex();
                        int photoIndex = _trackInfo.getPhotoList().getPhotoIndex(currentPhoto);
+                       int audioIndex = _trackInfo.getAudioList().getAudioIndex(currentPoint.getAudio());
                        DataPoint nextTrackPoint = _trackInfo.getTrack().getNextTrackPoint(pointIndex + 1);
                        // Construct Undo object
                        UndoOperation undo = new UndoDeletePoint(pointIndex, currentPoint, photoIndex,
                        DataPoint nextTrackPoint = _trackInfo.getTrack().getNextTrackPoint(pointIndex + 1);
                        // Construct Undo object
                        UndoOperation undo = new UndoDeletePoint(pointIndex, currentPoint, photoIndex,
-                               nextTrackPoint != null && nextTrackPoint.getSegmentStart());
+                               audioIndex, nextTrackPoint != null && nextTrackPoint.getSegmentStart());
                        // call track to delete point
                        if (_trackInfo.deletePoint())
                        {
                        // call track to delete point
                        if (_trackInfo.deletePoint())
                        {
@@ -312,94 +320,15 @@ public class App
                                                // decouple photo from point
                                                currentPhoto.setDataPoint(null);
                                        }
                                                // decouple photo from point
                                                currentPhoto.setDataPoint(null);
                                        }
-                                       UpdateMessageBroker.informSubscribers();
+                                       UpdateMessageBroker.informSubscribers(DataSubscriber.PHOTOS_MODIFIED);
                                }
                                }
-                               // Confirm
-                               UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.deletepoint.single"));
-                       }
-               }
-       }
-
-
-       /**
-        * Delete the currently selected range
-        */
-       public void deleteSelectedRange()
-       {
-               if (_track == null) return;
-               // Find out if photos should be deleted or not
-               int selStart = _trackInfo.getSelection().getStart();
-               int selEnd = _trackInfo.getSelection().getEnd();
-               if (selStart >= 0 && selEnd >= selStart)
-               {
-                       int numToDelete = selEnd - selStart + 1;
-                       boolean[] deletePhotos = new boolean[numToDelete];
-                       Photo[] photosToDelete = new Photo[numToDelete];
-                       boolean deleteAll = false;
-                       boolean deleteNone = false;
-                       String[] questionOptions = {I18nManager.getText("button.yes"), I18nManager.getText("button.no"),
-                               I18nManager.getText("button.yestoall"), I18nManager.getText("button.notoall"),
-                               I18nManager.getText("button.cancel")};
-                       DataPoint point = null;
-                       for (int i=0; i<numToDelete; i++)
-                       {
-                               point = _trackInfo.getTrack().getPoint(i + selStart);
-                               if (point != null && point.getPhoto() != null)
-                               {
-                                       if (deleteAll)
-                                       {
-                                               deletePhotos[i] = true;
-                                               photosToDelete[i] = point.getPhoto();
-                                       }
-                                       else if (deleteNone) {deletePhotos[i] = false;}
-                                       else
-                                       {
-                                               int response = JOptionPane.showOptionDialog(_frame,
-                                                       I18nManager.getText("dialog.deletepoint.deletephoto") + " " + point.getPhoto().getName(),
-                                                       I18nManager.getText("dialog.deletepoint.title"),
-                                                       JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null,
-                                                       questionOptions, questionOptions[1]);
-                                               // check for cancel or close
-                                               if (response == 4 || response == -1) {return;}
-                                               // check for yes or yes to all
-                                               if (response == 0 || response == 2)
-                                               {
-                                                       deletePhotos[i] = true;
-                                                       photosToDelete[i] = point.getPhoto();
-                                                       if (response == 2) {deleteAll = true;}
-                                               }
-                                               // check for no to all
-                                               if (response == 3) {deleteNone = true;}
-                                       }
+                               // Delete audio object (without bothering to ask)
+                               if (audioIndex > -1) {
+                                       _trackInfo.getAudioList().deleteAudio(audioIndex);
                                }
                                }
-                       }
-                       // add information to undo stack
-                       UndoDeleteRange undo = new UndoDeleteRange(_trackInfo);
-                       // delete requested photos
-                       for (int i=0; i<numToDelete; i++)
-                       {
-                               point = _trackInfo.getTrack().getPoint(i + selStart);
-                               if (point != null && point.getPhoto() != null)
-                               {
-                                       if (deletePhotos[i])
-                                       {
-                                               // delete photo from list
-                                               _trackInfo.getPhotoList().deletePhoto(_trackInfo.getPhotoList().getPhotoIndex(point.getPhoto()));
-                                       }
-                                       else
-                                       {
-                                               // decouple from point
-                                               point.getPhoto().setDataPoint(null);
-                                       }
-                               }
-                       }
-                       // call track to delete range
-                       if (_trackInfo.deleteRange())
-                       {
-                               _undoStack.push(undo);
                                // Confirm
                                // Confirm
-                               UpdateMessageBroker.informSubscribers("" + numToDelete + " "
-                                       + I18nManager.getText("confirm.deletepoint.multi"));
+                               UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.deletepoint.single"));
+                               UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_ADDED_OR_REMOVED);
                        }
                }
        }
                        }
                }
        }
@@ -410,7 +339,7 @@ public class App
         */
        public void finishCompressTrack()
        {
         */
        public void finishCompressTrack()
        {
-               UndoCompress undo = new UndoCompress(_track);
+               UndoDeleteMarked undo = new UndoDeleteMarked(_track);
                // call track to do compress
                int numPointsDeleted = _trackInfo.deleteMarkedPoints();
                // add to undo stack if successful
                // call track to do compress
                int numPointsDeleted = _trackInfo.deleteMarkedPoints();
                // add to undo stack if successful
@@ -422,7 +351,7 @@ public class App
                                 + (numPointsDeleted==1?I18nManager.getText("confirm.deletepoint.single"):I18nManager.getText("confirm.deletepoint.multi")));
                }
                else {
                                 + (numPointsDeleted==1?I18nManager.getText("confirm.deletepoint.single"):I18nManager.getText("confirm.deletepoint.multi")));
                }
                else {
-                       showErrorMessage("function.compress", "dialog.compress.nonefound");
+                       showErrorMessage("function.compress", "dialog.deletemarked.nonefound");
                }
        }
 
                }
        }
 
@@ -528,29 +457,6 @@ public class App
        }
 
 
        }
 
 
-       /**
-        * Interpolate the two selected points
-        */
-       public void interpolateSelection()
-       {
-               // Get number of points to add
-               Object numPointsStr = JOptionPane.showInputDialog(_frame,
-                       I18nManager.getText("dialog.interpolate.parameter.text"),
-                       I18nManager.getText("dialog.interpolate.title"),
-                       JOptionPane.QUESTION_MESSAGE, null, null, "");
-               int numPoints = parseNumber(numPointsStr);
-               if (numPoints <= 0) return;
-
-               UndoInsert undo = new UndoInsert(_trackInfo.getSelection().getStart() + 1,
-                       numPoints);
-               // call track to interpolate
-               if (_trackInfo.interpolate(numPoints))
-               {
-                       _undoStack.add(undo);
-               }
-       }
-
-
        /**
         * Average the selected points
         */
        /**
         * Average the selected points
         */
@@ -570,7 +476,7 @@ public class App
 
 
        /**
 
 
        /**
-        * Create a new point at the given position
+        * Create a new point at the end of the track
         * @param inPoint point to add
         */
        public void createPoint(DataPoint inPoint)
         * @param inPoint point to add
         */
        public void createPoint(DataPoint inPoint)
@@ -589,6 +495,26 @@ public class App
        }
 
 
        }
 
 
+       /**
+        * Create a new point before the given position
+        * @param inPoint point to add
+        * @param inIndex index of following point
+        */
+       public void createPoint(DataPoint inPoint, int inIndex)
+       {
+               // create undo object
+               UndoInsert undo = new UndoInsert(inIndex, 1);
+               _undoStack.add(undo);
+               // add point to track
+               _track.insertPoint(inPoint, inIndex);
+               // ensure track's field list contains point's fields
+               _track.extendFieldList(inPoint.getFieldList());
+               _trackInfo.selectPoint(inIndex);
+               // update listeners
+               UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.createpoint"));
+       }
+
+
        /**
         * Cut the current selection and move it to before the currently selected point
         */
        /**
         * Cut the current selection and move it to before the currently selected point
         */
@@ -638,19 +564,6 @@ public class App
                _track.clearDeletionMarkers();
        }
 
                _track.clearDeletionMarkers();
        }
 
-       /**
-        * Receive loaded data and start load
-        * @param inFieldArray array of fields
-        * @param inDataArray array of data
-        * @param inAltFormat altitude format
-        * @param inSourceInfo information about the source of the data
-        */
-       public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray,
-               Altitude.Format inAltFormat, SourceInfo inSourceInfo)
-       {
-               informDataLoaded(inFieldArray, inDataArray, inAltFormat, inSourceInfo, null, null);
-       }
-
        /**
         * Receive loaded data and determine whether to filter on tracks or not
         * @param inFieldArray array of fields
        /**
         * Receive loaded data and determine whether to filter on tracks or not
         * @param inFieldArray array of fields
@@ -715,6 +628,7 @@ public class App
                        // go directly to load
                        informDataLoaded(loadedTrack, inSourceInfo);
                }
                        // go directly to load
                        informDataLoaded(loadedTrack, inSourceInfo);
                }
+               setCurrentMode(AppMode.NORMAL);
        }
 
 
        }
 
 
@@ -730,16 +644,19 @@ public class App
                {
                        // ask whether to replace or append
                        int answer = 0;
                {
                        // ask whether to replace or append
                        int answer = 0;
-                       if (_dataFiles == null || _firstDataFile) {
+                       if (_autoAppendNextFile) {
+                               // Automatically append the next file
+                               answer = JOptionPane.YES_OPTION;
+                       }
+                       else {
+                               // Ask whether to append or not
                                answer = JOptionPane.showConfirmDialog(_frame,
                                        I18nManager.getText("dialog.openappend.text"),
                                        I18nManager.getText("dialog.openappend.title"),
                                        JOptionPane.YES_NO_CANCEL_OPTION);
                        }
                                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;
-                       }
+                       _autoAppendNextFile = false; // reset flag to cancel autoappend
+
                        if (answer == JOptionPane.YES_OPTION)
                        {
                                // append data to current Track
                        if (answer == JOptionPane.YES_OPTION)
                        {
                                // append data to current Track
@@ -807,12 +724,20 @@ public class App
                loadNextFile();
        }
 
                loadNextFile();
        }
 
+       /**
+        * External trigger to automatically append the next loaded file
+        * instead of prompting to replace or append
+        */
+       public void autoAppendNextFile()
+       {
+               _autoAppendNextFile = true;
+       }
+
        /**
         * Load the next file in the waiting list, if any
         */
        private void loadNextFile()
        {
        /**
         * Load the next file in the waiting list, if any
         */
        private void loadNextFile()
        {
-               _firstDataFile = false;
                if (_dataFiles == null || _dataFiles.size() == 0) {
                        _dataFiles = null;
                }
                if (_dataFiles == null || _dataFiles.size() == 0) {
                        _dataFiles = null;
                }
@@ -821,6 +746,7 @@ public class App
                                public void run() {
                                        File f = _dataFiles.get(0);
                                        _dataFiles.remove(0);
                                public void run() {
                                        File f = _dataFiles.get(0);
                                        _dataFiles.remove(0);
+                                       _autoAppendNextFile = true;
                                        _fileLoader.openFile(f);
                                }
                        }).start();
                                        _fileLoader.openFile(f);
                                }
                        }).start();
@@ -941,32 +867,12 @@ public class App
                        showErrorMessageNoLookup("error.undofailed.title",
                                I18nManager.getText("error.undofailed.text") + " : " + ue.getMessage());
                        _undoStack.clear();
                        showErrorMessageNoLookup("error.undofailed.title",
                                I18nManager.getText("error.undofailed.text") + " : " + ue.getMessage());
                        _undoStack.clear();
-                       UpdateMessageBroker.informSubscribers();
                }
                catch (EmptyStackException empty) {}
                }
                catch (EmptyStackException empty) {}
+               UpdateMessageBroker.informSubscribers();
        }
 
 
        }
 
 
-       /**
-        * Helper method to parse an Object into an integer
-        * @param inObject object, eg from dialog
-        * @return int value given
-        */
-       private static int parseNumber(Object inObject)
-       {
-               int num = 0;
-               if (inObject != null)
-               {
-                       try
-                       {
-                               num = Integer.parseInt(inObject.toString());
-                       }
-                       catch (NumberFormatException nfe)
-                       {}
-               }
-               return num;
-       }
-
        /**
         * Show a map url in an external browser
         * @param inSourceIndex index of map source to use
        /**
         * Show a map url in an external browser
         * @param inSourceIndex index of map source to use
@@ -1035,4 +941,14 @@ public class App
        public boolean isBusyLoading() {
                return _busyLoading;
        }
        public boolean isBusyLoading() {
                return _busyLoading;
        }
+
+       /** @return current app mode */
+       public AppMode getCurrentMode() {
+               return _appMode;
+       }
+
+       /** @param inMode the current app mode */
+       public void setCurrentMode(AppMode inMode) {
+               _appMode = inMode;
+       }
 }
 }
index 0830049b57bb69c74760bc6b608dd74cde760386..f06dbe457983ad723c8f00ee9f3c8b797517b656 100644 (file)
@@ -36,6 +36,9 @@ public abstract class FunctionLibrary
        public static RearrangeWaypointsFunction FUNCTION_REARRANGE_WAYPOINTS = null;
        public static GenericFunction FUNCTION_REARRANGE_PHOTOS = null;
        public static GenericFunction FUNCTION_COMPRESS = null;
        public static RearrangeWaypointsFunction FUNCTION_REARRANGE_WAYPOINTS = null;
        public static GenericFunction FUNCTION_REARRANGE_PHOTOS = null;
        public static GenericFunction FUNCTION_COMPRESS = null;
+       public static GenericFunction FUNCTION_DELETE_RANGE = null;
+       public static GenericFunction FUNCTION_CROP_TRACK = null;
+       public static GenericFunction FUNCTION_INTERPOLATE = null;
        public static GenericFunction FUNCTION_LOOKUP_SRTM = null;
        public static GenericFunction FUNCTION_LOOKUP_WIKIPEDIA = null;
        public static GenericFunction FUNCTION_SEARCH_WIKIPEDIA = null;
        public static GenericFunction FUNCTION_LOOKUP_SRTM = null;
        public static GenericFunction FUNCTION_LOOKUP_WIKIPEDIA = null;
        public static GenericFunction FUNCTION_SEARCH_WIKIPEDIA = null;
@@ -98,6 +101,9 @@ public abstract class FunctionLibrary
                FUNCTION_REARRANGE_WAYPOINTS = new RearrangeWaypointsFunction(inApp);
                FUNCTION_REARRANGE_PHOTOS = new RearrangePhotosFunction(inApp);
                FUNCTION_COMPRESS = new CompressTrackFunction(inApp);
                FUNCTION_REARRANGE_WAYPOINTS = new RearrangeWaypointsFunction(inApp);
                FUNCTION_REARRANGE_PHOTOS = new RearrangePhotosFunction(inApp);
                FUNCTION_COMPRESS = new CompressTrackFunction(inApp);
+               FUNCTION_DELETE_RANGE = new DeleteSelectedRangeFunction(inApp);
+               FUNCTION_CROP_TRACK = new CropToSelection(inApp);
+               FUNCTION_INTERPOLATE = new InterpolateFunction(inApp);
                FUNCTION_LOOKUP_SRTM = new LookupSrtmFunction(inApp);
                FUNCTION_LOOKUP_WIKIPEDIA = new GetWikipediaFunction(inApp);
                FUNCTION_SEARCH_WIKIPEDIA = new SearchWikipediaNames(inApp);
                FUNCTION_LOOKUP_SRTM = new LookupSrtmFunction(inApp);
                FUNCTION_LOOKUP_WIKIPEDIA = new GetWikipediaFunction(inApp);
                FUNCTION_SEARCH_WIKIPEDIA = new SearchWikipediaNames(inApp);
index a444a02c9960b5fc41e35ebc245c9c914b0aa413..e1dc55e0574b29549d5d5596d1a8c9c6c620c753 100644 (file)
@@ -28,16 +28,16 @@ import tim.prune.gui.profile.ProfileChart;
 /**
  * GpsPrune is a tool to visualize, edit, convert and prune GPS data
  * Please see the included readme.txt or http://activityworkshop.net
 /**
  * GpsPrune is a tool to visualize, edit, convert and prune GPS data
  * Please see the included readme.txt or http://activityworkshop.net
- * This software is copyright activityworkshop.net 2006-2011 and made available through the Gnu GPL version 2.
+ * This software is copyright activityworkshop.net 2006-2012 and made available through the Gnu GPL version 2.
  * For license details please see the included license.txt.
  * GpsPrune is the main entry point to the application, including initialisation and launch
  */
 public class GpsPrune
 {
        /** Version number of application, used in about screen and for version check */
  * For license details please see the included license.txt.
  * GpsPrune is the main entry point to the application, including initialisation and launch
  */
 public class GpsPrune
 {
        /** Version number of application, used in about screen and for version check */
-       public static final String VERSION_NUMBER = "13.4";
+       public static final String VERSION_NUMBER = "14";
        /** Build number, just used for about screen */
        /** Build number, just used for about screen */
-       public static final String BUILD_NUMBER = "244c";
+       public static final String BUILD_NUMBER = "265a";
        /** Static reference to App object */
        private static App APP = null;
 
        /** Static reference to App object */
        private static App APP = null;
 
@@ -87,7 +87,7 @@ public class GpsPrune
                        {
                                // Check if a data file has been given
                                File f = new File(arg);
                        {
                                // Check if a data file has been given
                                File f = new File(arg);
-                               if (f.exists() && f.canRead()) {
+                               if (f.exists() && f.isFile() && f.canRead()) {
                                        dataFiles.add(f);
                                }
                                else
                                        dataFiles.add(f);
                                }
                                else
@@ -258,8 +258,11 @@ public class GpsPrune
        private static String makeUnknownParameterString(String inParam)
        {
                File file = new File(inParam);
        private static String makeUnknownParameterString(String inParam)
        {
                File file = new File(inParam);
-               if (file.exists()) {
-                       return (file.canRead() ? "Something wrong with file" : "Cannot read file") + " '" + inParam + "'";
+               if (file.exists())
+               {
+                       if (file.isDirectory()) return "'" + inParam + "' is a directory";
+                       if (!file.canRead())    return "Cannot read file '" + inParam + "'";
+                       return "Something wrong with file '" + inParam + "'";
                }
                do
                {
                }
                do
                {
index a286d7fcc116315d03d4666b3af2d0cd4883b8af..5a95bebdebc62d52c6da4f52ec7391026781c206 100644 (file)
@@ -5,6 +5,8 @@ import java.io.FileInputStream;
 import java.util.Properties;
 
 import tim.prune.data.RecentFileList;
 import java.util.Properties;
 
 import tim.prune.data.RecentFileList;
+import tim.prune.data.UnitSet;
+import tim.prune.data.UnitSetLibrary;
 
 
 /**
 
 
 /**
@@ -21,6 +23,8 @@ public abstract class Config
        private static ColourScheme _colourScheme = new ColourScheme();
        /** Recently-used file list */
        private static RecentFileList _recentFiles = new RecentFileList();
        private static ColourScheme _colourScheme = new ColourScheme();
        /** Recently-used file list */
        private static RecentFileList _recentFiles = new RecentFileList();
+       /** Current unit set */
+       private static UnitSet _unitSet = UnitSetLibrary.getUnitSet(null);
 
        /** Default config file */
        public static final File DEFAULT_CONFIG_FILE = new File(".pruneconfig");
 
        /** Default config file */
        public static final File DEFAULT_CONFIG_FILE = new File(".pruneconfig");
@@ -40,8 +44,8 @@ public abstract class Config
        public static final String KEY_GPS_FORMAT = "prune.gpsformat";
        /** Key for Povray font */
        public static final String KEY_POVRAY_FONT = "prune.povrayfont";
        public static final String KEY_GPS_FORMAT = "prune.gpsformat";
        /** Key for Povray font */
        public static final String KEY_POVRAY_FONT = "prune.povrayfont";
-       /** Key for metric/imperial */
-       public static final String KEY_METRIC_UNITS = "prune.metricunits";
+       /** Key for the selected unit set */
+       public static final String KEY_UNITSET_KEY  = "prune.unitsetkey";
        /** Key for index of map source */
        public static final String KEY_MAPSOURCE_INDEX = "prune.mapsource";
        /** Key for number of fixed map sources */
        /** Key for index of map source */
        public static final String KEY_MAPSOURCE_INDEX = "prune.mapsource";
        /** Key for number of fixed map sources */
@@ -135,6 +139,8 @@ public abstract class Config
                _configValues.putAll(props);
                _colourScheme.loadFromHex(_configValues.getProperty(KEY_COLOUR_SCHEME));
                _recentFiles = new RecentFileList(_configValues.getProperty(KEY_RECENT_FILES));
                _configValues.putAll(props);
                _colourScheme.loadFromHex(_configValues.getProperty(KEY_COLOUR_SCHEME));
                _recentFiles = new RecentFileList(_configValues.getProperty(KEY_RECENT_FILES));
+               _unitSet = UnitSetLibrary.getUnitSet(_configValues.getProperty(KEY_UNITSET_KEY));
+
                if (loadFailed) {
                        throw new ConfigException();
                }
                if (loadFailed) {
                        throw new ConfigException();
                }
@@ -159,6 +165,7 @@ public abstract class Config
                props.put(KEY_KMZ_IMAGE_WIDTH, "240");
                props.put(KEY_KMZ_IMAGE_HEIGHT, "240");
                props.put(KEY_AUTOSAVE_SETTINGS, "0"); // autosave false by default
                props.put(KEY_KMZ_IMAGE_WIDTH, "240");
                props.put(KEY_KMZ_IMAGE_HEIGHT, "240");
                props.put(KEY_AUTOSAVE_SETTINGS, "0"); // autosave false by default
+               props.put(KEY_UNITSET_KEY, "unitset.kilometres"); // metric by default
                return props;
        }
 
                return props;
        }
 
@@ -287,9 +294,9 @@ public abstract class Config
         */
        public static boolean isKeyBoolean(String inKey)
        {
         */
        public static boolean isKeyBoolean(String inKey)
        {
-               // Only two boolean keys so far
+               // Only one boolean key so far (after metric flag was removed)
                return inKey != null && (
                return inKey != null && (
-                       inKey.equals(KEY_METRIC_UNITS) || inKey.equals(KEY_SHOW_MAP));
+                       inKey.equals(KEY_SHOW_MAP));
        }
 
        /**
        }
 
        /**
@@ -299,4 +306,18 @@ public abstract class Config
        {
                setConfigString(KEY_COLOUR_SCHEME, _colourScheme.toString());
        }
        {
                setConfigString(KEY_COLOUR_SCHEME, _colourScheme.toString());
        }
+
+       /**
+        * @return the current unit set
+        */
+       public static UnitSet getUnitSet() {
+               return _unitSet;
+       }
+
+       public static void selectUnitSet(int inIndex)
+       {
+               _unitSet = UnitSetLibrary.getUnitSet(inIndex);
+               // Set name of set in config
+               setConfigString(KEY_UNITSET_KEY, _unitSet.getNameKey());
+       }
 }
 }
index d65d1dda57ca108c6eb889548d2bfa055b6e4410..b690fdc51102c8e6ce0faa6bb227c9307a47456b 100644 (file)
@@ -1,4 +1,4 @@
-The source code of GpsPrune is copyright 2006-2011 activityworkshop.net
+The source code of GpsPrune is copyright 2006-2012 activityworkshop.net
 and is distributed under the terms of the Gnu GPL version 2.
 
 Portions of the package jpeg.drew (if included in this package) were taken
 and is distributed under the terms of the Gnu GPL version 2.
 
 Portions of the package jpeg.drew (if included in this package) were taken
index 2a4b49f882937100705aa67195c48552676f70f1..85b96e92304b0a5f1da3ea470272d8d165582972 100644 (file)
@@ -35,6 +35,8 @@ import tim.prune.data.MediaList;
 import tim.prune.data.TimeDifference;
 import tim.prune.data.Timestamp;
 import tim.prune.data.Track;
 import tim.prune.data.TimeDifference;
 import tim.prune.data.Timestamp;
 import tim.prune.data.Track;
+import tim.prune.data.Unit;
+import tim.prune.data.UnitSetLibrary;
 
 /**
  * Abstract superclass of the two correlator functions
 
 /**
  * Abstract superclass of the two correlator functions
@@ -312,8 +314,10 @@ public abstract class Correlator extends GenericFunction
        {
                JPanel card = new JPanel();
                card.setLayout(new BorderLayout(10, 10));
        {
                JPanel card = new JPanel();
                card.setLayout(new BorderLayout(10, 10));
-               card.add(new JLabel(I18nManager.getText(
-                       "dialog.correlate." + getMediaTypeKey() + "select.intro")), BorderLayout.NORTH);
+               JLabel introLabel = new JLabel(I18nManager.getText(
+                       "dialog.correlate." + getMediaTypeKey() + "select.intro"));
+               introLabel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
+               card.add(introLabel, BorderLayout.NORTH);
                // table doesn't have model yet - that will be attached later
                _selectionTable = new JTable();
                JScrollPane photoScrollPane = new JScrollPane(_selectionTable);
                // table doesn't have model yet - that will be attached later
                _selectionTable = new JTable();
                JScrollPane photoScrollPane = new JScrollPane(_selectionTable);
@@ -368,7 +372,7 @@ public abstract class Correlator extends GenericFunction
                offsetPanelBot.setLayout(new FlowLayout());
                offsetPanelBot.setBorder(null);
                _mediaLaterOption = new JRadioButton(I18nManager.getText("dialog.correlate.options." + getMediaTypeKey() + "later"));
                offsetPanelBot.setLayout(new FlowLayout());
                offsetPanelBot.setBorder(null);
                _mediaLaterOption = new JRadioButton(I18nManager.getText("dialog.correlate.options." + getMediaTypeKey() + "later"));
-               _pointLaterOption = new JRadioButton(I18nManager.getText("dialog.correlate.options.pointlaterphoto"));
+               _pointLaterOption = new JRadioButton(I18nManager.getText("dialog.correlate.options.pointlater" + getMediaTypeKey()));
                _mediaLaterOption.addItemListener(optionsChangedListener);
                _pointLaterOption.addItemListener(optionsChangedListener);
                ButtonGroup laterGroup = new ButtonGroup();
                _mediaLaterOption.addItemListener(optionsChangedListener);
                _pointLaterOption.addItemListener(optionsChangedListener);
                ButtonGroup laterGroup = new ButtonGroup();
@@ -380,6 +384,12 @@ public abstract class Correlator extends GenericFunction
                offsetPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
                card2Top.add(offsetPanel);
 
                offsetPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
                card2Top.add(offsetPanel);
 
+               // listener for radio buttons
+               ActionListener radioListener = new ActionListener() {
+                       public void actionPerformed(ActionEvent e) {
+                               enableEditBoxes();
+                       }
+               };
                // time limits section
                JPanel limitsPanel = new JPanel();
                limitsPanel.setBorder(BorderFactory.createTitledBorder(I18nManager.getText("dialog.correlate.options.limitspanel")));
                // time limits section
                JPanel limitsPanel = new JPanel();
                limitsPanel.setBorder(BorderFactory.createTitledBorder(I18nManager.getText("dialog.correlate.options.limitspanel")));
@@ -388,9 +398,11 @@ public abstract class Correlator extends GenericFunction
                timeLimitPanel.setLayout(new FlowLayout());
                JRadioButton noTimeLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.notimelimit"));
                noTimeLimitRadio.addItemListener(optionsChangedListener);
                timeLimitPanel.setLayout(new FlowLayout());
                JRadioButton noTimeLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.notimelimit"));
                noTimeLimitRadio.addItemListener(optionsChangedListener);
+               noTimeLimitRadio.addActionListener(radioListener);
                timeLimitPanel.add(noTimeLimitRadio);
                _timeLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.timelimit") + " : ");
                _timeLimitRadio.addItemListener(optionsChangedListener);
                timeLimitPanel.add(noTimeLimitRadio);
                _timeLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.timelimit") + " : ");
                _timeLimitRadio.addItemListener(optionsChangedListener);
+               _timeLimitRadio.addActionListener(radioListener);
                timeLimitPanel.add(_timeLimitRadio);
                groupRadioButtons(noTimeLimitRadio, _timeLimitRadio);
                _limitMinBox = new JTextField(3);
                timeLimitPanel.add(_timeLimitRadio);
                groupRadioButtons(noTimeLimitRadio, _timeLimitRadio);
                _limitMinBox = new JTextField(3);
@@ -407,9 +419,11 @@ public abstract class Correlator extends GenericFunction
                distLimitPanel.setLayout(new FlowLayout());
                JRadioButton noDistLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.nodistancelimit"));
                noDistLimitRadio.addItemListener(optionsChangedListener);
                distLimitPanel.setLayout(new FlowLayout());
                JRadioButton noDistLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.nodistancelimit"));
                noDistLimitRadio.addItemListener(optionsChangedListener);
+               noDistLimitRadio.addActionListener(radioListener);
                distLimitPanel.add(noDistLimitRadio);
                _distLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.distancelimit"));
                _distLimitRadio.addItemListener(optionsChangedListener);
                distLimitPanel.add(noDistLimitRadio);
                _distLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.distancelimit"));
                _distLimitRadio.addItemListener(optionsChangedListener);
+               _distLimitRadio.addActionListener(radioListener);
                distLimitPanel.add(_distLimitRadio);
                groupRadioButtons(noDistLimitRadio, _distLimitRadio);
                _limitDistBox = new JTextField(4);
                distLimitPanel.add(_distLimitRadio);
                groupRadioButtons(noDistLimitRadio, _distLimitRadio);
                _limitDistBox = new JTextField(4);
@@ -516,6 +530,18 @@ public abstract class Correlator extends GenericFunction
                _okButton.setEnabled(inCardNum == 2 && ((MediaPreviewTableModel) _previewTable.getModel()).hasAnySelected());
        }
 
                _okButton.setEnabled(inCardNum == 2 && ((MediaPreviewTableModel) _previewTable.getModel()).hasAnySelected());
        }
 
+       /**
+        * Enable or disable the edit boxes according to the radio button selections
+        */
+       private void enableEditBoxes()
+       {
+               // enable/disable text field for distance input
+               _limitDistBox.setEnabled(_distLimitRadio.isSelected());
+               // and for time limits
+               _limitMinBox.setEnabled(_timeLimitRadio.isSelected());
+               _limitSecBox.setEnabled(_timeLimitRadio.isSelected());
+       }
+
        /**
         * Parse the time limit values entered and validate them
         * @return TimeDifference object describing limit
        /**
         * Parse the time limit values entered and validate them
         * @return TimeDifference object describing limit
@@ -557,9 +583,9 @@ public abstract class Correlator extends GenericFunction
        /**
         * @return the selected distance units from the dropdown
         */
        /**
         * @return the selected distance units from the dropdown
         */
-       protected Distance.Units getSelectedDistanceUnits()
+       protected Unit getSelectedDistanceUnits()
        {
        {
-               final Distance.Units[] distUnits = {Distance.Units.KILOMETRES, Distance.Units.METRES, Distance.Units.MILES};
+               final Unit[] distUnits = {UnitSetLibrary.UNITS_KILOMETRES, UnitSetLibrary.UNITS_METRES, UnitSetLibrary.UNITS_MILES};
                return distUnits[_distUnitsDropdown.getSelectedIndex()];
        }
 
                return distUnits[_distUnitsDropdown.getSelectedIndex()];
        }
 
@@ -604,6 +630,7 @@ public abstract class Correlator extends GenericFunction
                _mediaLaterOption.setSelected(timeDiff.getIsPositive());
                _pointLaterOption.setSelected(!timeDiff.getIsPositive());
                _previewEnabled = true;
                _mediaLaterOption.setSelected(timeDiff.getIsPositive());
                _pointLaterOption.setSelected(!timeDiff.getIsPositive());
                _previewEnabled = true;
+               enableEditBoxes();
                createPreview(timeDiff, true);
        }
 
                createPreview(timeDiff, true);
        }
 
@@ -635,19 +662,22 @@ public abstract class Correlator extends GenericFunction
        protected PointMediaPair getPointPairForMedia(Track inTrack, MediaObject inMedia, TimeDifference inOffset)
        {
                PointMediaPair pair = new PointMediaPair(inMedia);
        protected PointMediaPair getPointPairForMedia(Track inTrack, MediaObject inMedia, TimeDifference inOffset)
        {
                PointMediaPair pair = new PointMediaPair(inMedia);
-               // Add/subtract offset to media timestamp
-               Timestamp mediaStamp = getMediaTimestamp(inMedia).createMinusOffset(inOffset);
-               int numPoints = inTrack.getNumPoints();
-               for (int i=0; i<numPoints; i++)
+               if (inMedia.hasTimestamp())
                {
                {
-                       DataPoint point = inTrack.getPoint(i);
-                       if (point.getPhoto() == null && point.getAudio() == null)
+                       // Add/subtract offset to media timestamp
+                       Timestamp mediaStamp = getMediaTimestamp(inMedia).createMinusOffset(inOffset);
+                       int numPoints = inTrack.getNumPoints();
+                       for (int i=0; i<numPoints; i++)
                        {
                        {
-                               Timestamp pointStamp = point.getTimestamp();
-                               if (pointStamp != null && pointStamp.isValid())
+                               DataPoint point = inTrack.getPoint(i);
+                               if (point.getPhoto() == null && point.getAudio() == null)
                                {
                                {
-                                       long numSeconds = pointStamp.getSecondsSince(mediaStamp);
-                                       pair.addPoint(point, numSeconds);
+                                       Timestamp pointStamp = point.getTimestamp();
+                                       if (pointStamp != null && pointStamp.isValid())
+                                       {
+                                               long numSeconds = pointStamp.getSecondsSince(mediaStamp);
+                                               pair.addPoint(point, numSeconds);
+                                       }
                                }
                        }
                }
                                }
                        }
                }
index 78120ec784050a9b697c9bd2e172200e427e0989..3d6efa8196c1ca57cf47aced06d83b211577c5f8 100644 (file)
@@ -4,7 +4,8 @@ import java.text.NumberFormat;
 import java.util.ArrayList;
 import javax.swing.table.AbstractTableModel;
 import tim.prune.I18nManager;
 import java.util.ArrayList;
 import javax.swing.table.AbstractTableModel;
 import tim.prune.I18nManager;
-import tim.prune.data.Distance;
+import tim.prune.data.Unit;
+import tim.prune.data.UnitSetLibrary;
 
 /**
  * Class to act as the table model for the correlation preview table
 
 /**
  * Class to act as the table model for the correlation preview table
@@ -16,7 +17,7 @@ public class MediaPreviewTableModel extends AbstractTableModel
        /** ArrayList containing TableRow objects */
        private ArrayList<MediaPreviewTableRow> _list = new ArrayList<MediaPreviewTableRow>();
        /** Distance units */
        /** ArrayList containing TableRow objects */
        private ArrayList<MediaPreviewTableRow> _list = new ArrayList<MediaPreviewTableRow>();
        /** Distance units */
-       private Distance.Units _distanceUnits = Distance.Units.KILOMETRES;
+       private Unit _distanceUnits = UnitSetLibrary.UNITS_KILOMETRES;
        /** Number formatter */
        private static final NumberFormat FORMAT_ONE_DP = NumberFormat.getNumberInstance();
 
        /** Number formatter */
        private static final NumberFormat FORMAT_ONE_DP = NumberFormat.getNumberInstance();
 
@@ -89,7 +90,10 @@ public class MediaPreviewTableModel extends AbstractTableModel
                MediaPreviewTableRow row = _list.get(inRowIndex);
                if (inColumnIndex == 0) return row.getMedia().getName();
                else if (inColumnIndex == 1) {
                MediaPreviewTableRow row = _list.get(inRowIndex);
                if (inColumnIndex == 0) return row.getMedia().getName();
                else if (inColumnIndex == 1) {
-                       return row.getMedia().getTimestamp().getText();
+                       if (row.getMedia().hasTimestamp()) {
+                               return row.getMedia().getTimestamp().getText();
+                       }
+                       return ""; // media doesn't have a timestamp
                }
                else if (inColumnIndex == 2) {
                        if (row.getPointPair().isValid()) {
                }
                else if (inColumnIndex == 2) {
                        if (row.getPointPair().isValid()) {
@@ -110,7 +114,7 @@ public class MediaPreviewTableModel extends AbstractTableModel
        /**
         * @param inUnits the distance units to use
         */
        /**
         * @param inUnits the distance units to use
         */
-       public void setDistanceUnits(Distance.Units inUnits)
+       public void setDistanceUnits(Unit inUnits)
        {
                _distanceUnits = inUnits;
        }
        {
                _distanceUnits = inUnits;
        }
index cadede31b39613e5512fc6a98be0d284e8cb814d..700336f7d1b928ecf5d5370100226e3435782ec9 100644 (file)
@@ -1,6 +1,7 @@
 package tim.prune.correlate;
 
 import tim.prune.data.Distance;
 package tim.prune.correlate;
 
 import tim.prune.data.Distance;
+import tim.prune.data.Unit;
 
 /**
  * Class to hold the contents of a single row in the correlation preview table
 
 /**
  * Class to hold the contents of a single row in the correlation preview table
@@ -9,7 +10,6 @@ public class MediaPreviewTableRow extends MediaSelectionTableRow
 {
        private PointMediaPair _pointPair = null;
        private double _distance = 0.0;
 {
        private PointMediaPair _pointPair = null;
        private double _distance = 0.0;
-       private int _status = 0;
        private boolean _correlate = false;
 
 
        private boolean _correlate = false;
 
 
@@ -22,7 +22,6 @@ public class MediaPreviewTableRow extends MediaSelectionTableRow
                super(inPointPair.getMedia(), inPointPair.getMinSeconds());
                _pointPair = inPointPair;
                _distance = inPointPair.getMinRadians();
                super(inPointPair.getMedia(), inPointPair.getMinSeconds());
                _pointPair = inPointPair;
                _distance = inPointPair.getMinRadians();
-               _status = 0;
                _correlate = (inPointPair.getMedia().getDataPoint() == null);
        }
 
                _correlate = (inPointPair.getMedia().getDataPoint() == null);
        }
 
@@ -30,19 +29,11 @@ public class MediaPreviewTableRow extends MediaSelectionTableRow
         * @param inUnits units to use
         * @return distance in selected format
         */
         * @param inUnits units to use
         * @return distance in selected format
         */
-       public double getDistance(Distance.Units inUnits)
+       public double getDistance(Unit inUnits)
        {
                return Distance.convertRadiansToDistance(_distance, inUnits);
        }
 
        {
                return Distance.convertRadiansToDistance(_distance, inUnits);
        }
 
-       /**
-        * @return point status
-        */
-       public int getStatus()
-       {
-               return _status;
-       }
-
        /**
         * @return point pair object
         */
        /**
         * @return point pair object
         */
index 69d059fffe53e2116f93bc94f81f416900a21ebd..93f8759bfa4c4352d653b489b85bbd649d52eb79 100644 (file)
@@ -83,7 +83,9 @@ public class MediaSelectionTableModel extends AbstractTableModel
                // MAYBE: only show time of photos (not date) if dates all identical
                MediaSelectionTableRow row = _list.get(inRowIndex);
                if (inColumnIndex == 0) return row.getMedia().getName();
                // MAYBE: only show time of photos (not date) if dates all identical
                MediaSelectionTableRow row = _list.get(inRowIndex);
                if (inColumnIndex == 0) return row.getMedia().getName();
-               else if (inColumnIndex == 1) return row.getMedia().getTimestamp().getText();
+               else if (inColumnIndex == 1) {
+                       return (row.getMedia().hasTimestamp() ? row.getMedia().getTimestamp().getText() : "");
+               }
                else if (inColumnIndex == 2) return row.getTimeDiff().getDescription();
                return (row.getTimeDiff().getIsPositive() ? I18nManager.getText("dialog.about.yes") :
                        I18nManager.getText("dialog.about.no"));
                else if (inColumnIndex == 2) return row.getTimeDiff().getDescription();
                return (row.getTimeDiff().getIsPositive() ? I18nManager.getText("dialog.about.yes") :
                        I18nManager.getText("dialog.about.no"));
index 06a32911197fc3e0560e81c45ac042bb5a080ed3..ac71d759cb4a45a8a7af971b8d6adc830010bf83 100644 (file)
@@ -21,8 +21,8 @@ public class Altitude
        }
 
        /** Constants for conversion */
        }
 
        /** Constants for conversion */
-       private static final double CONVERT_FEET_TO_METRES = 0.3048;
-       private static final double CONVERT_METRES_TO_FEET = 3.28084;
+       private static final double CONVERT_METRES_TO_FEET = UnitSetLibrary.UNITS_FEET.getMultFactorFromStd();
+       private static final double CONVERT_FEET_TO_METRES = 1 / CONVERT_METRES_TO_FEET;
 
        /** Constant for no altitude value */
        public static final Altitude NONE = new Altitude(null, Format.NO_FORMAT);
 
        /** Constant for no altitude value */
        public static final Altitude NONE = new Altitude(null, Format.NO_FORMAT);
@@ -75,6 +75,7 @@ public class Altitude
         */
        public void reset(Altitude inClone)
        {
         */
        public void reset(Altitude inClone)
        {
+               _stringValue = inClone._stringValue;
                _value = inClone._value;
                _format = inClone._format;
                _valid = inClone._valid;
                _value = inClone._value;
                _format = inClone._format;
                _valid = inClone._valid;
@@ -97,6 +98,14 @@ public class Altitude
                return _value;
        }
 
                return _value;
        }
 
+       /**
+        * @param inAltUnit altitude units to use
+        * @return rounded value in specified units
+        */
+       public int getValue(Unit inAltUnit)
+       {
+               return (int) (getMetricValue() * inAltUnit.getMultFactorFromStd());
+       }
 
        /**
         * @return format of number
 
        /**
         * @return format of number
@@ -124,6 +133,17 @@ public class Altitude
                return _value;
        }
 
                return _value;
        }
 
+       /**
+        * @return value of altitude in metres, used for calculations and charts
+        */
+       public double getMetricValue()
+       {
+               if (_format == Format.FEET) {
+                       return _value / UnitSetLibrary.UNITS_FEET.getMultFactorFromStd();
+               }
+               return _value;
+       }
+
        /**
         * Get a string version of the value
         * @param inFormat specified format
        /**
         * Get a string version of the value
         * @param inFormat specified format
@@ -196,6 +216,8 @@ public class Altitude
                        else
                                offset = inOffset * CONVERT_METRES_TO_FEET;
                }
                        else
                                offset = inOffset * CONVERT_METRES_TO_FEET;
                }
+               // FIXME: The following will fail if _stringValue is null - not sure how it can get in that state!
+               if (_stringValue == null) System.err.println("*** Altitude.addOffset - how did the string value get to be null?");
                // Add the offset
                double newValue = Double.parseDouble(_stringValue.trim()) + offset;
                _value = (int) newValue;
                // Add the offset
                double newValue = Double.parseDouble(_stringValue.trim()) + offset;
                _value = (int) newValue;
index 98fa20edd5295f0e8097ec3407c98856a8fa0f53..b7ec647ab6456f4ad9bdef0f625d513fa28360d4 100644 (file)
@@ -6,17 +6,35 @@ package tim.prune.data;
  */
 public class AltitudeRange
 {
  */
 public class AltitudeRange
 {
+       /** Range of altitudes in metres */
        private IntegerRange _range = new IntegerRange();
        private IntegerRange _range = new IntegerRange();
-       private Altitude.Format _format = Altitude.Format.NO_FORMAT;
+       /** Empty flag */
+       private boolean _empty;
+       /** Previous metric value */
+       private int _prevValue;
+       /** Total climb in metres */
+       private double _climb;
+       /** Total descent in metres */
+       private double _descent;
 
 
 
 
+       /**
+        * Constructor
+        */
+       public AltitudeRange() {
+               clear();
+       }
+
        /**
         * Clear the altitude range
         */
        public void clear()
        {
                _range.clear();
        /**
         * Clear the altitude range
         */
        public void clear()
        {
                _range.clear();
-               _format = Altitude.Format.NO_FORMAT;
+               _climb = 0.0;
+               _descent = 0.0;
+               _empty = true;
+               _prevValue = 0;
        }
 
 
        }
 
 
@@ -26,17 +44,33 @@ public class AltitudeRange
         */
        public void addValue(Altitude inAltitude)
        {
         */
        public void addValue(Altitude inAltitude)
        {
-               if (inAltitude != null)
+               if (inAltitude != null && inAltitude.isValid())
                {
                {
-                       int altValue = inAltitude.getValue(_format);
+                       int altValue = (int) inAltitude.getMetricValue();
                        _range.addValue(altValue);
                        _range.addValue(altValue);
-                       if (_format == Altitude.Format.NO_FORMAT)
+                       // Compare with previous value if any
+                       if (!_empty)
                        {
                        {
-                               _format = inAltitude.getFormat();
+                               if (altValue > _prevValue)
+                                       _climb += (altValue - _prevValue);
+                               else
+                                       _descent += (_prevValue - altValue);
                        }
                        }
+                       _prevValue = altValue;
+                       _empty = false;
                }
        }
 
                }
        }
 
+       /**
+        * Reset the climb/descent calculations starting from the given value
+        * @param inAltitude altitude value
+        */
+       public void ignoreValue(Altitude inAltitude)
+       {
+               // If we set the empty flag to true, that has the same effect as restarting a segment
+               _empty = true;
+               addValue(inAltitude);
+       }
 
        /**
         * @return true if altitude range found
 
        /**
         * @return true if altitude range found
@@ -48,28 +82,40 @@ public class AltitudeRange
 
 
        /**
 
 
        /**
+        * @param inUnit altitude units to use
         * @return minimum value, or -1 if none found
         */
         * @return minimum value, or -1 if none found
         */
-       public int getMinimum()
+       public int getMinimum(Unit inUnit)
        {
        {
-               return _range.getMinimum();
+               if (_range.getMinimum() <= 0) return _range.getMinimum();
+               return (int) (_range.getMinimum() * inUnit.getMultFactorFromStd());
        }
 
        }
 
-
        /**
        /**
+        * @param inUnit altitude units to use
         * @return maximum value, or -1 if none found
         */
         * @return maximum value, or -1 if none found
         */
-       public int getMaximum()
+       public int getMaximum(Unit inUnit)
        {
        {
-               return _range.getMaximum();
+               if (_range.getMaximum() <= 0) return _range.getMaximum();
+               return (int) (_range.getMaximum() * inUnit.getMultFactorFromStd());
        }
 
        }
 
+       /**
+        * @param inUnit altitude units to use
+        * @return total climb
+        */
+       public int getClimb(Unit inUnit)
+       {
+               return (int) (_climb * inUnit.getMultFactorFromStd());
+       }
 
        /**
 
        /**
-        * @return the altitude format used
+        * @param inUnit altitude units to use
+        * @return total descent
         */
         */
-       public Altitude.Format getFormat()
+       public int getDescent(Unit inUnit)
        {
        {
-               return _format;
+               return (int) (_descent * inUnit.getMultFactorFromStd());
        }
 }
        }
 }
index 3d17cbc5edec4797a3dd63fee6e58579bcdd6025..34d7bd72055275f81339e1fe23c434d2008603c6 100644 (file)
@@ -38,6 +38,8 @@ public class DataPoint
                _fieldValues = inValueArray;
                // save list of fields
                _fieldList = inFieldList;
                _fieldValues = inValueArray;
                // save list of fields
                _fieldList = inFieldList;
+               // Remove double quotes around values
+               removeQuotes(_fieldValues);
                // parse fields into objects
                parseFields(null, inAltFormat);
        }
                // parse fields into objects
                parseFields(null, inAltFormat);
        }
@@ -164,7 +166,7 @@ public class DataPoint
                }
                else {
                        // use default altitude format from config
                }
                else {
                        // use default altitude format from config
-                       parseFields(inField, Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?Altitude.Format.METRES:Altitude.Format.FEET);
+                       parseFields(inField, Config.getUnitSet().getDefaultAltitudeFormat());
                }
        }
 
                }
        }
 
@@ -363,6 +365,25 @@ public class DataPoint
                return _photo != null || _audio != null;
        }
 
                return _photo != null || _audio != null;
        }
 
+       /**
+        * @return name of attached photo and/or audio
+        */
+       public String getMediaName()
+       {
+               String mediaName = null;
+               if (_photo != null) mediaName = _photo.getName();
+               if (_audio != null)
+               {
+                       if (mediaName == null) {
+                               mediaName = _audio.getName();
+                       }
+                       else {
+                               mediaName = mediaName + ", " + _audio.getName();
+                       }
+               }
+               return mediaName;
+       }
+
        /**
         * Interpolate a set of points between this one and the given one
         * @param inEndPoint end point of interpolation
        /**
         * Interpolate a set of points between this one and the given one
         * @param inEndPoint end point of interpolation
@@ -457,6 +478,41 @@ public class DataPoint
        }
 
 
        }
 
 
+       /**
+        * Remove all single and double quotes surrounding each value
+        * @param inValues array of values
+        */
+       private static void removeQuotes(String[] inValues)
+       {
+               if (inValues == null) {return;}
+               for (int i=0; i<inValues.length; i++)
+               {
+                       inValues[i] = removeQuotes(inValues[i]);
+               }
+       }
+
+       /**
+        * Remove any single or double quotes surrounding a value
+        * @param inValue value to modify
+        * @return modified String
+        */
+       private static String removeQuotes(String inValue)
+       {
+               if (inValue == null) {return inValue;}
+               final int len = inValue.length();
+               if (len <= 1) {return inValue;}
+               // get the first and last characters
+               final char firstChar = inValue.charAt(0);
+               final char lastChar  = inValue.charAt(len-1);
+               if (firstChar == lastChar)
+               {
+                       if (firstChar == '\"' || firstChar == '\'') {
+                               return inValue.substring(1, len-1);
+                       }
+               }
+               return inValue;
+       }
+
        /**
         * Get string for debug
         * @see java.lang.Object#toString()
        /**
         * Get string for debug
         * @see java.lang.Object#toString()
index d12d98817d5c7fce86d687f12f566940a03dbbd7..83864a59e890216548957711513ae188c5ba8571 100644 (file)
@@ -1,70 +1,58 @@
 package tim.prune.data;
 
 package tim.prune.data;
 
+import tim.prune.config.Config;
+
 /**
  * Class to provide distance constants and functions
  */
 public abstract class Distance
 {
 /**
  * Class to provide distance constants and functions
  */
 public abstract class Distance
 {
-       /** distance units */
-       public enum Units
-       {
-               /** Kilometres */
-               KILOMETRES,
-               /** Miles */
-               MILES,
-               /** Metres */
-               METRES,
-               /** Feet */
-               FEET
-       }
-
        // Geographical constants
        // Geographical constants
-       private static final double EARTH_RADIUS_KM = 6372.795;
-       // Conversion constants
-       private static final double CONVERT_KM_TO_MILES = 0.621371192;
+       /** Earth radius in metres */
+       private static final double EARTH_RADIUS_M = 6372795.0;
 
 
        /**
         * Convert the given angle in radians into a distance
         * @param inAngDist angular distance in radians
 
 
        /**
         * Convert the given angle in radians into a distance
         * @param inAngDist angular distance in radians
-        * @param inUnits desired units, eg miles or km
-        * @return distance in specified format
+        * @return distance in currently configured distance units
         */
         */
-       public static double convertRadiansToDistance(double inAngDist, Units inUnits)
+       public static double convertRadiansToDistance(double inAngDist)
+       {
+               return convertRadiansToDistance(inAngDist, Config.getUnitSet().getDistanceUnit());
+       }
+
+       /**
+        * Convert the given angle in radians into a distance
+        * @param inAngDist angular distance in radians
+        * @param inUnit distance units
+        * @return distance in specified distance units
+        */
+       public static double convertRadiansToDistance(double inAngDist, Unit inUnit)
        {
                // Multiply by appropriate factor
        {
                // Multiply by appropriate factor
-               if (inUnits == Units.MILES)
-                       return inAngDist * EARTH_RADIUS_KM * CONVERT_KM_TO_MILES;
-               else if (inUnits == Units.METRES)
-                       return inAngDist * EARTH_RADIUS_KM * 1000;
-               // default kilometres
-               return inAngDist * EARTH_RADIUS_KM;
+               return inAngDist * EARTH_RADIUS_M * inUnit.getMultFactorFromStd();
        }
 
        /**
         * Convert the given distance into an angle in radians
        }
 
        /**
         * Convert the given distance into an angle in radians
-        * @param inDist distance to convert
-        * @param inUnits units, eg miles or km
+        * @param inDist distance to convert in the current distance units
         * @return angular distance in radians
         */
         * @return angular distance in radians
         */
-       public static double convertDistanceToRadians(double inDist, Units inUnits)
+       public static double convertDistanceToRadians(double inDist)
        {
        {
-               // Divide by appropriate factor
-               if (inUnits == Units.MILES)
-                       return inDist / EARTH_RADIUS_KM / CONVERT_KM_TO_MILES;
-               else if (inUnits == Units.METRES)
-                       return inDist / EARTH_RADIUS_KM / 1000;
-               // default kilometres
-               return inDist / EARTH_RADIUS_KM;
+               return convertDistanceToRadians(inDist, Config.getUnitSet().getDistanceUnit());
        }
 
        /**
        }
 
        /**
-        * Convert the given distance from metres to miles
-        * @param inMetres number of metres
-        * @return number of miles
+        * Convert the given distance into an angle in radians
+        * @param inDist distance to convert in the current distance units
+        * @param inUnit distance unit
+        * @return angular distance in radians
         */
         */
-       public static double convertMetresToMiles(double inMetres)
+       public static double convertDistanceToRadians(double inDist, Unit inUnit)
        {
        {
-               return inMetres / 1000.0 * CONVERT_KM_TO_MILES;
+               // Divide by appropriate factor
+               return inDist / EARTH_RADIUS_M / inUnit.getMultFactorFromStd();
        }
 }
        }
 }
index 6d877049e295515a7a6e895207b114f4c35b458c..d020a7ebdd5789e080e1323dd2459a8796c851cc 100644 (file)
@@ -20,10 +20,15 @@ public class Field
        public static final Field DESCRIPTION = new Field("fieldname.description", true);
        public static final Field NEW_SEGMENT = new Field("fieldname.newsegment", true);
 
        public static final Field DESCRIPTION = new Field("fieldname.description", true);
        public static final Field NEW_SEGMENT = new Field("fieldname.newsegment", true);
 
+       public static final Field SPEED          = new Field("fieldname.speed", true);
+       public static final Field VERTICAL_SPEED = new Field("fieldname.verticalspeed", true);
+
        // TODO: Field for photo filename, ability to load (from text) and save (to text)
 
        // TODO: Field for photo filename, ability to load (from text) and save (to text)
 
+       /** List of all the available fields */
        private static final Field[] ALL_AVAILABLE_FIELDS = {
                LATITUDE, LONGITUDE, ALTITUDE, TIMESTAMP, WAYPT_NAME, WAYPT_TYPE, DESCRIPTION, NEW_SEGMENT,
        private static final Field[] ALL_AVAILABLE_FIELDS = {
                LATITUDE, LONGITUDE, ALTITUDE, TIMESTAMP, WAYPT_NAME, WAYPT_TYPE, DESCRIPTION, NEW_SEGMENT,
+               SPEED, VERTICAL_SPEED,
                new Field(I18nManager.getText("fieldname.custom"))
        };
 
                new Field(I18nManager.getText("fieldname.custom"))
        };
 
index d7b4780e7cd6e32447dcaa77e10976cb73a9923f..c0f4408f3637a23e932679bd441449928ea5777e 100644 (file)
@@ -172,7 +172,7 @@ public abstract class MediaList
        public boolean hasUncorrelatedMedia()
        {
                for (MediaObject m : _media) {
        public boolean hasUncorrelatedMedia()
        {
                for (MediaObject m : _media) {
-                       if (m.getDataPoint() == null) {
+                       if (m.getDataPoint() == null && m.hasTimestamp()) {
                                return true;
                        }
                }
                                return true;
                        }
                }
index e028f4ab4ddc7f1050f0c9e2e3792da90c3e6c41..478618e4a5ac330795df9684600c4a54f3452e9c 100644 (file)
@@ -105,6 +105,15 @@ public abstract class MediaObject
                return _url;
        }
 
                return _url;
        }
 
+       /**
+        * @return the full path to the media, either filename or url
+        */
+       public String getFullPath()
+       {
+               if (_file != null) return _file.getAbsolutePath();
+               return getUrl();
+       }
+
        /**
         * @return true if details are valid (might not have timestamp)
         */
        /**
         * @return true if details are valid (might not have timestamp)
         */
diff --git a/tim/prune/data/MidpointData.java b/tim/prune/data/MidpointData.java
new file mode 100644 (file)
index 0000000..3fdebb2
--- /dev/null
@@ -0,0 +1,98 @@
+package tim.prune.data;
+
+/**
+ * Class to hold information about the mid-points between
+ * adjacent track points.  Used by the MapCanvas for creating
+ * points by dragging.
+ */
+public class MidpointData
+{
+       // track object
+       private Track _track = null;
+       // Scaled x, y values
+       private double[] _xValues = null;
+       private double[] _yValues = null;
+       // Validity flags
+       private boolean[] _valids = null;
+       // Flag to set data stale
+       private boolean _needRefresh = true;
+
+
+       /**
+        * Flag the data as needing to be updated
+        * @param inTrack track object from which to get the data
+        */
+       public void updateData(Track inTrack)
+       {
+               _track = inTrack;
+               _needRefresh = true;
+       }
+
+       /**
+        * Update the arrays of data from the track
+        */
+       private synchronized void updateData()
+       {
+               _needRefresh = false;
+               if (_track == null) return;
+               // Make arrays the right size
+               final int numPoints = _track.getNumPoints();
+               if (_xValues == null || _xValues.length != numPoints)
+               {
+                       _xValues = new double[numPoints];
+                       _yValues = new double[numPoints];
+                       _valids  = new boolean[numPoints];
+               }
+               if (numPoints <= 0) return;
+               _valids[0] = false;
+
+               // Loop over the points in the track
+               for (int i=1; i<numPoints; i++)
+               {
+                       boolean pointValid = false;
+                       DataPoint point = _track.getPoint(i);
+                       if (point != null && !point.getSegmentStart() && !point.isWaypoint())
+                       {
+                               _xValues[i] = (_track.getX(i) + _track.getX(i-1)) / 2.0;
+                               _yValues[i] = (_track.getY(i) + _track.getY(i-1)) / 2.0;
+                               pointValid = true;
+                       }
+                       _valids[i] = pointValid;
+               }
+       }
+
+       /**
+        * Find the nearest point to the specified x and y coordinates
+        * or -1 if no point is within the specified max distance
+        * @param inX x coordinate
+        * @param inY y coordinate
+        * @param inMaxDist maximum distance from selected coordinates
+        * @return index of nearest point or -1 if not found
+        */
+       public int getNearestPointIndex(double inX, double inY, double inMaxDist)
+       {
+               if (_track == null) return -1;
+               if (_needRefresh) updateData();
+               final int numPoints = _track.getNumPoints();
+               int nearestPoint = 0;
+               double nearestDist = -1.0;
+               double currDist;
+               for (int i=1; i < numPoints; i++)
+               {
+                       if (_valids[i])
+                       {
+                               currDist = Math.abs(_xValues[i] - inX) + Math.abs(_yValues[i] - inY);
+                               if (currDist < nearestDist || nearestDist < 0.0)
+                               {
+                                       nearestPoint = i;
+                                       nearestDist = currDist;
+                               }
+                       }
+               }
+               // Check whether it's within required distance
+               if (nearestDist > inMaxDist && inMaxDist > 0.0) {
+                       return -1;
+               }
+               return nearestPoint;
+       }
+}
index b3b94f3d2b6ce8751c78830fc5dad4ebe85c1b64..180f3a5aef74e131d0c9bab9649310b4e840ef5e 100644 (file)
@@ -84,7 +84,7 @@ public class PointScaler
                        DataPoint p2 = new DataPoint(new Latitude(latRange.getMaximum(), Coordinate.FORMAT_DEG),
                                new Longitude(_lonMedian, Coordinate.FORMAT_DEG), null);
                        double horizDist = Distance.convertRadiansToDistance(
                        DataPoint p2 = new DataPoint(new Latitude(latRange.getMaximum(), Coordinate.FORMAT_DEG),
                                new Longitude(_lonMedian, Coordinate.FORMAT_DEG), null);
                        double horizDist = Distance.convertRadiansToDistance(
-                               DataPoint.calculateRadiansBetween(p1, p2), Distance.Units.METRES);
+                               DataPoint.calculateRadiansBetween(p1, p2), UnitSetLibrary.UNITS_METRES); // both in m
                        _altFactor = 1.0 / horizDist;
 
                        // create new arrays for scaled values
                        _altFactor = 1.0 / horizDist;
 
                        // create new arrays for scaled values
index d13388d28e4c0da1911c6923eb6831da08dbce04..e7d95ba944bf19cff22f8d77a93f0e7bf0a63d73 100644 (file)
@@ -72,6 +72,7 @@ public class RecentFile
        public boolean isSameFile(RecentFile inOther)
        {
                return inOther != null && isValid() && inOther.isValid()
        public boolean isSameFile(RecentFile inOther)
        {
                return inOther != null && isValid() && inOther.isValid()
-                       && _file.equals(inOther._file);
+                       && (_file.equals(inOther._file) || _file.getAbsolutePath().equals(inOther._file.getAbsolutePath()));
+               // Note that the file.equals should be sufficient but sometimes it returns false even if the absolute paths are identical
        }
 }
        }
 }
index 81ab64ce7c6cc42dc7df15d788e06a90df9bb31f..f5c41ffd91f6015d8d4762e546fe8385c5dadc8e 100644 (file)
@@ -16,9 +16,7 @@ public class Selection
        private int _startIndex = -1, _endIndex = -1;
        private int _currentPhotoIndex = -1;
        private int _currentAudioIndex = -1;
        private int _startIndex = -1, _endIndex = -1;
        private int _currentPhotoIndex = -1;
        private int _currentAudioIndex = -1;
-       private IntegerRange _altitudeRange = null;
-       private int _climb = -1, _descent = -1;
-       private Altitude.Format _altitudeFormat = Altitude.Format.NO_FORMAT;
+       private AltitudeRange _altitudeRange = null;
        private long _totalSeconds = 0L, _movingSeconds = 0L;
        private double _angDistance = -1.0, _angMovingDistance = -1.0;
        private int _numSegments = 0;
        private long _totalSeconds = 0L, _movingSeconds = 0L;
        private double _angDistance = -1.0, _angMovingDistance = -1.0;
        private int _numSegments = 0;
@@ -66,7 +64,6 @@ public class Selection
         */
        private void recalculate()
        {
         */
        private void recalculate()
        {
-               _altitudeFormat = Altitude.Format.NO_FORMAT;
                _numSegments = 0;
                final int numPoints = _track.getNumPoints();
                // Recheck if the number of points has changed
                _numSegments = 0;
                final int numPoints = _track.getNumPoints();
                // Recheck if the number of points has changed
@@ -76,18 +73,14 @@ public class Selection
                }
                if (numPoints > 0 && hasRangeSelected())
                {
                }
                if (numPoints > 0 && hasRangeSelected())
                {
-                       _altitudeRange = new IntegerRange();
-                       _climb = 0;
-                       _descent = 0;
+                       _altitudeRange = new AltitudeRange();
                        Altitude altitude = null;
                        Timestamp time = null, startTime = null, endTime = null;
                        Timestamp previousTime = null;
                        DataPoint lastPoint = null, currPoint = null;
                        _angDistance = 0.0; _angMovingDistance = 0.0;
                        _totalSeconds = 0L; _movingSeconds = 0L;
                        Altitude altitude = null;
                        Timestamp time = null, startTime = null, endTime = null;
                        Timestamp previousTime = null;
                        DataPoint lastPoint = null, currPoint = null;
                        _angDistance = 0.0; _angMovingDistance = 0.0;
                        _totalSeconds = 0L; _movingSeconds = 0L;
-                       int altValue = 0;
-                       int lastAltValue = 0;
-                       boolean foundAlt = false;
+                       // Loop over points in selection
                        for (int i=_startIndex; i<=_endIndex; i++)
                        {
                                currPoint = _track.getPoint(i);
                        for (int i=_startIndex; i<=_endIndex; i++)
                        {
                                currPoint = _track.getPoint(i);
@@ -95,19 +88,7 @@ public class Selection
                                // Ignore waypoints in altitude calculations
                                if (!currPoint.isWaypoint() && altitude.isValid())
                                {
                                // Ignore waypoints in altitude calculations
                                if (!currPoint.isWaypoint() && altitude.isValid())
                                {
-                                       altValue = altitude.getValue(_altitudeFormat);
-                                       if (_altitudeFormat == Altitude.Format.NO_FORMAT)
-                                               _altitudeFormat = altitude.getFormat();
-                                       _altitudeRange.addValue(altValue);
-                                       if (foundAlt)
-                                       {
-                                               if (altValue > lastAltValue)
-                                                       _climb += (altValue - lastAltValue);
-                                               else
-                                                       _descent += (lastAltValue - altValue);
-                                       }
-                                       lastAltValue = altValue;
-                                       foundAlt = true;
+                                       _altitudeRange.addValue(altitude);
                                }
                                // Store the first and last timestamp in the range
                                time = currPoint.getTimestamp();
                                }
                                // Store the first and last timestamp in the range
                                time = currPoint.getTimestamp();
@@ -167,44 +148,16 @@ public class Selection
                return _endIndex;
        }
 
                return _endIndex;
        }
 
-
-       /**
-        * @return the altitude format, ie feet or metres
-        */
-       public Altitude.Format getAltitudeFormat()
-       {
-               return _altitudeFormat;
-       }
-
        /**
         * @return altitude range
         */
        /**
         * @return altitude range
         */
-       public IntegerRange getAltitudeRange()
+       public AltitudeRange getAltitudeRange()
        {
                if (!_valid) recalculate();
                return _altitudeRange;
        }
 
 
        {
                if (!_valid) recalculate();
                return _altitudeRange;
        }
 
 
-       /**
-        * @return climb
-        */
-       public int getClimb()
-       {
-               if (!_valid) recalculate();
-               return _climb;
-       }
-
-       /**
-        * @return descent
-        */
-       public int getDescent()
-       {
-               if (!_valid) recalculate();
-               return _descent;
-       }
-
-
        /**
         * @return number of seconds spanned by selection
         */
        /**
         * @return number of seconds spanned by selection
         */
@@ -224,21 +177,19 @@ public class Selection
        }
 
        /**
        }
 
        /**
-        * @param inUnits distance units to use, from class Distance
         * @return distance of Selection in specified units
         */
         * @return distance of Selection in specified units
         */
-       public double getDistance(Distance.Units inUnits)
+       public double getDistance()
        {
        {
-               return Distance.convertRadiansToDistance(_angDistance, inUnits);
+               return Distance.convertRadiansToDistance(_angDistance);
        }
 
        /**
        }
 
        /**
-        * @param inUnits distance units to use, from class Distance
-        * @return moving distance of Selection in specified units
+        * @return moving distance of Selection in current units
         */
         */
-       public double getMovingDistance(Distance.Units inUnits)
+       public double getMovingDistance()
        {
        {
-               return Distance.convertRadiansToDistance(_angMovingDistance, inUnits);
+               return Distance.convertRadiansToDistance(_angMovingDistance);
        }
 
        /**
        }
 
        /**
diff --git a/tim/prune/data/SpeedCalculator.java b/tim/prune/data/SpeedCalculator.java
new file mode 100644 (file)
index 0000000..d83a7bd
--- /dev/null
@@ -0,0 +1,204 @@
+package tim.prune.data;
+
+import tim.prune.config.Config;
+
+/**
+ * Abstract class to hold static calculation functions
+ * for speed (and vertical speed)
+ */
+public abstract class SpeedCalculator
+{
+       /**
+        * Calculate the speed value of the track at the specified index
+        * @param inTrack track object
+        * @param inIndex index of point to calculate speed for
+        * @param inValue object in which to place result of calculation
+        */
+       public static void calculateSpeed(Track inTrack, int inIndex, SpeedValue inValue)
+       {
+               if (inTrack == null || inIndex < 0 || inValue == null) {
+                       System.err.println("Cannot calculate speed for index " + inIndex);
+                       return;
+               }
+               inValue.setInvalid();
+
+               DataPoint point = inTrack.getPoint(inIndex);
+               if (point == null) {return;}
+               boolean pointHasSpeed = false;
+               double  speedValue = 0.0;
+
+               // First, see if point has a speed value already
+               // FIXME: How do we know what units this speed is in?  m/s or mph or km/h or what?
+               String speedStr = point.getFieldValue(Field.SPEED);
+               try {
+                       speedValue = Double.parseDouble(speedStr);
+                       pointHasSpeed = true;
+               }
+               catch (Exception e) {} // ignore, leave pointHasSpeed false
+
+               // otherwise, see if we can calculate it from the timestamps
+               if (!pointHasSpeed && point.hasTimestamp() && !point.isWaypoint())
+               {
+                       double totalRadians = 0.0;
+                       int index = inIndex-1;
+                       DataPoint p = null;
+                       DataPoint q = point;
+                       Timestamp earlyStamp = point.getTimestamp();
+                       boolean stop = false;
+
+                       // Count backwards until timestamp earlier than now; total distances back to this point
+                       if (!point.getSegmentStart())
+                       {
+                               do
+                               {
+                                       p = inTrack.getPoint(index);
+                                       boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isAfter(point.getTimestamp());
+                                       boolean pValid = timeOk && !p.isWaypoint();
+                                       if (pValid) {
+                                               totalRadians += DataPoint.calculateRadiansBetween(p, q);
+                                               earlyStamp = p.getTimestamp();
+                                       }
+                                       stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
+                                               || p.getSegmentStart());
+                                       index--;
+                                       if (p != null && !p.isWaypoint()) {
+                                               q = p;
+                                       }
+                               }
+                               while (!stop);
+                       }
+                       // Count forwards until timestamp later than now; total distances forward to this point
+                       Timestamp lateStamp = point.getTimestamp();
+                       q = point;
+                       index = inIndex+1;
+                       do
+                       {
+                               p = inTrack.getPoint(index);
+                               boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isBefore(point.getTimestamp());
+                               boolean pValid = timeOk && !p.isWaypoint() && !p.getSegmentStart();
+                               if (pValid) {
+                                       totalRadians += DataPoint.calculateRadiansBetween(p, q);
+                                       lateStamp = p.getTimestamp();
+                               }
+                               stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
+                                       || p.getSegmentStart());
+                               index++;
+                               if (p != null && !p.isWaypoint()) {
+                                       q = p;
+                               }
+                       }
+                       while (!stop);
+
+                       // See if we've managed to get a time range of at least a second
+                       long milliseconds = lateStamp.getMillisecondsSince(earlyStamp);
+                       if (milliseconds >= 1000L)
+                       {
+                               double dist = Distance.convertRadiansToDistance(totalRadians);
+                               // Store the value and maintain max and min values
+                               speedValue = dist / milliseconds * 1000.0 * 60.0 * 60.0; // convert from per millisec to per hour
+                               pointHasSpeed = true;
+                       }
+               }
+               // Did we get a value?
+               if (pointHasSpeed)
+               {
+                       inValue.setValue(speedValue);
+               }
+               // otherwise, just leave value as invalid
+       }
+
+
+       /**
+        * Calculate the vertical speed value of the track at the specified index
+        * @param inTrack track object
+        * @param inIndex index of point to calculate speed for
+        * @param inValue object in which to place the result of calculation
+        */
+       public static void calculateVerticalSpeed(Track inTrack, int inIndex, SpeedValue inValue)
+       {
+               if (inTrack == null || inIndex < 0 || inValue == null) {
+                       System.err.println("Cannot calculate vert speed for index " + inIndex);
+                       return;
+               }
+               inValue.setInvalid();
+
+               DataPoint point = inTrack.getPoint(inIndex);
+               boolean pointHasSpeed = false;
+               double  speedValue = 0.0;
+
+               // First, see if point has a speed value already
+               if (point != null)
+               {
+                       // FIXME: Can we assume m/s or ft/s?
+                       String speedStr = point.getFieldValue(Field.VERTICAL_SPEED);
+                       try {
+                               speedValue = Double.parseDouble(speedStr);
+                               pointHasSpeed = true;
+                       }
+                       catch (Exception e) {} // ignore, leave pointHasSpeed false
+               }
+               // otherwise, see if we can calculate it from the heights and timestamps
+               if (!pointHasSpeed
+                       && point != null && point.hasTimestamp() && point.hasAltitude() && !point.isWaypoint())
+               {
+                       int index = inIndex-1;
+                       DataPoint p = null;
+                       Timestamp earlyStamp = point.getTimestamp();
+                       Altitude firstAlt = point.getAltitude();
+                       boolean stop = false;
+
+                       // Count backwards until timestamp earlier than now
+                       if (!point.getSegmentStart())
+                       {
+                               do
+                               {
+                                       p = inTrack.getPoint(index);
+                                       boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isAfter(point.getTimestamp());
+                                       boolean pValid = timeOk && !p.isWaypoint();
+                                       if (pValid) {
+                                               earlyStamp = p.getTimestamp();
+                                               if (p.hasAltitude()) firstAlt = p.getAltitude();
+                                       }
+                                       stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
+                                               || p.getSegmentStart());
+                                       index--;
+                               }
+                               while (!stop);
+                       }
+
+                       // Count forwards until timestamp later than now
+                       Timestamp lateStamp = point.getTimestamp();
+                       Altitude lastAlt = point.getAltitude();
+                       index = inIndex+1;
+                       do
+                       {
+                               p = inTrack.getPoint(index);
+                               boolean timeOk = p != null && p.hasTimestamp() && !p.getTimestamp().isBefore(point.getTimestamp());
+                               boolean pValid = timeOk && !p.isWaypoint() && !p.getSegmentStart();
+                               if (pValid) {
+                                       lateStamp = p.getTimestamp();
+                                       if (p.hasAltitude()) lastAlt = p.getAltitude();
+                               }
+                               stop = (p == null) || (p.hasTimestamp() && !p.getTimestamp().isEqual(point.getTimestamp())
+                                       || p.getSegmentStart());
+                               index++;
+                       }
+                       while (!stop);
+
+                       // See if we've managed to get a non-zero time range
+                       long milliseconds = lateStamp.getMillisecondsSince(earlyStamp);
+                       if (milliseconds >= 1000L)
+                       {
+                               double altDiff = (lastAlt.getMetricValue() - firstAlt.getMetricValue())
+                                * Config.getUnitSet().getVerticalSpeedUnit().getMultFactorFromStd();
+                               speedValue = altDiff / milliseconds * 1000.0; // units are feet/sec or metres/sec
+                               pointHasSpeed = true;
+                       }
+               }
+               // Check whether we got a value from either method
+               if (pointHasSpeed)
+               {
+                       inValue.setValue(speedValue);
+               }
+       }
+}
diff --git a/tim/prune/data/SpeedValue.java b/tim/prune/data/SpeedValue.java
new file mode 100644 (file)
index 0000000..45ed28e
--- /dev/null
@@ -0,0 +1,45 @@
+package tim.prune.data;
+
+/**
+ * Holder for a speed value, including a boolean valid flag
+ */
+public class SpeedValue
+{
+       /** Valid flag */
+       private boolean _valid = false;
+       /** Value as a double, using current units */
+       private double  _value = 0.0;
+
+
+       /**
+        * Set the flag to invalid
+        */
+       public void setInvalid()
+       {
+               _valid = false;
+               _value = 0.0;
+       }
+
+       /**
+        * @param inValue speed value to set
+        */
+       public void setValue(double inValue)
+       {
+               _valid = true;
+               _value = inValue;
+       }
+
+       /**
+        * @return true if value is valid
+        */
+       public boolean isValid() {
+               return _valid;
+       }
+
+       /**
+        * @return numeric value
+        */
+       public double getValue() {
+               return _value;
+       }
+}
index e7a0ab90e3af6e5625bbdc833810e2c60fb5e92b..477a7227125a0a82a7a4fcd4a7c899d2352bc03a 100644 (file)
@@ -15,7 +15,7 @@ import java.util.regex.Pattern;
 public class Timestamp
 {
        private boolean _valid = false;
 public class Timestamp
 {
        private boolean _valid = false;
-       private long _seconds = 0L;
+       private long _milliseconds = 0L;
        private String _text = null;
        private String _timeText = null;
 
        private String _text = null;
        private String _timeText = null;
 
@@ -25,6 +25,8 @@ public class Timestamp
        private static final DateFormat ISO_8601_FORMAT_NOZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        private static DateFormat[] ALL_DATE_FORMATS = null;
        private static Calendar CALENDAR = null;
        private static final DateFormat ISO_8601_FORMAT_NOZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        private static DateFormat[] ALL_DATE_FORMATS = null;
        private static Calendar CALENDAR = null;
+       private static final Pattern ISO8601_FRACTIONAL_PATTERN
+               = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})\\.(\\d{1,3})Z?");
        private static final Pattern GENERAL_TIMESTAMP_PATTERN
                = Pattern.compile("(\\d{4})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})");
        private static long SECS_SINCE_1970 = 0L;
        private static final Pattern GENERAL_TIMESTAMP_PATTERN
                = Pattern.compile("(\\d{4})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})");
        private static long SECS_SINCE_1970 = 0L;
@@ -41,6 +43,27 @@ public class Timestamp
        /** Specifies ISO 8601 timestamp format */
        public static final int FORMAT_ISO_8601 = 2;
 
        /** Specifies ISO 8601 timestamp format */
        public static final int FORMAT_ISO_8601 = 2;
 
+       /** Identifier for the parsing strategy to use */
+       private enum ParseType
+       {
+               NONE,
+               ISO8601_FRACTIONAL,
+               LONG,
+               FIXED_FORMAT0,
+               FIXED_FORMAT1,
+               FIXED_FORMAT2,
+               FIXED_FORMAT3,
+               FIXED_FORMAT4,
+               FIXED_FORMAT5,
+               FIXED_FORMAT6,
+               GENERAL_STRING
+       }
+
+       /** Array of parse types to loop through (first one is changed to last successful type) */
+       private static ParseType[] ALL_PARSE_TYPES = {ParseType.NONE, ParseType.ISO8601_FRACTIONAL, ParseType.LONG,
+               ParseType.FIXED_FORMAT0, ParseType.FIXED_FORMAT1, ParseType.FIXED_FORMAT2, ParseType.FIXED_FORMAT3,
+               ParseType.FIXED_FORMAT4, ParseType.FIXED_FORMAT5, ParseType.FIXED_FORMAT6, ParseType.GENERAL_STRING};
+
        // Static block to initialise offsets
        static
        {
        // Static block to initialise offsets
        static
        {
@@ -69,51 +92,116 @@ public class Timestamp
         */
        public Timestamp(String inString)
        {
         */
        public Timestamp(String inString)
        {
-               // TODO: Does it really help to store timestamps in seconds rather than ms?
+               _valid = false;
                if (inString != null && !inString.equals(""))
                {
                if (inString != null && !inString.equals(""))
                {
-                       // Try to parse into a long
-                       try
+                       // Try each of the parse types in turn
+                       for (ParseType type : ALL_PARSE_TYPES)
                        {
                        {
-                               long rawValue = Long.parseLong(inString.trim());
-                               _seconds = getSeconds(rawValue);
-                               _valid = true;
+                               if (parseString(inString, type))
+                               {
+                                       ALL_PARSE_TYPES[0] = type;
+                                       _valid = true;
+                                       return;
+                               }
                        }
                        }
-                       catch (NumberFormatException nfe)
-                       {
-                               // String is not a long, so try a date/time string instead
-                               // try each of the date formatters in turn
-                               Date date = null;
-                               for (int i=0; i<ALL_DATE_FORMATS.length && !_valid; i++)
+               }
+       }
+
+       /**
+        * Try to parse the given string in the specified way
+        * @param inString String to parse
+        * @param inType parse type to use
+        * @return true if successful
+        */
+       private boolean parseString(String inString, ParseType inType)
+       {
+               if (inString == null || inString.equals("")) {
+                       return false;
+               }
+               switch (inType)
+               {
+                       case NONE: return false;
+                       case LONG:
+                               // Try to parse into a long
+                               try
                                {
                                {
-                                       try
-                                       {
-                                               date = ALL_DATE_FORMATS[i].parse(inString);
-                                               CALENDAR.setTime(date);
-                                               _seconds = CALENDAR.getTimeInMillis() / 1000L;
-                                               _valid = true;
+                                       long rawValue = Long.parseLong(inString.trim());
+                                       _milliseconds = getMilliseconds(rawValue);
+                                       return true;
+                               }
+                               catch (NumberFormatException nfe)
+                               {}
+                               break;
+
+                       case ISO8601_FRACTIONAL:
+                               final Matcher fmatcher = ISO8601_FRACTIONAL_PATTERN.matcher(inString);
+                               if (fmatcher.matches())
+                               {
+                                       try {
+                                               _milliseconds = getMilliseconds(Integer.parseInt(fmatcher.group(1)), // year
+                                                       Integer.parseInt(fmatcher.group(2)), // month
+                                                       Integer.parseInt(fmatcher.group(3)), // day
+                                                       Integer.parseInt(fmatcher.group(4)), // hour
+                                                       Integer.parseInt(fmatcher.group(5)), // minute
+                                                       Integer.parseInt(fmatcher.group(6)), // second
+                                                       fmatcher.group(7));                  // fractional seconds
+                                               return true;
                                        }
                                        }
-                                       catch (ParseException e) {}
+                                       catch (NumberFormatException nfe) {}
                                }
                                }
-                               if (!_valid && inString.length() == 19)
+                               break;
+
+                       case FIXED_FORMAT0: return parseString(inString, ALL_DATE_FORMATS[0]);
+                       case FIXED_FORMAT1: return parseString(inString, ALL_DATE_FORMATS[1]);
+                       case FIXED_FORMAT2: return parseString(inString, ALL_DATE_FORMATS[2]);
+                       case FIXED_FORMAT3: return parseString(inString, ALL_DATE_FORMATS[3]);
+                       case FIXED_FORMAT4: return parseString(inString, ALL_DATE_FORMATS[4]);
+                       case FIXED_FORMAT5: return parseString(inString, ALL_DATE_FORMATS[5]);
+                       case FIXED_FORMAT6: return parseString(inString, ALL_DATE_FORMATS[6]);
+
+                       case GENERAL_STRING:
+                               if (inString.length() == 19)
                                {
                                        final Matcher matcher = GENERAL_TIMESTAMP_PATTERN.matcher(inString);
                                        if (matcher.matches())
                                        {
                                                try {
                                {
                                        final Matcher matcher = GENERAL_TIMESTAMP_PATTERN.matcher(inString);
                                        if (matcher.matches())
                                        {
                                                try {
-                                                       _seconds = getSeconds(Integer.parseInt(matcher.group(1)),
+                                                       _milliseconds = getMilliseconds(Integer.parseInt(matcher.group(1)),
                                                                Integer.parseInt(matcher.group(2)),
                                                                Integer.parseInt(matcher.group(3)),
                                                                Integer.parseInt(matcher.group(4)),
                                                                Integer.parseInt(matcher.group(5)),
                                                                Integer.parseInt(matcher.group(2)),
                                                                Integer.parseInt(matcher.group(3)),
                                                                Integer.parseInt(matcher.group(4)),
                                                                Integer.parseInt(matcher.group(5)),
-                                                               Integer.parseInt(matcher.group(6)));
-                                                       _valid = true;
+                                                               Integer.parseInt(matcher.group(6)),
+                                                               null); // no fractions of a second
+                                                       return true;
                                                }
                                                catch (NumberFormatException nfe2) {} // parse shouldn't fail if matcher matched
                                        }
                                }
                                                }
                                                catch (NumberFormatException nfe2) {} // parse shouldn't fail if matcher matched
                                        }
                                }
-                       }
+                               return false;
                }
                }
+               return false;
+       }
+
+
+       /**
+        * Try to parse the given string with the given date format
+        * @param inString String to parse
+        * @param inDateFormat Date format to use
+        * @return true if successful
+        */
+       private boolean parseString(String inString, DateFormat inDateFormat)
+       {
+               try
+               {
+                       Date date = inDateFormat.parse(inString);
+                       CALENDAR.setTime(date);
+                       _milliseconds = CALENDAR.getTimeInMillis();
+                       return true;
+               }
+               catch (ParseException e) {}
+               return false;
        }
 
 
        }
 
 
@@ -128,7 +216,7 @@ public class Timestamp
         */
        public Timestamp(int inYear, int inMonth, int inDay, int inHour, int inMinute, int inSecond)
        {
         */
        public Timestamp(int inYear, int inMonth, int inDay, int inHour, int inMinute, int inSecond)
        {
-               _seconds = getSeconds(inYear, inMonth, inDay, inHour, inMinute, inSecond);
+               _milliseconds = getMilliseconds(inYear, inMonth, inDay, inHour, inMinute, inSecond, null);
                _valid = true;
        }
 
                _valid = true;
        }
 
@@ -139,22 +227,24 @@ public class Timestamp
         */
        public Timestamp(long inMillis)
        {
         */
        public Timestamp(long inMillis)
        {
-               _seconds = inMillis / 1000;
+               _milliseconds = inMillis;
                _valid = true;
        }
 
 
        /**
                _valid = true;
        }
 
 
        /**
-        * Convert the given timestamp parameters into a number of seconds
+        * Convert the given timestamp parameters into a number of milliseconds
         * @param inYear year
         * @param inMonth month, beginning with 1
         * @param inDay day of month, beginning with 1
         * @param inHour hour of day, 0-24
         * @param inMinute minute
         * @param inSecond seconds
         * @param inYear year
         * @param inMonth month, beginning with 1
         * @param inDay day of month, beginning with 1
         * @param inHour hour of day, 0-24
         * @param inMinute minute
         * @param inSecond seconds
-        * @return number of seconds
+        * @param inFraction fractions of a second
+        * @return number of milliseconds
         */
         */
-       private static long getSeconds(int inYear, int inMonth, int inDay, int inHour, int inMinute, int inSecond)
+       private static long getMilliseconds(int inYear, int inMonth, int inDay,
+               int inHour, int inMinute, int inSecond, String inFraction)
        {
                Calendar cal = Calendar.getInstance();
                cal.set(Calendar.YEAR, inYear);
        {
                Calendar cal = Calendar.getInstance();
                cal.set(Calendar.YEAR, inYear);
@@ -163,16 +253,30 @@ public class Timestamp
                cal.set(Calendar.HOUR_OF_DAY, inHour);
                cal.set(Calendar.MINUTE, inMinute);
                cal.set(Calendar.SECOND, inSecond);
                cal.set(Calendar.HOUR_OF_DAY, inHour);
                cal.set(Calendar.MINUTE, inMinute);
                cal.set(Calendar.SECOND, inSecond);
-               cal.set(Calendar.MILLISECOND, 0);
-               return cal.getTimeInMillis() / 1000;
+               int millis = 0;
+               if (inFraction != null)
+               {
+                       try {
+                               int frac = Integer.parseInt(inFraction);
+                               final int fracLen = inFraction.length();
+                               switch (fracLen) {
+                                       case 1: millis = frac * 100; break;
+                                       case 2: millis = frac * 10;  break;
+                                       case 3: millis = frac;       break;
+                               }
+                       }
+                       catch (NumberFormatException nfe) {} // ignore errors, millis stay at 0
+               }
+               cal.set(Calendar.MILLISECOND, millis);
+               return cal.getTimeInMillis();
        }
 
        /**
        }
 
        /**
-        * Convert the given long parameters into a number of seconds
+        * Convert the given long parameters into a number of millisseconds
         * @param inRawValue long value representing seconds / milliseconds
         * @param inRawValue long value representing seconds / milliseconds
-        * @return number of seconds
+        * @return number of milliseconds
         */
         */
-       private static long getSeconds(long inRawValue)
+       private static long getMilliseconds(long inRawValue)
        {
                // check for each format possibility and pick nearest
                long diff1 = Math.abs(SECS_SINCE_1970 - inRawValue);
        {
                // check for each format possibility and pick nearest
                long diff1 = Math.abs(SECS_SINCE_1970 - inRawValue);
@@ -182,28 +286,28 @@ public class Timestamp
 
                // Start off with "seconds since 1970" format
                long smallestDiff = diff1;
 
                // Start off with "seconds since 1970" format
                long smallestDiff = diff1;
-               long seconds = inRawValue;
+               long millis = inRawValue * 1000;
                // Now check millis since 1970
                if (diff2 < smallestDiff)
                {
                        // milliseconds since 1970
                // Now check millis since 1970
                if (diff2 < smallestDiff)
                {
                        // milliseconds since 1970
-                       seconds = inRawValue / 1000L;
+                       millis = inRawValue;
                        smallestDiff = diff2;
                }
                // Now millis since 1990
                if (diff3 < smallestDiff)
                {
                        // milliseconds since 1990
                        smallestDiff = diff2;
                }
                // Now millis since 1990
                if (diff3 < smallestDiff)
                {
                        // milliseconds since 1990
-                       seconds = inRawValue / 1000L + TWENTY_YEARS_IN_SECS;
+                       millis = inRawValue + TWENTY_YEARS_IN_SECS * 1000L;
                        smallestDiff = diff3;
                }
                // Lastly, check gartrip offset
                if (diff4 < smallestDiff)
                {
                        // seconds since gartrip offset
                        smallestDiff = diff3;
                }
                // Lastly, check gartrip offset
                if (diff4 < smallestDiff)
                {
                        // seconds since gartrip offset
-                       seconds = inRawValue + GARTRIP_OFFSET;
+                       millis = (inRawValue + GARTRIP_OFFSET) * 1000L;
                }
                }
-               return seconds;
+               return millis;
        }
 
        /**
        }
 
        /**
@@ -216,11 +320,11 @@ public class Timestamp
 
        /**
         * @param inOther other Timestamp
 
        /**
         * @param inOther other Timestamp
-        * @return true if this one is after the other
+        * @return true if this one is at least a second after the other
         */
        public boolean isAfter(Timestamp inOther)
        {
         */
        public boolean isAfter(Timestamp inOther)
        {
-               return _seconds > inOther._seconds;
+               return getSecondsSince(inOther) > 0L;
        }
 
        /**
        }
 
        /**
@@ -230,7 +334,35 @@ public class Timestamp
         */
        public long getSecondsSince(Timestamp inOther)
        {
         */
        public long getSecondsSince(Timestamp inOther)
        {
-               return _seconds - inOther._seconds;
+               return (_milliseconds - inOther._milliseconds) / 1000L;
+       }
+
+       /**
+        * Calculate the difference between two Timestamps in milliseconds
+        * @param inOther other, earlier Timestamp
+        * @return number of millisseconds since other timestamp
+        */
+       public long getMillisecondsSince(Timestamp inOther)
+       {
+               return _milliseconds - inOther._milliseconds;
+       }
+
+       /**
+        * @param inOther other timestamp to compare
+        * @return true if they're equal to the nearest second
+        */
+       public boolean isEqual(Timestamp inOther)
+       {
+               return getSecondsSince(inOther) == 0L;
+       }
+
+       /**
+        * @param inOther other Timestamp
+        * @return true if this one is before the other
+        */
+       public boolean isBefore(Timestamp inOther)
+       {
+               return getSecondsSince(inOther) < 0L;
        }
 
        /**
        }
 
        /**
@@ -239,7 +371,7 @@ public class Timestamp
         */
        public void addOffset(long inOffset)
        {
         */
        public void addOffset(long inOffset)
        {
-               _seconds += inOffset;
+               _milliseconds += (inOffset * 1000L);
                _text = null;
        }
 
                _text = null;
        }
 
@@ -260,7 +392,7 @@ public class Timestamp
         */
        public Timestamp createPlusOffset(long inSeconds)
        {
         */
        public Timestamp createPlusOffset(long inSeconds)
        {
-               return new Timestamp((_seconds + inSeconds) * 1000L);
+               return new Timestamp(_milliseconds + (inSeconds * 1000L));
        }
 
 
        }
 
 
@@ -271,7 +403,7 @@ public class Timestamp
         */
        public Timestamp createMinusOffset(TimeDifference inOffset)
        {
         */
        public Timestamp createMinusOffset(TimeDifference inOffset)
        {
-               return new Timestamp((_seconds - inOffset.getTotalSeconds()) * 1000L);
+               return new Timestamp(_milliseconds - (inOffset.getTotalSeconds() * 1000L));
        }
 
 
        }
 
 
@@ -321,7 +453,7 @@ public class Timestamp
         */
        private String format(DateFormat inFormat)
        {
         */
        private String format(DateFormat inFormat)
        {
-               CALENDAR.setTimeInMillis(_seconds * 1000L);
+               CALENDAR.setTimeInMillis(_milliseconds);
                return inFormat.format(CALENDAR.getTime());
        }
 
                return inFormat.format(CALENDAR.getTime());
        }
 
@@ -331,7 +463,7 @@ public class Timestamp
        public Calendar getCalendar()
        {
                Calendar cal = Calendar.getInstance();
        public Calendar getCalendar()
        {
                Calendar cal = Calendar.getInstance();
-               cal.setTimeInMillis(_seconds * 1000L);
+               cal.setTimeInMillis(_milliseconds);
                return cal;
        }
 }
                return cal;
        }
 }
index 63cd01faaf488028085a6712c5648ad9ffa8ea1d..b28fd3642091cdc485e1a9130a72c3f2ecd14dac 100644 (file)
@@ -3,7 +3,6 @@ package tim.prune.data;
 import java.util.List;
 
 import tim.prune.UpdateMessageBroker;
 import java.util.List;
 
 import tim.prune.UpdateMessageBroker;
-import tim.prune.config.Config;
 import tim.prune.function.edit.FieldEdit;
 import tim.prune.function.edit.FieldEditList;
 import tim.prune.gui.map.MapUtils;
 import tim.prune.function.edit.FieldEdit;
 import tim.prune.function.edit.FieldEditList;
 import tim.prune.gui.map.MapUtils;
@@ -27,7 +26,6 @@ public class Track
        // Master field list
        private FieldList _masterFieldList = null;
        // variable ranges
        // Master field list
        private FieldList _masterFieldList = null;
        // variable ranges
-       private AltitudeRange _altitudeRange = null;
        private DoubleRange _latRange = null, _longRange = null;
        private DoubleRange _xRange = null, _yRange = null;
 
        private DoubleRange _latRange = null, _longRange = null;
        private DoubleRange _xRange = null, _yRange = null;
 
@@ -580,7 +578,7 @@ public class Track
                double latitudeDiff = 0.0, longitudeDiff = 0.0;
                double totalAltitude = 0;
                int numAltitudes = 0;
                double latitudeDiff = 0.0, longitudeDiff = 0.0;
                double totalAltitude = 0;
                int numAltitudes = 0;
-               Altitude.Format altFormat = Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?Altitude.Format.METRES:Altitude.Format.FEET;
+               Altitude.Format altFormat = Altitude.Format.NO_FORMAT;
                // loop between start and end points
                for (int i=inStartIndex; i<= inEndIndex; i++)
                {
                // loop between start and end points
                for (int i=inStartIndex; i<= inEndIndex; i++)
                {
@@ -589,6 +587,9 @@ public class Track
                        longitudeDiff += (currPoint.getLongitude().getDouble() - firstLongitude);
                        if (currPoint.hasAltitude()) {
                                totalAltitude += currPoint.getAltitude().getValue(altFormat);
                        longitudeDiff += (currPoint.getLongitude().getDouble() - firstLongitude);
                        if (currPoint.hasAltitude()) {
                                totalAltitude += currPoint.getAltitude().getValue(altFormat);
+                               // Use altitude format of first valid altitude
+                               if (altFormat == Altitude.Format.NO_FORMAT)
+                                       altFormat = currPoint.getAltitude().getFormat();
                                numAltitudes++;
                        }
                }
                                numAltitudes++;
                        }
                }
@@ -643,16 +644,6 @@ public class Track
                return null;
        }
 
                return null;
        }
 
-
-       /**
-        * @return altitude range of points as AltitudeRange object
-        */
-       public AltitudeRange getAltitudeRange()
-       {
-               if (!_scaled) scalePoints();
-               return _altitudeRange;
-       }
-
        /**
         * @return the number of (valid) points in the track
         */
        /**
         * @return the number of (valid) points in the track
         */
@@ -873,10 +864,9 @@ public class Track
         */
        private void scalePoints()
        {
         */
        private void scalePoints()
        {
-               // Loop through all points in track, to see limits of lat, long and altitude
+               // Loop through all points in track, to see limits of lat, long
                _longRange = new DoubleRange();
                _latRange = new DoubleRange();
                _longRange = new DoubleRange();
                _latRange = new DoubleRange();
-               _altitudeRange = new AltitudeRange();
                int p;
                _hasWaypoint = false; _hasTrackpoint = false;
                for (p=0; p < getNumPoints(); p++)
                int p;
                _hasWaypoint = false; _hasTrackpoint = false;
                for (p=0; p < getNumPoints(); p++)
@@ -886,10 +876,6 @@ public class Track
                        {
                                _longRange.addValue(point.getLongitude().getDouble());
                                _latRange.addValue(point.getLatitude().getDouble());
                        {
                                _longRange.addValue(point.getLongitude().getDouble());
                                _latRange.addValue(point.getLatitude().getDouble());
-                               if (point.getAltitude().isValid())
-                               {
-                                       _altitudeRange.addValue(point.getAltitude());
-                               }
                                if (point.isWaypoint())
                                        _hasWaypoint = true;
                                else
                                if (point.isWaypoint())
                                        _hasWaypoint = true;
                                else
@@ -930,16 +916,21 @@ public class Track
        {
                int nearestPoint = 0;
                double nearestDist = -1.0;
        {
                int nearestPoint = 0;
                double nearestDist = -1.0;
-               double currDist;
+               double mDist, yDist;
                for (int i=0; i < getNumPoints(); i++)
                {
                        if (!inJustTrackPoints || !_dataPoints[i].isWaypoint())
                        {
                for (int i=0; i < getNumPoints(); i++)
                {
                        if (!inJustTrackPoints || !_dataPoints[i].isWaypoint())
                        {
-                               currDist = Math.abs(_xValues[i] - inX) + Math.abs(_yValues[i] - inY);
-                               if (currDist < nearestDist || nearestDist < 0.0)
+                               yDist = Math.abs(_yValues[i] - inY);
+                               if (yDist < nearestDist || nearestDist < 0.0)
                                {
                                {
-                                       nearestPoint = i;
-                                       nearestDist = currDist;
+                                       // y dist is within range, so check x too
+                                       mDist = yDist + getMinXDist(_xValues[i] - inX);
+                                       if (mDist < nearestDist || nearestDist < 0.0)
+                                       {
+                                               nearestPoint = i;
+                                               nearestDist = mDist;
+                                       }
                                }
                        }
                }
                                }
                        }
                }
@@ -951,6 +942,16 @@ public class Track
                return nearestPoint;
        }
 
                return nearestPoint;
        }
 
+       /**
+        * @param inX x value of point
+        * @return minimum wrapped value
+        */
+       private static final double getMinXDist(double inX)
+       {
+               // TODO: Can use some kind of floor here?
+               return Math.min(Math.min(Math.abs(inX), Math.abs(inX-1.0)), Math.abs(inX+1.0));
+       }
+
        /**
         * Get the next track point starting from the given index
         * @param inStartIndex index to start looking from
        /**
         * Get the next track point starting from the given index
         * @param inStartIndex index to start looking from
index 58344142d390faf734df76edbf8fc557d5649c8e..7bcbc641e75fcae730f07178d5ad93637486145c 100644 (file)
@@ -184,21 +184,6 @@ public class TrackInfo
                return numAudiosAdded;
        }
 
                return numAudiosAdded;
        }
 
-       /**
-        * Delete the currently selected range of points
-        * @return true if successful
-        */
-       public boolean deleteRange()
-       {
-               int startSel = _selection.getStart();
-               int endSel = _selection.getEnd();
-               boolean answer = _track.deleteRange(startSel, endSel);
-               // clear range selection
-               _selection.modifyRangeDeleted();
-               return answer;
-       }
-
-
        /**
         * Delete the currently selected point
         * @return true if point deleted
        /**
         * Delete the currently selected point
         * @return true if point deleted
@@ -335,20 +320,6 @@ public class TrackInfo
                return true;
        }
 
                return true;
        }
 
-       /**
-        * Interpolate extra points between two selected ones
-        * @param inNumPoints num points to insert
-        * @return true if successful
-        */
-       public boolean interpolate(int inNumPoints)
-       {
-               boolean success = _track.interpolate(_selection.getStart(), inNumPoints);
-               if (success) {
-                       _selection.selectRangeEnd(_selection.getEnd() + inNumPoints);
-               }
-               return success;
-       }
-
 
        /**
         * Average selected points to create a new one
 
        /**
         * Average selected points to create a new one
@@ -453,11 +424,13 @@ public class TrackInfo
                // Has the new point got an audio clip?
                DataPoint selectedPoint = _track.getPoint(pointIndex);
                int audioIndex = _selection.getCurrentAudioIndex();
                // Has the new point got an audio clip?
                DataPoint selectedPoint = _track.getPoint(pointIndex);
                int audioIndex = _selection.getCurrentAudioIndex();
-               if (selectedPoint != null) {
-                       if (selectedPoint.getAudio() != null) audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
+               if (selectedPoint != null && selectedPoint.getAudio() != null) {
+                       // New point has an audio, so select it
+                       audioIndex = _audioList.getAudioIndex(selectedPoint.getAudio());
                }
                }
-               else {
-                       if (selectedPoint != currPoint && currPoint.getAudio() != null) {audioIndex = -1;}
+               else if (currPoint != null && selectedPoint != currPoint && currPoint.getAudio() != null) {
+                       // Old point had an audio, so deselect it
+                       audioIndex = -1;
                }
                // give to selection object
                _selection.selectPointPhotoAudio(pointIndex, inPhotoIndex, audioIndex);
                }
                // give to selection object
                _selection.selectPointPhotoAudio(pointIndex, inPhotoIndex, audioIndex);
@@ -496,11 +469,13 @@ public class TrackInfo
                // Has the new point got a photo?
                DataPoint selectedPoint = _track.getPoint(pointIndex);
                int photoIndex = _selection.getCurrentPhotoIndex();
                // Has the new point got a photo?
                DataPoint selectedPoint = _track.getPoint(pointIndex);
                int photoIndex = _selection.getCurrentPhotoIndex();
-               if (selectedPoint != null) {
-                       if (selectedPoint.getPhoto() != null) photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
+               if (selectedPoint != null && selectedPoint.getPhoto() != null) {
+                       // New point has a photo, so select it
+                       photoIndex = _photoList.getPhotoIndex(selectedPoint.getPhoto());
                }
                }
-               else {
-                       if (selectedPoint != currPoint && currPoint.getPhoto() != null) {photoIndex = -1;}
+               else if (currPoint != null && selectedPoint != currPoint && currPoint.getPhoto() != null) {
+                       // Old point had a photo, so deselect it
+                       photoIndex = -1;
                }
                // give to selection object
                _selection.selectPointPhotoAudio(pointIndex, photoIndex, inAudioIndex);
                }
                // give to selection object
                _selection.selectPointPhotoAudio(pointIndex, photoIndex, inAudioIndex);
diff --git a/tim/prune/data/Unit.java b/tim/prune/data/Unit.java
new file mode 100644 (file)
index 0000000..b4e82e3
--- /dev/null
@@ -0,0 +1,75 @@
+package tim.prune.data;
+
+/**
+ * Class to represent a single distance or speed unit
+ * such as kilometres, mph, feet etc
+ */
+public class Unit
+{
+       private String _nameKey = null;
+       private double _multFactorFromStd = 1.0;
+       private boolean _isStandard = false;
+
+       /**
+        * Unit constructor
+        * @param inNameKey name key
+        * @param inMultFactor multiplication factor from standard units
+        */
+       public Unit(String inNameKey, double inMultFactor)
+       {
+               _nameKey = inNameKey;
+               _multFactorFromStd = inMultFactor;
+               _isStandard = false;
+       }
+
+       /**
+        * Unit constructor for standard unit
+        * @param inNameKey name key
+        */
+       public Unit(String inNameKey)
+       {
+               _nameKey = inNameKey;
+               _multFactorFromStd = 1.0;
+               _isStandard = true;
+       }
+
+       /**
+        * Unit constructor
+        * @param inParent parent unit
+        * @param inSuffix suffix to name key
+        */
+       public Unit(Unit inParent, String inSuffix)
+       {
+               _nameKey = inParent._nameKey + inSuffix;
+               _multFactorFromStd = inParent._multFactorFromStd;
+               _isStandard = inParent._isStandard;
+       }
+
+       /**
+        * @return name key
+        */
+       public String getNameKey() {
+               return "units." + _nameKey;
+       }
+
+       /**
+        * @return shortname key
+        */
+       public String getShortnameKey() {
+               return getNameKey() + ".short";
+       }
+
+       /**
+        * @return multiplication factor from standard units
+        */
+       public double getMultFactorFromStd() {
+               return _multFactorFromStd;
+       }
+
+       /**
+        * @return true if this is the standard unit (mult factor 1.0)
+        */
+       public boolean isStandard() {
+               return _isStandard;
+       }
+}
diff --git a/tim/prune/data/UnitSet.java b/tim/prune/data/UnitSet.java
new file mode 100644 (file)
index 0000000..bd53e1b
--- /dev/null
@@ -0,0 +1,74 @@
+package tim.prune.data;
+
+/**
+ * Class to hold a set of units for distance, altitude and speed
+ */
+public class UnitSet
+{
+       private String _nameKey = null;
+       private Unit _distanceUnit = null;
+       private Unit _speedUnit = null;
+       private Unit _altitudeUnit = null;
+       private Unit _vertSpeedUnit = null;
+       private Altitude.Format _defaultAltitudeFormat = Altitude.Format.METRES;
+
+       /**
+        * Constructor
+        * @param inNameKey name key
+        * @param inDistanceUnit distance unit
+        * @param inAltitudeUnit altitude unit
+        * @param inAltitudeFormat default altitude format
+        */
+       public UnitSet(String inNameKey, Unit inDistanceUnit,
+               Unit inAltitudeUnit, Altitude.Format inAltitudeFormat)
+       {
+               _nameKey = inNameKey;
+               _distanceUnit = inDistanceUnit;
+               _speedUnit = new Unit(_distanceUnit, "perhour");
+               _altitudeUnit = inAltitudeUnit;
+               _defaultAltitudeFormat = inAltitudeFormat;
+               _vertSpeedUnit = new Unit(_altitudeUnit, "persec");
+       }
+
+       /**
+        * @return name key
+        */
+       public String getNameKey() {
+               return _nameKey;
+       }
+
+       /**
+        * @return distance unit
+        */
+       public Unit getDistanceUnit() {
+               return _distanceUnit;
+       }
+
+       /**
+        * @return speed unit
+        */
+       public Unit getSpeedUnit() {
+               return _speedUnit;
+       }
+
+       /**
+        * @return altitude unit
+        */
+       public Unit getAltitudeUnit() {
+               return _altitudeUnit;
+       }
+
+       /**
+        * @return vertical speed unit
+        */
+       public Unit getVerticalSpeedUnit() {
+               return _vertSpeedUnit;
+       }
+
+       /**
+        * @return default altitude format
+        */
+       public Altitude.Format getDefaultAltitudeFormat() {
+               return _defaultAltitudeFormat;
+       }
+}
diff --git a/tim/prune/data/UnitSetLibrary.java b/tim/prune/data/UnitSetLibrary.java
new file mode 100644 (file)
index 0000000..b270124
--- /dev/null
@@ -0,0 +1,66 @@
+package tim.prune.data;
+
+/**
+ * List of all possible unit sets, for example
+ * metric, imperial, nautical
+ */
+public abstract class UnitSetLibrary
+{
+       // Distance units - all conversion factors are from metres
+       /** Units for feet (used for loading and converting values) */
+       public static final Unit UNITS_FEET       = new Unit("feet", 3.2808);
+       /** Units for metres */
+       public static final Unit UNITS_METRES     = new Unit("metres");
+       /** Units for km */
+       public static final Unit UNITS_KILOMETRES = new Unit("kilometres", 1/1000.0);
+       /** Units for miles */
+       public static final Unit UNITS_MILES      = new Unit("miles", 1/1609.3);
+       /** Units for nautical miles */
+       public static final Unit UNITS_NAUTICAL_MILES = new Unit("nauticalmiles", 1/1852.0);
+
+       /** Array of available unit sets */
+       private static UnitSet[] _sets = {
+               new UnitSet("unitset.kilometres", UNITS_KILOMETRES, UNITS_METRES, Altitude.Format.METRES),
+               new UnitSet("unitset.miles", UNITS_MILES, UNITS_FEET, Altitude.Format.FEET),
+               new UnitSet("unitset.nautical", UNITS_NAUTICAL_MILES, UNITS_FEET, Altitude.Format.FEET)
+       };
+
+       /**
+        * @return number of available unit sets
+        */
+       public static int getNumUnitSets() {
+               return _sets.length;
+       }
+
+       /**
+        * Get the specified unit set
+        * @param inIndex index of set starting from 0
+        * @return specified unit set or the default one if index out of range
+        */
+       public static UnitSet getUnitSet(int inIndex)
+       {
+               if (inIndex >= 0 && inIndex < getNumUnitSets()) {
+                       return _sets[inIndex];
+               }
+               return _sets[0];
+       }
+
+       /**
+        * Get the unit set specified by the given key
+        * @param inKey key to look for
+        * @return unit set with given key, or default set if key not found
+        */
+       public static UnitSet getUnitSet(String inKey)
+       {
+               // Loop over all available unit sets
+               for (int i=0; i<getNumUnitSets(); i++)
+               {
+                       UnitSet set = getUnitSet(i);
+                       if (set.getNameKey().equals(inKey)) {
+                               return set;
+                       }
+               }
+               // Not found in list, so just return the first one
+               return getUnitSet(0);
+       }
+}
index 1032fcfca84f2ea8e3105973dbe7c5731f1996c0..85c52dee7f5291bc8293be3aa3b5038a0068a150 100644 (file)
@@ -18,6 +18,7 @@ import javax.swing.JTextField;
 import tim.prune.App;
 import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
 import tim.prune.App;
 import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
+import tim.prune.config.Config;
 import tim.prune.data.Altitude;
 import tim.prune.data.Field;
 
 import tim.prune.data.Altitude;
 import tim.prune.data.Field;
 
@@ -69,7 +70,7 @@ public class AddAltitudeOffset extends GenericFunction
                        _dialog.pack();
                }
                // Set label according to altitude units
                        _dialog.pack();
                }
                // Set label according to altitude units
-               setLabelText(selStart, selEnd);
+               setLabelText();
                // Select the contents of the edit field
                _editField.selectAll();
                _dialog.setVisible(true);
                // Select the contents of the edit field
                _editField.selectAll();
                _dialog.setVisible(true);
@@ -148,20 +149,11 @@ public class AddAltitudeOffset extends GenericFunction
 
        /**
         * Set the label text according to the current units
 
        /**
         * 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)
+       private void setLabelText()
        {
        {
-               _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.FEET;
+               if (Config.getUnitSet().getAltitudeUnit().isStandard()) {
                        _altFormat = Altitude.Format.METRES;
                }
                final String unitKey = (_altFormat==Altitude.Format.METRES?"units.metres.short":"units.feet.short");
                        _altFormat = Altitude.Format.METRES;
                }
                final String unitKey = (_altFormat==Altitude.Format.METRES?"units.metres.short":"units.feet.short");
diff --git a/tim/prune/function/CropToSelection.java b/tim/prune/function/CropToSelection.java
new file mode 100644 (file)
index 0000000..e8575af
--- /dev/null
@@ -0,0 +1,51 @@
+package tim.prune.function;
+
+import tim.prune.App;
+import tim.prune.data.Track;
+
+/**
+ * Class to provide the function to crop the track
+ * to the current selection
+ */
+public class CropToSelection extends DeleteBitOfTrackFunction
+{
+       /**
+        * Constructor
+        * @param inApp application object for callback
+        */
+       public CropToSelection(App inApp)
+       {
+               super(inApp);
+       }
+
+       /** Get the name key */
+       public String getNameKey() {
+               return "function.croptrack";
+       }
+
+       /**
+        * @return name key for undo operation
+        */
+       protected String getUndoNameKey() {
+               return "undo.croptrack";
+       }
+
+       /**
+        * Begin the function
+        */
+       public void begin()
+       {
+               // check track
+               Track track = _app.getTrackInfo().getTrack();
+               if (track == null || track.getNumPoints() <= 0) return;
+               // check selection
+               final int selStart = _app.getTrackInfo().getSelection().getStart();
+               final int selEnd = _app.getTrackInfo().getSelection().getEnd();
+               if (selStart < 0 || selEnd < 0 || selEnd <= selStart) return;
+               // check for all selected
+               if (selStart == 0 && selEnd == (track.getNumPoints() - 1)) return;
+
+               // Pass indexes to parent class
+               deleteTwoSections(0, selStart-1, selEnd+1, track.getNumPoints()-1);
+       }
+}
diff --git a/tim/prune/function/DeleteBitOfTrackFunction.java b/tim/prune/function/DeleteBitOfTrackFunction.java
new file mode 100644 (file)
index 0000000..eb145cd
--- /dev/null
@@ -0,0 +1,209 @@
+package tim.prune.function;
+
+import javax.swing.JOptionPane;
+
+import tim.prune.App;
+import tim.prune.DataSubscriber;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
+import tim.prune.data.DataPoint;
+import tim.prune.data.TrackInfo;
+import tim.prune.undo.UndoDeleteRange;
+
+
+/**
+ * Abstract class to hold general deletion routines to delete
+ * either one or two track sections.  Forms parent class to
+ * the DeleteSelection and CropToSelection functions
+ */
+public abstract class DeleteBitOfTrackFunction extends GenericFunction
+{
+       /**
+        * Constructor
+        * @param inApp application object for callback
+        */
+       public DeleteBitOfTrackFunction(App inApp)
+       {
+               super(inApp);
+       }
+
+       /**
+        * @return key of undo text
+        */
+       protected abstract String getUndoNameKey();
+
+       /**
+        * Delete a single section
+        * @param inStart1 start index of section
+        * @param inEnd1 end index of section
+        */
+       protected void deleteSection(int inStart1, int inEnd1)
+       {
+               deleteTwoSections(inStart1, inEnd1, -1, -1);
+       }
+
+       /**
+        * Delete the two specified sections
+        * @param inStart1 start index of first section to delete
+        * @param inEnd1 end index of first section
+        * @param inStart2 start index of second section to delete
+        * @param inEnd2 end index of second section
+        */
+       protected void deleteTwoSections(int inStart1, int inEnd1, int inStart2, int inEnd2)
+       {
+               boolean[] deleteAllOrNone = {false, false};
+               // TODO: Check for range overlap?  And test!
+               if (inStart1 < 0 || inEnd1 < 0 || inEnd1 < inStart1) {
+                       inStart1 = inEnd1 = -1;
+               }
+               if (inStart2 < 0 || inEnd2 < 0 || inEnd2 < inStart2) {
+                       inStart2 = inEnd2 = -1;
+               }
+               if ((inStart1 >= 0 && inEnd1 < inStart1)
+                       || (inStart2 >= 0 && (inStart2 < inEnd1 || inEnd2 <= inStart2)))
+               {
+                       System.err.println("Invalid ranges: (" + inStart1 + " - " + inEnd1 + "), (" + inStart2 + " - " + inEnd2 + ")");
+                       return;
+               }
+               // First section (if any)
+               int numPoints = inEnd1 - inStart1 + 1;
+               boolean[] deleteMedia1 = new boolean[numPoints];
+               int numDeleted1 = prepareDeleteMedia(inStart1, inEnd1, deleteAllOrNone, deleteMedia1);
+               if (numDeleted1 < 0) return;
+
+               // Second section (if any)
+               numPoints = inEnd2 - inStart2 + 1;
+               boolean[] deleteMedia2 = new boolean[numPoints];
+               int numDeleted2 = prepareDeleteMedia(inStart2, inEnd2, deleteAllOrNone, deleteMedia2);
+               if (numDeleted2 < 0) return;
+               int numDeleted = numDeleted1 + numDeleted2;
+               if (numDeleted <= 0) return;
+
+               // create undo object
+               UndoDeleteRange undo = new UndoDeleteRange(_app.getTrackInfo(), getUndoNameKey(),
+                       inStart1, deleteMedia1, inStart2, deleteMedia2);
+
+               // Loop through media to remove or disconnect
+               if (numDeleted1 > 0) {
+                       resolveMedia(_app.getTrackInfo(), inStart1, deleteMedia1);
+               }
+               if (numDeleted2 > 0) {
+                       resolveMedia(_app.getTrackInfo(), inStart2, deleteMedia2);
+               }
+
+               // Call track to delete ranges 1 and 2
+               if (numDeleted2 > 0) { // delete range2 first
+                       _app.getTrackInfo().getTrack().deleteRange(inStart2, inEnd2);
+               }
+               if (numDeleted1 > 0) { // delete range1 first
+                       _app.getTrackInfo().getTrack().deleteRange(inStart1, inEnd1);
+               }
+
+               // clear selection and notify
+               _app.getTrackInfo().getSelection().clearAll();
+               UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_ADDED_OR_REMOVED);
+
+               // pass back to _app
+               _app.completeFunction(undo, "" + numDeleted + " "
+                       + I18nManager.getText("confirm.deletepoint.multi"));
+       }
+
+       /**
+        * Prepare to delete the media in the given section, including prompting to delete or not
+        * @param inStart start index of the range to delete
+        * @param inEnd end index
+        * @param inDeleteAllOrNone boolean flags for delete all and delete none, held in an array
+        * @param inDeleteMedia boolean flag for each point, whether to delete media or not
+        * @return number of points to delete
+        */
+       private int prepareDeleteMedia(int inStart, int inEnd, boolean[] inDeleteAllOrNone, boolean[] inDeleteMedia)
+       {
+               // Check sanity of inputs
+               if (inStart < 0 || inEnd < 0 || inEnd < inStart) return 0;
+               final int numPoints = inEnd - inStart + 1;
+               if (inDeleteAllOrNone == null || inDeleteAllOrNone.length != 2
+                       || inDeleteMedia == null || inDeleteMedia.length != numPoints) {
+                       return 0;
+               }
+
+               // define buttons on prompt
+               String[] questionOptions = {I18nManager.getText("button.yes"), I18nManager.getText("button.no"),
+                       I18nManager.getText("button.yestoall"), I18nManager.getText("button.notoall"),
+                       I18nManager.getText("button.cancel")};
+
+               // Loop over points to check for media
+               for (int i=0; i<numPoints; i++)
+               {
+                       DataPoint point = _app.getTrackInfo().getTrack().getPoint(inStart + i);
+                       if (point.hasMedia())
+                       {
+                               // point has either photo or audio
+                               if (inDeleteAllOrNone[0]) // delete all has already been selected
+                               {
+                                       inDeleteMedia[i] = true;
+                               }
+                               else if (inDeleteAllOrNone[1]) // delete none has already been selected
+                               {
+                                       inDeleteMedia[i] = false;
+                               }
+                               else
+                               {
+                                       int response = JOptionPane.showOptionDialog(_app.getFrame(),
+                                               I18nManager.getText("dialog.deletepoint.deletephoto") + " " + point.getMediaName(),
+                                               I18nManager.getText("dialog.deletepoint.title"),
+                                               JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null,
+                                               questionOptions, questionOptions[1]);
+                                       // check for cancel or close
+                                       if (response == 4 || response == -1) {return -1;}
+                                       // check for yes or yes to all
+                                       if (response == 0 || response == 2)
+                                       {
+                                               inDeleteMedia[i] = true;
+                                               if (response == 2) {inDeleteAllOrNone[0] = true;}
+                                       }
+                                       // check for no to all
+                                       if (response == 3) {inDeleteAllOrNone[1] = true;}
+                               }
+                       }
+               }
+               return numPoints;
+       }
+
+       /**
+        * Resolve the media from the given points by either detaching or deleting
+        * @param inTrack track object
+        * @param inStart start index of range
+        * @param inDeleteFlags media deletion flags
+        */
+       private static void resolveMedia(TrackInfo inTrackInfo, int inStart, boolean[] inDeleteFlags)
+       {
+               for (int i=0; i<inDeleteFlags.length; i++)
+               {
+                       DataPoint point = inTrackInfo.getTrack().getPoint(i + inStart);
+                       if (point != null && point.hasMedia())
+                       {
+                               if (inDeleteFlags[i])
+                               {
+                                       // delete photo and/or audio from lists
+                                       if (point.getPhoto() != null) {
+                                               inTrackInfo.getPhotoList().deletePhoto(inTrackInfo.getPhotoList().getPhotoIndex(point.getPhoto()));
+                                       }
+                                       if (point.getAudio() != null) {
+                                               inTrackInfo.getAudioList().deleteAudio(inTrackInfo.getAudioList().getAudioIndex(point.getAudio()));
+                                       }
+                               }
+                               else
+                               {
+                                       // decouple photo and/or audio from point
+                                       if (point.getPhoto() != null) {
+                                               point.getPhoto().setDataPoint(null);
+                                       }
+                                       if (point.getAudio() != null) {
+                                               point.getAudio().setDataPoint(null);
+                                       }
+                               }
+                       }
+               }
+       }
+}
diff --git a/tim/prune/function/DeleteSelectedRangeFunction.java b/tim/prune/function/DeleteSelectedRangeFunction.java
new file mode 100644 (file)
index 0000000..18f3061
--- /dev/null
@@ -0,0 +1,41 @@
+package tim.prune.function;
+
+import tim.prune.App;
+
+/**
+ * Class to provide the function to delete the currently selected range
+ */
+public class DeleteSelectedRangeFunction extends DeleteBitOfTrackFunction
+{
+       /**
+        * Constructor
+        * @param inApp application object for callback
+        */
+       public DeleteSelectedRangeFunction(App inApp)
+       {
+               super(inApp);
+       }
+
+       /** Get the name key */
+       public String getNameKey() {
+               return "function.deleterange";
+       }
+
+       /**
+        * @return name key for undo operation
+        */
+       protected String getUndoNameKey() {
+               return "undo.deleterange";
+       }
+
+       /**
+        * Begin the function
+        */
+       public void begin()
+       {
+               // Get the currently selected range and pass indexes to parent class
+               final int startIndex = _app.getTrackInfo().getSelection().getStart();
+               final int endIndex   = _app.getTrackInfo().getSelection().getEnd();
+               deleteSection(startIndex, endIndex);
+       }
+}
index 1a4fdb19f1c7310b1613d45377abcf4d92c55f79..915bed1041bd6fdc7342c390ed70ab4575d4868c 100644 (file)
@@ -235,7 +235,12 @@ public class DiskCacheConfig extends GenericFunction
                                        I18nManager.getText(getNameKey()), JOptionPane.WARNING_MESSAGE);
                                return;
                        }
                                        I18nManager.getText(getNameKey()), JOptionPane.WARNING_MESSAGE);
                                return;
                        }
-                       // TODO: Check path is writeable too, and give warning if not
+                       // Check that the cache path is writable too, and give warning if not
+                       if (cacheDir.exists() && cacheDir.isDirectory() && !cacheDir.canWrite())
+                       {
+                               JOptionPane.showMessageDialog(_dialog, I18nManager.getText("dialog.diskcache.cannotwrite"),
+                                       I18nManager.getText(getNameKey()), JOptionPane.WARNING_MESSAGE);
+                       }
                }
                Config.setConfigString(Config.KEY_DISK_CACHE, cachePath);
                // inform subscribers so that tiles are wiped from memory and refetched
                }
                Config.setConfigString(Config.KEY_DISK_CACHE, cachePath);
                // inform subscribers so that tiles are wiped from memory and refetched
index 338bf0bebbe1e1aef4d0130cf9b5d904b9c1a5c5..a0bae6517a09419dd5af77622f49b983de0e601e 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.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
 import java.text.NumberFormat;
 
 import javax.swing.BorderFactory;
 import java.text.NumberFormat;
 
 import javax.swing.BorderFactory;
@@ -19,8 +21,10 @@ import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
 import tim.prune.config.Config;
 import tim.prune.data.Altitude;
 import tim.prune.I18nManager;
 import tim.prune.config.Config;
 import tim.prune.data.Altitude;
-import tim.prune.data.Distance;
+import tim.prune.data.AltitudeRange;
+import tim.prune.data.DataPoint;
 import tim.prune.data.Selection;
 import tim.prune.data.Selection;
+import tim.prune.data.Unit;
 import tim.prune.gui.DisplayUtils;
 import tim.prune.gui.profile.SpeedData;
 
 import tim.prune.gui.DisplayUtils;
 import tim.prune.gui.profile.SpeedData;
 
@@ -31,15 +35,34 @@ public class FullRangeDetails extends GenericFunction
 {
        /** Dialog */
        private JDialog _dialog = null;
 {
        /** Dialog */
        private JDialog _dialog = null;
+       /** Label for number of points */
+       private JLabel _numPointsLabel = null;
        /** Label for number of segments */
        private JLabel _numSegsLabel = null;
        /** Label for number of segments */
        private JLabel _numSegsLabel = null;
-       /** Label for pace */
-       private JLabel _paceLabel = null;
-       /** Label for gradient */
-       private JLabel _gradientLabel = null;
-       /** Moving distance, speed */
-       private JLabel _movingDistanceLabel = null, _aveMovingSpeedLabel = null;
+       /** Label for the maximum speed */
        private JLabel _maxSpeedLabel = null;
        private JLabel _maxSpeedLabel = null;
+
+       /** Label for heading of "total" column */
+       private JLabel _colTotalLabel = null;
+       /** Label for heading of "segments" column */
+       private JLabel _colSegmentsLabel = null;
+       /** Labels for distances */
+       private JLabel _totalDistanceLabel = null, _movingDistanceLabel = null;
+       /** Labels for durations */
+       private JLabel _totalDurationLabel = null, _movingDurationLabel = null;
+       /** Labels for climbs */
+       private JLabel _totalClimbLabel = null, _movingClimbLabel = null;
+       /** Labels for descents */
+       private JLabel _totalDescentLabel = null, _movingDescentLabel = null;
+       /** Labels for pace */
+       private JLabel _totalPaceLabel = null, _movingPaceLabel = null;
+       /** Labels for gradient */
+       private JLabel _totalGradientLabel = null, _movingGradientLabel = null;
+       /** Labels for speed */
+       private JLabel _totalSpeedLabel, _movingSpeedLabel = null;
+       /** Labels for vertical speed */
+       private JLabel _totalVertSpeedLabel, _movingVertSpeedLabel = null;
+
        /** Number formatter for one decimal place */
        private static final NumberFormat FORMAT_ONE_DP = NumberFormat.getNumberInstance();
        /** Flexible number formatter for different decimal places */
        /** Number formatter for one decimal place */
        private static final NumberFormat FORMAT_ONE_DP = NumberFormat.getNumberInstance();
        /** Flexible number formatter for different decimal places */
@@ -87,50 +110,116 @@ public class FullRangeDetails extends GenericFunction
                JPanel dialogPanel = new JPanel();
                dialogPanel.setLayout(new BorderLayout(5, 5));
                // Label at top
                JPanel dialogPanel = new JPanel();
                dialogPanel.setLayout(new BorderLayout(5, 5));
                // Label at top
-               JLabel topLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.intro"));
+               JLabel topLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.intro") + ":");
                topLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
                dialogPanel.add(topLabel, BorderLayout.NORTH);
 
                // Details panel in middle
                JPanel midPanel = new JPanel();
                topLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
                dialogPanel.add(topLabel, BorderLayout.NORTH);
 
                // Details panel in middle
                JPanel midPanel = new JPanel();
-               midPanel.setLayout(new GridLayout(0, 2, 6, 2));
+               midPanel.setLayout(new GridLayout(0, 3, 6, 2));
                midPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
                midPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+               // Number of points
+               JLabel pointsLabel = new JLabel(I18nManager.getText("details.track.points") + ": ");
+               pointsLabel.setHorizontalAlignment(JLabel.RIGHT);
+               midPanel.add(pointsLabel);
+               _numPointsLabel = new JLabel("100");
+               midPanel.add(_numPointsLabel);
+               midPanel.add(new JLabel(" "));
                // Number of segments
                JLabel segLabel = new JLabel(I18nManager.getText("details.range.numsegments") + ": ");
                segLabel.setHorizontalAlignment(JLabel.RIGHT);
                midPanel.add(segLabel);
                _numSegsLabel = new JLabel("100");
                midPanel.add(_numSegsLabel);
                // Number of segments
                JLabel segLabel = new JLabel(I18nManager.getText("details.range.numsegments") + ": ");
                segLabel.setHorizontalAlignment(JLabel.RIGHT);
                midPanel.add(segLabel);
                _numSegsLabel = new JLabel("100");
                midPanel.add(_numSegsLabel);
+               midPanel.add(new JLabel(" "));
+               // Maximum speed
+               JLabel maxSpeedLabel = new JLabel(I18nManager.getText("details.range.maxspeed") + ": ");
+               maxSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
+               midPanel.add(maxSpeedLabel);
+               _maxSpeedLabel = new JLabel("10 km/h");
+               midPanel.add(_maxSpeedLabel);
+               midPanel.add(new JLabel(" "));
+
+               // blank row
+               for (int i=0; i<3; i++) midPanel.add(new JLabel(" "));
+
+               // Row for column headings
+               midPanel.add(new JLabel(" "));
+               _colTotalLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.coltotal"));
+               midPanel.add(_colTotalLabel);
+               _colSegmentsLabel = new JLabel(I18nManager.getText("dialog.fullrangedetails.colsegments"));
+               midPanel.add(_colSegmentsLabel);
+
+               // Distance
+               JLabel distLabel = new JLabel(I18nManager.getText("fieldname.distance") + ": ");
+               distLabel.setHorizontalAlignment(JLabel.RIGHT);
+               midPanel.add(distLabel);
+               _totalDistanceLabel = new JLabel("5 km");
+               midPanel.add(_totalDistanceLabel);
+               _movingDistanceLabel = new JLabel("5 km");
+               midPanel.add(_movingDistanceLabel);
+
+               // Duration
+               JLabel durationLabel = new JLabel(I18nManager.getText("fieldname.duration") + ": ");
+               durationLabel.setHorizontalAlignment(JLabel.RIGHT);
+               midPanel.add(durationLabel);
+               _totalDurationLabel = new JLabel("15 min");
+               midPanel.add(_totalDurationLabel);
+               _movingDurationLabel = new JLabel("15 min");
+               midPanel.add(_movingDurationLabel);
+
+               // Speed
+               JLabel speedLabel = new JLabel(I18nManager.getText("details.range.avespeed") + ": ");
+               speedLabel.setHorizontalAlignment(JLabel.RIGHT);
+               midPanel.add(speedLabel);
+               _totalSpeedLabel = new JLabel("5.5 km/h");
+               midPanel.add(_totalSpeedLabel);
+               _movingSpeedLabel = new JLabel("5.5 km/h");
+               midPanel.add(_movingSpeedLabel);
+
                // Pace
                JLabel paceLabel = new JLabel(I18nManager.getText("details.range.pace") + ": ");
                paceLabel.setHorizontalAlignment(JLabel.RIGHT);
                midPanel.add(paceLabel);
                // Pace
                JLabel paceLabel = new JLabel(I18nManager.getText("details.range.pace") + ": ");
                paceLabel.setHorizontalAlignment(JLabel.RIGHT);
                midPanel.add(paceLabel);
-               _paceLabel = new JLabel("8 min/km");
-               midPanel.add(_paceLabel);
+               _totalPaceLabel = new JLabel("8 min/km");
+               midPanel.add(_totalPaceLabel);
+               _movingPaceLabel = new JLabel("8 min/km");
+               midPanel.add(_movingPaceLabel);
+
+               // Climb
+               JLabel climbLabel = new JLabel(I18nManager.getText("details.range.climb") + ": ");
+               climbLabel.setHorizontalAlignment(JLabel.RIGHT);
+               midPanel.add(climbLabel);
+               _totalClimbLabel = new JLabel("1000 m");
+               midPanel.add(_totalClimbLabel);
+               _movingClimbLabel = new JLabel("1000 m");
+               midPanel.add(_movingClimbLabel);
+               // Descent
+               JLabel descentLabel = new JLabel(I18nManager.getText("details.range.descent") + ": ");
+               descentLabel.setHorizontalAlignment(JLabel.RIGHT);
+               midPanel.add(descentLabel);
+               _totalDescentLabel = new JLabel("1000 m");
+               midPanel.add(_totalDescentLabel);
+               _movingDescentLabel = new JLabel("1000 m");
+               midPanel.add(_movingDescentLabel);
+
                // Gradient
                JLabel gradientLabel = new JLabel(I18nManager.getText("details.range.gradient") + ": ");
                gradientLabel.setHorizontalAlignment(JLabel.RIGHT);
                midPanel.add(gradientLabel);
                // Gradient
                JLabel gradientLabel = new JLabel(I18nManager.getText("details.range.gradient") + ": ");
                gradientLabel.setHorizontalAlignment(JLabel.RIGHT);
                midPanel.add(gradientLabel);
-               _gradientLabel = new JLabel("10 %");
-               midPanel.add(_gradientLabel);
-               // Moving distance
-               JLabel movingDistLabel = new JLabel(I18nManager.getText("fieldname.movingdistance") + ": ");
-               movingDistLabel.setHorizontalAlignment(JLabel.RIGHT);
-               midPanel.add(movingDistLabel);
-               _movingDistanceLabel = new JLabel("5 km");
-               midPanel.add(_movingDistanceLabel);
-               // Moving speed
-               JLabel movingSpeedLabel = new JLabel(I18nManager.getText("details.range.avemovingspeed") + ": ");
-               movingSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
-               midPanel.add(movingSpeedLabel);
-               _aveMovingSpeedLabel = new JLabel("5 km/h");
-               midPanel.add(_aveMovingSpeedLabel);
-               // Maximum speed
-               JLabel maxSpeedLabel = new JLabel(I18nManager.getText("details.range.maxspeed") + ": ");
-               maxSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
-               midPanel.add(maxSpeedLabel);
-               _maxSpeedLabel = new JLabel("10 km/h");
-               midPanel.add(_maxSpeedLabel);
+               _totalGradientLabel = new JLabel("10 %");
+               midPanel.add(_totalGradientLabel);
+               _movingGradientLabel = new JLabel("10 %");
+               midPanel.add(_movingGradientLabel);
+
+               // Vertical speed
+               JLabel vSpeedLabel = new JLabel(I18nManager.getText("fieldname.verticalspeed") + ": ");
+               vSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
+               midPanel.add(vSpeedLabel);
+               _totalVertSpeedLabel = new JLabel("1 m/s");
+               midPanel.add(_totalVertSpeedLabel);
+               _movingVertSpeedLabel = new JLabel("1 m/s");
+               midPanel.add(_movingVertSpeedLabel);
 
                dialogPanel.add(midPanel, BorderLayout.CENTER);
                // button panel at bottom
 
                dialogPanel.add(midPanel, BorderLayout.CENTER);
                // button panel at bottom
@@ -143,6 +232,12 @@ public class FullRangeDetails extends GenericFunction
                                _dialog.dispose();
                        }
                });
                                _dialog.dispose();
                        }
                });
+               closeButton.addKeyListener(new KeyAdapter() {
+                       public void keyPressed(KeyEvent inE) {
+                               if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
+                               super.keyPressed(inE);
+                       }
+               });
                buttonPanel.add(closeButton);
                dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
                return dialogPanel;
                buttonPanel.add(closeButton);
                dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
                return dialogPanel;
@@ -155,59 +250,153 @@ public class FullRangeDetails extends GenericFunction
        private void updateDetails()
        {
                Selection selection = _app.getTrackInfo().getSelection();
        private void updateDetails()
        {
                Selection selection = _app.getTrackInfo().getSelection();
+               // Number of points
+               _numPointsLabel.setText("" + (selection.getEnd()-selection.getStart()+1));
                // Number of segments
                _numSegsLabel.setText("" + selection.getNumSegments());
                // Number of segments
                _numSegsLabel.setText("" + selection.getNumSegments());
-               // Pace value
-               if (selection.getNumSeconds() > 0)
+               final boolean isMultiSegments = (selection.getNumSegments() > 1);
+               // Set visibility of third column accordingly
+               _movingDistanceLabel.setVisible(isMultiSegments);
+               _movingDurationLabel.setVisible(isMultiSegments);
+               _movingClimbLabel.setVisible(isMultiSegments);
+               _movingDescentLabel.setVisible(isMultiSegments);
+               _movingSpeedLabel.setVisible(isMultiSegments);
+               _movingPaceLabel.setVisible(isMultiSegments);
+               _movingGradientLabel.setVisible(isMultiSegments);
+               _movingVertSpeedLabel.setVisible(isMultiSegments);
+
+               // Distance in current units
+               final Unit distUnit = Config.getUnitSet().getDistanceUnit();
+               final String distUnitsStr = I18nManager.getText(distUnit.getShortnameKey());
+               final double selectionDistance = selection.getDistance();
+               _totalDistanceLabel.setText(roundedNumber(selectionDistance) + " " + distUnitsStr);
+
+               // Duration
+               long numSecs = selection.getNumSeconds();
+               _totalDurationLabel.setText(DisplayUtils.buildDurationString(numSecs));
+               // Climb and descent
+               final Unit altUnit = Config.getUnitSet().getAltitudeUnit();
+               final String altUnitsStr = " " + I18nManager.getText(altUnit.getShortnameKey());
+               if (selection.getAltitudeRange().hasRange()) {
+                       _totalClimbLabel.setText(selection.getAltitudeRange().getClimb(altUnit) + altUnitsStr);
+                       _totalDescentLabel.setText(selection.getAltitudeRange().getDescent(altUnit) + altUnitsStr);
+               }
+               else {
+                       _totalClimbLabel.setText("");
+                       _totalDescentLabel.setText("");
+               }
+
+               // Overall pace and speed
+               final String speedUnitsStr = I18nManager.getText(Config.getUnitSet().getSpeedUnit().getShortnameKey());
+               if (numSecs > 0 && selectionDistance > 0)
                {
                {
-                       boolean useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
-                       Distance.Units distUnits = useMetric?Distance.Units.KILOMETRES:Distance.Units.MILES;
-                       String distUnitsStr = I18nManager.getText(useMetric?"units.kilometres.short":"units.miles.short");
-                       _paceLabel.setText(DisplayUtils.buildDurationString(
-                                       (long) (selection.getNumSeconds()/selection.getDistance(distUnits)))
+                       _totalPaceLabel.setText(
+                               DisplayUtils.buildDurationString((long) (numSecs/selectionDistance))
                                + " / " + distUnitsStr);
                                + " / " + distUnitsStr);
+                       _totalSpeedLabel.setText(roundedNumber(selectionDistance/numSecs*3600.0)
+                               + " " + speedUnitsStr);
                }
                else {
                }
                else {
-                       _paceLabel.setText("");
+                       _totalPaceLabel.setText("");
+                       _totalSpeedLabel.setText("");
                }
                }
-               // Gradient
-               Altitude firstAlt = _app.getTrackInfo().getTrack().getPoint(selection.getStart()).getAltitude();
-               Altitude lastAlt = _app.getTrackInfo().getTrack().getPoint(selection.getEnd()).getAltitude();
-               double metreDist = selection.getDistance(Distance.Units.METRES);
-               if (firstAlt.isValid() && lastAlt.isValid() && metreDist > 0.0)
+
+               // Moving distance
+               double movingDist = selection.getMovingDistance();
+               _movingDistanceLabel.setText(roundedNumber(movingDist) + " " + distUnitsStr);
+               // Moving average speed
+               long numMovingSecs = selection.getMovingSeconds();
+               if (numMovingSecs > 0)
+               {
+                       _movingDurationLabel.setText(DisplayUtils.buildDurationString(numMovingSecs));
+                       _movingSpeedLabel.setText(roundedNumber(movingDist/numMovingSecs*3600.0)
+                               + " " + speedUnitsStr);
+                       _movingPaceLabel.setText(
+                               DisplayUtils.buildDurationString((long) (numMovingSecs/movingDist))
+                               + " / " + distUnitsStr);
+               }
+               else
+               {
+                       _movingDurationLabel.setText("");
+                       _movingSpeedLabel.setText("");
+                       _movingPaceLabel.setText("");
+               }
+
+               // Moving gradient and moving climb/descent
+               Altitude firstAlt = null, lastAlt = null;
+               Altitude veryFirstAlt = null, veryLastAlt = null;
+               AltitudeRange altRange = new AltitudeRange();
+               double movingHeightDiff = 0.0;
+               if (movingDist > 0.0)
+               {
+                       for (int pNum = selection.getStart(); pNum <= selection.getEnd(); pNum++)
+                       {
+                               DataPoint p = _app.getTrackInfo().getTrack().getPoint(pNum);
+                               if (p != null && !p.isWaypoint())
+                               {
+                                       // If we're starting a new segment, calculate the height diff of the previous one
+                                       if (p.getSegmentStart())
+                                       {
+                                               if (firstAlt != null && firstAlt.isValid() && lastAlt != null && lastAlt.isValid())
+                                                       movingHeightDiff = movingHeightDiff + lastAlt.getMetricValue() - firstAlt.getMetricValue();
+                                               firstAlt = null; lastAlt = null;
+                                       }
+                                       Altitude alt = p.getAltitude();
+                                       if (alt != null && alt.isValid())
+                                       {
+                                               if (firstAlt == null) firstAlt = alt;
+                                               else lastAlt = alt;
+                                               if (veryFirstAlt == null) veryFirstAlt = alt;
+                                               else veryLastAlt = alt;
+                                       }
+                                       // Keep track of climb and descent too
+                                       if (p.getSegmentStart())
+                                               altRange.ignoreValue(alt);
+                                       else
+                                               altRange.addValue(alt);
+                               }
+                       }
+                       // deal with last segment
+                       if (firstAlt != null && firstAlt.isValid() && lastAlt != null && lastAlt.isValid())
+                               movingHeightDiff = movingHeightDiff + lastAlt.getMetricValue() - firstAlt.getMetricValue();
+                       final double metricMovingDist = movingDist / distUnit.getMultFactorFromStd(); // convert back to metres
+                       final double gradient = movingHeightDiff * 100.0 / metricMovingDist;
+                       _movingGradientLabel.setText(FORMAT_ONE_DP.format(gradient) + " %");
+               }
+               if (!altRange.hasRange()) {
+                       _movingGradientLabel.setText("");
+               }
+               final boolean hasAltitudes = veryFirstAlt != null && veryFirstAlt.isValid() && veryLastAlt != null && veryLastAlt.isValid();
+
+               // Total gradient
+               final double metreDist = selection.getDistance() / distUnit.getMultFactorFromStd(); // convert back to metres
+               if (hasAltitudes && metreDist > 0.0)
                {
                        // got an altitude and range
                {
                        // got an altitude and range
-                       int altDiffInMetres = lastAlt.getValue(Altitude.Format.METRES) - firstAlt.getValue(Altitude.Format.METRES);
+                       int altDiffInMetres = veryLastAlt.getValue(Altitude.Format.METRES) - veryFirstAlt.getValue(Altitude.Format.METRES);
                        double gradient = altDiffInMetres * 100.0 / metreDist;
                        double gradient = altDiffInMetres * 100.0 / metreDist;
-                       _gradientLabel.setText(FORMAT_ONE_DP.format(gradient) + " %");
+                       _totalGradientLabel.setText(FORMAT_ONE_DP.format(gradient) + " %");
                }
                else {
                        // no altitude given
                }
                else {
                        // no altitude given
-                       _gradientLabel.setText("");
+                       _totalGradientLabel.setText("");
                }
 
                }
 
-               // Show moving distance and average even when number of segments is 1
-               final boolean isMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
-               final Distance.Units distUnits = isMetric?Distance.Units.KILOMETRES:Distance.Units.MILES;
-               final String distUnitsStr = I18nManager.getText(isMetric?"units.kilometres.short":"units.miles.short");
-               final String speedUnitsStr = I18nManager.getText(isMetric?"units.kmh":"units.mph");
-               // Moving distance
-               _movingDistanceLabel.setText(roundedNumber(selection.getMovingDistance(distUnits)) + " " + distUnitsStr);
-               // Moving average speed
-               long numSecs = selection.getMovingSeconds();
-               if (numSecs > 0) {
-                       _aveMovingSpeedLabel.setText(roundedNumber(selection.getMovingDistance(distUnits)/numSecs*3600.0)
-                               + " " + speedUnitsStr);
+               // Moving climb/descent
+               if (altRange.hasRange()) {
+                       _movingClimbLabel.setText(altRange.getClimb(altUnit) + altUnitsStr);
+                       _movingDescentLabel.setText(altRange.getDescent(altUnit) + altUnitsStr);
                }
                else {
                }
                else {
-                       _aveMovingSpeedLabel.setText("");
+                       _movingClimbLabel.setText("");
+                       _movingDescentLabel.setText("");
                }
                }
-
                // Maximum speed
                SpeedData speeds = new SpeedData(_app.getTrackInfo().getTrack());
                // Maximum speed
                SpeedData speeds = new SpeedData(_app.getTrackInfo().getTrack());
-               speeds.init();
+               speeds.init(Config.getUnitSet());
                double maxSpeed = 0.0;
                double maxSpeed = 0.0;
-               for (int i=selection.getStart(); i<=selection.getEnd(); i++) {
+               for (int i=selection.getStart(); i<=selection.getEnd(); i++)
+               {
                        if (speeds.hasData(i) && (speeds.getData(i) > maxSpeed)) {
                                maxSpeed = speeds.getData(i);
                        }
                        if (speeds.hasData(i) && (speeds.getData(i) > maxSpeed)) {
                                maxSpeed = speeds.getData(i);
                        }
@@ -218,6 +407,23 @@ public class FullRangeDetails extends GenericFunction
                else {
                        _maxSpeedLabel.setText("");
                }
                else {
                        _maxSpeedLabel.setText("");
                }
+
+               // vertical speed
+               final String vertSpeedUnitsStr = I18nManager.getText(Config.getUnitSet().getVerticalSpeedUnit().getShortnameKey());
+               if (hasAltitudes && metreDist > 0.0 && numSecs > 0)
+               {
+                       // got an altitude and time - do total
+                       final int altDiffInMetres = veryLastAlt.getValue(Altitude.Format.METRES) - veryFirstAlt.getValue(Altitude.Format.METRES);
+                       final double altDiff = altDiffInMetres * altUnit.getMultFactorFromStd();
+                       _totalVertSpeedLabel.setText(roundedNumber(altDiff/numSecs) + " " + vertSpeedUnitsStr);
+                       // and moving
+                       _movingVertSpeedLabel.setText(roundedNumber(movingHeightDiff * altUnit.getMultFactorFromStd() / numMovingSecs) + " " + vertSpeedUnitsStr);
+               }
+               else {
+                       // no vertical speed available
+                       _totalVertSpeedLabel.setText("");
+                       _movingVertSpeedLabel.setText("");
+               }
        }
 
        /**
        }
 
        /**
index dc2da5b3cf37419704e8f08078208bf96210b26f..0e6d9eb5ae432454b505cc8fb8ba4a200b2bf57c 100644 (file)
@@ -120,21 +120,27 @@ public class GetWikipediaFunction extends GenericDownloaderFunction
 
 
        /**
 
 
        /**
-        * Load the selected track or point
+        * Load the selected point(s)
         */
        protected void loadSelected()
        {
         */
        protected void loadSelected()
        {
-               // Find the row selected in the table and get the corresponding track
-               int rowNum = _trackTable.getSelectedRow();
-               if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
+               // Find the rows selected in the table and get the corresponding coords
+               int numSelected = _trackTable.getSelectedRowCount();
+               if (numSelected < 1) return;
+               int[] rowNums = _trackTable.getSelectedRows();
+               for (int i=0; i<numSelected; i++)
                {
                {
-                       String coords = _trackListModel.getTrack(rowNum).getDownloadLink();
-                       String[] latlon = coords.split(",");
-                       if (latlon.length == 2)
+                       int rowNum = rowNums[i];
+                       if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
                        {
                        {
-                               DataPoint point = new DataPoint(new Latitude(latlon[0]), new Longitude(latlon[1]), null);
-                               point.setFieldValue(Field.WAYPT_NAME, _trackListModel.getTrack(rowNum).getTrackName(), false);
-                               _app.createPoint(point);
+                               String coords = _trackListModel.getTrack(rowNum).getDownloadLink();
+                               String[] latlon = coords.split(",");
+                               if (latlon.length == 2)
+                               {
+                                       DataPoint point = new DataPoint(new Latitude(latlon[0]), new Longitude(latlon[1]), null);
+                                       point.setFieldValue(Field.WAYPT_NAME, _trackListModel.getTrack(rowNum).getTrackName(), false);
+                                       _app.createPoint(point);
+                               }
                        }
                }
                // Close the dialog
                        }
                }
                // Close the dialog
diff --git a/tim/prune/function/InterpolateFunction.java b/tim/prune/function/InterpolateFunction.java
new file mode 100644 (file)
index 0000000..8482614
--- /dev/null
@@ -0,0 +1,164 @@
+package tim.prune.function;
+
+import javax.swing.JOptionPane;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.data.DataPoint;
+import tim.prune.data.Track;
+import tim.prune.undo.UndoInterpolate;
+
+/**
+ * Function to interpolate between the points in a range
+ */
+public class InterpolateFunction extends GenericFunction
+{
+       /**
+        * Constructor
+        * @param inApp app object
+        */
+       public InterpolateFunction(App inApp) {
+               super(inApp);
+       }
+
+       /** @return name key */
+       public String getNameKey() {
+               return "function.interpolate";
+       }
+
+       /**
+        * Perform the operation
+        */
+       public void begin()
+       {
+               // Firstly, work out whether the selected range only contains waypoints or not
+               final int startIndex = _app.getTrackInfo().getSelection().getStart();
+               final int endIndex   = _app.getTrackInfo().getSelection().getEnd();
+               boolean betweenWaypoints = false;
+               // if there are only waypoints, then ask whether to interpolate them
+               if (!selectedRangeHasTrackpoints(_app.getTrackInfo().getTrack(), startIndex, endIndex))
+               {
+                       int answer = JOptionPane.showConfirmDialog(_parentFrame,
+                               I18nManager.getText("dialog.interpolate.betweenwaypoints"),
+                               I18nManager.getText(getNameKey()), JOptionPane.YES_NO_OPTION);
+                       if (answer == JOptionPane.NO_OPTION) {
+                               // user said no, so nothing to do
+                               return;
+                       }
+                       betweenWaypoints = true;
+               }
+
+               // Get number of points to add
+               Object numPointsStr = JOptionPane.showInputDialog(_parentFrame,
+                       I18nManager.getText("dialog.interpolate.parameter.text"),
+                       I18nManager.getText(getNameKey()),
+                       JOptionPane.QUESTION_MESSAGE, null, null, "");
+               if (numPointsStr == null) {return;}
+               int numToAdd = parseNumber(numPointsStr);
+               if (numToAdd <= 0 || numToAdd > 1000)
+               {
+                       _app.showErrorMessage(getNameKey(), "error.interpolate.invalidparameter");
+                       return;
+               }
+
+               if (startIndex < 0 || endIndex < 0 || endIndex <= startIndex) {
+                       return;
+               }
+
+               // construct new point array with the interpolated points
+               final Track track = _app.getTrackInfo().getTrack();
+               final int maxToAdd = (endIndex-startIndex) * numToAdd;
+               final int extendedSize = track.getNumPoints() + maxToAdd;
+               DataPoint[] oldPoints = track.cloneContents();
+               DataPoint[] newPoints = new DataPoint[extendedSize];
+               // Copy points before
+               System.arraycopy(oldPoints, 0, newPoints, 0, startIndex);
+               // Loop, copying points and interpolating
+               int destIndex = startIndex;
+               DataPoint prevPoint = null;
+               for (int i=startIndex; i<= endIndex; i++)
+               {
+                       DataPoint p = _app.getTrackInfo().getTrack().getPoint(i);
+                       if (prevPoint != null && ((p.isWaypoint() && betweenWaypoints) || (!p.isWaypoint() && !p.getSegmentStart())))
+                       {
+                               // interpolate between the previous point and this one
+                               DataPoint[] addition = prevPoint.interpolate(p, numToAdd);
+                               System.arraycopy(addition, 0, newPoints, destIndex, numToAdd);
+                               destIndex += numToAdd;
+                       }
+                       // copy point
+                       newPoints[destIndex] = p;
+                       destIndex++;
+                       if (!p.isWaypoint() || betweenWaypoints)
+                       {
+                               prevPoint = p;
+                       }
+                       else if (!p.isWaypoint()) {
+                               prevPoint = null;
+                       }
+                       // If it's a waypoint, then keep the old prevPoint
+               }
+               final int totalInserted = destIndex - endIndex - 1;
+               // Copy the points after the selected range
+               System.arraycopy(oldPoints, endIndex, newPoints, destIndex-1, track.getNumPoints()-endIndex);
+
+               // If necessary, make a new array of the correct size and do another arraycopy into it
+               final int newTotalPoints = track.getNumPoints() + totalInserted;
+               if (newTotalPoints != newPoints.length)
+               {
+                       DataPoint[] croppedPoints = new DataPoint[newTotalPoints];
+                       System.arraycopy(newPoints, 0, croppedPoints, 0, newTotalPoints);
+                       newPoints = croppedPoints;
+               }
+
+               // Make undo object
+               UndoInterpolate undo = new UndoInterpolate(_app.getTrackInfo(), totalInserted);
+               // Replace track with new points array
+               if (track.replaceContents(newPoints))
+               {
+                       _app.completeFunction(undo, I18nManager.getText("confirm.interpolate"));
+                       // Alter selection
+                       _app.getTrackInfo().getSelection().selectRange(startIndex, endIndex + totalInserted);
+               }
+       }
+
+       /**
+        * Check if the given Track has trackpoints in the specified range
+        * @param inTrack track object
+        * @param inStart start index
+        * @param inEnd end index
+        * @return true if there are any non-waypoints in the range
+        */
+       private static boolean selectedRangeHasTrackpoints(Track inTrack, int inStart, int inEnd)
+       {
+               for (int i=inStart; i<= inEnd; i++)
+               {
+                       DataPoint p = inTrack.getPoint(i);
+                       if (p != null && !p.isWaypoint()) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+
+       /**
+        * Helper method to parse an Object into an integer
+        * @param inObject object, eg from dialog
+        * @return int value given
+        */
+       private static int parseNumber(Object inObject)
+       {
+               int num = 0;
+               if (inObject != null)
+               {
+                       try
+                       {
+                               num = Integer.parseInt(inObject.toString());
+                       }
+                       catch (NumberFormatException nfe)
+                       {}
+               }
+               return num;
+       }
+}
index 23fe8d285afd8af965a47e62f3fcdc0827a12603..7587949b25c893e5a4c9565d69d6a723ae603ec2 100644 (file)
@@ -75,8 +75,8 @@ public class PasteCoordinates extends GenericFunction
                // MAYBE: Paste clipboard into the edit field
                _coordField.setText("");
                _nameField.setText("");
                // MAYBE: Paste clipboard into the edit field
                _coordField.setText("");
                _nameField.setText("");
-               boolean metric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
-               _altUnitsDropDown.setSelectedIndex(metric?0:1);
+               boolean useMetres = (Config.getUnitSet().getDefaultAltitudeFormat() == Altitude.Format.METRES);
+               _altUnitsDropDown.setSelectedIndex(useMetres?0:1);
                enableOK();
                _dialog.setVisible(true);
        }
                enableOK();
                _dialog.setVisible(true);
        }
diff --git a/tim/prune/function/PhotoComparer.java b/tim/prune/function/PhotoComparer.java
new file mode 100644 (file)
index 0000000..86252d1
--- /dev/null
@@ -0,0 +1,109 @@
+package tim.prune.function;
+
+import java.util.Comparator;
+
+import tim.prune.data.DataPoint;
+
+/**
+ * Class for comparing photos to sort them by name or timestamp
+ */
+public class PhotoComparer implements Comparator<DataPoint>
+{
+       public enum SortMode {
+               SORTBY_NAME, SORTBY_TIME
+       };
+
+       /** Sort mode */
+       private SortMode _sortMode = SortMode.SORTBY_NAME;
+
+       /**
+        * Constructor
+        * @param inMode sort mode
+        */
+       public PhotoComparer(SortMode inMode)
+       {
+               _sortMode = inMode;
+       }
+
+       /**
+        * Main compare method
+        */
+       public int compare(DataPoint inP1, DataPoint inP2)
+       {
+               if (inP2 == null || inP2.getPhoto() == null) return -1; // all nulls at end
+               if (inP1 == null || inP1.getPhoto() == null) return 1;
+               // Sort by name
+               int result = 0;
+               if (_sortMode == SortMode.SORTBY_NAME) {
+                       result = compareNames(inP1, inP2);
+               }
+               if (result == 0) {
+                       result = compareTimes(inP1, inP2);
+               }
+               // check names if times didn't work
+               if (result == 0 && _sortMode == SortMode.SORTBY_TIME) {
+                       result = compareNames(inP1, inP2);
+               }
+               // names and times equal, try width and height
+               if (result == 0) {
+                       result = compareSizes(inP1, inP2);
+               }
+               return 0;
+       }
+
+       /**
+        * Compare the names of the two photo points
+        * @param inP1 first point
+        * @param inP2 second point
+        * @return compare value (-1,0,1)
+        */
+       private int compareNames(DataPoint inP1, DataPoint inP2)
+       {
+               // If the files can't be compared, use the photo names
+               if (inP1.getPhoto().getFile() == null || inP2.getPhoto().getFile() == null) {
+                       return inP1.getPhoto().getName().compareTo(inP2.getPhoto().getName());
+               }
+               // both photos have files, so just compare the files
+               return inP1.getPhoto().getFile().compareTo(inP2.getPhoto().getFile());
+       }
+
+       /**
+        * Compare the timestamps of the two photo points
+        * @param inP1 first point
+        * @param inP2 second point
+        * @return compare value (-1,0,1)
+        */
+       private int compareTimes(DataPoint inP1, DataPoint inP2)
+       {
+               // Photos might not have timestamps
+               if (!inP2.hasTimestamp()) return -1;
+               if (!inP1.hasTimestamp()) return 1;
+               // Compare the timestamps
+               long secDiff = inP1.getPhoto().getTimestamp().getSecondsSince(inP2.getPhoto().getTimestamp());
+               return (secDiff<0?-1:(secDiff==0?0:1));
+       }
+
+       /**
+        * Compare the sizes of the two photos
+        * @param inP1 first point
+        * @param inP2 second point
+        * @return compare value (-1,0,1)
+        */
+       private int compareSizes(DataPoint inP1, DataPoint inP2)
+       {
+               // Try the widths
+               int w1 = inP1.getPhoto().getWidth();
+               int w2 = inP2.getPhoto().getWidth();
+               if (w2 <= 0) return -1;
+               if (w1 <= 0) return 1;
+               if (w1 != w2) return (w2 > w1 ? 1 : -1);
+               // Try the heights
+               int h1 = inP1.getPhoto().getHeight();
+               int h2 = inP2.getPhoto().getHeight();
+               if (h2 <= 0) return -1;
+               if (h1 <= 0) return 1;
+               if (h1 != h2) return (h2 > h1 ? 1 : -1);
+               // sizes same
+               return 0;
+       }
+}
index 1a81be110ad7636a6a314b8e44942be8e71887b1..da9c5ca127d869ca64be4fb56fe63049a800c7b2 100644 (file)
@@ -61,7 +61,14 @@ public class PhotoPopupFunction extends GenericFunction
                        _frame.setLocationRelativeTo(_parentFrame);
                }
                initFrame();
                        _frame.setLocationRelativeTo(_parentFrame);
                }
                initFrame();
-               _frame.setVisible(true);
+               final Photo photo = _app.getTrackInfo().getCurrentPhoto();
+               if (photo.getWidth() <= 0 || photo.getHeight() <= 0) {
+                       _app.showErrorMessageNoLookup(getNameKey(), I18nManager.getText("error.showphoto.failed")
+                        + " : " + photo.getName());
+               }
+               else {
+                       _frame.setVisible(true);
+               }
        }
 
        /**
        }
 
        /**
index 0e14d7c9ad1f9f6c9f4df9f761b7c466838b751d..2ac71e93b6e38bbbaab727aa1a6d7d421c4a117a 100644 (file)
@@ -1,8 +1,12 @@
 package tim.prune.function;
 
 package tim.prune.function;
 
+import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.ByteArrayInputStream;
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
 import javax.sound.sampled.AudioInputStream;
 import javax.sound.sampled.AudioSystem;
 import javax.sound.sampled.Clip;
 import javax.sound.sampled.AudioInputStream;
 import javax.sound.sampled.AudioSystem;
 import javax.sound.sampled.Clip;
@@ -58,39 +62,34 @@ public class PlayAudioFunction extends GenericFunction implements Runnable
                {
                        // First choice is to play using java
                        played = playClip(audio);
                {
                        // First choice is to play using java
                        played = playClip(audio);
-                       // Second choice is to try the Desktop library from java 6, if available
+                       // If this didn't work, then try to play the file another way
                        if (!played) {
                        if (!played) {
-                               try {
-                                       Class<?> d = Class.forName("java.awt.Desktop");
-                                       d.getDeclaredMethod("open", new Class[] {File.class}).invoke(
-                                               d.getDeclaredMethod("getDesktop").invoke(null), new Object[] {audioFile});
-                                       //above code mimics: Desktop.getDesktop().open(audioFile);
-                                       played = true;
-                               }
-                               catch (Exception ignore) {
-                                       played = false;
-                               }
+                               played = playAudioFile(audioFile);
                        }
                        }
-                       // If the Desktop call failed, need to try backup methods
+               }
+               else if (audioFile == null && audio.getByteData() != null)
+               {
+                       // Try to play audio clip using byte array
+                       played = playClip(audio);
+                       // If this didn't work, then need to copy the byte data to a file and play it from there
                        if (!played)
                        {
                        if (!played)
                        {
-                               // If system looks like a Mac, try open command
-                               String osName = System.getProperty("os.name").toLowerCase();
-                               boolean isMacOsx = osName.indexOf("mac os") >= 0 || osName.indexOf("darwin") >= 0;
-                               if (isMacOsx) {
-                                       String[] command = new String[] {"open", audioFile.getAbsolutePath()};
-                                       try {
-                                               Runtime.getRuntime().exec(command);
-                                               played = true;
-                                       }
-                                       catch (IOException ioe) {}
+                               try
+                               {
+                                       String suffix = getSuffix(audio.getName());
+                                       File tempFile = File.createTempFile("gpsaudio", suffix);
+                                       tempFile.deleteOnExit();
+                                       // Copy byte data to this file
+                                       BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tempFile));
+                                       bos.write(audio.getByteData(), 0, audio.getByteData().length);
+                                       bos.close();
+                                       played = playAudioFile(tempFile);
+                               }
+                               catch (IOException ignore) {
+                                       System.err.println("Error: " + ignore.getClass().getName() + " - " + ignore.getMessage());
                                }
                        }
                }
                                }
                        }
                }
-               else if (audioFile == null && audio.getByteData() != null) {
-                       // Try to play audio clip using byte array (can't use Desktop or Runtime)
-                       played = playClip(audio);
-               }
                if (!played)
                {
                        // If still not worked, show error message
                if (!played)
                {
                        // If still not worked, show error message
@@ -134,6 +133,54 @@ public class PlayAudioFunction extends GenericFunction implements Runnable
                return success;
        }
 
                return success;
        }
 
+       /**
+        * Try to play the specified audio file
+        * @param inFile file to play
+        * @return true if play was successful
+        */
+       private boolean playAudioFile(File inFile)
+       {
+               boolean played = false;
+               // Try the Desktop library from java 6, if available
+               if (!played)
+               {
+                       try
+                       {
+                               Class<?> d = Class.forName("java.awt.Desktop");
+                               d.getDeclaredMethod("open", new Class[] {File.class}).invoke(
+                                       d.getDeclaredMethod("getDesktop").invoke(null), new Object[] {inFile});
+                               //above code mimics: Desktop.getDesktop().open(audioFile);
+                               played = true;
+                       }
+                       catch (InvocationTargetException e) {
+                               System.err.println("ITE: " + e.getCause().getClass().getName() + " - " + e.getCause().getMessage());
+                               played = false;
+                       }
+                       catch (Exception ignore) {
+                               System.err.println(ignore.getClass().getName() + " - " + ignore.getMessage());
+                               played = false;
+                       }
+               }
+
+               // If the Desktop call failed, need to try backup methods
+               if (!played)
+               {
+                       // If system looks like a Mac, try the open command
+                       String osName = System.getProperty("os.name").toLowerCase();
+                       boolean isMacOsx = osName.indexOf("mac os") >= 0 || osName.indexOf("darwin") >= 0;
+                       if (isMacOsx)
+                       {
+                               String[] command = new String[] {"open", inFile.getAbsolutePath()};
+                               try {
+                                       Runtime.getRuntime().exec(command);
+                                       played = true;
+                               }
+                               catch (IOException ioe) {}
+                       }
+               }
+               return played;
+       }
+
        /**
         * Try to stop a currently playing clip
         */
        /**
         * Try to stop a currently playing clip
         */
@@ -163,4 +210,16 @@ public class PlayAudioFunction extends GenericFunction implements Runnable
                }
                return percent;
        }
                }
                return percent;
        }
+
+       /**
+        * @param inName name of audio file
+        * @return suffix (rest of name after the dot) - expect mp3, wav, ogg
+        */
+       private static final String getSuffix(String inName)
+       {
+               if (inName == null || inName.equals("")) {return ".tmp";}
+               final int dotPos = inName.lastIndexOf('.');
+               if (dotPos < 0) {return inName;} // no dot found
+               return inName.substring(dotPos);
+       }
 }
 }
index b8d9312de7dce3c1c349c466ec101b8fe72c3d56..c55928021fcaaa08af3f84fa516bdf8f927f1469 100644 (file)
@@ -5,7 +5,6 @@ import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.util.Arrays;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.util.Arrays;
-import java.util.Comparator;
 
 import javax.swing.BoxLayout;
 import javax.swing.ButtonGroup;
 
 import javax.swing.BoxLayout;
 import javax.swing.ButtonGroup;
@@ -193,32 +192,7 @@ public class RearrangePhotosFunction extends GenericFunction
         */
        private static void sortPhotos(DataPoint[] inPhotos, boolean inSortByFile)
        {
         */
        private static void sortPhotos(DataPoint[] inPhotos, boolean inSortByFile)
        {
-               Comparator<DataPoint> comparator = null;
-               if (inSortByFile)
-               {
-                       // sort by filename
-                       comparator = new Comparator<DataPoint>() {
-                               public int compare(DataPoint inP1, DataPoint inP2) {
-                                       if (inP2 == null) return -1; // all nulls at end
-                                       if (inP1 == null) return 1;
-                                       if (inP1.getPhoto().getFile() == null || inP2.getPhoto().getFile() == null)
-                                               return inP1.getPhoto().getName().compareTo(inP2.getPhoto().getName());
-                                       return inP1.getPhoto().getFile().compareTo(inP2.getPhoto().getFile());
-                               }
-                       };
-               }
-               else
-               {
-                       // sort by photo timestamp
-                       comparator = new Comparator<DataPoint>() {
-                               public int compare(DataPoint inP1, DataPoint inP2) {
-                                       if (inP2 == null) return -1; // all nulls at end
-                                       if (inP1 == null) return 1;
-                                       long secDiff = inP1.getPhoto().getTimestamp().getSecondsSince(inP2.getPhoto().getTimestamp());
-                                       return (secDiff<0?-1:(secDiff==0?0:1));
-                               }
-                       };
-               }
-               Arrays.sort(inPhotos, comparator);
+               PhotoComparer comparer = new PhotoComparer(inSortByFile ? PhotoComparer.SortMode.SORTBY_NAME : PhotoComparer.SortMode.SORTBY_TIME);
+               Arrays.sort(inPhotos, comparer);
        }
 }
        }
 }
index ab24522eb68120168b49c420996f245ea8ffb32d..0458943036ed8007ffecb0838bf66c504aff4e6d 100644 (file)
@@ -130,22 +130,29 @@ public class SearchWikipediaNames extends GenericDownloaderFunction
                _statusLabel.setText(descMessage);
        }
 
                _statusLabel.setText(descMessage);
        }
 
+
        /**
        /**
-        * Load the selected track or point
+        * Load the selected point(s)
         */
        protected void loadSelected()
        {
         */
        protected void loadSelected()
        {
-               // Find the row selected in the table and get the corresponding track
-               int rowNum = _trackTable.getSelectedRow();
-               if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
+               // Find the rows selected in the table and get the corresponding coords
+               int numSelected = _trackTable.getSelectedRowCount();
+               if (numSelected < 1) return;
+               int[] rowNums = _trackTable.getSelectedRows();
+               for (int i=0; i<numSelected; i++)
                {
                {
-                       String coords = _trackListModel.getTrack(rowNum).getDownloadLink();
-                       String[] latlon = coords.split(",");
-                       if (latlon.length == 2)
+                       int rowNum = rowNums[i];
+                       if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
                        {
                        {
-                               DataPoint point = new DataPoint(new Latitude(latlon[0]), new Longitude(latlon[1]), null);
-                               point.setFieldValue(Field.WAYPT_NAME, _trackListModel.getTrack(rowNum).getTrackName(), false);
-                               _app.createPoint(point);
+                               String coords = _trackListModel.getTrack(rowNum).getDownloadLink();
+                               String[] latlon = coords.split(",");
+                               if (latlon.length == 2)
+                               {
+                                       DataPoint point = new DataPoint(new Latitude(latlon[0]), new Longitude(latlon[1]), null);
+                                       point.setFieldValue(Field.WAYPT_NAME, _trackListModel.getTrack(rowNum).getTrackName(), false);
+                                       _app.createPoint(point);
+                               }
                        }
                }
                // Close the dialog
                        }
                }
                // Close the dialog
index 65565987529d3885d72a38d12a7b545317e22ed9..04e3cc14e60e5d01a1cb21f02d8cea9b73fb106b 100644 (file)
@@ -395,18 +395,13 @@ public class ManageCacheFunction extends GenericFunction implements Runnable
                                if (subdir.isDirectory()) {
                                        numDeleted += deleteFilesFrom(subdir, inMaxDays);
                                }
                                if (subdir.isDirectory()) {
                                        numDeleted += deleteFilesFrom(subdir, inMaxDays);
                                }
-                               else if (subdir.isFile() && subdir.exists())
+                               else if (subdir.isFile() && subdir.exists() && _TILEFILTER.accept(subdir))
                                {
                                {
-                                       boolean isTileFile = _TILEFILTER.accept(subdir);
-                                       boolean isBadFile = !isTileFile && subdir.getName().toLowerCase().endsWith("png");
-                                       if (isTileFile || isBadFile)
+                                       long fileAge = (now - subdir.lastModified()) / 1000 / 60 / 60 / 24;
+                                       if (inMaxDays < 0 || fileAge > inMaxDays)
                                        {
                                        {
-                                               long fileAge = (now - subdir.lastModified()) / 1000 / 60 / 60 / 24;
-                                               if (inMaxDays < 0 || fileAge > inMaxDays || isBadFile)
-                                               {
-                                                       if (subdir.delete()) {
-                                                               numDeleted++;
-                                                       }
+                                               if (subdir.delete()) {
+                                                       numDeleted++;
                                                }
                                        }
                                }
                                                }
                                        }
                                }
index dc90abd65066d6cd16868ca3a1ce693ec4a5f642..8c7ee23d00d39133b269268994f9c1174506d91f 100644 (file)
@@ -86,6 +86,7 @@ public class RowInfo
 
        /**
         * Mark that an unexpected file or directory was found
 
        /**
         * Mark that an unexpected file or directory was found
+        * TODO: Is this needed?
         */
        public void foundUnexpected() {
                _unexpected = true;
         */
        public void foundUnexpected() {
                _unexpected = true;
index 502c91439dc1434085e42cce1165352708e10ab5..0bb377fe2b1c4fe728b1020c1fe6799456ce6a66 100644 (file)
@@ -29,13 +29,13 @@ import tim.prune.ExternalTools;
 import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
 import tim.prune.config.Config;
 import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
 import tim.prune.config.Config;
-import tim.prune.data.Altitude;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Distance;
 import tim.prune.data.Field;
 import tim.prune.data.Timestamp;
 import tim.prune.data.Track;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Distance;
 import tim.prune.data.Field;
 import tim.prune.data.Timestamp;
 import tim.prune.data.Track;
-import tim.prune.data.Distance.Units;
+import tim.prune.gui.profile.SpeedData;
+import tim.prune.gui.profile.VerticalSpeedData;
 import tim.prune.load.GenericFileFilter;
 
 /**
 import tim.prune.load.GenericFileFilter;
 
 /**
@@ -219,7 +219,7 @@ public class Charter extends GenericFunction
        private boolean setupDialog(Track inTrack)
        {
                boolean hasTimes = inTrack.hasData(Field.TIMESTAMP);
        private boolean setupDialog(Track inTrack)
        {
                boolean hasTimes = inTrack.hasData(Field.TIMESTAMP);
-               boolean hasAltitudes = inTrack.getAltitudeRange().hasRange();
+               boolean hasAltitudes = inTrack.hasAltitudeData();
                _timeRadio.setEnabled(hasTimes);
 
                // Add checks to prevent choosing unavailable combinations
                _timeRadio.setEnabled(hasTimes);
 
                // Add checks to prevent choosing unavailable combinations
@@ -397,9 +397,15 @@ public class Charter extends GenericFunction
                        catch (Exception e) {}
                }
 
                        catch (Exception e) {}
                }
 
+               // Sort out units to use
+               final String distLabel = I18nManager.getText(Config.getUnitSet().getDistanceUnit().getShortnameKey());
+               final String altLabel  = I18nManager.getText(Config.getUnitSet().getAltitudeUnit().getShortnameKey());
+               final String speedLabel = I18nManager.getText(Config.getUnitSet().getSpeedUnit().getShortnameKey());
+               final String vertSpeedLabel = I18nManager.getText(Config.getUnitSet().getVerticalSpeedUnit().getShortnameKey());
+
                // Set x axis label
                if (inDistance) {
                // Set x axis label
                if (inDistance) {
-                       inWriter.write("set xlabel '" + I18nManager.getText("fieldname.distance") + " (" + getUnitsLabel("units.kilometres.short", "units.miles.short") + ")'\n");
+                       inWriter.write("set xlabel '" + I18nManager.getText("fieldname.distance") + " (" + distLabel + ")'\n");
                }
                else {
                        inWriter.write("set xlabel '" + I18nManager.getText("fieldname.time") + " (" + I18nManager.getText("units.hours") + ")'\n");
                }
                else {
                        inWriter.write("set xlabel '" + I18nManager.getText("fieldname.time") + " (" + I18nManager.getText("units.hours") + ")'\n");
@@ -410,19 +416,19 @@ public class Charter extends GenericFunction
                switch (inYaxis)
                {
                case 0: // y axis is distance
                switch (inYaxis)
                {
                case 0: // y axis is distance
-                       inWriter.write("set ylabel '" + I18nManager.getText("fieldname.distance") + " (" + getUnitsLabel("units.kilometres.short", "units.miles.short") + ")'\n");
+                       inWriter.write("set ylabel '" + I18nManager.getText("fieldname.distance") + " (" + distLabel + ")'\n");
                        chartTitle = I18nManager.getText("fieldname.distance");
                        break;
                case 1: // y axis is altitude
                        chartTitle = I18nManager.getText("fieldname.distance");
                        break;
                case 1: // y axis is altitude
-                       inWriter.write("set ylabel '" + I18nManager.getText("fieldname.altitude") + " (" + getUnitsLabel("units.metres.short", "units.feet.short") + ")'\n");
+                       inWriter.write("set ylabel '" + I18nManager.getText("fieldname.altitude") + " (" + altLabel + ")'\n");
                        chartTitle = I18nManager.getText("fieldname.altitude");
                        break;
                case 2: // y axis is speed
                        chartTitle = I18nManager.getText("fieldname.altitude");
                        break;
                case 2: // y axis is speed
-                       inWriter.write("set ylabel '" + I18nManager.getText("fieldname.speed") + " (" + getUnitsLabel("units.kmh", "units.mph") + ")'\n");
+                       inWriter.write("set ylabel '" + I18nManager.getText("fieldname.speed") + " (" + speedLabel + ")'\n");
                        chartTitle = I18nManager.getText("fieldname.speed");
                        break;
                case 3: // y axis is vertical speed
                        chartTitle = I18nManager.getText("fieldname.speed");
                        break;
                case 3: // y axis is vertical speed
-                       inWriter.write("set ylabel '" + I18nManager.getText("fieldname.verticalspeed") + " (" + getUnitsLabel("units.metrespersec", "units.feetpersec") + ")'\n");
+                       inWriter.write("set ylabel '" + I18nManager.getText("fieldname.verticalspeed") + " (" + vertSpeedLabel + ")'\n");
                        chartTitle = I18nManager.getText("fieldname.verticalspeed");
                        break;
                }
                        chartTitle = I18nManager.getText("fieldname.verticalspeed");
                        break;
                }
@@ -430,18 +436,6 @@ public class Charter extends GenericFunction
                inWriter.write("plot '" + tempFile.getAbsolutePath() + "' title '" + chartTitle + "' with filledcurve y1=0 lt rgb \"#009000\"\n");
        }
 
                inWriter.write("plot '" + tempFile.getAbsolutePath() + "' title '" + chartTitle + "' with filledcurve y1=0 lt rgb \"#009000\"\n");
        }
 
-       /**
-        * Get the units label for the given keys
-        * @param inMetric key if metric
-        * @param inImperial key if imperial
-        * @return display label with appropriate text
-        */
-       private static String getUnitsLabel(String inMetric, String inImperial)
-       {
-               String key = Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?inMetric:inImperial;
-               return I18nManager.getText(key);
-       }
-
 
        /**
         * Calculate the distance values for each point in the given track
 
        /**
         * Calculate the distance values for each point in the given track
@@ -461,11 +455,10 @@ public class Charter extends GenericFunction
                        {
                                totalRads += DataPoint.calculateRadiansBetween(prevPoint, currPoint);
                        }
                        {
                                totalRads += DataPoint.calculateRadiansBetween(prevPoint, currPoint);
                        }
-                       if (Config.getConfigBoolean(Config.KEY_METRIC_UNITS)) {
-                               values.setData(i, Distance.convertRadiansToDistance(totalRads, Units.KILOMETRES));
-                       } else {
-                               values.setData(i, Distance.convertRadiansToDistance(totalRads, Units.MILES));
-                       }
+
+                       // distance values use currently configured units
+                       values.setData(i, Distance.convertRadiansToDistance(totalRads));
+
                        prevPoint = currPoint;
                }
                return values;
                        prevPoint = currPoint;
                }
                return values;
@@ -506,10 +499,10 @@ public class Charter extends GenericFunction
        private static ChartSeries getAltitudeValues(Track inTrack)
        {
                ChartSeries values = new ChartSeries(inTrack.getNumPoints());
        private static ChartSeries getAltitudeValues(Track inTrack)
        {
                ChartSeries values = new ChartSeries(inTrack.getNumPoints());
-               Altitude.Format altFormat = Config.getConfigBoolean(Config.KEY_METRIC_UNITS)?Altitude.Format.METRES:Altitude.Format.FEET;
+               final double multFactor = Config.getUnitSet().getAltitudeUnit().getMultFactorFromStd();
                for (int i=0; i<inTrack.getNumPoints(); i++) {
                        if (inTrack.getPoint(i).hasAltitude()) {
                for (int i=0; i<inTrack.getNumPoints(); i++) {
                        if (inTrack.getPoint(i).hasAltitude()) {
-                               values.setData(i, inTrack.getPoint(i).getAltitude().getValue(altFormat));
+                               values.setData(i, inTrack.getPoint(i).getAltitude().getMetricValue() * multFactor);
                        }
                }
                return values;
                        }
                }
                return values;
@@ -522,31 +515,17 @@ public class Charter extends GenericFunction
         */
        private static ChartSeries getSpeedValues(Track inTrack)
        {
         */
        private static ChartSeries getSpeedValues(Track inTrack)
        {
-               // Calculate speeds and fill in in values array
-               ChartSeries values = new ChartSeries(inTrack.getNumPoints());
-               DataPoint prevPoint = null, currPoint = null, nextPoint = null;
-               DataPoint[] points = getDataPoints(inTrack, false);
-               final boolean useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
+               // Calculate speeds using the same formula as the profile chart
+               SpeedData speeds = new SpeedData(inTrack);
+
+               final int numPoints = inTrack.getNumPoints();
+               ChartSeries values = new ChartSeries(numPoints);
                // Loop over collected points
                // Loop over collected points
-               for (int i=1; i<(points.length-1); i++)
+               for (int i=0; i<numPoints; i++)
                {
                {
-                       prevPoint = points[i-1];
-                       currPoint = points[i];
-                       nextPoint = points[i+1];
-                       if (prevPoint != null && currPoint != null && nextPoint != null
-                               && nextPoint.getTimestamp().isAfter(currPoint.getTimestamp())
-                               && currPoint.getTimestamp().isAfter(prevPoint.getTimestamp()))
+                       if (speeds.hasData(i))
                        {
                        {
-                               // Calculate average speed between prevPoint and nextPoint
-                               double rads = DataPoint.calculateRadiansBetween(prevPoint, currPoint)
-                                       + DataPoint.calculateRadiansBetween(currPoint, nextPoint);
-                               double time = nextPoint.getTimestamp().getSecondsSince(prevPoint.getTimestamp()) / 60.0 / 60.0;
-                               // Convert to distance and pass to chartseries
-                               if (useMetric) {
-                                       values.setData(i, Distance.convertRadiansToDistance(rads, Units.KILOMETRES) / time);
-                               } else {
-                                       values.setData(i, Distance.convertRadiansToDistance(rads, Units.MILES) / time);
-                               }
+                               values.setData(i, speeds.getData(i));
                        }
                }
                return values;
                        }
                }
                return values;
@@ -559,59 +538,23 @@ public class Charter extends GenericFunction
         */
        private static ChartSeries getVertSpeedValues(Track inTrack)
        {
         */
        private static ChartSeries getVertSpeedValues(Track inTrack)
        {
-               // Calculate speeds and fill in in values array
-               ChartSeries values = new ChartSeries(inTrack.getNumPoints());
-               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
+               // Calculate speeds using the same formula as the profile chart
+               VerticalSpeedData speeds = new VerticalSpeedData(inTrack);
+
+               final int numPoints = inTrack.getNumPoints();
+               ChartSeries values = new ChartSeries(numPoints);
                // Loop over collected points
                // Loop over collected points
-               for (int i=1; i<(points.length-1); i++)
+               for (int i=0; i<numPoints; i++)
                {
                {
-                       prevPoint = points[i-1];
-                       currPoint = points[i];
-                       nextPoint = points[i+1];
-                       if (prevPoint != null && currPoint != null && nextPoint != null
-                               && nextPoint.getTimestamp().isAfter(currPoint.getTimestamp())
-                               && currPoint.getTimestamp().isAfter(prevPoint.getTimestamp()))
+                       if (speeds.hasData(i))
                        {
                        {
-                               // Calculate average vertical speed between prevPoint and nextPoint
-                               double vspeed = (nextPoint.getAltitude().getValue(altFormat) - prevPoint.getAltitude().getValue(altFormat))
-                                * 1.0 / nextPoint.getTimestamp().getSecondsSince(prevPoint.getTimestamp());
-                               values.setData(i, vspeed);
+                               values.setData(i, speeds.getData(i));
                        }
                }
                return values;
        }
 
 
                        }
                }
                return values;
        }
 
 
-       /**
-        * Get an array of DataPoints with data for the charts
-        * @param inTrack track object containing points
-        * @param inRequireAltitudes true if only points with altitudes are considered
-        * @return array of points with contiguous non-null elements (<= size) with timestamps
-        */
-       private static DataPoint[] getDataPoints(Track inTrack, boolean inRequireAltitudes)
-       {
-               DataPoint[] points = new DataPoint[inTrack.getNumPoints()];
-               DataPoint currPoint = null;
-               int pointNum = 0;
-               // Loop over all points
-               for (int i=0; i<inTrack.getNumPoints(); i++)
-               {
-                       currPoint = inTrack.getPoint(i);
-                       if (currPoint != null && !currPoint.isWaypoint() && currPoint.hasTimestamp()
-                               && (!inRequireAltitudes || currPoint.hasAltitude()))
-                       {
-                               points[pointNum] = currPoint;
-                               pointNum++;
-                       }
-               }
-               // Any elements at the end of the array will stay null
-               // Also note, chronological order is not checked
-               return points;
-       }
-
-
        /**
         * Select a file to write for the SVG output
         * @return selected File object or null if cancelled
        /**
         * Select a file to write for the SVG output
         * @return selected File object or null if cancelled
index d4ecc8898e59208de1c1aa815c7067860e5bbc7e..5aa76aa76a1c570c89330fafab5192a329082b8a 100644 (file)
@@ -11,6 +11,7 @@ import javax.swing.Box;
 import javax.swing.BoxLayout;
 import javax.swing.JButton;
 import javax.swing.JDialog;
 import javax.swing.BoxLayout;
 import javax.swing.JButton;
 import javax.swing.JDialog;
+import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 
 import tim.prune.App;
 import javax.swing.JPanel;
 
 import tim.prune.App;
@@ -169,14 +170,27 @@ public class CompressTrackFunction extends GenericFunction
        {
                boolean[] deleteFlags = preview();
                // All flags are now combined in deleteFlags array
        {
                boolean[] deleteFlags = preview();
                // All flags are now combined in deleteFlags array
+               int numMarked = 0;
                for (int i=0; i<deleteFlags.length; i++)
                {
                        DataPoint point = _track.getPoint(i);
                for (int i=0; i<deleteFlags.length; i++)
                {
                        DataPoint point = _track.getPoint(i);
-                       point.setMarkedForDeletion(deleteFlags[i] && !point.hasMedia());
+                       boolean deletePoint = deleteFlags[i] && !point.hasMedia();
+                       point.setMarkedForDeletion(deletePoint);
+                       if (deletePoint) numMarked++;
                }
 
                // Close dialog and inform listeners
                UpdateMessageBroker.informSubscribers();
                _dialog.dispose();
                }
 
                // Close dialog and inform listeners
                UpdateMessageBroker.informSubscribers();
                _dialog.dispose();
+               // Show confirmation dialog with OK button (not status bar message)
+               if (numMarked > 0) {
+                       JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("dialog.compress.confirm1")
+                               + " " + numMarked + " " + I18nManager.getText("dialog.compress.confirm2"),
+                               I18nManager.getText(getNameKey()), JOptionPane.INFORMATION_MESSAGE);
+               }
+               else {
+                       JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("dialog.compress.confirmnone"),
+                               I18nManager.getText(getNameKey()), JOptionPane.INFORMATION_MESSAGE);
+               }
        }
 }
        }
 }
index cd1f9dfac0073a10de728a9496cdf371c3bde00c..2cd5d77f9db184ea7d5c2532734601ee7ab589ac 100644 (file)
@@ -78,6 +78,7 @@ public abstract class CompressionAlgorithm
                if (isActivated())
                {
                        // Run the compression and set the deletion flags
                if (isActivated())
                {
                        // Run the compression and set the deletion flags
+                       _trackDetails.initialise();
                        numDeleted = compress(inFlags);
                        _summaryLabel.setValue(numDeleted);
                }
                        numDeleted = compress(inFlags);
                        _summaryLabel.setValue(numDeleted);
                }
diff --git a/tim/prune/function/compress/MarkPointsInRectangleFunction.java b/tim/prune/function/compress/MarkPointsInRectangleFunction.java
new file mode 100644 (file)
index 0000000..73c867f
--- /dev/null
@@ -0,0 +1,103 @@
+package tim.prune.function.compress;
+
+import javax.swing.JOptionPane;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
+import tim.prune.data.DataPoint;
+
+/**
+ * Function to mark all the points in the selected rectangle
+ */
+public class MarkPointsInRectangleFunction extends GenericFunction
+{
+       /** Minimum and maximum latitude values of rectangle */
+       private double _minLat = 0.0, _maxLat = 0.0;
+       /** Minimum and maximum longitude values of rectangle */
+       private double _minLon = 0.0, _maxLon = 0.0;
+
+
+       /**
+        * Constructor
+        * @param inApp App object
+        */
+       public MarkPointsInRectangleFunction(App inApp)
+       {
+               super(inApp);
+       }
+
+       /**
+        * Set the coordinates of the rectangle
+        * @param inLon1 first longitude value
+        * @param inLat1 first latitude value
+        * @param inLon2 second longitude value
+        * @param inLat2 second latitude value
+        */
+       public void setRectCoords(double inLon1, double inLat1, double inLon2, double inLat2)
+       {
+               if (inLon1 == inLon2 || inLat1 == inLat2)
+               {
+                       // Coordinates not valid
+                       _minLat = _maxLat = _minLon = _maxLon = 0.0;
+               }
+               else
+               {
+                       if (inLon2 > inLon1) {
+                               _minLon = inLon1; _maxLon = inLon2;
+                       }
+                       else {
+                               _minLon = inLon2; _maxLon = inLon1;
+                       }
+                       if (inLat2 > inLat1) {
+                               _minLat = inLat1; _maxLat = inLat2;
+                       }
+                       else {
+                               _minLat = inLat2; _maxLat = inLat1;
+                       }
+               }
+       }
+
+       /**
+        * Begin the function using the set parameters
+        */
+       public void begin()
+       {
+               if (_maxLon == _minLon || _maxLat == _minLat) {
+                       return;
+               }
+
+               // Loop over all points in track
+               final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
+               int numMarked = 0;
+               for (int i=0; i<numPoints; i++)
+               {
+                       DataPoint point = _app.getTrackInfo().getTrack().getPoint(i);
+                       // For each point, see if it's within the rectangle
+                       final double pointLon = point.getLongitude().getDouble();
+                       final double pointLat = point.getLatitude().getDouble();
+                       final boolean insideRect = (pointLon >= _minLon && pointLon <= _maxLon
+                               && pointLat >= _minLat && pointLat <= _maxLat);
+                       // If so, then mark it
+                       point.setMarkedForDeletion(insideRect);
+                       if (insideRect) {
+                               numMarked++;
+                       }
+               }
+
+               // Inform subscribers to update display
+               UpdateMessageBroker.informSubscribers();
+               // Confirm message showing how many marked
+               if (numMarked > 0) {
+                       JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("dialog.compress.confirm1")
+                               + " " + numMarked + " " + I18nManager.getText("dialog.compress.confirm2"),
+                               I18nManager.getText(getNameKey()), JOptionPane.INFORMATION_MESSAGE);
+               }
+       }
+
+       /** @return name key */
+       public String getNameKey() {
+               return "menu.track.markrectangle";
+       }
+}
index dada3f0bd510c4e6163460d69b474fbd1679c6dd..5fe6e7e7d9e307d901ad25c23b2a4ea021acc3d3 100644 (file)
@@ -7,6 +7,8 @@ import java.awt.FlowLayout;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 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.util.ArrayList;
 
 import javax.swing.BorderFactory;
 import java.util.ArrayList;
 
 import javax.swing.BorderFactory;
@@ -123,6 +125,17 @@ public class DistanceFunction extends GenericFunction
                mainPanel.add(scrollPane);
                dialogPanel.add(mainPanel, BorderLayout.CENTER);
 
                mainPanel.add(scrollPane);
                dialogPanel.add(mainPanel, BorderLayout.CENTER);
 
+               // close window if escape pressed
+               KeyAdapter escListener = new KeyAdapter() {
+                       public void keyReleased(KeyEvent inE) {
+                               if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                                       _dialog.dispose();
+                               }
+                       }
+               };
+               _pointTable.addKeyListener(escListener);
+               distTable.addKeyListener(escListener);
+
                // button panel at bottom
                JPanel buttonPanel = new JPanel();
                buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
                // button panel at bottom
                JPanel buttonPanel = new JPanel();
                buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
index 48ba1722be3bedf224ec28ed14fe362129d8fedf..faa059ea4b1bb2ada4ce6340b30bc6014a9ce65a 100644 (file)
@@ -4,6 +4,7 @@ import tim.prune.I18nManager;
 import tim.prune.config.Config;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Distance;
 import tim.prune.config.Config;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Distance;
+import tim.prune.data.Unit;
 
 /**
  * Class to hold the table model for the distances table
 
 /**
  * Class to hold the table model for the distances table
@@ -12,10 +13,6 @@ public class DistanceTableModel extends GenericTableModel
 {
        /** Distances */
        private double[] _distances = null;
 {
        /** Distances */
        private double[] _distances = null;
-       /** Metric distances? */
-       private boolean _useMetric = true;
-       /** Previous value of metric flag (to spot changes) */
-       private boolean _prevUseMetric = false;
        /** Column heading */
        private static final String _toColLabel = I18nManager.getText("dialog.distances.column.to");
        /** Column heading (depends on metric/imperial settings) */
        /** Column heading */
        private static final String _toColLabel = I18nManager.getText("dialog.distances.column.to");
        /** Column heading (depends on metric/imperial settings) */
@@ -68,9 +65,10 @@ public class DistanceTableModel extends GenericTableModel
         */
        public void recalculate(int inIndex)
        {
         */
        public void recalculate(int inIndex)
        {
-               // Use metric or not?
-               _useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
-               _distanceLabel = getDistanceLabel(_useMetric);
+               // Which units to use?
+               Unit distUnit = Config.getUnitSet().getDistanceUnit();
+               _distanceLabel = I18nManager.getText("fieldname.distance") + " (" +
+                       I18nManager.getText(distUnit.getShortnameKey()) + ")";
                // Initialize array of distances
                int numRows = getRowCount();
                if (_distances == null || _distances.length != numRows) {
                // Initialize array of distances
                int numRows = getRowCount();
                if (_distances == null || _distances.length != numRows) {
@@ -83,26 +81,10 @@ public class DistanceTableModel extends GenericTableModel
                        }
                        else {
                                double rads = DataPoint.calculateRadiansBetween(fromPoint, _pointList.get(i));
                        }
                        else {
                                double rads = DataPoint.calculateRadiansBetween(fromPoint, _pointList.get(i));
-                               _distances[i] = Distance.convertRadiansToDistance(rads, _useMetric?Distance.Units.KILOMETRES:Distance.Units.MILES);
+                               _distances[i] = Distance.convertRadiansToDistance(rads);
                        }
                }
                        }
                }
-               // Let table know that it has to refresh data (and maybe refresh column headings too)
-               if (_useMetric == _prevUseMetric) {
-                       fireTableDataChanged();
-               }
-               else {
-                       fireTableStructureChanged();
-               }
-               _prevUseMetric = _useMetric;
-       }
-
-       /**
-        * @param inMetric true to use metric distances
-        * @return distance label for column heading
-        */
-       private static String getDistanceLabel(boolean inMetric)
-       {
-               return I18nManager.getText("fieldname.distance") + " (" +
-                       I18nManager.getText(inMetric?"units.kilometres.short" : "units.miles.short") + ")";
+               // Let table know that it has to refresh data (and might as well refresh column headings too)
+               fireTableStructureChanged();
        }
 }
        }
 }
index 3fc630e2b96506789f36ad0ee7878d13fee8bb0d..bfa46c4bf4d54f9df5f4e9101b859903a26cd172 100644 (file)
@@ -125,16 +125,16 @@ public class PointNameEditor extends GenericFunction
                        }
                });
                rightPanel.add(lowerButton);
                        }
                });
                rightPanel.add(lowerButton);
-               JButton sentenceButton = new JButton(I18nManager.getText("dialog.pointnameedit.sentencecase"));
-               sentenceButton.addActionListener(new ActionListener() {
+               JButton titleButton = new JButton(I18nManager.getText("dialog.pointnameedit.titlecase"));
+               titleButton.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                        public void actionPerformed(ActionEvent e)
                        {
-                               _nameField.setText(sentenceCase(_nameField.getText()));
+                               _nameField.setText(titleCase(_nameField.getText()));
                                _okButton.setEnabled(true);
                                _nameField.requestFocus();
                        }
                });
                                _okButton.setEnabled(true);
                                _nameField.requestFocus();
                        }
                });
-               rightPanel.add(sentenceButton);
+               rightPanel.add(titleButton);
                panel.add(rightPanel, BorderLayout.EAST);
                // Bottom panel for OK, cancel buttons
                JPanel lowerPanel = new JPanel();
                panel.add(rightPanel, BorderLayout.EAST);
                // Bottom panel for OK, cancel buttons
                JPanel lowerPanel = new JPanel();
@@ -167,11 +167,11 @@ public class PointNameEditor extends GenericFunction
        }
 
        /**
        }
 
        /**
-        * Turn a String into sentence case by capitalizing each word
+        * Turn a String into title case by capitalizing each word
         * @param inString String to convert
         * @return capitalized String
         */
         * @param inString String to convert
         * @return capitalized String
         */
-       private static String sentenceCase(String inString)
+       private static String titleCase(String inString)
        {
                // Check first for empty strings
                if (inString == null || inString.equals(""))
        {
                // Check first for empty strings
                if (inString == null || inString.equals(""))
index e9049a82b9a89705472601eefb0179c4a599729a..cf634c0fbc6b48b932382d21b3695b9e30ddc575 100644 (file)
@@ -18,7 +18,6 @@ import javax.swing.JScrollPane;
 import javax.swing.JSplitPane;
 import javax.swing.JTable;
 import javax.swing.JTextArea;
 import javax.swing.JSplitPane;
 import javax.swing.JTable;
 import javax.swing.JTextArea;
-import javax.swing.ListSelectionModel;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 
@@ -112,21 +111,20 @@ public abstract class GenericDownloaderFunction extends GenericFunction implemen
                        public void valueChanged(ListSelectionEvent e) {
                                if (!e.getValueIsAdjusting())
                                {
                        public void valueChanged(ListSelectionEvent e) {
                                if (!e.getValueIsAdjusting())
                                {
-                                       if (_trackTable.getSelectedRow() >= 0
-                                        && _trackTable.getSelectedRow() < _trackListModel.getRowCount())
+                                       final int numSelected = _trackTable.getSelectedRowCount();
+                                       if (numSelected > 0)
                                        {
                                        {
-                                               _loadButton.setEnabled(true);
-                                               _showButton.setEnabled(true);
                                                setDescription(_trackListModel.getTrack(_trackTable.getSelectedRow()).getDescription());
                                                _descriptionBox.setCaretPosition(0);
                                        }
                                        else {
                                                _descriptionBox.setText("");
                                        }
                                                setDescription(_trackListModel.getTrack(_trackTable.getSelectedRow()).getDescription());
                                                _descriptionBox.setCaretPosition(0);
                                        }
                                        else {
                                                _descriptionBox.setText("");
                                        }
+                                       _loadButton.setEnabled(numSelected > 0);
+                                       _showButton.setEnabled(numSelected == 1);
                                }
                        }
                });
                                }
                        }
                });
-               _trackTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // only allow one to be selected
                _trackTable.getColumnModel().getColumn(0).setPreferredWidth(300);
                if (_trackListModel.getColumnCount() > 1) {
                        _trackTable.getColumnModel().getColumn(1).setPreferredWidth(70);
                _trackTable.getColumnModel().getColumn(0).setPreferredWidth(300);
                if (_trackListModel.getColumnCount() > 1) {
                        _trackTable.getColumnModel().getColumn(1).setPreferredWidth(70);
index 51085cf14742a8ae57b6b4bf75930439ee1fb8b0..e60ed7429c4578e2bbfb44f8e3902dd69e102d63 100644 (file)
@@ -63,7 +63,6 @@ public class GetGpsiesFunction extends GenericDownloaderFunction
                _statusLabel.setText(I18nManager.getText("confirm.running"));
                // Act on callback to update list and send another request if necessary
                double[] coords = _app.getViewport().getBounds();
                _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;
                int currPage = 1;
 
                ArrayList<GpsiesTrack> trackList = null;
@@ -73,6 +72,7 @@ public class GetGpsiesFunction extends GenericDownloaderFunction
                // Loop for each page of the results
                do
                {
                // Loop for each page of the results
                do
                {
+                       // Example http://ws.gpsies.com/api.do?BBOX=10,51,12,53&limit=20&resultPage=1&key=oumgvvbckiwpvsnb
                        String urlString = "http://ws.gpsies.com/api.do?BBOX=" +
                                coords[1] + "," + coords[0] + "," + coords[3] + "," + coords[2] +
                                "&limit=" + RESULTS_PER_PAGE + "&resultPage=" + currPage +
                        String urlString = "http://ws.gpsies.com/api.do?BBOX=" +
                                coords[1] + "," + coords[0] + "," + coords[3] + "," + coords[2] +
                                "&limit=" + RESULTS_PER_PAGE + "&resultPage=" + currPage +
@@ -112,23 +112,30 @@ public class GetGpsiesFunction extends GenericDownloaderFunction
        }
 
        /**
        }
 
        /**
-        * Load the selected track or point
+        * Load the selected track(s)
         */
        protected void loadSelected()
        {
         */
        protected void loadSelected()
        {
-               // Find the row selected in the table and get the corresponding track
-               int rowNum = _trackTable.getSelectedRow();
-               if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
+               // Find the row(s) selected in the table and get the corresponding track
+               int numSelected = _trackTable.getSelectedRowCount();
+               if (numSelected < 1) return;
+               int[] rowNums = _trackTable.getSelectedRows();
+               for (int i=0; i<numSelected; i++)
                {
                {
-                       String url = _trackListModel.getTrack(rowNum).getDownloadLink();
-                       XmlFileLoader xmlLoader = new XmlFileLoader(_app);
-                       ZipFileLoader loader = new ZipFileLoader(_app, xmlLoader);
-                       try
+                       int rowNum = rowNums[i];
+                       if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
                        {
                        {
-                               loader.openStream(new URL(url).openStream());
-                       }
-                       catch (IOException ioe) {
-                               System.err.println("IO Exception : " + ioe.getMessage());
+                               String url = _trackListModel.getTrack(rowNum).getDownloadLink();
+                               XmlFileLoader xmlLoader = new XmlFileLoader(_app);
+                               ZipFileLoader loader = new ZipFileLoader(_app, xmlLoader);
+                               if (i>0) _app.autoAppendNextFile();
+                               try
+                               {
+                                       loader.openStream(new URL(url).openStream());
+                               }
+                               catch (IOException ioe) {
+                                       System.err.println("IO Exception : " + ioe.getMessage());
+                               }
                        }
                }
                // Close the dialog
                        }
                }
                // Close the dialog
index 3a7326f647409b131d70964ad48279ac086ab275..904dd8bc62248d49fe4e5669ee37fccc19a643a3 100644 (file)
@@ -7,7 +7,7 @@ import javax.swing.table.AbstractTableModel;
 
 import tim.prune.I18nManager;
 import tim.prune.config.Config;
 
 import tim.prune.I18nManager;
 import tim.prune.config.Config;
-import tim.prune.data.Distance;
+import tim.prune.data.Unit;
 
 /**
  * Model for list of tracks from gpsies.com
 
 /**
  * Model for list of tracks from gpsies.com
@@ -77,12 +77,11 @@ public class TrackListModel extends AbstractTableModel
                GpsiesTrack track = _trackList.get(inRowNum);
                if (inColNum == 0) {return track.getTrackName();}
                double lengthM = track.getLength();
                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");
+               // convert to current distance units
+               Unit distUnit = Config.getUnitSet().getDistanceUnit();
+               double length = lengthM * distUnit.getMultFactorFromStd();
+               // Make text
+               return _distanceFormatter.format(length) + " " + I18nManager.getText(distUnit.getShortnameKey());
        }
 
        /**
        }
 
        /**
@@ -92,10 +91,15 @@ public class TrackListModel extends AbstractTableModel
        public void addTracks(ArrayList<GpsiesTrack> inList)
        {
                if (_trackList == null) {_trackList = new ArrayList<GpsiesTrack>();}
        public void addTracks(ArrayList<GpsiesTrack> inList)
        {
                if (_trackList == null) {_trackList = new ArrayList<GpsiesTrack>();}
+               final int prevCount = _trackList.size();
                if (inList != null && inList.size() > 0) {
                        _trackList.addAll(inList);
                }
                if (inList != null && inList.size() > 0) {
                        _trackList.addAll(inList);
                }
-               fireTableDataChanged();
+               final int updatedCount = _trackList.size();
+               if (prevCount <= 0)
+                       fireTableDataChanged();
+               else
+                       fireTableRowsInserted(prevCount, updatedCount-1);
        }
 
        /**
        }
 
        /**
index 49bd000c79d99e688dfef33c0256210a218a1dd9..586cbb6d72eede3c5a62d77b68c8649b8845c5d8 100644 (file)
@@ -280,7 +280,7 @@ public class UploadGpsiesFunction extends GenericFunction
                                public void run() {
                                        boolean[] saveFlags = {true, true, true, true, false, true}; // export everything
                                        try {
                                public void run() {
                                        boolean[] saveFlags = {true, true, true, true, false, true}; // export everything
                                        try {
-                                               GpxExporter.exportData(_writer, _app.getTrackInfo(), _nameField.getText(), null, saveFlags, false);
+                                               GpxExporter.exportData(_writer, _app.getTrackInfo(), _nameField.getText(), null, saveFlags, null);
                                        } catch (IOException e) {}
                                        finally {
                                                try {_writer.close();} catch (IOException e) {}
                                        } catch (IOException e) {}
                                        finally {
                                                try {_writer.close();} catch (IOException e) {}
index ec68e162633dc66472138c20d6c1ac3a602c7303..7b3a4ff6843f9b34c4c7df048081a54f92ec17e6 100644 (file)
@@ -26,16 +26,19 @@ import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
 import tim.prune.UpdateMessageBroker;
 import tim.prune.config.Config;
 import tim.prune.I18nManager;
 import tim.prune.UpdateMessageBroker;
 import tim.prune.config.Config;
-import tim.prune.data.Altitude;
+import tim.prune.data.AltitudeRange;
 import tim.prune.data.AudioClip;
 import tim.prune.data.Coordinate;
 import tim.prune.data.DataPoint;
 import tim.prune.data.AudioClip;
 import tim.prune.data.Coordinate;
 import tim.prune.data.DataPoint;
-import tim.prune.data.Distance;
 import tim.prune.data.Field;
 import tim.prune.data.Field;
-import tim.prune.data.IntegerRange;
 import tim.prune.data.Photo;
 import tim.prune.data.Selection;
 import tim.prune.data.Photo;
 import tim.prune.data.Selection;
+import tim.prune.data.SpeedCalculator;
+import tim.prune.data.SpeedValue;
 import tim.prune.data.TrackInfo;
 import tim.prune.data.TrackInfo;
+import tim.prune.data.Unit;
+import tim.prune.data.UnitSet;
+import tim.prune.data.UnitSetLibrary;
 
 /**
  * Class to hold point details and selection details
 
 /**
  * Class to hold point details and selection details
@@ -47,7 +50,8 @@ public class DetailsDisplay extends GenericDisplay
        private JLabel _indexLabel = null;
        private JLabel _latLabel = null, _longLabel = null;
        private JLabel _altLabel = null;
        private JLabel _indexLabel = null;
        private JLabel _latLabel = null, _longLabel = null;
        private JLabel _altLabel = null;
-       private JLabel _timeLabel = null, _speedLabel = null;
+       private JLabel _timeLabel = null;
+       private JLabel _speedLabel = null, _vSpeedLabel = null;
        private JLabel _nameLabel = null, _typeLabel = null;
 
        // Range details
        private JLabel _nameLabel = null, _typeLabel = null;
 
        // Range details
@@ -60,6 +64,7 @@ public class DetailsDisplay extends GenericDisplay
        // Photo details
        private JPanel _photoDetailsPanel = null;
        private JLabel _photoLabel = null;
        // Photo details
        private JPanel _photoDetailsPanel = null;
        private JLabel _photoLabel = null;
+       private JLabel _photoPathLabel = null;
        private PhotoThumbnail _photoThumbnail = null;
        private JLabel _photoTimestampLabel = null;
        private JLabel _photoConnectedLabel = null;
        private PhotoThumbnail _photoThumbnail = null;
        private JLabel _photoTimestampLabel = null;
        private JLabel _photoConnectedLabel = null;
@@ -69,6 +74,7 @@ public class DetailsDisplay extends GenericDisplay
        // Audio details
        private JPanel _audioDetailsPanel = null;
        private JLabel _audioLabel = null;
        // Audio details
        private JPanel _audioDetailsPanel = null;
        private JLabel _audioLabel = null;
+       private JLabel _audioPathLabel = null;
        private JLabel _audioConnectedLabel = null;
        private JLabel _audioTimestampLabel = null;
        private JLabel _audioLengthLabel = null;
        private JLabel _audioConnectedLabel = null;
        private JLabel _audioTimestampLabel = null;
        private JLabel _audioLengthLabel = null;
@@ -89,6 +95,8 @@ public class DetailsDisplay extends GenericDisplay
        private static final String LABEL_POINT_TIMESTAMP = I18nManager.getText("fieldname.timestamp") + ": ";
        private static final String LABEL_POINT_WAYPOINTNAME = I18nManager.getText("fieldname.waypointname") + ": ";
        private static final String LABEL_POINT_WAYPOINTTYPE = I18nManager.getText("fieldname.waypointtype") + ": ";
        private static final String LABEL_POINT_TIMESTAMP = I18nManager.getText("fieldname.timestamp") + ": ";
        private static final String LABEL_POINT_WAYPOINTNAME = I18nManager.getText("fieldname.waypointname") + ": ";
        private static final String LABEL_POINT_WAYPOINTTYPE = I18nManager.getText("fieldname.waypointtype") + ": ";
+       private static final String LABEL_POINT_SPEED        = I18nManager.getText("fieldname.speed") + ": ";
+       private static final String LABEL_POINT_VERTSPEED    = I18nManager.getText("fieldname.verticalspeed") + ": ";
        private static final String LABEL_RANGE_SELECTED = I18nManager.getText("details.range.selected") + ": ";
        private static final String LABEL_RANGE_DURATION = I18nManager.getText("fieldname.duration") + ": ";
        private static final String LABEL_RANGE_DISTANCE = I18nManager.getText("fieldname.distance") + ": ";
        private static final String LABEL_RANGE_SELECTED = I18nManager.getText("details.range.selected") + ": ";
        private static final String LABEL_RANGE_DURATION = I18nManager.getText("fieldname.duration") + ": ";
        private static final String LABEL_RANGE_DISTANCE = I18nManager.getText("fieldname.distance") + ": ";
@@ -96,8 +104,7 @@ public class DetailsDisplay extends GenericDisplay
        private static final String LABEL_RANGE_CLIMB = I18nManager.getText("details.range.climb") + ": ";
        private static final String LABEL_RANGE_DESCENT = ", " + I18nManager.getText("details.range.descent") + ": ";
        private static final String LABEL_AUDIO_FILE = I18nManager.getText("details.audio.file") + ": ";
        private static final String LABEL_RANGE_CLIMB = I18nManager.getText("details.range.climb") + ": ";
        private static final String LABEL_RANGE_DESCENT = ", " + I18nManager.getText("details.range.descent") + ": ";
        private static final String LABEL_AUDIO_FILE = I18nManager.getText("details.audio.file") + ": ";
-       private static String LABEL_POINT_ALTITUDE_UNITS = null;
-       private static Altitude.Format LABEL_POINT_ALTITUDE_FORMAT = Altitude.Format.NO_FORMAT;
+       private static final String LABEL_FULL_PATH = I18nManager.getText("details.media.fullpath") + ": ";
 
 
        /**
 
 
        /**
@@ -130,6 +137,8 @@ public class DetailsDisplay extends GenericDisplay
                pointDetailsPanel.add(_timeLabel);
                _speedLabel = new JLabel("");
                pointDetailsPanel.add(_speedLabel);
                pointDetailsPanel.add(_timeLabel);
                _speedLabel = new JLabel("");
                pointDetailsPanel.add(_speedLabel);
+               _vSpeedLabel = new JLabel("");
+               pointDetailsPanel.add(_vSpeedLabel);
                _nameLabel = new JLabel("");
                pointDetailsPanel.add(_nameLabel);
                _typeLabel = new JLabel("");
                _nameLabel = new JLabel("");
                pointDetailsPanel.add(_nameLabel);
                _typeLabel = new JLabel("");
@@ -156,6 +165,8 @@ public class DetailsDisplay extends GenericDisplay
                _photoDetailsPanel = makeDetailsPanel("details.photodetails", biggerFont);
                _photoLabel = new JLabel(I18nManager.getText("details.nophoto"));
                _photoDetailsPanel.add(_photoLabel);
                _photoDetailsPanel = makeDetailsPanel("details.photodetails", biggerFont);
                _photoLabel = new JLabel(I18nManager.getText("details.nophoto"));
                _photoDetailsPanel.add(_photoLabel);
+               _photoPathLabel = new JLabel("");
+               _photoDetailsPanel.add(_photoPathLabel);
                _photoTimestampLabel = new JLabel("");
                _photoTimestampLabel.setMinimumSize(new Dimension(120, 10));
                _photoDetailsPanel.add(_photoTimestampLabel);
                _photoTimestampLabel = new JLabel("");
                _photoTimestampLabel.setMinimumSize(new Dimension(120, 10));
                _photoDetailsPanel.add(_photoTimestampLabel);
@@ -185,6 +196,8 @@ public class DetailsDisplay extends GenericDisplay
                _audioDetailsPanel = makeDetailsPanel("details.audiodetails", biggerFont);
                _audioLabel = new JLabel(I18nManager.getText("details.noaudio"));
                _audioDetailsPanel.add(_audioLabel);
                _audioDetailsPanel = makeDetailsPanel("details.audiodetails", biggerFont);
                _audioLabel = new JLabel(I18nManager.getText("details.noaudio"));
                _audioDetailsPanel.add(_audioLabel);
+               _audioPathLabel = new JLabel("");
+               _audioDetailsPanel.add(_audioPathLabel);
                _audioTimestampLabel = new JLabel("");
                _audioTimestampLabel.setMinimumSize(new Dimension(120, 10));
                _audioDetailsPanel.add(_audioTimestampLabel);
                _audioTimestampLabel = new JLabel("");
                _audioTimestampLabel.setMinimumSize(new Dimension(120, 10));
                _audioDetailsPanel.add(_audioTimestampLabel);
@@ -241,13 +254,17 @@ public class DetailsDisplay extends GenericDisplay
                JLabel unitsLabel = new JLabel(I18nManager.getText("details.distanceunits") + ": ");
                unitsLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
                lowerPanel.add(unitsLabel);
                JLabel unitsLabel = new JLabel(I18nManager.getText("details.distanceunits") + ": ");
                unitsLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
                lowerPanel.add(unitsLabel);
-               String[] distUnits = {I18nManager.getText("units.kilometres"), I18nManager.getText("units.miles")};
-               _distUnitsDropdown = new JComboBox(distUnits);
-               if (!Config.getConfigBoolean(Config.KEY_METRIC_UNITS)) {_distUnitsDropdown.setSelectedIndex(1);}
+               // Make dropdown for distance units
+               _distUnitsDropdown = new JComboBox();
+               final UnitSet currUnits = Config.getUnitSet();
+               for (int i=0; i<UnitSetLibrary.getNumUnitSets(); i++) {
+                       _distUnitsDropdown.addItem(I18nManager.getText(UnitSetLibrary.getUnitSet(i).getDistanceUnit().getNameKey()));
+                       if (UnitSetLibrary.getUnitSet(i) == currUnits) {_distUnitsDropdown.setSelectedIndex(i);}
+               }
                _distUnitsDropdown.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _distUnitsDropdown.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
-                               Config.setConfigBoolean(Config.KEY_METRIC_UNITS, _distUnitsDropdown.getSelectedIndex() == 0);
+                               Config.selectUnitSet(_distUnitsDropdown.getSelectedIndex());
                                UpdateMessageBroker.informSubscribers(DataSubscriber.UNITS_CHANGED);
                        }
                });
                                UpdateMessageBroker.informSubscribers(DataSubscriber.UNITS_CHANGED);
                        }
                });
@@ -269,9 +286,9 @@ public class DetailsDisplay extends GenericDisplay
                if ((inUpdateType | DATA_ADDED_OR_REMOVED) > 0) selection.markInvalid();
                int currentPointIndex = selection.getCurrentPointIndex();
                _speedLabel.setText("");
                if ((inUpdateType | DATA_ADDED_OR_REMOVED) > 0) selection.markInvalid();
                int currentPointIndex = selection.getCurrentPointIndex();
                _speedLabel.setText("");
-               Distance.Units distUnits = _distUnitsDropdown.getSelectedIndex()==0?Distance.Units.KILOMETRES:Distance.Units.MILES;
-               String distUnitsStr = I18nManager.getText(_distUnitsDropdown.getSelectedIndex()==0?"units.kilometres.short":"units.miles.short");
-               String speedUnitsStr = I18nManager.getText(_distUnitsDropdown.getSelectedIndex()==0?"units.kmh":"units.mph");
+               UnitSet unitSet = UnitSetLibrary.getUnitSet(_distUnitsDropdown.getSelectedIndex());
+               String distUnitsStr = I18nManager.getText(unitSet.getDistanceUnit().getShortnameKey());
+               String speedUnitsStr = I18nManager.getText(unitSet.getSpeedUnit().getShortnameKey());
                if (_track == null || currentPoint == null)
                {
                        _indexLabel.setText(I18nManager.getText("details.nopointselection"));
                if (_track == null || currentPoint == null)
                {
                        _indexLabel.setText(I18nManager.getText("details.nopointselection"));
@@ -281,6 +298,8 @@ public class DetailsDisplay extends GenericDisplay
                        _timeLabel.setText("");
                        _nameLabel.setText("");
                        _typeLabel.setText("");
                        _timeLabel.setText("");
                        _nameLabel.setText("");
                        _typeLabel.setText("");
+                       _speedLabel.setText("");
+                       _vSpeedLabel.setText("");
                }
                else
                {
                }
                else
                {
@@ -289,34 +308,42 @@ public class DetailsDisplay extends GenericDisplay
                                + " " + _track.getNumPoints());
                        _latLabel.setText(makeCoordinateLabel(LABEL_POINT_LATITUDE, currentPoint.getLatitude(), _coordFormatDropdown.getSelectedIndex()));
                        _longLabel.setText(makeCoordinateLabel(LABEL_POINT_LONGITUDE, currentPoint.getLongitude(), _coordFormatDropdown.getSelectedIndex()));
                                + " " + _track.getNumPoints());
                        _latLabel.setText(makeCoordinateLabel(LABEL_POINT_LATITUDE, currentPoint.getLatitude(), _coordFormatDropdown.getSelectedIndex()));
                        _longLabel.setText(makeCoordinateLabel(LABEL_POINT_LONGITUDE, currentPoint.getLongitude(), _coordFormatDropdown.getSelectedIndex()));
+                       Unit altUnit = Config.getUnitSet().getAltitudeUnit();
                        _altLabel.setText(currentPoint.hasAltitude()?
                        _altLabel.setText(currentPoint.hasAltitude()?
-                               (LABEL_POINT_ALTITUDE + currentPoint.getAltitude().getValue() + getAltitudeUnitsLabel(currentPoint.getAltitude().getFormat()))
-                               :"");
-                       if (currentPoint.getTimestamp().isValid())
-                       {
-                               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())
-                                       {
-                                               // use total distance and total time between neighbouring points
-                                               long diff = nextPoint.getTimestamp().getSecondsSince(prevPoint.getTimestamp());
-                                               if (diff < 1000 && diff > 0)
-                                               {
-                                                       double rads = DataPoint.calculateRadiansBetween(prevPoint, currentPoint) +
-                                                               DataPoint.calculateRadiansBetween(currentPoint, nextPoint);
-                                                       double dist = Distance.convertRadiansToDistance(rads, distUnits);
-                                                       String speed = roundedNumber(3600 * dist / diff) + " " + speedUnitsStr;
-                                                       _speedLabel.setText(I18nManager.getText("fieldname.speed") + ": " + speed);
-                                               }
-                                       }
-                               }
+                               (LABEL_POINT_ALTITUDE + currentPoint.getAltitude().getValue(altUnit) + " " +
+                               I18nManager.getText(altUnit.getShortnameKey()))
+                               : "");
+                       if (currentPoint.hasTimestamp()) {
                                _timeLabel.setText(LABEL_POINT_TIMESTAMP + currentPoint.getTimestamp().getText());
                        }
                        else {
                                _timeLabel.setText("");
                        }
                                _timeLabel.setText(LABEL_POINT_TIMESTAMP + currentPoint.getTimestamp().getText());
                        }
                        else {
                                _timeLabel.setText("");
                        }
+
+                       // Speed can come from either timestamps and distances, or speed values in data
+                       SpeedValue speedValue = new SpeedValue();
+                       SpeedCalculator.calculateSpeed(_track, currentPointIndex, speedValue);
+                       if (speedValue.isValid())
+                       {
+                               String speed = roundedNumber(speedValue.getValue()) + " " + speedUnitsStr;
+                               _speedLabel.setText(LABEL_POINT_SPEED + speed);
+                       }
+                       else {
+                               _speedLabel.setText("");
+                       }
+
+                       // Now do the vertical speed in the same way
+                       SpeedCalculator.calculateVerticalSpeed(_track, currentPointIndex, speedValue);
+                       if (speedValue.isValid())
+                       {
+                               String vSpeedUnitsStr = I18nManager.getText(unitSet.getVerticalSpeedUnit().getShortnameKey());
+                               String speed = roundedNumber(speedValue.getValue()) + " " + vSpeedUnitsStr;
+                               _vSpeedLabel.setText(LABEL_POINT_VERTSPEED + speed);
+                       }
+                       else {
+                               _vSpeedLabel.setText("");
+                       }
+
                        // Waypoint name
                        final String name = currentPoint.getWaypointName();
                        if (name != null && !name.equals(""))
                        // Waypoint name
                        final String name = currentPoint.getWaypointName();
                        if (name != null && !name.equals(""))
@@ -347,27 +374,28 @@ public class DetailsDisplay extends GenericDisplay
                        _rangeLabel.setText(LABEL_RANGE_SELECTED
                                + (selection.getStart()+1) + " " + I18nManager.getText("details.range.to")
                                + " " + (selection.getEnd()+1));
                        _rangeLabel.setText(LABEL_RANGE_SELECTED
                                + (selection.getStart()+1) + " " + I18nManager.getText("details.range.to")
                                + " " + (selection.getEnd()+1));
-                       _distanceLabel.setText(LABEL_RANGE_DISTANCE + roundedNumber(selection.getDistance(distUnits)) + " " + distUnitsStr);
+                       _distanceLabel.setText(LABEL_RANGE_DISTANCE + roundedNumber(selection.getDistance()) + " " + distUnitsStr);
                        if (selection.getNumSeconds() > 0)
                        {
                                _durationLabel.setText(LABEL_RANGE_DURATION + DisplayUtils.buildDurationString(selection.getNumSeconds()));
                                _aveSpeedLabel.setText(I18nManager.getText("details.range.avespeed") + ": "
                        if (selection.getNumSeconds() > 0)
                        {
                                _durationLabel.setText(LABEL_RANGE_DURATION + DisplayUtils.buildDurationString(selection.getNumSeconds()));
                                _aveSpeedLabel.setText(I18nManager.getText("details.range.avespeed") + ": "
-                                       + roundedNumber(selection.getDistance(distUnits)/selection.getNumSeconds()*3600.0) + " " + speedUnitsStr);
+                                       + roundedNumber(selection.getDistance()/selection.getNumSeconds()*3600.0) + " " + speedUnitsStr);
                        }
                        else {
                                _durationLabel.setText("");
                                _aveSpeedLabel.setText("");
                        }
                        }
                        else {
                                _durationLabel.setText("");
                                _aveSpeedLabel.setText("");
                        }
-                       String altUnitsLabel = getAltitudeUnitsLabel(selection.getAltitudeFormat());
-                       IntegerRange altRange = selection.getAltitudeRange();
-                       if (altRange.getMinimum() >= 0 && altRange.getMaximum() >= 0)
+                       AltitudeRange altRange = selection.getAltitudeRange();
+                       Unit altUnit = Config.getUnitSet().getAltitudeUnit();
+                       String altUnitsLabel = I18nManager.getText(altUnit.getShortnameKey());
+                       if (altRange.hasRange())
                        {
                                _altRangeLabel.setText(LABEL_RANGE_ALTITUDE
                        {
                                _altRangeLabel.setText(LABEL_RANGE_ALTITUDE
-                                       + altRange.getMinimum() + altUnitsLabel + " "
+                                       + altRange.getMinimum(altUnit) + altUnitsLabel + " "
                                        + I18nManager.getText("details.altitude.to") + " "
                                        + I18nManager.getText("details.altitude.to") + " "
-                                       + altRange.getMaximum() + altUnitsLabel);
-                               _updownLabel.setText(LABEL_RANGE_CLIMB + selection.getClimb() + altUnitsLabel
-                                       + LABEL_RANGE_DESCENT + selection.getDescent() + altUnitsLabel);
+                                       + altRange.getMaximum(altUnit) + altUnitsLabel);
+                               _updownLabel.setText(LABEL_RANGE_CLIMB + altRange.getClimb(altUnit) + altUnitsLabel
+                                       + LABEL_RANGE_DESCENT + altRange.getDescent(altUnit) + altUnitsLabel);
                        }
                        else
                        {
                        }
                        else
                        {
@@ -382,6 +410,8 @@ public class DetailsDisplay extends GenericDisplay
                {
                        // no photo, hide details
                        _photoLabel.setText(I18nManager.getText("details.nophoto"));
                {
                        // no photo, hide details
                        _photoLabel.setText(I18nManager.getText("details.nophoto"));
+                       _photoPathLabel.setText("");
+                       _photoPathLabel.setToolTipText("");
                        _photoTimestampLabel.setText("");
                        _photoConnectedLabel.setText("");
                        _photoBearingLabel.setText("");
                        _photoTimestampLabel.setText("");
                        _photoConnectedLabel.setText("");
                        _photoBearingLabel.setText("");
@@ -392,6 +422,10 @@ public class DetailsDisplay extends GenericDisplay
                {
                        if (currentPhoto == null) {currentPhoto = currentPoint.getPhoto();}
                        _photoLabel.setText(I18nManager.getText("details.photofile") + ": " + currentPhoto.getName());
                {
                        if (currentPhoto == null) {currentPhoto = currentPoint.getPhoto();}
                        _photoLabel.setText(I18nManager.getText("details.photofile") + ": " + currentPhoto.getName());
+                       String fullPath = currentPhoto.getFullPath();
+                       String shortPath = shortenPath(fullPath);
+                       _photoPathLabel.setText(fullPath == null ? "" : LABEL_FULL_PATH + shortPath);
+                       _photoPathLabel.setToolTipText(currentPhoto.getFullPath());
                        _photoTimestampLabel.setText(currentPhoto.hasTimestamp()?(LABEL_POINT_TIMESTAMP + currentPhoto.getTimestamp().getText()):"");
                        _photoConnectedLabel.setText(I18nManager.getText("details.media.connected") + ": "
                                + (currentPhoto.getCurrentStatus() == Photo.Status.NOT_CONNECTED ?
                        _photoTimestampLabel.setText(currentPhoto.hasTimestamp()?(LABEL_POINT_TIMESTAMP + currentPhoto.getTimestamp().getText()):"");
                        _photoConnectedLabel.setText(I18nManager.getText("details.media.connected") + ": "
                                + (currentPhoto.getCurrentStatus() == Photo.Status.NOT_CONNECTED ?
@@ -412,8 +446,11 @@ public class DetailsDisplay extends GenericDisplay
                // audio details
                _audioDetailsPanel.setVisible(_trackInfo.getAudioList().getNumAudios() > 0);
                AudioClip currentAudio = _trackInfo.getAudioList().getAudio(_trackInfo.getSelection().getCurrentAudioIndex());
                // audio details
                _audioDetailsPanel.setVisible(_trackInfo.getAudioList().getNumAudios() > 0);
                AudioClip currentAudio = _trackInfo.getAudioList().getAudio(_trackInfo.getSelection().getCurrentAudioIndex());
-               if (currentAudio == null) {
+               if (currentAudio == null)
+               {
                        _audioLabel.setText(I18nManager.getText("details.noaudio"));
                        _audioLabel.setText(I18nManager.getText("details.noaudio"));
+                       _audioPathLabel.setText("");
+                       _audioPathLabel.setToolTipText("");
                        _audioTimestampLabel.setText("");
                        _audioLengthLabel.setText("");
                        _audioConnectedLabel.setText("");
                        _audioTimestampLabel.setText("");
                        _audioLengthLabel.setText("");
                        _audioConnectedLabel.setText("");
@@ -421,6 +458,10 @@ public class DetailsDisplay extends GenericDisplay
                else
                {
                        _audioLabel.setText(LABEL_AUDIO_FILE + currentAudio.getName());
                else
                {
                        _audioLabel.setText(LABEL_AUDIO_FILE + currentAudio.getName());
+                       String fullPath = currentAudio.getFullPath();
+                       String shortPath = shortenPath(fullPath);
+                       _audioPathLabel.setText(fullPath == null ? "" : LABEL_FULL_PATH + shortPath);
+                       _audioPathLabel.setToolTipText(fullPath == null ? "" : fullPath);
                        _audioTimestampLabel.setText(currentAudio.hasTimestamp()?(LABEL_POINT_TIMESTAMP + currentAudio.getTimestamp().getText()):"");
                        int audioLength = currentAudio.getLengthInSeconds();
                        _audioLengthLabel.setText(audioLength < 0?"":LABEL_RANGE_DURATION + DisplayUtils.buildDurationString(audioLength));
                        _audioTimestampLabel.setText(currentAudio.hasTimestamp()?(LABEL_POINT_TIMESTAMP + currentAudio.getTimestamp().getText()):"");
                        int audioLength = currentAudio.getLengthInSeconds();
                        _audioLengthLabel.setText(audioLength < 0?"":LABEL_RANGE_DURATION + DisplayUtils.buildDurationString(audioLength));
@@ -432,22 +473,6 @@ public class DetailsDisplay extends GenericDisplay
        }
 
 
        }
 
 
-       /**
-        * Choose the appropriate altitude units label for the specified format
-        * @param inFormat altitude format
-        * @return language-sensitive string
-        */
-       private static String getAltitudeUnitsLabel(Altitude.Format inFormat)
-       {
-               if (inFormat == LABEL_POINT_ALTITUDE_FORMAT && LABEL_POINT_ALTITUDE_UNITS != null)
-                       return LABEL_POINT_ALTITUDE_UNITS;
-               LABEL_POINT_ALTITUDE_FORMAT = inFormat;
-               if (inFormat == Altitude.Format.METRES)
-                       return " " + I18nManager.getText("units.metres.short");
-               return " " + I18nManager.getText("units.feet.short");
-       }
-
-
        /**
         * Construct an appropriate coordinate label using the selected format
         * @param inPrefix prefix of label
        /**
         * Construct an appropriate coordinate label using the selected format
         * @param inPrefix prefix of label
@@ -550,4 +575,22 @@ public class DetailsDisplay extends GenericDisplay
                button.addActionListener(new FunctionLauncher(inFunction));
                return button;
        }
                button.addActionListener(new FunctionLauncher(inFunction));
                return button;
        }
+
+       /**
+        * @param inFullPath full file path or URL to be shortened
+        * @return shortened string from beginning of path
+        */
+       private static String shortenPath(String inFullPath)
+       {
+               // Chop off the home path if possible
+               final String homePath = System.getProperty("user.home").toLowerCase();
+               if (inFullPath != null && inFullPath.toLowerCase().startsWith(homePath)) {
+                       inFullPath = inFullPath.substring(homePath.length()+1);
+               }
+               if (inFullPath == null || inFullPath.length() < 21) {
+                       return inFullPath;
+               }
+               // path is too long
+               return inFullPath.substring(0, 20) + "...";
+       }
 }
 }
index 1c0cc7e43d478e86d43073b438b91835284b4d40..72537b4098716d08c2a23a4e61f62465ed3c620f 100644 (file)
@@ -28,6 +28,10 @@ public abstract class IconManager
        public static final String POINTS_CONNECTED_BUTTON = "points_connected.gif";
        /** Icon for points disconnected icon on main map display */
        public static final String POINTS_DISCONNECTED_BUTTON = "points_disconnected.gif";
        public static final String POINTS_CONNECTED_BUTTON = "points_connected.gif";
        /** Icon for points disconnected icon on main map display */
        public static final String POINTS_DISCONNECTED_BUTTON = "points_disconnected.gif";
+        /** Icon for edit mode button on main map display when not selected */
+       public static final String EDIT_MODE_BUTTON = "drag_points_icon.gif";
+        /** Icon for edit mode button on main map display when selected */
+       public static final String EDIT_MODE_BUTTON_ON = "drag_points_icon_on.gif";
        /** Icon for zoom in button on main map display */
        public static final String ZOOM_IN_BUTTON = "zoom_in.gif";
        /** Icon for zoom out button on main map display */
        /** Icon for zoom in button on main map display */
        public static final String ZOOM_IN_BUTTON = "zoom_in.gif";
        /** Icon for zoom out button on main map display */
index 3fa7a1a8fdb2ca822f4a7e226d7459f3b80eca5c..d152ecca5b1c78549d6fcb7ea0f65878984a5436 100644 (file)
@@ -70,15 +70,19 @@ public abstract class ImageUtils
         */
        public static Dimension getThumbnailSize(int inOrigWidth, int inOrigHeight, int inMaxWidth, int inMaxHeight)
        {
         */
        public static Dimension getThumbnailSize(int inOrigWidth, int inOrigHeight, int inMaxWidth, int inMaxHeight)
        {
-               assert(inMaxWidth > 0 && inMaxHeight > 0);
+               if (inMaxWidth <= 0 || inMaxHeight <= 0) {return new Dimension(1, 1);}
                // work out maximum zoom ratio available so that thumbnail isn't too big
                double xZoom = inMaxWidth * 1.0 / inOrigWidth;
                double yZoom = inMaxHeight * 1.0 / inOrigHeight;
                double zoom = (xZoom > yZoom?yZoom:xZoom);
                // Don't make thumbnail bigger than picture
                if (zoom > 1.0) {return new Dimension(inOrigWidth, inOrigHeight);}
                // work out maximum zoom ratio available so that thumbnail isn't too big
                double xZoom = inMaxWidth * 1.0 / inOrigWidth;
                double yZoom = inMaxHeight * 1.0 / inOrigHeight;
                double zoom = (xZoom > yZoom?yZoom:xZoom);
                // Don't make thumbnail bigger than picture
                if (zoom > 1.0) {return new Dimension(inOrigWidth, inOrigHeight);}
+
                // calculate new width and height
                // calculate new width and height
-               return new Dimension ((int) (zoom * inOrigWidth), (int) (zoom * inOrigHeight));
+               final int xSize = (int) (zoom * inOrigWidth);
+               final int ySize = (int) (zoom * inOrigHeight);
+               if (xSize <= 0 || ySize <= 0) {return new Dimension(1, 1);}
+               return new Dimension (xSize, ySize);
        }
 
 
        }
 
 
index 8229aa322fb58458db950de8eabdb27f9e16ddeb..c5501eee75dd653b3a72685bdd71867e14df7cc4 100644 (file)
@@ -54,7 +54,9 @@ public class MenuManager implements DataSubscriber
        private JMenuItem _editWaypointNameItem = null;
        private JMenuItem _deletePointItem = null;
        private JMenuItem _deleteRangeItem = null;
        private JMenuItem _editWaypointNameItem = null;
        private JMenuItem _deletePointItem = null;
        private JMenuItem _deleteRangeItem = null;
+       private JMenuItem _cropTrackItem = null;
        private JMenuItem _compressItem = null;
        private JMenuItem _compressItem = null;
+       private JMenuItem _markRectangleItem = null;
        private JMenuItem _deleteMarkedPointsItem = null;
        private JMenuItem _interpolateItem = null;
        private JMenuItem _averageItem = null;
        private JMenuItem _deleteMarkedPointsItem = null;
        private JMenuItem _interpolateItem = null;
        private JMenuItem _averageItem = null;
@@ -109,7 +111,6 @@ public class MenuManager implements DataSubscriber
        private ActionListener _undoAction = null;
        private ActionListener _editPointAction = null;
        private ActionListener _deletePointAction = null;
        private ActionListener _undoAction = null;
        private ActionListener _editPointAction = null;
        private ActionListener _deletePointAction = null;
-       private ActionListener _deleteRangeAction = null;
        private ActionListener _selectStartAction = null;
        private ActionListener _selectEndAction = null;
 
        private ActionListener _selectStartAction = null;
        private ActionListener _selectEndAction = null;
 
@@ -119,6 +120,7 @@ public class MenuManager implements DataSubscriber
        private JButton _editPointButton = null;
        private JButton _deletePointButton = null;
        private JButton _deleteRangeButton = null;
        private JButton _editPointButton = null;
        private JButton _deletePointButton = null;
        private JButton _deleteRangeButton = null;
+       private JButton _cutAndMoveButton = null;
        private JButton _selectStartButton = null;
        private JButton _selectEndButton = null;
        private JButton _connectButton = null;
        private JButton _selectStartButton = null;
        private JButton _selectEndButton = null;
        private JButton _connectButton = null;
@@ -250,6 +252,15 @@ public class MenuManager implements DataSubscriber
                _compressItem = makeMenuItem(FunctionLibrary.FUNCTION_COMPRESS, false);
                setShortcut(_compressItem, "shortcut.menu.edit.compress");
                trackMenu.add(_compressItem);
                _compressItem = makeMenuItem(FunctionLibrary.FUNCTION_COMPRESS, false);
                setShortcut(_compressItem, "shortcut.menu.edit.compress");
                trackMenu.add(_compressItem);
+               _markRectangleItem = new JMenuItem(I18nManager.getText("menu.track.markrectangle"));
+               _markRectangleItem.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e) {
+                               _app.setCurrentMode(App.AppMode.DRAWRECT);
+                               UpdateMessageBroker.informSubscribers();
+                       }
+               });
+               _markRectangleItem.setEnabled(false);
+               trackMenu.add(_markRectangleItem);
                _deleteMarkedPointsItem = new JMenuItem(I18nManager.getText("menu.track.deletemarked"));
                _deleteMarkedPointsItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                _deleteMarkedPointsItem = new JMenuItem(I18nManager.getText("menu.track.deletemarked"));
                _deleteMarkedPointsItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
@@ -343,15 +354,10 @@ public class MenuManager implements DataSubscriber
                _selectEndItem.addActionListener(_selectEndAction);
                rangeMenu.add(_selectEndItem);
                rangeMenu.addSeparator();
                _selectEndItem.addActionListener(_selectEndAction);
                rangeMenu.add(_selectEndItem);
                rangeMenu.addSeparator();
-               _deleteRangeItem = new JMenuItem(I18nManager.getText("menu.range.deleterange"));
-               _deleteRangeAction = new ActionListener() {
-                       public void actionPerformed(ActionEvent e) {
-                               _app.deleteSelectedRange();
-                       }
-               };
-               _deleteRangeItem.addActionListener(_deleteRangeAction);
-               _deleteRangeItem.setEnabled(false);
+               _deleteRangeItem = makeMenuItem(FunctionLibrary.FUNCTION_DELETE_RANGE, false);
                rangeMenu.add(_deleteRangeItem);
                rangeMenu.add(_deleteRangeItem);
+               _cropTrackItem = makeMenuItem(FunctionLibrary.FUNCTION_CROP_TRACK, false);
+               rangeMenu.add(_cropTrackItem);
                _reverseItem = new JMenuItem(I18nManager.getText("menu.range.reverse"));
                _reverseItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                _reverseItem = new JMenuItem(I18nManager.getText("menu.range.reverse"));
                _reverseItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
@@ -375,13 +381,7 @@ public class MenuManager implements DataSubscriber
                _deleteFieldValuesItem = makeMenuItem(FunctionLibrary.FUNCTION_DELETE_FIELD_VALUES, false);
                rangeMenu.add(_deleteFieldValuesItem);
                rangeMenu.addSeparator();
                _deleteFieldValuesItem = makeMenuItem(FunctionLibrary.FUNCTION_DELETE_FIELD_VALUES, false);
                rangeMenu.add(_deleteFieldValuesItem);
                rangeMenu.addSeparator();
-               _interpolateItem = new JMenuItem(I18nManager.getText("menu.range.interpolate"));
-               _interpolateItem.addActionListener(new ActionListener() {
-                       public void actionPerformed(ActionEvent e) {
-                               _app.interpolateSelection();
-                       }
-               });
-               _interpolateItem.setEnabled(false);
+               _interpolateItem = makeMenuItem(FunctionLibrary.FUNCTION_INTERPOLATE, false);
                rangeMenu.add(_interpolateItem);
                _averageItem = new JMenuItem(I18nManager.getText("menu.range.average"));
                _averageItem.addActionListener(new ActionListener() {
                rangeMenu.add(_interpolateItem);
                _averageItem = new JMenuItem(I18nManager.getText("menu.range.average"));
                _averageItem.addActionListener(new ActionListener() {
@@ -449,8 +449,8 @@ public class MenuManager implements DataSubscriber
                _mapCheckbox.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                                Config.setConfigBoolean(Config.KEY_SHOW_MAP, _mapCheckbox.isSelected());
                _mapCheckbox.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                                Config.setConfigBoolean(Config.KEY_SHOW_MAP, _mapCheckbox.isSelected());
-                               UpdateMessageBroker.informSubscribers();
-                       }
+                               UpdateMessageBroker.informSubscribers(MAPSERVER_CHANGED);
+                       }
                });
                viewMenu.add(_mapCheckbox);
                // Turn off the sidebars
                });
                viewMenu.add(_mapCheckbox);
                // Turn off the sidebars
@@ -761,10 +761,24 @@ public class MenuManager implements DataSubscriber
                toolbar.add(_deletePointButton);
                // Delete range
                _deleteRangeButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_RANGE));
                toolbar.add(_deletePointButton);
                // Delete range
                _deleteRangeButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_RANGE));
-               _deleteRangeButton.setToolTipText(I18nManager.getText("menu.range.deleterange"));
-               _deleteRangeButton.addActionListener(_deleteRangeAction);
+               _deleteRangeButton.setToolTipText(I18nManager.getText("function.deleterange"));
+               _deleteRangeButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent arg0) {
+                               FunctionLibrary.FUNCTION_DELETE_RANGE.begin();
+                       }
+               });
                _deleteRangeButton.setEnabled(false);
                toolbar.add(_deleteRangeButton);
                _deleteRangeButton.setEnabled(false);
                toolbar.add(_deleteRangeButton);
+               // Cut and move
+               _cutAndMoveButton = new JButton(IconManager.getImageIcon(IconManager.CUT_AND_MOVE));
+               _cutAndMoveButton.setToolTipText(I18nManager.getText("menu.range.cutandmove"));
+               _cutAndMoveButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent arg0) {
+                               _app.cutAndMoveSelection();
+                       }
+               });
+               _cutAndMoveButton.setEnabled(false);
+               toolbar.add(_cutAndMoveButton);
                // Select start, end
                _selectStartButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_START));
                _selectStartButton.setToolTipText(I18nManager.getText("menu.range.start"));
                // Select start, end
                _selectStartButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_START));
                _selectStartButton.setToolTipText(I18nManager.getText("menu.range.start"));
@@ -821,6 +835,7 @@ public class MenuManager implements DataSubscriber
                _exportPovItem.setEnabled(hasData);
                _exportSvgItem.setEnabled(hasData);
                _compressItem.setEnabled(hasData);
                _exportPovItem.setEnabled(hasData);
                _exportSvgItem.setEnabled(hasData);
                _compressItem.setEnabled(hasData);
+               _markRectangleItem.setEnabled(hasData);
                _deleteMarkedPointsItem.setEnabled(hasData && _track.hasMarkedPoints());
                _rearrangeMenu.setEnabled(hasData && _track.hasTrackPoints() && _track.hasWaypoints());
                _selectAllItem.setEnabled(hasData);
                _deleteMarkedPointsItem.setEnabled(hasData && _track.hasMarkedPoints());
                _rearrangeMenu.setEnabled(hasData && _track.hasTrackPoints() && _track.hasWaypoints());
                _selectAllItem.setEnabled(hasData);
@@ -884,8 +899,8 @@ public class MenuManager implements DataSubscriber
                boolean hasRange = (hasData && _selection.hasRangeSelected());
                _deleteRangeItem.setEnabled(hasRange);
                _deleteRangeButton.setEnabled(hasRange);
                boolean hasRange = (hasData && _selection.hasRangeSelected());
                _deleteRangeItem.setEnabled(hasRange);
                _deleteRangeButton.setEnabled(hasRange);
-               _interpolateItem.setEnabled(hasRange
-                       && (_selection.getEnd() - _selection.getStart()) == 1);
+               _cropTrackItem.setEnabled(hasRange);
+               _interpolateItem.setEnabled(hasRange);
                _averageItem.setEnabled(hasRange);
                _mergeSegmentsItem.setEnabled(hasRange);
                _reverseItem.setEnabled(hasRange);
                _averageItem.setEnabled(hasRange);
                _mergeSegmentsItem.setEnabled(hasRange);
                _reverseItem.setEnabled(hasRange);
@@ -895,9 +910,11 @@ public class MenuManager implements DataSubscriber
                _deleteFieldValuesItem.setEnabled(hasRange);
                _fullRangeDetailsItem.setEnabled(hasRange);
                // Is the currently selected point outside the current range?
                _deleteFieldValuesItem.setEnabled(hasRange);
                _fullRangeDetailsItem.setEnabled(hasRange);
                // Is the currently selected point outside the current range?
-               _cutAndMoveItem.setEnabled(hasRange && hasPoint &&
+               boolean canCutAndMove = hasRange && hasPoint &&
                        (_selection.getCurrentPointIndex() < _selection.getStart()
                        (_selection.getCurrentPointIndex() < _selection.getStart()
-                               || _selection.getCurrentPointIndex() > (_selection.getEnd()+1)));
+                       || _selection.getCurrentPointIndex() > (_selection.getEnd()+1));
+               _cutAndMoveItem.setEnabled(canCutAndMove);
+               _cutAndMoveButton.setEnabled(canCutAndMove);
                // Has the map been switched on/off?
                boolean mapsOn = Config.getConfigBoolean(Config.KEY_SHOW_MAP);
                if (_mapCheckbox.isSelected() != mapsOn) {
                // Has the map been switched on/off?
                boolean mapsOn = Config.getConfigBoolean(Config.KEY_SHOW_MAP);
                if (_mapCheckbox.isSelected() != mapsOn) {
index 73a504a50160efa3581feb9cb43e001898616aae..0f2b66b4610c93a102c7289414fac6af2c27c703 100644 (file)
@@ -253,7 +253,7 @@ public class SelectorDisplay extends GenericDisplay
                {
                        _waypointListModel.fireChanged();
                }
                {
                        _waypointListModel.fireChanged();
                }
-               if ((inUpdateType |
+               if ((inUpdateType &
                        (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.PHOTOS_MODIFIED)) > 0)
                {
                        _photoListModel.fireChanged();
                        (DataSubscriber.DATA_ADDED_OR_REMOVED | DataSubscriber.DATA_EDITED | DataSubscriber.PHOTOS_MODIFIED)) > 0)
                {
                        _photoListModel.fireChanged();
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index e80306b2345eda50aeed511dd12685e4d1dff352..c7be0b1571a8757932c0f4a9850693e250cb8703 100644 (file)
Binary files a/tim/prune/gui/images/autopan.gif and b/tim/prune/gui/images/autopan.gif differ
diff --git a/tim/prune/gui/images/connect_photo_icon.png b/tim/prune/gui/images/connect_photo_icon.png
deleted file mode 100644 (file)
index d32d52e..0000000
Binary files a/tim/prune/gui/images/connect_photo_icon.png and /dev/null differ
index 2249560383dcef3cd1c696c18c5139ca9a5a786b..b2e0afbbeb3938f6d7be728c467a92b65c04fe12 100644 (file)
Binary files a/tim/prune/gui/images/cut_and_move.gif and b/tim/prune/gui/images/cut_and_move.gif differ
diff --git a/tim/prune/gui/images/drag_points_icon.gif b/tim/prune/gui/images/drag_points_icon.gif
new file mode 100644 (file)
index 0000000..67cedba
Binary files /dev/null and b/tim/prune/gui/images/drag_points_icon.gif differ
diff --git a/tim/prune/gui/images/drag_points_icon_on.gif b/tim/prune/gui/images/drag_points_icon_on.gif
new file mode 100644 (file)
index 0000000..d490471
Binary files /dev/null and b/tim/prune/gui/images/drag_points_icon_on.gif differ
index 99b74f4e2643e2600b5423acb6310c9da630fea0..322eb8ef4157cd4c6430a53bd4368cf74b257ea5 100644 (file)
Binary files a/tim/prune/gui/images/scalebar.gif and b/tim/prune/gui/images/scalebar.gif differ
index 99aa809654c810be01d9ba7d80d4e5054593f0c3..17d4efe305916db645bef30bceafba51315ee558 100644 (file)
@@ -8,7 +8,7 @@ public class CloudmadeMapSource extends OsmMapSource
        /** Selected style number */
        private String _style = null;
        /** Server prefix including API-key unique to GpsPrune application */
        /** Selected style number */
        private String _style = null;
        /** Server prefix including API-key unique to GpsPrune application */
-       private static final String SERVER_PREFIX = "tile.cloudmade.com/03d86b66f51f4a3b8c236ac06f2a2e57/";
+       private static final String SERVER_PREFIX = "[abc].tile.cloudmade.com/03d86b66f51f4a3b8c236ac06f2a2e57/";
 
        /**
         * Constructor
 
        /**
         * Constructor
index 40216f8c1fe532ea1a5f49a3ae3f49c8061019b8..350b3b4b1cdb1f2bbc53ff9f98accadbb1d0bbe5 100644 (file)
@@ -8,6 +8,10 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashSet;
+
+import tim.prune.GpsPrune;
 
 /**
  * Class to control the reading and saving of map tiles
 
 /**
  * Class to control the reading and saving of map tiles
@@ -23,6 +27,8 @@ public class DiskTileCacher implements Runnable
        private ImageObserver _observer = null;
        /** Time limit to cache images for */
        private static final long CACHE_TIME_LIMIT = 20 * 24 * 60 * 60 * 1000; // 20 days in ms
        private ImageObserver _observer = null;
        /** Time limit to cache images for */
        private static final long CACHE_TIME_LIMIT = 20 * 24 * 60 * 60 * 1000; // 20 days in ms
+       /** Hashset of all blocked / 404 tiles to avoid requesting them again */
+       private static final HashSet<String> BLOCKED_URLS = new HashSet<String>();
 
        /**
         * Private constructor
 
        /**
         * Private constructor
@@ -49,7 +55,8 @@ public class DiskTileCacher implements Runnable
                if (inBasePath == null) {return null;}
                File tileFile = new File(inBasePath, inTilePath);
                Image image = null;
                if (inBasePath == null) {return null;}
                File tileFile = new File(inBasePath, inTilePath);
                Image image = null;
-               if (tileFile.exists() && tileFile.canRead() && tileFile.length() > 0) {
+               if (tileFile.exists() && tileFile.canRead() && tileFile.length() > 0)
+               {
                        long fileStamp = tileFile.lastModified();
                        if (!inCheckAge || ((System.currentTimeMillis()-fileStamp) < CACHE_TIME_LIMIT))
                        {
                        long fileStamp = tileFile.lastModified();
                        if (!inCheckAge || ((System.currentTimeMillis()-fileStamp) < CACHE_TIME_LIMIT))
                        {
@@ -72,7 +79,6 @@ public class DiskTileCacher implements Runnable
         */
        public static boolean saveTile(URL inUrl, String inBasePath, String inTilePath, ImageObserver inObserver)
        {
         */
        public static boolean saveTile(URL inUrl, String inBasePath, String inTilePath, ImageObserver inObserver)
        {
-               // TODO: Check that these are getting blocked properly
                if (inBasePath == null || inTilePath == null) {return false;}
                // save file if possible
                File basePath = new File(inBasePath);
                if (inBasePath == null || inTilePath == null) {return false;}
                // save file if possible
                File basePath = new File(inBasePath);
@@ -83,6 +89,8 @@ public class DiskTileCacher implements Runnable
                File tileFile = new File(basePath, inTilePath);
                // Check if this file is already being loaded
                if (isBeingLoaded(tileFile)) {return true;}
                File tileFile = new File(basePath, inTilePath);
                // Check if this file is already being loaded
                if (isBeingLoaded(tileFile)) {return true;}
+               // Check if it has already failed
+               if (BLOCKED_URLS.contains(inUrl.toString())) {return true;}
 
                File dir = tileFile.getParentFile();
                // Start a new thread to load the image if necessary
 
                File dir = tileFile.getParentFile();
                // Start a new thread to load the image if necessary
@@ -115,7 +123,8 @@ public class DiskTileCacher implements Runnable
                FileOutputStream out = null;
                File tempFile = new File(_file.getAbsolutePath() + ".temp");
                // Use a synchronized block across all threads to make sure this url is only fetched once
                FileOutputStream out = null;
                File tempFile = new File(_file.getAbsolutePath() + ".temp");
                // Use a synchronized block across all threads to make sure this url is only fetched once
-               synchronized (DiskTileCacher.class) {
+               synchronized (DiskTileCacher.class)
+               {
                        if (tempFile.exists()) {return;}
                        try {
                                if (!tempFile.createNewFile()) {return;}
                        if (tempFile.exists()) {return;}
                        try {
                                if (!tempFile.createNewFile()) {return;}
@@ -126,14 +135,20 @@ public class DiskTileCacher implements Runnable
                {
                        // Open streams from URL and to file
                        out = new FileOutputStream(tempFile);
                {
                        // Open streams from URL and to file
                        out = new FileOutputStream(tempFile);
-                       in = _url.openStream();
+                       // Set http user agent on connection
+                       URLConnection conn = _url.openConnection();
+                       conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER);
+                       in = conn.getInputStream();
                        int d = 0;
                        // Loop over each byte in the stream (maybe buffering is more efficient?)
                        while ((d = in.read()) >= 0) {
                                out.write(d);
                        }
                        finished = true;
                        int d = 0;
                        // Loop over each byte in the stream (maybe buffering is more efficient?)
                        while ((d = in.read()) >= 0) {
                                out.write(d);
                        }
                        finished = true;
-               } catch (IOException e) {}
+               } catch (IOException e) {
+                       System.err.println("ioe: " + e.getClass().getName() + " - " + e.getMessage());
+                       BLOCKED_URLS.add(_url.toString());
+               }
                finally
                {
                        // clean up files
                finally
                {
                        // clean up files
index 7fc5c489dd06f4f3ad1cf0860b0f969deab9b6a4..96ff22367e89d5137e1710c96e104a2911ff80de 100644 (file)
@@ -3,6 +3,7 @@ package tim.prune.gui.map;
 import java.awt.BasicStroke;
 import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.BasicStroke;
 import java.awt.BorderLayout;
 import java.awt.Color;
+import java.awt.Cursor;
 import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.FontMetrics;
 import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.FontMetrics;
@@ -44,11 +45,17 @@ import tim.prune.data.Checker;
 import tim.prune.data.Coordinate;
 import tim.prune.data.DataPoint;
 import tim.prune.data.DoubleRange;
 import tim.prune.data.Coordinate;
 import tim.prune.data.DataPoint;
 import tim.prune.data.DoubleRange;
+import tim.prune.data.Field;
+import tim.prune.data.FieldList;
 import tim.prune.data.Latitude;
 import tim.prune.data.Longitude;
 import tim.prune.data.Latitude;
 import tim.prune.data.Longitude;
+import tim.prune.data.MidpointData;
 import tim.prune.data.Selection;
 import tim.prune.data.Track;
 import tim.prune.data.TrackInfo;
 import tim.prune.data.Selection;
 import tim.prune.data.Track;
 import tim.prune.data.TrackInfo;
+import tim.prune.function.compress.MarkPointsInRectangleFunction;
+import tim.prune.function.edit.FieldEdit;
+import tim.prune.function.edit.FieldEditList;
 import tim.prune.gui.IconManager;
 
 /**
 import tim.prune.gui.IconManager;
 
 /**
@@ -65,6 +72,10 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        private TrackInfo _trackInfo = null;
        /** Selection object */
        private Selection _selection = null;
        private TrackInfo _trackInfo = null;
        /** Selection object */
        private Selection _selection = null;
+       /** Object to keep track of midpoints */
+       private MidpointData _midpoints = null;
+       /** Index of point clicked at mouseDown */
+       private int _clickedPoint = -1;
        /** Previously selected point */
        private int _prevSelectedPoint = -1;
        /** Tile manager */
        /** Previously selected point */
        private int _prevSelectedPoint = -1;
        /** Tile manager */
@@ -81,6 +92,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        private JCheckBox _autopanCheckBox = null;
        /** Checkbox for connecting track points */
        private JCheckBox _connectCheckBox = null;
        private JCheckBox _autopanCheckBox = null;
        /** Checkbox for connecting track points */
        private JCheckBox _connectCheckBox = null;
+       /** Checkbox for enable edit mode */
+       private JCheckBox _editmodeCheckBox = null;
        /** Right-click popup menu */
        private JPopupMenu _popup = null;
        /** Top component panel */
        /** Right-click popup menu */
        private JPopupMenu _popup = null;
        /** Top component panel */
@@ -97,18 +110,12 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        private boolean _checkBounds = false;
        /** Map position */
        private MapPosition _mapPosition = null;
        private boolean _checkBounds = false;
        /** Map position */
        private MapPosition _mapPosition = null;
-       /** x coordinate of drag from point */
-       private int _dragFromX = -1;
-       /** y coordinate of drag from point */
-       private int _dragFromY = -1;
-       /** x coordinate of drag to point */
-       private int _dragToX = -1;
-       /** y coordinate of drag to point */
-       private int _dragToY = -1;
-       /** x coordinate of popup menu */
-       private int _popupMenuX = -1;
-       /** y coordinate of popup menu */
-       private int _popupMenuY = -1;
+       /** coordinates of drag from point */
+       private int _dragFromX = -1, _dragFromY = -1;
+       /** coordinates of drag to point */
+       private int _dragToX = -1, _dragToY = -1;
+       /** coordinates of popup menu */
+       private int _popupMenuX = -1, _popupMenuY = -1;
        /** Flag to prevent showing too often the error message about loading maps */
        private boolean _shownOsmErrorAlready = false;
        /** Current drawing mode */
        /** Flag to prevent showing too often the error message about loading maps */
        private boolean _shownOsmErrorAlready = false;
        /** Current drawing mode */
@@ -129,6 +136,12 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        private static final int MODE_ZOOM_RECT = 1;
        private static final int MODE_DRAW_POINTS_START = 2;
        private static final int MODE_DRAW_POINTS_CONT = 3;
        private static final int MODE_ZOOM_RECT = 1;
        private static final int MODE_DRAW_POINTS_START = 2;
        private static final int MODE_DRAW_POINTS_CONT = 3;
+       private static final int MODE_DRAG_POINT = 4;
+       private static final int MODE_CREATE_MIDPOINT = 5;
+       private static final int MODE_MARK_RECTANGLE = 6;
+
+       private static final int INDEX_UNKNOWN  = -2;
+
 
        /**
         * Constructor
 
        /**
         * Constructor
@@ -141,6 +154,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                _trackInfo = inTrackInfo;
                _track = inTrackInfo.getTrack();
                _selection = inTrackInfo.getSelection();
                _trackInfo = inTrackInfo;
                _track = inTrackInfo.getTrack();
                _selection = inTrackInfo.getSelection();
+               _midpoints = new MidpointData();
                _mapPosition = new MapPosition();
                addMouseListener(this);
                addMouseMotionListener(this);
                _mapPosition = new MapPosition();
                addMouseListener(this);
                addMouseMotionListener(this);
@@ -163,6 +177,10 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                _recalculate = true;
                                Config.setConfigBoolean(Config.KEY_SHOW_MAP, e.getStateChange() == ItemEvent.SELECTED);
                                UpdateMessageBroker.informSubscribers(); // to let menu know
                                _recalculate = true;
                                Config.setConfigBoolean(Config.KEY_SHOW_MAP, e.getStateChange() == ItemEvent.SELECTED);
                                UpdateMessageBroker.informSubscribers(); // to let menu know
+                               // If the track is only partially visible and you turn the map off, make the track fully visible again
+                               if (e.getStateChange() == ItemEvent.DESELECTED && _transparencySlider.getValue() < 0) {
+                                       _transparencySlider.setValue(0);
+                               }
                        }
                };
                _topPanel = new OverlayPanel();
                        }
                };
                _topPanel = new OverlayPanel();
@@ -225,6 +243,15 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                _connectCheckBox.setFocusable(false); // stop button from stealing keyboard focus
                _topPanel.add(_connectCheckBox);
 
                _connectCheckBox.setFocusable(false); // stop button from stealing keyboard focus
                _topPanel.add(_connectCheckBox);
 
+               // Add checkbox button for edit mode or not
+               _editmodeCheckBox = new JCheckBox(IconManager.getImageIcon(IconManager.EDIT_MODE_BUTTON), false);
+               _editmodeCheckBox.setSelectedIcon(IconManager.getImageIcon(IconManager.EDIT_MODE_BUTTON_ON));
+               _editmodeCheckBox.setOpaque(false);
+               _editmodeCheckBox.setToolTipText(I18nManager.getText("menu.map.editmode"));
+               _editmodeCheckBox.addItemListener(itemListener);
+               _editmodeCheckBox.setFocusable(false); // stop button from stealing keyboard focus
+               _topPanel.add(_editmodeCheckBox);
+
                // Add zoom in, zoom out buttons
                _sidePanel = new OverlayPanel();
                _sidePanel.setLayout(new BoxLayout(_sidePanel, BoxLayout.Y_AXIS));
                // Add zoom in, zoom out buttons
                _sidePanel = new OverlayPanel();
                _sidePanel.setLayout(new BoxLayout(_sidePanel, BoxLayout.Y_AXIS));
@@ -396,23 +423,38 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        if (_mapImage != null) {
                                inG.drawImage(_mapImage, 0, 0, getWidth(), getHeight(), null);
                        }
                        if (_mapImage != null) {
                                inG.drawImage(_mapImage, 0, 0, getWidth(), getHeight(), null);
                        }
-                       // Draw the zoom rectangle if necessary
-                       if (_drawMode == MODE_ZOOM_RECT)
-                       {
-                               inG.setColor(Color.RED);
-                               inG.drawLine(_dragFromX, _dragFromY, _dragFromX, _dragToY);
-                               inG.drawLine(_dragFromX, _dragFromY, _dragToX, _dragFromY);
-                               inG.drawLine(_dragToX, _dragFromY, _dragToX, _dragToY);
-                               inG.drawLine(_dragFromX, _dragToY, _dragToX, _dragToY);
-                       }
-                       else if (_drawMode == MODE_DRAW_POINTS_CONT)
+
+                       switch (_drawMode)
                        {
                        {
-                               // draw line to mouse position to show drawing mode
-                               inG.setColor(Config.getColourScheme().getColour(ColourScheme.IDX_POINT));
-                               int prevIndex = _track.getNumPoints()-1;
-                               int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(prevIndex));
-                               int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(prevIndex));
-                               inG.drawLine(px, py, _dragToX, _dragToY);
+                               case MODE_DRAG_POINT:
+                                       drawDragLines(inG, _selection.getCurrentPointIndex()-1, _selection.getCurrentPointIndex()+1);
+                                       break;
+
+                               case MODE_CREATE_MIDPOINT:
+                                       drawDragLines(inG, _clickedPoint-1, _clickedPoint);
+                                       break;
+
+                               case MODE_ZOOM_RECT:
+                               case MODE_MARK_RECTANGLE:
+                                       if (_dragFromX != -1 && _dragFromY != -1)
+                                       {
+                                               // Draw the zoom rectangle if necessary
+                                               inG.setColor(Color.RED);
+                                               inG.drawLine(_dragFromX, _dragFromY, _dragFromX, _dragToY);
+                                               inG.drawLine(_dragFromX, _dragFromY, _dragToX, _dragFromY);
+                                               inG.drawLine(_dragToX, _dragFromY, _dragToX, _dragToY);
+                                               inG.drawLine(_dragFromX, _dragToY, _dragToX, _dragToY);
+                                       }
+                                       break;
+                                       
+                               case MODE_DRAW_POINTS_CONT:
+                                       // draw line to mouse position to show drawing mode
+                                       inG.setColor(Config.getColourScheme().getColour(ColourScheme.IDX_POINT));
+                                       int prevIndex = _track.getNumPoints()-1;
+                                       int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(prevIndex));
+                                       int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(prevIndex));
+                                       inG.drawLine(px, py, _dragToX, _dragToY);
+                                       break;
                        }
                }
                else
                        }
                }
                else
@@ -545,6 +587,15 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                final Color secondColour = makeTransparentColour(cs.getColour(ColourScheme.IDX_SECONDARY), opacity);
                final Color textColour   = makeTransparentColour(cs.getColour(ColourScheme.IDX_TEXT), opacity);
 
                final Color secondColour = makeTransparentColour(cs.getColour(ColourScheme.IDX_SECONDARY), opacity);
                final Color textColour   = makeTransparentColour(cs.getColour(ColourScheme.IDX_TEXT), opacity);
 
+               final int winWidth  = getWidth();
+               final int winHeight = getHeight();
+               final int halfWinWidth  = winWidth / 2;
+               final int halfWinHeight = winHeight / 2;
+
+               final int numPoints = _track.getNumPoints();
+               final int[] xPixels = new int[numPoints];
+               final int[] yPixels = new int[numPoints];
+
                // try to set line width for painting
                if (inG instanceof Graphics2D)
                {
                // try to set line width for painting
                if (inG instanceof Graphics2D)
                {
@@ -560,11 +611,16 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                boolean prevPointVisible = false, currPointVisible = false;
                boolean anyWaypoints = false;
                boolean isWaypoint = false;
                boolean prevPointVisible = false, currPointVisible = false;
                boolean anyWaypoints = false;
                boolean isWaypoint = false;
-               for (int i=0; i<_track.getNumPoints(); i++)
+               for (int i=0; i<numPoints; i++)
                {
                {
-                       int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(i));
-                       int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(i));
-                       currPointVisible = px >= 0 && px < getWidth() && py >= 0 && py < getHeight();
+                       // Calculate pixel position of point from its x, y coordinates
+                       int px = halfWinWidth  + _mapPosition.getXFromCentre(_track.getX(i));
+                       int py = halfWinHeight + _mapPosition.getYFromCentre(_track.getY(i));
+                       px = wrapLongitudeValue(px, winWidth, _mapPosition.getZoom());
+                       // Remember these calculated pixel values so they don't have to be recalculated
+                       xPixels[i] = px; yPixels[i] = py;
+
+                       currPointVisible = px >= 0 && px < winWidth && py >= 0 && py < winHeight;
                        isWaypoint = _track.getPoint(i).isWaypoint();
                        anyWaypoints = anyWaypoints || isWaypoint;
                        if (currPointVisible)
                        isWaypoint = _track.getPoint(i).isWaypoint();
                        anyWaypoints = anyWaypoints || isWaypoint;
                        if (currPointVisible)
@@ -600,16 +656,15 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                inG.setColor(textColour);
                FontMetrics fm = inG.getFontMetrics();
                int nameHeight = fm.getHeight();
                inG.setColor(textColour);
                FontMetrics fm = inG.getFontMetrics();
                int nameHeight = fm.getHeight();
-               int width = getWidth();
-               int height = getHeight();
-               if (anyWaypoints) {
+               if (anyWaypoints)
+               {
                        for (int i=0; i<_track.getNumPoints(); i++)
                        {
                                if (_track.getPoint(i).isWaypoint())
                                {
                        for (int i=0; i<_track.getNumPoints(); i++)
                        {
                                if (_track.getPoint(i).isWaypoint())
                                {
-                                       int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(i));
-                                       int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(i));
-                                       if (px >= 0 && px < getWidth() && py >= 0 && py < getHeight())
+                                       int px = xPixels[i];
+                                       int py = yPixels[i];
+                                       if (px >= 0 && px < winWidth && py >= 0 && py < winHeight)
                                        {
                                                inG.fillRect(px-3, py-3, 6, 6);
                                                pointsPainted++;
                                        {
                                                inG.fillRect(px-3, py-3, 6, 6);
                                                pointsPainted++;
@@ -621,9 +676,9 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        {
                                if (_track.getPoint(i).isWaypoint())
                                {
                        {
                                if (_track.getPoint(i).isWaypoint())
                                {
-                                       int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(i));
-                                       int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(i));
-                                       if (px >= 0 && px < getWidth() && py >= 0 && py < getHeight())
+                                       int px = xPixels[i];
+                                       int py = yPixels[i];
+                                       if (px >= 0 && px < winWidth && py >= 0 && py < winHeight)
                                        {
                                                // Figure out where to draw waypoint name so it doesn't obscure track
                                                String waypointName = _track.getPoint(i).getWaypointName();
                                        {
                                                // Figure out where to draw waypoint name so it doesn't obscure track
                                                String waypointName = _track.getPoint(i).getWaypointName();
@@ -640,8 +695,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                                        // Check each direction in turn right left up down
                                                        for (int a=0; a<4; a++)
                                                        {
                                                        // Check each direction in turn right left up down
                                                        for (int a=0; a<4; a++)
                                                        {
-                                                               if (nameXs[a] > 0 && (nameXs[a] + nameWidth) < width
-                                                                       && nameYs[a] < height && (nameYs[a] - nameHeight) > 0
+                                                               if (nameXs[a] > 0 && (nameXs[a] + nameWidth) < winWidth
+                                                                       && nameYs[a] < winHeight && (nameYs[a] - nameHeight) > 0
                                                                        && !overlapsPoints(nameXs[a], nameYs[a], nameWidth, nameHeight, textColour))
                                                                {
                                                                        // Found a rectangle to fit - draw name here and quit
                                                                        && !overlapsPoints(nameXs[a], nameYs[a], nameWidth, nameHeight, textColour))
                                                                {
                                                                        // Found a rectangle to fit - draw name here and quit
@@ -661,9 +716,9 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                {
                        if (_track.getPoint(i).hasMedia())
                        {
                {
                        if (_track.getPoint(i).hasMedia())
                        {
-                               int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(i));
-                               int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(i));
-                               if (px >= 0 && px < getWidth() && py >= 0 && py < getHeight())
+                               int px = xPixels[i];
+                               int py = yPixels[i];
+                               if (px >= 0 && px < winWidth && py >= 0 && py < winHeight)
                                {
                                        inG.drawRect(px-1, py-1, 2, 2);
                                        inG.drawRect(px-2, py-2, 4, 4);
                                {
                                        inG.drawRect(px-1, py-1, 2, 2);
                                        inG.drawRect(px-2, py-2, 4, 4);
@@ -678,30 +733,85 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        inG.setColor(rangeColour);
                        for (int i=_selection.getStart(); i<=_selection.getEnd(); i++)
                        {
                        inG.setColor(rangeColour);
                        for (int i=_selection.getStart(); i<=_selection.getEnd(); i++)
                        {
-                               int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(i));
-                               int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(i));
+                               int px = xPixels[i];
+                               int py = yPixels[i];
                                inG.drawRect(px-1, py-1, 2, 2);
                        }
                }
 
                                inG.drawRect(px-1, py-1, 2, 2);
                        }
                }
 
-               // Draw selected point, crosshairs
+               // Draw crosshairs at selected point
                int selectedPoint = _selection.getCurrentPointIndex();
                if (selectedPoint >= 0)
                {
                int selectedPoint = _selection.getCurrentPointIndex();
                if (selectedPoint >= 0)
                {
-                       int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(selectedPoint));
-                       int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(selectedPoint));
+                       int px = xPixels[selectedPoint];
+                       int py = yPixels[selectedPoint];
                        inG.setColor(currentColour);
                        // crosshairs
                        inG.setColor(currentColour);
                        // crosshairs
-                       inG.drawLine(px, 0, px, getHeight());
-                       inG.drawLine(0, py, getWidth(), py);
-                       // oval
-                       inG.drawOval(px - 2, py - 2, 4, 4);
-                       inG.drawOval(px - 3, py - 3, 6, 6);
+                       inG.drawLine(px, 0, px, winHeight);
+                       inG.drawLine(0, py, winWidth, py);
                }
                // Return the number of points painted
                return pointsPainted;
        }
 
                }
                // Return the number of points painted
                return pointsPainted;
        }
 
+       /**
+        * Wrap the given pixel value if appropriate and possible
+        * @param inPx Pixel x coordinate
+        * @param inWinWidth window width in pixels
+        * @param inZoom zoom level
+        * @return modified pixel x coordinate
+        */
+       private static int wrapLongitudeValue(int inPx, int inWinWidth, int inZoom)
+       {
+               if (inPx > inWinWidth)
+               {
+                       // Pixel is too far right, could we wrap it back onto the screen?
+                       int px = inPx;
+                       while (px > inWinWidth) {
+                               px -= (256 << inZoom);
+                       }
+                       if (px >= 0) {
+                               return px; // successfully wrapped back onto the screen
+                       }
+               }
+               else if (inPx < 0)
+               {
+                       // Pixel is too far left, could we wrap it back onto the screen?
+                       int px = inPx;
+                       while (px < 0) {
+                               px += (256 << inZoom);
+                       }
+                       if (px < inWinWidth) {
+                               return px; // successfully wrapped back onto the screen
+                       }
+               }
+               // Either it's already on the screen or couldn't be wrapped
+               return inPx;
+       }
+
+       /**
+        * Draw the lines while dragging a point
+        * @param inG graphics object
+        * @param inPrevIndex index of point to draw from
+        * @param inNextIndex index of point to draw to
+        */
+       private void drawDragLines(Graphics inG, int inPrevIndex, int inNextIndex)
+       {
+               inG.setColor(Config.getColourScheme().getColour(ColourScheme.IDX_POINT));
+               // line from prev point to cursor
+               if (inPrevIndex > -1 && !_track.getPoint(inPrevIndex+1).getSegmentStart())
+               {
+                       final int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(inPrevIndex));
+                       final int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(inPrevIndex));
+                       inG.drawLine(px, py, _dragToX, _dragToY);
+               }
+               if (inNextIndex < _track.getNumPoints() && !_track.getPoint(inNextIndex).getSegmentStart())
+               {
+                       final int px = getWidth() / 2 + _mapPosition.getXFromCentre(_track.getX(inNextIndex));
+                       final int py = getHeight() / 2 + _mapPosition.getYFromCentre(_track.getY(inNextIndex));
+                       inG.drawLine(px, py, _dragToX, _dragToY);
+               }
+       }
 
        /**
         * Tests whether there are any dark pixels within the specified x,y rectangle
 
        /**
         * Tests whether there are any dark pixels within the specified x,y rectangle
@@ -827,6 +937,48 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        new Longitude(lon, Coordinate.FORMAT_NONE), null);
        }
 
                        new Longitude(lon, Coordinate.FORMAT_NONE), null);
        }
 
+       /**
+        * Move a DataPoint object to the given mouse coordinates
+        * @param startX start x coordinate of mouse
+        * @param startY start y coordinate of mouse
+        * @param endX end x coordinate of mouse
+        * @param endY end y coordinate of mouse
+        */
+       private void movePointToMouse(int startX, int startY, int endX, int endY )
+       {
+               double lat1 = MapUtils.getLatitudeFromY(_mapPosition.getYFromPixels(startY, getHeight()));
+               double lon1 = MapUtils.getLongitudeFromX(_mapPosition.getXFromPixels(startX, getWidth()));
+               double lat_delta = MapUtils.getLatitudeFromY(_mapPosition.getYFromPixels(endY, getHeight())) - lat1;
+               double lon_delta = MapUtils.getLongitudeFromX(_mapPosition.getXFromPixels(endX, getWidth())) - lon1;
+
+               DataPoint point = _trackInfo.getCurrentPoint();
+               if (point == null) {
+                       return;
+               }
+
+               // Make lists for edit and undo, and add each changed field in turn
+               FieldEditList editList = new FieldEditList();
+               FieldEditList undoList = new FieldEditList();
+
+               // Check field list
+               FieldList fieldList = _track.getFieldList();
+               int numFields = fieldList.getNumFields();
+               for (int i=0; i<numFields; i++)
+               {
+                       Field field = fieldList.getField(i);
+                       if (field == Field.LATITUDE) {
+                               editList.addEdit(new FieldEdit(field, Double.toString(point.getLatitude().getDouble() + lat_delta)));
+                               undoList.addEdit(new FieldEdit(field, point.getFieldValue(Field.LATITUDE)));
+                       }
+                       else if (field == Field.LONGITUDE) {
+                               editList.addEdit(new FieldEdit(field, Double.toString(point.getLongitude().getDouble() + lon_delta)));
+                               undoList.addEdit(new FieldEdit(field, point.getFieldValue(Field.LONGITUDE)));
+                       }
+               }
+               _app.completePointEdit(editList, undoList);
+       }
+
+
        /**
         * @see javax.swing.JComponent#getMinimumSize()
         */
        /**
         * @see javax.swing.JComponent#getMinimumSize()
         */
@@ -861,10 +1013,15 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                        // single click
                                        if (_drawMode == MODE_DEFAULT)
                                        {
                                        // single click
                                        if (_drawMode == MODE_DEFAULT)
                                        {
-                                               int pointIndex = _track.getNearestPointIndex(
+                                               int pointIndex = _clickedPoint;
+                                               if (pointIndex == INDEX_UNKNOWN)
+                                               {
+                                                       // index hasn't been calculated yet
+                                                       pointIndex = _track.getNearestPointIndex(
                                                         _mapPosition.getXFromPixels(inE.getX(), getWidth()),
                                                         _mapPosition.getYFromPixels(inE.getY(), getHeight()),
                                                         _mapPosition.getBoundsFromPixels(CLICK_SENSITIVITY), false);
                                                         _mapPosition.getXFromPixels(inE.getX(), getWidth()),
                                                         _mapPosition.getYFromPixels(inE.getY(), getHeight()),
                                                         _mapPosition.getBoundsFromPixels(CLICK_SENSITIVITY), false);
+                                               }
                                                // Extend selection for shift-click
                                                if (inE.isShiftDown()) {
                                                        _trackInfo.extendSelection(pointIndex);
                                                // Extend selection for shift-click
                                                if (inE.isShiftDown()) {
                                                        _trackInfo.extendSelection(pointIndex);
@@ -907,6 +1064,9 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                _popup.show(this, _popupMenuX, _popupMenuY);
                        }
                }
                                _popup.show(this, _popupMenuX, _popupMenuY);
                        }
                }
+               // Reset app mode
+               _app.setCurrentMode(App.AppMode.NORMAL);
+               if (_drawMode == MODE_MARK_RECTANGLE) _drawMode = MODE_DEFAULT;
        }
 
        /**
        }
 
        /**
@@ -928,12 +1088,55 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        }
 
        /**
        }
 
        /**
-        * Ignore mouse pressed events
+        * React to mouse pressed events to initiate a point drag
         * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
         */
        public void mousePressed(MouseEvent inE)
        {
         * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
         */
        public void mousePressed(MouseEvent inE)
        {
-               // ignore
+               _clickedPoint = INDEX_UNKNOWN;
+               if (_track == null || _track.getNumPoints() <= 0)
+                       return;
+               if (!inE.isMetaDown())
+               {
+                       // Left mouse drag - check if point is near; if so select it for dragging
+                       if (_drawMode == MODE_DEFAULT)
+                       {
+                               /* Drag points if edit mode is enabled OR ALT is pressed */
+                               if (_editmodeCheckBox.isSelected() || inE.isAltDown() || inE.isAltGraphDown())
+                               {
+                                       final double clickX = _mapPosition.getXFromPixels(inE.getX(), getWidth());
+                                       final double clickY = _mapPosition.getYFromPixels(inE.getY(), getHeight());
+                                       final double clickSens = _mapPosition.getBoundsFromPixels(CLICK_SENSITIVITY);
+                                       _clickedPoint = _track.getNearestPointIndex(clickX, clickY, clickSens, false);
+
+                                       if (_clickedPoint >= 0)
+                                       {
+                                               // TODO: maybe use another color of the cross or remove the cross while dragging???
+
+                                               _trackInfo.selectPoint(_clickedPoint);
+                                               if (_trackInfo.getCurrentPoint() != null)
+                                               {
+                                                       _drawMode = MODE_DRAG_POINT;
+                                                       _dragFromX = _dragToX = inE.getX();
+                                                       _dragFromY = _dragToY = inE.getY();
+                                               }
+                                       }
+                                       else
+                                       {
+                                               // Not a click on a point, so check half-way between two (connected) trackpoints
+                                               int midpointIndex = _midpoints.getNearestPointIndex(clickX, clickY, clickSens);
+                                               if (midpointIndex > 0)
+                                               {
+                                                       _drawMode = MODE_CREATE_MIDPOINT;
+                                                       _clickedPoint = midpointIndex;
+                                                       _dragFromX = _dragToX = inE.getX();
+                                                       _dragFromY = _dragToY = inE.getY();
+                                               }
+                                       }
+                               }
+                       }
+               }
+               // else right-press ignored
        }
 
        /**
        }
 
        /**
@@ -943,13 +1146,48 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        public void mouseReleased(MouseEvent inE)
        {
                _recalculate = true;
        public void mouseReleased(MouseEvent inE)
        {
                _recalculate = true;
-               if (_drawMode == MODE_ZOOM_RECT && Math.abs(_dragToX - _dragFromX) > 20
-                       && Math.abs(_dragToY - _dragFromY) > 20)
+
+               if (_drawMode == MODE_DRAG_POINT)
+               {
+                       if (Math.abs(_dragToX - _dragFromX) > 2
+                               || Math.abs(_dragToY - _dragFromY) > 2)
+                       {
+                               movePointToMouse(_dragFromX, _dragFromY, _dragToX, _dragToY );
+                       }
+                       _drawMode = MODE_DEFAULT;
+               }
+               else if (_drawMode == MODE_CREATE_MIDPOINT)
+               {
+                       _drawMode = MODE_DEFAULT;
+                       _app.createPoint(createPointFromClick(_dragToX, _dragToY), _clickedPoint);
+               }
+               else if (_drawMode == MODE_ZOOM_RECT)
                {
                {
-                       _mapPosition.zoomToPixels(_dragFromX, _dragToX, _dragFromY, _dragToY, getWidth(), getHeight());
+                       if (Math.abs(_dragToX - _dragFromX) > 20
+                        && Math.abs(_dragToY - _dragFromY) > 20)
+                       {
+                               _mapPosition.zoomToPixels(_dragFromX, _dragToX, _dragFromY, _dragToY, getWidth(), getHeight());
+                       }
+                       _drawMode = MODE_DEFAULT;
                }
                }
-               if (_drawMode == MODE_ZOOM_RECT) {
+               else if (_drawMode == MODE_MARK_RECTANGLE)
+               {
+                       // Reset app mode
+                       _app.setCurrentMode(App.AppMode.NORMAL);
                        _drawMode = MODE_DEFAULT;
                        _drawMode = MODE_DEFAULT;
+                       // Call a function to mark the points
+                       MarkPointsInRectangleFunction marker = new MarkPointsInRectangleFunction(_app);
+                       double lon1 = MapUtils.getLongitudeFromX(_mapPosition.getXFromPixels(_dragFromX, getWidth()));
+                       double lat1 = MapUtils.getLatitudeFromY(_mapPosition.getYFromPixels(_dragFromY, getHeight()));
+                       double lon2 = MapUtils.getLongitudeFromX(_mapPosition.getXFromPixels(_dragToX, getWidth()));
+                       double lat2 = MapUtils.getLatitudeFromY(_mapPosition.getYFromPixels(_dragToY, getHeight()));
+                       // Invalidate rectangle if pixel coords are (-1,-1)
+                       if (_dragFromX < 0 || _dragFromY < 0) {
+                               lon1 = lon2;
+                               lat1 = lat2;
+                       }
+                       marker.setRectCoords(lon1, lat1, lon2, lat2);
+                       marker.begin();
                }
                _dragFromX = _dragFromY = -1;
                repaint();
                }
                _dragFromX = _dragFromY = -1;
                repaint();
@@ -963,19 +1201,40 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        {
                if (!inE.isMetaDown())
                {
        {
                if (!inE.isMetaDown())
                {
-                       // Left mouse drag - pan map by appropriate amount
-                       if (_dragFromX != -1)
+                       // Left mouse drag - either drag the point or pan the map
+                       if (_drawMode == MODE_DRAG_POINT || _drawMode == MODE_CREATE_MIDPOINT)
                        {
                        {
-                               panMap(_dragFromX - inE.getX(), _dragFromY - inE.getY());
+                               // move point
+                               _dragToX = inE.getX();
+                               _dragToY = inE.getY();
                                _recalculate = true;
                                repaint();
                        }
                                _recalculate = true;
                                repaint();
                        }
-                       _dragFromX = _dragToX = inE.getX();
-                       _dragFromY = _dragToY = inE.getY();
+                       else if (_drawMode == MODE_MARK_RECTANGLE)
+                       {
+                               // draw a rectangle for marking points
+                               if (_dragFromX == -1) {
+                                       _dragFromX = inE.getX();
+                                       _dragFromY = inE.getY();
+                               }
+                               _dragToX = inE.getX();
+                               _dragToY = inE.getY();
+                               repaint();
+                       }
+                       else
+                       {
+                               // regular left-drag pans map by appropriate amount
+                               if (_dragFromX != -1)
+                               {
+                                       panMap(_dragFromX - inE.getX(), _dragFromY - inE.getY());
+                               }
+                               _dragFromX = _dragToX = inE.getX();
+                               _dragFromY = _dragToY = inE.getY();
+                       }
                }
                else
                {
                }
                else
                {
-                       // Right-click and drag - draw rectangle and control zoom
+                       // Right-click and drag - update rectangle
                        _drawMode = MODE_ZOOM_RECT;
                        if (_dragFromX == -1) {
                                _dragFromX = inE.getX();
                        _drawMode = MODE_ZOOM_RECT;
                        if (_dragFromX == -1) {
                                _dragFromX = inE.getX();
@@ -993,6 +1252,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
         */
        public void mouseMoved(MouseEvent inEvent)
        {
         */
        public void mouseMoved(MouseEvent inEvent)
        {
+               boolean useCrosshairs = false;
+               boolean useResize     = false;
                // Ignore unless we're drawing points
                if (_drawMode == MODE_DRAW_POINTS_CONT)
                {
                // Ignore unless we're drawing points
                if (_drawMode == MODE_DRAW_POINTS_CONT)
                {
@@ -1000,6 +1261,29 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        _dragToY = inEvent.getY();
                        repaint();
                }
                        _dragToY = inEvent.getY();
                        repaint();
                }
+               else if (_drawMode == MODE_MARK_RECTANGLE) {
+                       useResize = true;
+               }
+               else if (_editmodeCheckBox.isSelected() || inEvent.isAltDown() || inEvent.isAltGraphDown())
+               {
+                       // Try to find a point or a midpoint at this location, and if there is one
+                       // then change the cursor to crosshairs
+                       final double clickX = _mapPosition.getXFromPixels(inEvent.getX(), getWidth());
+                       final double clickY = _mapPosition.getYFromPixels(inEvent.getY(), getHeight());
+                       final double clickSens = _mapPosition.getBoundsFromPixels(CLICK_SENSITIVITY);
+                       useCrosshairs = (_track.getNearestPointIndex(clickX, clickY, clickSens, false) >= 0
+                               || _midpoints.getNearestPointIndex(clickX, clickY, clickSens) >= 0
+                       );
+               }
+               if (useCrosshairs && !isCursorSet()) {
+                       setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
+               }
+               else if (useResize && !isCursorSet()) {
+                       setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
+               }
+               else if (!useCrosshairs && !useResize && isCursorSet()) {
+                       setCursor(null);
+               }
        }
 
        /**
        }
 
        /**
@@ -1024,6 +1308,17 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                if ((inUpdateType & DataSubscriber.MAPSERVER_CHANGED) > 0) {
                        _tileManager.resetConfig();
                }
                if ((inUpdateType & DataSubscriber.MAPSERVER_CHANGED) > 0) {
                        _tileManager.resetConfig();
                }
+               if ((inUpdateType & (DataSubscriber.DATA_ADDED_OR_REMOVED + DataSubscriber.DATA_EDITED)) > 0) {
+                       _midpoints.updateData(_track);
+               }
+               // See if rect mode has been activated
+               if (_app.getCurrentMode() == App.AppMode.DRAWRECT)
+               {
+                       _drawMode = MODE_MARK_RECTANGLE;
+                       if (!isCursorSet()) {
+                               setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
+                       }
+               }
                repaint();
                // enable or disable components
                boolean hasData = _track.getNumPoints() > 0;
                repaint();
                // enable or disable components
                boolean hasData = _track.getNumPoints() > 0;
index d035f10bb3f8bd74ddff6959e13e2a20bfdd1c36..25f05fc1a2a238370d8888ea4b807b7d3f5f8adb 100644 (file)
@@ -9,9 +9,9 @@ public class MapPosition
        private static final int MAP_TILE_SIZE = 256;
 
        /** x position (scale depends on zoom) */
        private static final int MAP_TILE_SIZE = 256;
 
        /** x position (scale depends on zoom) */
-       private long _xPosition = 0L;
+       private int _xPosition = 0;
        /** y position (scale depends on zoom) */
        /** y position (scale depends on zoom) */
-       private long _yPosition = 0L;
+       private int _yPosition = 0;
 
        /** Zoom level, from 2 to max */
        private int _zoom = 12;
 
        /** Zoom level, from 2 to max */
        private int _zoom = 12;
@@ -48,12 +48,21 @@ public class MapPosition
                }
                if (requiredZoom < 2) requiredZoom = 2;
                // Set position
                }
                if (requiredZoom < 2) requiredZoom = 2;
                // Set position
-               _zoom = requiredZoom;
-               _zoomFactor = 1 << _zoom;
+               setZoom(requiredZoom);
                _xPosition = transformToPixels((inMinX + inMaxX) / 2.0);
                _yPosition = transformToPixels((inMinY + inMaxY) / 2.0);
        }
 
                _xPosition = transformToPixels((inMinX + inMaxX) / 2.0);
                _yPosition = transformToPixels((inMinY + inMaxY) / 2.0);
        }
 
+       /**
+        * Ensure that zoom and zoomFactor remain in sync
+        * @param inZoom zoom level to set
+        */
+       private void setZoom(int inZoom)
+       {
+               _zoom = inZoom;
+               _zoomFactor = 1 << _zoom;
+       }
+
        /**
         * Zoom and pan to show the selected area
         * @param inMinX minimum pixels X
        /**
         * Zoom and pan to show the selected area
         * @param inMinX minimum pixels X
@@ -80,8 +89,7 @@ public class MapPosition
                                break;
                        }
                }
                                break;
                        }
                }
-               _zoom = requiredZoom;
-               _zoomFactor = 1 << _zoom;
+               setZoom(requiredZoom);
                // Set position
                _xPosition = (_xPosition - inWidth/2 + (inMinX + inMaxX) / 2) * multFactor;
                _yPosition = (_yPosition - inHeight/2 + (inMinY + inMaxY) / 2) * multFactor;
                // Set position
                _xPosition = (_xPosition - inWidth/2 + (inMinX + inMaxX) / 2) * multFactor;
                _yPosition = (_yPosition - inHeight/2 + (inMinY + inMaxY) / 2) * multFactor;
@@ -92,7 +100,7 @@ public class MapPosition
         * @param inValue value to transform
         * @return pixels
         */
         * @param inValue value to transform
         * @return pixels
         */
-       private long transformToPixels(double inValue)
+       private int transformToPixels(double inValue)
        {
                return transformToPixels(inValue, _zoom);
        }
        {
                return transformToPixels(inValue, _zoom);
        }
@@ -103,9 +111,9 @@ public class MapPosition
         * @param inZoom zoom value to use
         * @return pixels
         */
         * @param inZoom zoom value to use
         * @return pixels
         */
-       private static long transformToPixels(double inValue, int inZoom)
+       private static int transformToPixels(double inValue, int inZoom)
        {
        {
-               return (long) (inValue * MAP_TILE_SIZE * (1 << inZoom));
+               return (int) (inValue * MAP_TILE_SIZE * (1 << inZoom));
        }
 
        /**
        }
 
        /**
@@ -137,7 +145,7 @@ public class MapPosition
         */
        public int getXFromCentre(double inValue)
        {
         */
        public int getXFromCentre(double inValue)
        {
-               return (int) (transformToPixels(inValue) - _xPosition);
+               return transformToPixels(inValue) - _xPosition;
        }
 
        /**
        }
 
        /**
@@ -147,7 +155,7 @@ public class MapPosition
         */
        public int getYFromCentre(double inValue)
        {
         */
        public int getYFromCentre(double inValue)
        {
-               return (int) (transformToPixels(inValue) - _yPosition);
+               return transformToPixels(inValue) - _yPosition;
        }
 
        /**
        }
 
        /**
@@ -209,19 +217,19 @@ public class MapPosition
         * @param inPosition position of point
         * @return tile index for that point
         */
         * @param inPosition position of point
         * @return tile index for that point
         */
-       private int getTileIndex(long inPosition)
+       private int getTileIndex(int inPosition)
        {
        {
-               return (int) (inPosition / MAP_TILE_SIZE);
+               return inPosition / MAP_TILE_SIZE;
        }
 
        /**
         * @param inPosition position of point
         * @return pixel offset for that point
         */
        }
 
        /**
         * @param inPosition position of point
         * @return pixel offset for that point
         */
-       private int getDisplayOffset(long inPosition)
+       private int getDisplayOffset(int inPosition)
        {
        {
-               return (int) (inPosition % MAP_TILE_SIZE);
-               // Maybe >> 8 would be slightly faster?
+               return inPosition % MAP_TILE_SIZE;
+               // I thought that &255 would be slightly faster, but it gives the wrong result
        }
 
        /**
        }
 
        /**
@@ -231,8 +239,7 @@ public class MapPosition
        {
                if (_zoom < MAX_ZOOM)
                {
        {
                if (_zoom < MAX_ZOOM)
                {
-                       _zoom++;
-                       _zoomFactor = 1 << _zoom;
+                       setZoom(_zoom + 1);
                        _xPosition *= 2;
                        _yPosition *= 2;
                }
                        _xPosition *= 2;
                        _yPosition *= 2;
                }
@@ -243,10 +250,9 @@ public class MapPosition
         */
        public void zoomOut()
        {
         */
        public void zoomOut()
        {
-               if (_zoom >= 2)
+               if (_zoom >= 3)
                {
                {
-                       _zoom--;
-                       _zoomFactor = 1 << _zoom;
+                       setZoom(_zoom - 1);
                        _xPosition /= 2;
                        _yPosition /= 2;
                }
                        _xPosition /= 2;
                        _yPosition /= 2;
                }
index e3ac2ed2227a1825d01526c87800c3abdd9819d4..d838ef34d99d47a7f7fe524b8a63e87cf98609b6 100644 (file)
@@ -2,6 +2,8 @@ package tim.prune.gui.map;
 
 import java.net.MalformedURLException;
 import java.net.URL;
 
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Class to represent any map source, whether an OsmMapSource
 
 /**
  * Class to represent any map source, whether an OsmMapSource
@@ -14,6 +16,9 @@ public abstract class MapSource
        /** File extensions */
        protected String[] _extensions = null;
 
        /** File extensions */
        protected String[] _extensions = null;
 
+       /** Regular expression for catching server wildcards */
+       protected static final Pattern WILD_PATTERN = Pattern.compile("^(.*)\\[(.*)\\](.*)$");
+
 
        /**
         * @return the number of layers used in this source
 
        /**
         * @return the number of layers used in this source
@@ -81,9 +86,10 @@ public abstract class MapSource
                String urlstr = inUrl;
                // check prefix
                try {
                String urlstr = inUrl;
                // check prefix
                try {
-                       new URL(urlstr);
+                       new URL(urlstr.replace('[', 'w').replace(']', 'w'));
                }
                }
-               catch (MalformedURLException e) {
+               catch (MalformedURLException e)
+               {
                        // fail if protocol specified
                        if (urlstr.indexOf("://") >= 0) {return null;}
                        // add the http protocol
                        // fail if protocol specified
                        if (urlstr.indexOf("://") >= 0) {return null;}
                        // add the http protocol
@@ -95,7 +101,7 @@ public abstract class MapSource
                }
                // Validate current url, return null if not ok
                try {
                }
                // Validate current url, return null if not ok
                try {
-                       URL url = new URL(urlstr);
+                       URL url = new URL(urlstr.replace('[', 'w').replace(']', 'w'));
                        // url host must contain a dot
                        if (url.getHost().indexOf('.') < 0) {return null;}
                }
                        // url host must contain a dot
                        if (url.getHost().indexOf('.') < 0) {return null;}
                }
@@ -118,6 +124,17 @@ public abstract class MapSource
                int idx = url.indexOf("://");
                if (idx >= 0) {url = url.substring(idx + 3);}
                if (url.startsWith("www.")) {url = url.substring(4);}
                int idx = url.indexOf("://");
                if (idx >= 0) {url = url.substring(idx + 3);}
                if (url.startsWith("www.")) {url = url.substring(4);}
+               // Strip out any "[.*]" as well
+               if (url.indexOf('[') >= 0)
+               {
+                       Matcher matcher = WILD_PATTERN.matcher(url);
+                       if (matcher.matches()) {
+                               url = matcher.group(1) + matcher.group(3);
+                               if (url.length() > 1 && url.charAt(0) == '.') {
+                                       url = url.substring(1);
+                               }
+                       }
+               }
                return url;
        }
 
                return url;
        }
 
index eae105515fe7960c1024badaed908fea8777a970..425df6a6cd72b1c1cebe5d417c4469339939a08e 100644 (file)
@@ -38,8 +38,8 @@ public abstract class MapSourceLibrary
         */
        private static void addFixedSources()
        {
         */
        private static void addFixedSources()
        {
-               _sourceList.add(new OsmMapSource("Mapnik", "http://tile.openstreetmap.org/"));
-               _sourceList.add(new OsmMapSource("Cyclemap", "http://tile.opencyclemap.org/cycle/"));
+               _sourceList.add(new OsmMapSource("Mapnik", "http://[abc].tile.openstreetmap.org/"));
+               _sourceList.add(new OsmMapSource("Cyclemap", "http://[abc].tile.opencyclemap.org/cycle/"));
                _sourceList.add(new OsmMapSource("Reitkarte", "http://wanderreitkarte.de/hills/",
                        "http://topo2.wanderreitkarte.de/topo/", 18));
                _sourceList.add(new MffMapSource("Mapsforfree", "http://maps-for-free.com/layer/relief/", "jpg",
                _sourceList.add(new OsmMapSource("Reitkarte", "http://wanderreitkarte.de/hills/",
                        "http://topo2.wanderreitkarte.de/topo/", 18));
                _sourceList.add(new MffMapSource("Mapsforfree", "http://maps-for-free.com/layer/relief/", "jpg",
index 829f824ffa09d06f6e37e2d3bd64e5bd7121725c..75f170a20f57df5ec5e84d3a2afa904a66d247e1 100644 (file)
@@ -1,7 +1,6 @@
 package tim.prune.gui.map;
 
 import java.awt.Image;
 package tim.prune.gui.map;
 
 import java.awt.Image;
-import java.awt.Toolkit;
 import java.awt.image.ImageObserver;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.awt.image.ImageObserver;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -24,8 +23,6 @@ public class MapTileManager implements ImageObserver
        private int _numLayers = -1;
        /** Current zoom level */
        private int _zoom = 0;
        private int _numLayers = -1;
        /** Current zoom level */
        private int _zoom = 0;
-       /** Currently blocked zoom level, to prevent looping for non-existent images */
-       private int _blockedZoom = 0;
        /** Number of tiles in each direction for this zoom level */
        private int _numTileIndices = 1;
 
        /** Number of tiles in each direction for this zoom level */
        private int _numTileIndices = 1;
 
@@ -141,8 +138,9 @@ public class MapTileManager implements ImageObserver
         */
        public Image getTile(int inLayer, int inX, int inY)
        {
         */
        public Image getTile(int inLayer, int inX, int inY)
        {
-               // Check tile boundaries
-               if (inX < 0 || inX >= _numTileIndices || inY < 0 || inY >= _numTileIndices) return null;
+               if (inY < 0 || inY >= _numTileIndices) return null;
+               // Wrap tile indices which are too big or too small
+               inX = ((inX % _numTileIndices) + _numTileIndices) % _numTileIndices;
 
                // Check first in memory cache for tile
                MemTileCacher tempCache = _tempCaches[inLayer]; // Should probably guard against nulls and array indexes here
 
                // Check first in memory cache for tile
                MemTileCacher tempCache = _tempCaches[inLayer]; // Should probably guard against nulls and array indexes here
@@ -161,15 +159,14 @@ public class MapTileManager implements ImageObserver
                        if (tile != null)
                        {
                                // Pass tile to memory cache
                        if (tile != null)
                        {
                                // Pass tile to memory cache
-                               tempCache.setTile(tile, inX, inY);
+                               tempCache.setTile(tile, inX, inY, _zoom);
                                if (tile.getWidth(this) > 0) {return tile;}
                                return null;
                        }
                }
                // Tile wasn't in memory or on disk, so if online let's get it
                                if (tile.getWidth(this) > 0) {return tile;}
                                return null;
                        }
                }
                // Tile wasn't in memory or on disk, so if online let's get it
-               if (onlineMode && _blockedZoom != _zoom)
+               if (onlineMode)
                {
                {
-                       _blockedZoom = 0; // reset to try again
                        try
                        {
                                URL tileUrl = new URL(_mapSource.makeURL(inLayer, _zoom, inX, inY));
                        try
                        {
                                URL tileUrl = new URL(_mapSource.makeURL(inLayer, _zoom, inX, inY));
@@ -181,10 +178,9 @@ public class MapTileManager implements ImageObserver
                                else
                                {
                                        // Load image asynchronously, using observer
                                else
                                {
                                        // Load image asynchronously, using observer
-                                       tile = Toolkit.getDefaultToolkit().createImage(tileUrl);
-                                       // Pass to memory cache
-                                       _tempCaches[inLayer].setTile(tile, inX, inY);
-                                       if (tile.getWidth(this) > 0) {return tile;}
+                                       // tile = Toolkit.getDefaultToolkit().createImage(tileUrl);
+                                       // In order to set the http user agent, need to use a TileDownloader instead
+                                       TileDownloader.triggerLoad(this, tileUrl, inLayer, inX, inY, _zoom);
                                }
                        }
                        catch (MalformedURLException urle) {} // ignore
                                }
                        }
                        catch (MalformedURLException urle) {} // ignore
@@ -206,12 +202,31 @@ public class MapTileManager implements ImageObserver
        {
                boolean loaded = (infoflags & ImageObserver.ALLBITS) > 0;
                boolean error = (infoflags & ImageObserver.ERROR) > 0;
        {
                boolean loaded = (infoflags & ImageObserver.ALLBITS) > 0;
                boolean error = (infoflags & ImageObserver.ERROR) > 0;
-               if (error) {
-                       _blockedZoom = _zoom;
-               }
                if (loaded || error) {
                        _parent.tilesUpdated(loaded);
                }
                return !loaded;
        }
                if (loaded || error) {
                        _parent.tilesUpdated(loaded);
                }
                return !loaded;
        }
+
+       /**
+        * Callback method from TileDownloader to let us know that an image has been loaded
+        * @param inTile Loaded Image object
+        * @param inLayer layer index from 0
+        * @param inX x coordinate of tile
+        * @param inY y coordinate of tile
+        * @param inZoom zoom level of loaded image
+        */
+       public void notifyImageLoaded(Image inTile, int inLayer, int inX, int inY, int inZoom)
+       {
+               if (inTile != null)
+               {
+                       MemTileCacher tempCache = _tempCaches[inLayer]; // Should probably guard against nulls and array indexes here
+                       if (tempCache.getTile(inX, inY) == null)
+                       {
+                               // Check with cache that the zoom level is still valid
+                               tempCache.setTile(inTile, inX, inY, inZoom);
+                               inTile.getWidth(this); // trigger imageUpdate when image is ready
+                       }
+               }
+       }
 }
 }
index 0c6cd1cb2ee5818e96444b944732772ad7fdeafd..78206a3956959f6126ed1568a29893a61ce76e36 100644 (file)
@@ -27,12 +27,16 @@ public abstract class MapUtils
 
        /**
         * Transform an x coordinate into a longitude
 
        /**
         * Transform an x coordinate into a longitude
-        * @param inX scaled X value from 0 to 1
+        * @param inX scaled X value from 0(-180deg) to 1(+180deg)
         * @return longitude in degrees
         */
        public static double getLongitudeFromX(double inX)
        {
         * @return longitude in degrees
         */
        public static double getLongitudeFromX(double inX)
        {
-               return inX * 360.0 - 180.0;
+               // Ensure x is really between 0 and 1 (to wrap longitudes)
+               double x = ((inX % 1.0) + 1.0) % 1.0;
+               // Note: First %1.0 restricts range to (-1,1), then +1.0 shifts to (0,2)
+               // Finally, %1.0 to give (0,1)
+               return x * 360.0 - 180.0;
        }
 
        /**
        }
 
        /**
index 69b5f831b19f3ad65a7a97c2f9a96e51d3f5756e..20d7a213a1a0c1b76001272f862739cec19f5051 100644 (file)
@@ -47,8 +47,8 @@ public class MemTileCacher
                // Mark boundaries as invalid
                for (int i=0; i<GRID_SIZE; i++)
                {
                // Mark boundaries as invalid
                for (int i=0; i<GRID_SIZE; i++)
                {
-                       _tiles[getArrayIndex(_tileX + GRID_SIZE/2 + 1, _tileY + i - GRID_SIZE/2)] = null;
-                       _tiles[getArrayIndex(_tileX + i - GRID_SIZE/2, _tileY + GRID_SIZE/2 + 1)] = null;
+                       _tiles[getArrayIndexNoWrap(_tileX + GRID_SIZE/2 + 1, _tileY + i - GRID_SIZE/2)] = null;
+                       _tiles[getArrayIndexNoWrap(_tileX + i - GRID_SIZE/2, _tileY + GRID_SIZE/2 + 1)] = null;
                }
        }
 
                }
        }
 
@@ -66,18 +66,34 @@ public class MemTileCacher
        }
 
        /**
        }
 
        /**
-        * Get the array index for the given coordinates
+        * Get the array index for the given coordinates, including regular lon wrapping
         * @param inX x coord of tile
         * @param inY y coord of tile
         * @return array index
         */
        private int getArrayIndex(int inX, int inY)
        {
         * @param inX x coord of tile
         * @param inY y coord of tile
         * @return array index
         */
        private int getArrayIndex(int inX, int inY)
        {
-               //System.out.println("Getting array index for (" + inX + ", " + inY + ") where the centre is at ("  + _tileX + ", " + _tileY
-               //      + ") and grid coords (" + _gridCentreX + ", " + _gridCentreY + ")");
+               final int tileSpan = 1 << _zoom;
+               int deltaX = (inX - _tileX);
+               while (deltaX > (tileSpan/2))  {deltaX -= tileSpan;}
+               while (deltaX < (-tileSpan/2)) {deltaX += tileSpan;}
+
+               int x = getCacheCoordinate(deltaX + _gridCentreX);
+               int y = getCacheCoordinate(inY - _tileY + _gridCentreY);
+               return (x + y * GRID_SIZE);
+       }
+
+       /**
+        * Get the array index for the given coordinates, without wrapping x coords
+        * (used for deletion to avoid deleting the wrong tile)
+        * @param inX x coord of tile
+        * @param inY y coord of tile
+        * @return array index
+        */
+       private int getArrayIndexNoWrap(int inX, int inY)
+       {
                int x = getCacheCoordinate(inX - _tileX + _gridCentreX);
                int y = getCacheCoordinate(inY - _tileY + _gridCentreY);
                int x = getCacheCoordinate(inX - _tileX + _gridCentreX);
                int y = getCacheCoordinate(inY - _tileY + _gridCentreY);
-               //System.out.println("Transformed to (" + x + ", " + y + ")");
                return (x + y * GRID_SIZE);
        }
 
                return (x + y * GRID_SIZE);
        }
 
@@ -86,7 +102,6 @@ public class MemTileCacher
         */
        public void clearAll()
        {
         */
        public void clearAll()
        {
-               // Clear all images if zoom changed
                for (int i=0; i<_tiles.length; i++) {
                        _tiles[i] = null;
                }
                for (int i=0; i<_tiles.length; i++) {
                        _tiles[i] = null;
                }
@@ -107,9 +122,13 @@ public class MemTileCacher
         * @param inTile image to save
         * @param inX x coordinate of tile
         * @param inY y coordinate of tile
         * @param inTile image to save
         * @param inX x coordinate of tile
         * @param inY y coordinate of tile
+        * @param inZoom zoom level
         */
         */
-       public void setTile(Image inTile, int inX, int inY)
+       public void setTile(Image inTile, int inX, int inY, int inZoom)
        {
        {
-               _tiles[getArrayIndex(inX, inY)] = inTile;
+               // Ignore images received for a different zoom level
+               if (inZoom == _zoom) {
+                       _tiles[getArrayIndex(inX, inY)] = inTile;
+               }
        }
 }
        }
 }
index 09def4597eb72977357930b9ea492c1c9d198a45..2f8d0ba97980c366ebaf824a515c0912e12f2174 100644 (file)
@@ -1,5 +1,6 @@
 package tim.prune.gui.map;
 
 package tim.prune.gui.map;
 
+import java.util.regex.Matcher;
 import tim.prune.I18nManager;
 
 /**
 import tim.prune.I18nManager;
 
 /**
@@ -145,7 +146,9 @@ public class OsmMapSource extends MapSource
         */
        public String makeURL(int inLayerNum, int inZoom, int inX, int inY)
        {
         */
        public String makeURL(int inLayerNum, int inZoom, int inX, int inY)
        {
-               return _baseUrls[inLayerNum] + inZoom + "/" + inX + "/" + inY + "." + getFileExtension(inLayerNum);
+               // Check if the base url has a [1234], if so replace at random
+               return pickServerUrl(_baseUrls[inLayerNum])
+                       + inZoom + "/" + inX + "/" + inY + "." + getFileExtension(inLayerNum);
        }
 
        /**
        }
 
        /**
@@ -156,6 +159,35 @@ public class OsmMapSource extends MapSource
                return _maxZoom;
        }
 
                return _maxZoom;
        }
 
+       /**
+        * If the base url contains something like [1234], then pick a server
+        * @param inBaseUrl base url
+        * @return modified base url
+        */
+       protected static final String pickServerUrl(String inBaseUrl)
+       {
+               if (inBaseUrl == null || inBaseUrl.indexOf('[') < 0) {
+                       return inBaseUrl;
+               }
+               // Check for [.*] (once only)
+               // Only need to support one, make things a bit easier
+               final Matcher matcher = WILD_PATTERN.matcher(inBaseUrl);
+               // if not, return base url unchanged
+               if (!matcher.matches()) {
+                       return inBaseUrl;
+               }
+               // if so, pick one at random and replace in the String
+               final String match = matcher.group(2);
+               final int numMatches = match.length();
+               String server = null;
+               if (numMatches > 0)
+               {
+                       int matchNum = (int) Math.floor(Math.random() * numMatches);
+                       server = "" + match.charAt(matchNum);
+               }
+               final String result = matcher.group(1) + (server==null?"":server) + matcher.group(3);
+               return result;
+       }
 
        /**
         * @return semicolon-separated list of all fields
 
        /**
         * @return semicolon-separated list of all fields
index 3f3f848ee505f55938b88a7d121d644d705d37b0..37e12b65bfbbdebb76216869232d4f3089ee35f3 100644 (file)
@@ -8,6 +8,7 @@ import javax.swing.JPanel;
 import tim.prune.I18nManager;
 import tim.prune.config.ColourScheme;
 import tim.prune.config.Config;
 import tim.prune.I18nManager;
 import tim.prune.config.ColourScheme;
 import tim.prune.config.Config;
+import tim.prune.data.Unit;
 
 /**
  * Class to show a scale bar on the main map of GpsPrune
 
 /**
  * Class to show a scale bar on the main map of GpsPrune
@@ -59,8 +60,8 @@ public class ScaleBar extends JPanel
                if (_zoomLevel > -1)
                {
                        try {
                if (_zoomLevel > -1)
                {
                        try {
-                               boolean useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
-                               double drightSide = LEFT_OFFSET + _metricPixels[_zoomLevel] * (useMetric?1:1.609);
+                               final double distScaleFactor = Config.getUnitSet().getDistanceUnit().getMultFactorFromStd();
+                               double drightSide = LEFT_OFFSET + _metricPixels[_zoomLevel] / 1000.0 / distScaleFactor;
                                int scale = _scales[_zoomLevel];
 
                                // work out cos(latitude) from y position, and apply to scale
                                int scale = _scales[_zoomLevel];
 
                                // work out cos(latitude) from y position, and apply to scale
@@ -102,7 +103,7 @@ public class ScaleBar extends JPanel
                                inG.drawLine(rightSide, Y_OFFSET+1, rightSide, Y_OFFSET-TICK_HEIGHT);
                                inG.drawLine(rightSide+1, Y_OFFSET+1, rightSide+1, Y_OFFSET-TICK_HEIGHT);
                                // text
                                inG.drawLine(rightSide, Y_OFFSET+1, rightSide, Y_OFFSET-TICK_HEIGHT);
                                inG.drawLine(rightSide+1, Y_OFFSET+1, rightSide+1, Y_OFFSET-TICK_HEIGHT);
                                // text
-                               String text = getScaleText(scale, useMetric);
+                               String text = getScaleText(scale, Config.getUnitSet().getDistanceUnit());
                                inG.setColor(blankColour);
                                inG.drawString(text, rightSide+MARGIN_WIDTH-1, Y_OFFSET);
                                inG.drawString(text, rightSide+MARGIN_WIDTH+1, Y_OFFSET);
                                inG.setColor(blankColour);
                                inG.drawString(text, rightSide+MARGIN_WIDTH-1, Y_OFFSET);
                                inG.drawString(text, rightSide+MARGIN_WIDTH+1, Y_OFFSET);
@@ -118,22 +119,19 @@ public class ScaleBar extends JPanel
        /**
         * Get the scale text for the given scale
         * @param inScale scale number
        /**
         * Get the scale text for the given scale
         * @param inScale scale number
-        * @param inUseMetric true to use km/m, false for miles/ft
+        * @param inDistUnit distance unit
         * @return scale text as string
         */
         * @return scale text as string
         */
-       private static String getScaleText(int inScale, boolean inUseMetric)
+       private static String getScaleText(int inScale, Unit inDistUnit)
        {
                if (inScale > 0) {
                        // Positive scale means km or miles
                        return "" + inScale     + " " +
        {
                if (inScale > 0) {
                        // Positive scale means km or miles
                        return "" + inScale     + " " +
-                               I18nManager.getText(inUseMetric?"units.kilometres.short":"units.miles.short");
+                               I18nManager.getText(inDistUnit.getShortnameKey());
                }
                }
-               if (inUseMetric) {
-                       // negative scale means m
-                       return "" + (-1000 / inScale) + " " + I18nManager.getText("units.metres.short");
-               }
-               // fallen through to feet
-               return "" + (-5280 / inScale) + " " + I18nManager.getText("units.feet.short");
+               // negative scale means a fraction
+               return "" + (-1.0 / inScale) + " " + I18nManager.getText(inDistUnit.getShortnameKey());
+               // might be nice to say 100m instead of 0.1km, 275ft instead of 0.2miles, etc - need to be done by Unit itself?
        }
 
        /**
        }
 
        /**
diff --git a/tim/prune/gui/map/TileDownloader.java b/tim/prune/gui/map/TileDownloader.java
new file mode 100644 (file)
index 0000000..df820fc
--- /dev/null
@@ -0,0 +1,111 @@
+package tim.prune.gui.map;
+
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashSet;
+
+import tim.prune.GpsPrune;
+
+/**
+ * Class to asynchronously download a tile from a url
+ * and populate an Image object with the contents
+ */
+public class TileDownloader implements Runnable
+{
+       private MapTileManager _manager = null;
+       private URL _url = null;
+       private int _layer = 0;
+       private int _x = 0, _y = 0;
+       private int _zoom = 0;
+       /** Hashset of all blocked / 404 tiles to avoid requesting them again */
+       private static final HashSet<String> BLOCKED_URLS = new HashSet<String>();
+       /** Hashset of all currently loading tiles to avoid requesting them again */
+       private static final HashSet<String> LOADING_URLS = new HashSet<String>();
+
+
+       /**
+        * Constructor (private)
+        * @param inManager parent manager for callback
+        * @param inUrl URL to load
+        * @param inLayer layer index from 0
+        * @param inX x coordinate of tile
+        * @param inY y coordinate of tile
+        * @param inZoom zoom level
+        */
+       private TileDownloader(MapTileManager inManager, URL inUrl, int inLayer, int inX, int inY, int inZoom)
+       {
+               _manager = inManager;
+               _url = inUrl;
+               _layer = inLayer;
+               _x = inX; _y = inY;
+               _zoom = inZoom;
+       }
+
+       /**
+        * Trigger a download in a new thread
+        * @param inManager manager to callback when image is loaded
+        * @param inUrl URL to load
+        * @param inLayer layer index from 0
+        * @param inX x coordinate of tile
+        * @param inY y coordinate of tile
+        * @param inZoom current zoom level
+        */
+       public static synchronized void triggerLoad(MapTileManager inManager, URL inUrl, int inLayer,
+               int inX, int inY, int inZoom)
+       {
+               if (inManager != null && inUrl != null)
+               {
+                       String url = inUrl.toString();
+                       if (!BLOCKED_URLS.contains(url) && !LOADING_URLS.contains(url))
+                       {
+                               LOADING_URLS.add(url);
+                               new Thread(new TileDownloader(inManager, inUrl, inLayer, inX, inY, inZoom)).start();
+                       }
+               }
+       }
+
+       /**
+        * Run method, called in separate thread
+        */
+       public void run()
+       {
+               InputStream in = null;
+               try
+               {
+                       // Set http user agent on connection
+                       URLConnection conn = _url.openConnection();
+                       conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER);
+                       in = conn.getInputStream();
+                       int len = conn.getContentLength();
+                       if (len > 0)
+                       {
+                               byte[] data = new byte[len];
+                               int totalRead = 0;
+                               while (totalRead < len)
+                               {
+                                       int numRead = in.read(data, totalRead, len-totalRead);
+                                       totalRead += numRead;
+                               }
+                               Image tile = Toolkit.getDefaultToolkit().createImage(data);
+                               in.close();
+
+                               // Pass back to manager so it can be stored in its memory cache
+                               _manager.notifyImageLoaded(tile, _layer, _x, _y, _zoom);
+                       }
+               }
+               catch (IOException e)
+               {
+                       System.err.println("IOE: " + e.getClass().getName() + " - " + e.getMessage());
+                       synchronized(this.getClass())
+                       {
+                               BLOCKED_URLS.add(_url.toString());
+                       }
+                       try {in.close();} catch (Exception e2) {}
+               }
+               LOADING_URLS.remove(_url.toString());
+       }
+}
index e3bfbea327dea79a2558a09fbe13cdb1976d0a77..9c19862166b2421b4cdaab9d102a75b5eb26dad6 100644 (file)
@@ -1,19 +1,15 @@
 package tim.prune.gui.profile;
 
 import tim.prune.I18nManager;
 package tim.prune.gui.profile;
 
 import tim.prune.I18nManager;
-import tim.prune.data.Altitude;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Track;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Track;
+import tim.prune.data.UnitSet;
 
 /**
  * Class to provide a source of altitude data for the profile chart
  */
 public class AltitudeData extends ProfileData
 {
 
 /**
  * Class to provide a source of altitude data for the profile chart
  */
 public class AltitudeData extends ProfileData
 {
-       /** Altitude format for values */
-       private Altitude.Format _altitudeFormat = Altitude.Format.NO_FORMAT;
-
-
        /**
         * Constructor
         * @param inTrack track object
        /**
         * Constructor
         * @param inTrack track object
@@ -25,11 +21,13 @@ public class AltitudeData extends ProfileData
        /**
         * Get the data and populate the instance arrays
         */
        /**
         * Get the data and populate the instance arrays
         */
-       public void init()
+       public void init(UnitSet inUnitSet)
        {
        {
+               setUnitSet(inUnitSet);
                initArrays();
                _hasData = false;
                initArrays();
                _hasData = false;
-               _altitudeFormat = Altitude.Format.NO_FORMAT;
+               // multiplication factor for unit conversion
+               final double multFactor = _unitSet.getAltitudeUnit().getMultFactorFromStd();
                if (_track != null)
                {
                        for (int i=0; i<_track.getNumPoints(); i++)
                if (_track != null)
                {
                        for (int i=0; i<_track.getNumPoints(); i++)
@@ -39,17 +37,11 @@ public class AltitudeData extends ProfileData
                                        DataPoint point = _track.getPoint(i);
                                        if (point != null && point.hasAltitude())
                                        {
                                        DataPoint point = _track.getPoint(i);
                                        if (point != null && point.hasAltitude())
                                        {
-                                               // Point has an altitude - if it's the first one, use its format
-                                               if (_altitudeFormat == Altitude.Format.NO_FORMAT)
-                                               {
-                                                       _altitudeFormat = point.getAltitude().getFormat();
-                                                       _minValue = _maxValue = point.getAltitude().getValue();
-                                               }
-                                               // Store the value and maintain max and min values
-                                               double value = point.getAltitude().getValue(_altitudeFormat);
+                                               // Point has an altitude - store value and maintain max and min values
+                                               double value = point.getAltitude().getMetricValue() * multFactor;
                                                _pointValues[i] = value;
                                                _pointValues[i] = value;
-                                               if (value < _minValue) {_minValue = value;}
-                                               if (value > _maxValue) {_maxValue = value;}
+                                               if (value < _minValue || !_hasData) {_minValue = value;}
+                                               if (value > _maxValue || !_hasData) {_maxValue = value;}
 
                                                _hasData = true;
                                                _pointHasData[i] = true;
 
                                                _hasData = true;
                                                _pointHasData[i] = true;
@@ -69,7 +61,7 @@ public class AltitudeData extends ProfileData
        public String getLabel()
        {
                return I18nManager.getText("fieldname.altitude") + " ("
        public String getLabel()
        {
                return I18nManager.getText("fieldname.altitude") + " ("
-                       + I18nManager.getText(_altitudeFormat==Altitude.Format.FEET?"units.feet.short":"units.metres.short")
+                       + I18nManager.getText(_unitSet.getAltitudeUnit().getShortnameKey())
                        + ")";
        }
 
                        + ")";
        }
 
index 17ea32b2a4c004328b1ce1afcaf592b97423780c..770a211ea777535d900bb43bfed109c047b771a5 100644 (file)
@@ -33,7 +33,7 @@ public class ProfileChart extends GenericDisplay implements MouseListener
        private JPopupMenu _popup = null;
 
        /** Possible scales to use */
        private JPopupMenu _popup = null;
 
        /** Possible scales to use */
-       private static final int[] LINE_SCALES = {10000, 5000, 2000, 1000, 500, 200, 100, 50, 10, 5};
+       private static final int[] LINE_SCALES = {10000, 5000, 2000, 1000, 500, 200, 100, 50, 10, 5, 2, 1};
        /** Border width around black line */
        private static final int BORDER_WIDTH = 6;
        /** Minimum size for profile chart in pixels */
        /** Border width around black line */
        private static final int BORDER_WIDTH = 6;
        /** Minimum size for profile chart in pixels */
@@ -41,7 +41,7 @@ public class ProfileChart extends GenericDisplay implements MouseListener
        /** Colour to use for text if no data found */
        private static final Color COLOR_NODATA_TEXT = Color.GRAY;
        /** Chart type */
        /** Colour to use for text if no data found */
        private static final Color COLOR_NODATA_TEXT = Color.GRAY;
        /** Chart type */
-       private static enum ChartType {ALTITUDE, SPEED};
+       private static enum ChartType {ALTITUDE, SPEED, VERT_SPEED};
 
 
        /**
 
 
        /**
@@ -54,7 +54,7 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                _data = new AltitudeData(inTrackInfo.getTrack());
                addMouseListener(this);
                setLayout(new FlowLayout(FlowLayout.LEFT));
                _data = new AltitudeData(inTrackInfo.getTrack());
                addMouseListener(this);
                setLayout(new FlowLayout(FlowLayout.LEFT));
-               _label = new JLabel("Altitude");
+               _label = new JLabel("Altitude"); // text will be replaced later
                add(_label);
                makePopup();
        }
                add(_label);
                makePopup();
        }
@@ -79,7 +79,6 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                paintBackground(g, colourScheme);
                if (_track != null && _track.getNumPoints() > 0)
                {
                paintBackground(g, colourScheme);
                if (_track != null && _track.getNumPoints() > 0)
                {
-                       _data.init();
                        _label.setText(_data.getLabel());
                        int width = getWidth();
                        int height = getHeight();
                        _label.setText(_data.getLabel());
                        int width = getWidth();
                        int height = getHeight();
@@ -121,11 +120,14 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                        // horizontal lines for scale - set to round numbers eg 500
                        int lineScale = getLineScale(minValue, maxValue);
                        int scaleValue = (int) (minValue/lineScale + 1) * lineScale;
                        // horizontal lines for scale - set to round numbers eg 500
                        int lineScale = getLineScale(minValue, maxValue);
                        int scaleValue = (int) (minValue/lineScale + 1) * lineScale;
+                       if (minValue < 0.0) {scaleValue -= lineScale;}
                        int x = 0, y = 0;
                        int x = 0, y = 0;
+                       final int zeroY = height - BORDER_WIDTH - (int) (yScaleFactor * (0.0 - minValue));
+
                        double value = 0.0;
                        double value = 0.0;
-                       if (lineScale > 1)
+                       g.setColor(lineColour);
+                       if (lineScale >= 1)
                        {
                        {
-                               g.setColor(lineColour);
                                while (scaleValue < maxValue)
                                {
                                        y = height - BORDER_WIDTH - (int) (yScaleFactor * (scaleValue - minValue));
                                while (scaleValue < maxValue)
                                {
                                        y = height - BORDER_WIDTH - (int) (yScaleFactor * (scaleValue - minValue));
@@ -133,6 +135,12 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                                        scaleValue += lineScale;
                                }
                        }
                                        scaleValue += lineScale;
                                }
                        }
+                       else if (minValue < 0.0)
+                       {
+                               // just draw zero line
+                               y = zeroY;
+                               g.drawLine(BORDER_WIDTH + 1, y, width - BORDER_WIDTH - 1, y);
+                       }
 
                        try
                        {
 
                        try
                        {
@@ -148,8 +156,22 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                                        if (_data.hasData(p))
                                        {
                                                value = _data.getData(p);
                                        if (_data.hasData(p))
                                        {
                                                value = _data.getData(p);
-                                               y = (int) (yScaleFactor * (value - minValue));
-                                               g.fillRect(BORDER_WIDTH+x, height-BORDER_WIDTH - y, barWidth, y);
+                                               // Normal case is the minimum value greater than zero
+                                               if (minValue >= 0)
+                                               {
+                                                       y = (int) (yScaleFactor * (value - minValue));
+                                                       g.fillRect(BORDER_WIDTH+x, height-BORDER_WIDTH - y, barWidth, y);
+                                               }
+                                               else if (value >= 0.0) {
+                                                       // Bar upwards from the zero line
+                                                       y = height-BORDER_WIDTH - (int) (yScaleFactor * (value - minValue));
+                                                       g.fillRect(BORDER_WIDTH+x, y, barWidth, zeroY - y);
+                                               }
+                                               else {
+                                                       // Bar downwards from the zero line
+                                                       int barHeight = (int) (yScaleFactor * value);
+                                                       g.fillRect(BORDER_WIDTH+x, zeroY, barWidth, -barHeight);
+                                               }
                                        }
                                }
                                // current point (make sure it's drawn last)
                                        }
                                }
                                // current point (make sure it's drawn last)
@@ -170,10 +192,11 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                        catch (NullPointerException npe) { // ignore, probably due to data being changed
                        }
                        // Draw numbers on top of the graph to mark scale
                        catch (NullPointerException npe) { // ignore, probably due to data being changed
                        }
                        // Draw numbers on top of the graph to mark scale
-                       if (lineScale > 1)
+                       if (lineScale >= 1)
                        {
                                int textHeight = g.getFontMetrics().getHeight();
                                scaleValue = (int) (minValue / lineScale + 1) * lineScale;
                        {
                                int textHeight = g.getFontMetrics().getHeight();
                                scaleValue = (int) (minValue / lineScale + 1) * lineScale;
+                               if (minValue < 0.0) {scaleValue -= lineScale;}
                                y = 0;
                                g.setColor(currentColour);
                                while (scaleValue < maxValue)
                                y = 0;
                                g.setColor(currentColour);
                                while (scaleValue < maxValue)
@@ -242,6 +265,13 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                                changeView(ChartType.SPEED);
                        }});
                _popup.add(speedItem);
                                changeView(ChartType.SPEED);
                        }});
                _popup.add(speedItem);
+               JMenuItem vertSpeedItem = new JMenuItem(I18nManager.getText("fieldname.verticalspeed"));
+               vertSpeedItem.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               changeView(ChartType.VERT_SPEED);
+                       }});
+               _popup.add(vertSpeedItem);
        }
 
        /**
        }
 
        /**
@@ -252,7 +282,7 @@ public class ProfileChart extends GenericDisplay implements MouseListener
         */
        private int getLineScale(double inMin, double inMax)
        {
         */
        private int getLineScale(double inMin, double inMax)
        {
-               if ((inMax - inMin) < 5 || inMax < 0) {
+               if ((inMax - inMin) < 2.0) {
                        return -1;
                }
                int numScales = LINE_SCALES.length;
                        return -1;
                }
                int numScales = LINE_SCALES.length;
@@ -275,7 +305,10 @@ public class ProfileChart extends GenericDisplay implements MouseListener
         */
        public void dataUpdated(byte inUpdateType)
        {
         */
        public void dataUpdated(byte inUpdateType)
        {
-               _data.init();
+               // Try not to recalculate all the values unless necessary
+               if (inUpdateType != SELECTION_CHANGED) {
+                       _data.init(Config.getUnitSet());
+               }
                repaint();
        }
 
                repaint();
        }
 
@@ -324,7 +357,10 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                else if (inType == ChartType.SPEED && !(_data instanceof SpeedData)) {
                        _data = new SpeedData(_track);
                }
                else if (inType == ChartType.SPEED && !(_data instanceof SpeedData)) {
                        _data = new SpeedData(_track);
                }
-               _data.init();
+               else if (inType == ChartType.VERT_SPEED && !(_data instanceof VerticalSpeedData)) {
+                       _data = new VerticalSpeedData(_track);
+               }
+               _data.init(Config.getUnitSet());
                repaint();
        }
 
                repaint();
        }
 
index b72c43a03b7afd3b5cbb42e4519fd9239471a111..0716b9332282164f28a8eb99ae43170dd8ec1a65 100644 (file)
@@ -1,6 +1,7 @@
 package tim.prune.gui.profile;
 
 import tim.prune.data.Track;
 package tim.prune.gui.profile;
 
 import tim.prune.data.Track;
+import tim.prune.data.UnitSet;
 
 /**
  * Abstract class for all sources of profile data,
 
 /**
  * Abstract class for all sources of profile data,
@@ -10,6 +11,8 @@ public abstract class ProfileData
 {
        /** Track object */
        protected final Track _track;
 {
        /** Track object */
        protected final Track _track;
+       /** Unit set to use */
+       protected UnitSet _unitSet = null;
        /** Flag for availability of any data */
        protected boolean _hasData = false;
        /** Array of booleans for data per point */
        /** Flag for availability of any data */
        protected boolean _hasData = false;
        /** Array of booleans for data per point */
@@ -74,7 +77,15 @@ public abstract class ProfileData
        /**
         * Get the data from the track and populate the value arrays
         */
        /**
         * Get the data from the track and populate the value arrays
         */
-       public abstract void init();
+       public abstract void init(UnitSet inUnitSet);
+
+       /**
+        * Set the UnitSet to use for the calculations
+        * @param inUnitSet unit set
+        */
+       protected void setUnitSet(UnitSet inUnitSet) {
+               _unitSet = inUnitSet;
+       }
 
        /**
         * @return text for label including units
 
        /**
         * @return text for label including units
index d836543420a9e55578363981f685d10224232eca..cd4d49d61c1e1d61793af57ed3f3f63e21fe50d8 100644 (file)
@@ -1,20 +1,16 @@
 package tim.prune.gui.profile;
 
 import tim.prune.I18nManager;
 package tim.prune.gui.profile;
 
 import tim.prune.I18nManager;
-import tim.prune.config.Config;
-import tim.prune.data.DataPoint;
-import tim.prune.data.Distance;
+import tim.prune.data.SpeedCalculator;
+import tim.prune.data.SpeedValue;
 import tim.prune.data.Track;
 import tim.prune.data.Track;
-import tim.prune.data.Distance.Units;
+import tim.prune.data.UnitSet;
 
 /**
  * Class to provide a source of speed data for the profile chart
  */
 public class SpeedData extends ProfileData
 {
 
 /**
  * Class to provide a source of speed data for the profile chart
  */
 public class SpeedData extends ProfileData
 {
-       /** Flag for metric units */
-       private boolean _metric = true;
-
        /**
         * Constructor
         * @param inTrack track object
        /**
         * Constructor
         * @param inTrack track object
@@ -26,41 +22,28 @@ public class SpeedData extends ProfileData
        /**
         * Get the data and populate the instance arrays
         */
        /**
         * Get the data and populate the instance arrays
         */
-       public void init()
+       public void init(UnitSet inUnitSet)
        {
        {
+               setUnitSet(inUnitSet);
                initArrays();
                initArrays();
-               _metric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
                _hasData = false;
                _minValue = _maxValue = 0.0;
                _hasData = false;
                _minValue = _maxValue = 0.0;
-               if (_track != null) {
-                       DataPoint prevPrevPoint = null, prevPoint = null, point = null;
+               SpeedValue speed = new SpeedValue();
+               if (_track != null)
+               {
                        for (int i=0; i<_track.getNumPoints(); i++)
                        {
                        for (int i=0; i<_track.getNumPoints(); i++)
                        {
-                               point = _track.getPoint(i);
-                               if (prevPrevPoint != null && prevPrevPoint.hasTimestamp()
-                                       && prevPoint != null && prevPoint.hasTimestamp()
-                                       && point != null && point.hasTimestamp())
+                               // Get the speed either from the speed value or from the distances and timestamps
+                               SpeedCalculator.calculateSpeed(_track, i, speed);
+                               if (speed.isValid())
                                {
                                {
-                                       // All three points have timestamps
-                                       double seconds = point.getTimestamp().getSecondsSince(prevPrevPoint.getTimestamp());
-                                       if (seconds > 0)
-                                       {
-                                               double distInRads = DataPoint.calculateRadiansBetween(prevPrevPoint, prevPoint)
-                                                       + DataPoint.calculateRadiansBetween(prevPoint, point);
-                                               double dist = Distance.convertRadiansToDistance(distInRads, _metric?Units.KILOMETRES:Units.MILES);
-                                               // Store the value and maintain max and min values
-                                               double value = dist / seconds * 60.0 * 60.0;
-                                               _pointValues[i-1] = value;
-                                               if (value < _minValue || _minValue == 0.0) {_minValue = value;}
-                                               if (value > _maxValue) {_maxValue = value;}
-
-                                               _hasData = true;
-                                               _pointHasData[i-1] = true;
-                                       }
+                                       double speedValue = speed.getValue();
+                                       _pointValues[i] = speedValue;
+                                       if (speedValue < _minValue || _minValue == 0.0) {_minValue = speedValue;}
+                                       if (speedValue > _maxValue) {_maxValue = speedValue;}
+                                       _hasData = true;
                                }
                                }
-                               // Exchange points
-                               prevPrevPoint = prevPoint;
-                               prevPoint = point;
+                               _pointHasData[i] = speed.isValid();
                        }
                }
        }
                        }
                }
        }
@@ -71,7 +54,7 @@ public class SpeedData extends ProfileData
        public String getLabel()
        {
                return I18nManager.getText("fieldname.speed") + " ("
        public String getLabel()
        {
                return I18nManager.getText("fieldname.speed") + " ("
-                       + I18nManager.getText(_metric?"units.kmh":"units.mph") + ")";
+                       + I18nManager.getText(_unitSet.getSpeedUnit().getShortnameKey()) + ")";
        }
 
        /**
        }
 
        /**
diff --git a/tim/prune/gui/profile/VerticalSpeedData.java b/tim/prune/gui/profile/VerticalSpeedData.java
new file mode 100644 (file)
index 0000000..510de88
--- /dev/null
@@ -0,0 +1,71 @@
+package tim.prune.gui.profile;
+
+import tim.prune.I18nManager;
+import tim.prune.data.SpeedCalculator;
+import tim.prune.data.SpeedValue;
+import tim.prune.data.Track;
+import tim.prune.data.UnitSet;
+
+/**
+ * Class to provide a source of vertical speed data for the profile chart
+ */
+public class VerticalSpeedData extends ProfileData
+{
+       /**
+        * Constructor
+        * @param inTrack track object
+        */
+       public VerticalSpeedData(Track inTrack) {
+               super(inTrack);
+       }
+
+       /**
+        * Get the data and populate the instance arrays
+        */
+       public void init(UnitSet inUnitSet)
+       {
+               setUnitSet(inUnitSet);
+               initArrays();
+               _hasData = false;
+               _minValue = _maxValue = 0.0;
+               SpeedValue speed = new SpeedValue();
+               if (_track != null)
+               {
+                       for (int i=0; i<_track.getNumPoints(); i++)
+                       {
+                               SpeedCalculator.calculateVerticalSpeed(_track, i, speed);
+                               // Check whether we got a value from either method
+                               if (speed.isValid())
+                               {
+                                       // Store the value and maintain max and min values
+                                       double speedValue = speed.getValue();
+                                       _pointValues[i] = speedValue;
+                                       if (speedValue < _minValue || _minValue == 0.0) {_minValue = speedValue;}
+                                       if (speedValue > _maxValue) {_maxValue = speedValue;}
+                                       _hasData = true;
+                               }
+                               _pointHasData[i] = speed.isValid();
+                       }
+               }
+       }
+
+       /**
+        * @return text description including units
+        */
+       public String getLabel()
+       {
+               return I18nManager.getText("fieldname.verticalspeed") + " ("
+                       + I18nManager.getText(_unitSet.getVerticalSpeedUnit().getShortnameKey()) + ")";
+       }
+
+       /**
+        * @return key for message when no speeds present
+        */
+       public String getNoDataKey()
+       {
+               if (!_track.hasAltitudeData()) {
+                       return "display.noaltitudes";
+               }
+               return "display.notimestamps";
+       }
+}
index 58618b8cd32c07ecc960ecaafcd4d03b84b7b3b8..2d0e54afef2a9dd2de1f4ad3e887e20841b2fa28 100644 (file)
@@ -1,5 +1,5 @@
 # Text entries for the GpsPrune application
 # Text entries for the GpsPrune application
-# Afrikaans entries as extra
+# Afrikaans entries
 
 # Menu entries
 menu.file=L\u00eaer
 
 # Menu entries
 menu.file=L\u00eaer
@@ -19,8 +19,8 @@ menu.range.all=Selekteer Alles
 menu.range.none=Selekteer Niks
 menu.range.start=Stel Reeks Begin
 menu.range.end=Stel Reeks Einde
 menu.range.none=Selekteer Niks
 menu.range.start=Stel Reeks Begin
 menu.range.end=Stel Reeks Einde
-menu.range.deleterange=Reeks Uitvee
-menu.range.interpolate=Interpoleer
+function.deleterange=Reeks Uitvee
+function.interpolate=Interpoleer punte
 menu.range.average=Gemiddelde Seleksie
 menu.range.reverse=Reeks Omkeer
 menu.range.mergetracksegments=Saamvoeg van spoor segmente
 menu.range.average=Gemiddelde Seleksie
 menu.range.reverse=Reeks Omkeer
 menu.range.mergetracksegments=Saamvoeg van spoor segmente
@@ -30,7 +30,9 @@ menu.point.editpoint=Redigeer Punt
 menu.point.deletepoint=Punt Uitvee
 menu.photo=Foto
 menu.photo.saveexif=Stoor na EXIF
 menu.point.deletepoint=Punt Uitvee
 menu.photo=Foto
 menu.photo.saveexif=Stoor na EXIF
+menu.audio=Audio
 menu.view=Kyk
 menu.view=Kyk
+menu.view.showsidebars=Wys kantstawe
 menu.view.browser=Kaart in werf blaaier
 menu.view.browser.google=Google Kaarte
 menu.view.browser.openstreetmap=Openstreetmap
 menu.view.browser=Kaart in werf blaaier
 menu.view.browser.google=Google Kaarte
 menu.view.browser.openstreetmap=Openstreetmap
@@ -38,12 +40,15 @@ menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Yahoo Kaarte
 menu.view.browser.bing=Bing Kaarte
 menu.settings=Stellings
 menu.view.browser.yahoo=Yahoo Kaarte
 menu.view.browser.bing=Bing Kaarte
 menu.settings=Stellings
+menu.settings.onlinemode=Laai kaarte vanaf internet
+menu.settings.autosave=Autostoor stellings op uitgaan
 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.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.drawpoints=Skep reeks van punte
 menu.map.connect=Connekteer baan punte
 menu.map.autopan=Automatiese Skuif van Kyk Venster
 menu.map.showmap=Wys Kaart
 menu.map.connect=Connekteer baan punte
 menu.map.autopan=Automatiese Skuif van Kyk Venster
 menu.map.showmap=Wys Kaart
@@ -51,10 +56,12 @@ menu.map.showscalebar=Wys SkalleerStaaf
 
 # Alt keys for menus
 altkey.menu.file=L
 
 # Alt keys for menus
 altkey.menu.file=L
+altkey.menu.track=B
 altkey.menu.range=R
 altkey.menu.point=P
 altkey.menu.view=K
 altkey.menu.photo=F
 altkey.menu.range=R
 altkey.menu.point=P
 altkey.menu.view=K
 altkey.menu.photo=F
+altkey.menu.audio=A
 altkey.menu.settings=S
 altkey.menu.help=H
 
 altkey.menu.settings=S
 altkey.menu.help=H
 
@@ -79,18 +86,22 @@ function.editwaypointname=Redigeer Baken Naam
 function.compress=Kompakteer spoor
 function.addtimeoffset=Voeg tyd spruit by
 function.addaltitudeoffset=Voeg hoogte spruit by
 function.compress=Kompakteer spoor
 function.addtimeoffset=Voeg tyd spruit by
 function.addaltitudeoffset=Voeg hoogte spruit by
-function.convertnamestotimes=Omskakel baken name na tye
+function.convertnamestotimes=Skakel baken name na tye
+function.deletefieldvalues=Verwyder veld waardes
 function.findwaypoint=Vind Baken
 function.pastecoordinates=Enter nuwe koordinate
 function.charts=Grafieke
 function.findwaypoint=Vind Baken
 function.pastecoordinates=Enter nuwe koordinate
 function.charts=Grafieke
-function.show3d=3D Kyk
+function.show3d=3D Vertoon
 function.distances=Afstande
 function.fullrangedetails=Vol reeks besonderhede
 function.setmapbg=Stel Kaart agtergrond
 function.distances=Afstande
 function.fullrangedetails=Vol reeks besonderhede
 function.setmapbg=Stel Kaart agtergrond
+function.setkmzimagesize=Stel KMZ beeld groote
 function.setpaths=Stel program paaie
 function.getgpsies=Kry GPS spore
 function.setpaths=Stel program paaie
 function.getgpsies=Kry GPS spore
+function.lookupsrtm=Kry hoogtes vanaf SRTM
 function.duplicatepoint=Dupliseer Punt
 function.setcolours=Stel kleure
 function.duplicatepoint=Dupliseer Punt
 function.setcolours=Stel kleure
+function.setlinewidth=Stel lyn dikte
 function.setlanguage=Stel tale
 function.connecttopoint=Las foto by huidige punt
 function.disconnectfrompoint=Ontkoppel vanaf huidige punt
 function.setlanguage=Stel tale
 function.connecttopoint=Las foto by huidige punt
 function.disconnectfrompoint=Ontkoppel vanaf huidige punt
@@ -102,12 +113,13 @@ function.rotatephotoright=Roteer foto regs
 function.ignoreexifthumb=Ignoreer EXIF thumbnail
 function.help=Hulp
 function.showkeys=Wys Kortpad sleutels
 function.ignoreexifthumb=Ignoreer EXIF thumbnail
 function.help=Hulp
 function.showkeys=Wys Kortpad sleutels
-function.about=Omtrent Prune
+function.about=Omtrent GpsPrune
 function.checkversion=Kyk vir nuwe weergawe
 function.saveconfig=Stoor Stellings
 function.checkversion=Kyk vir nuwe weergawe
 function.saveconfig=Stoor Stellings
+function.diskcache=Stoor kaarte na skyf
 
 # Dialogs
 
 # Dialogs
-dialog.exit.confirm.title=Uitgaan uit Prune
+dialog.exit.confirm.title=Uitgaan uit GpsPrune
 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.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?
@@ -120,7 +132,7 @@ dialog.openoptions.filesnippet=Ekstrak vanuit L\u00eaer
 dialog.load.table.field=Veld
 dialog.load.table.datatype=Data Tipe
 dialog.load.table.description=Beskrywing
 dialog.load.table.field=Veld
 dialog.load.table.datatype=Data Tipe
 dialog.load.table.description=Beskrywing
-dialog.delimiter.label=Veld Skeinding Karakter
+dialog.delimiter.label=Veld Skeiding Karakter
 dialog.delimiter.comma=Komma ,
 dialog.delimiter.tab=Tab
 dialog.delimiter.space=Spasie
 dialog.delimiter.comma=Komma ,
 dialog.delimiter.tab=Tab
 dialog.delimiter.space=Spasie
@@ -129,7 +141,10 @@ dialog.delimiter.other=Ander
 dialog.openoptions.deliminfo.records=Rekords, met
 dialog.openoptions.deliminfo.fields=velde
 dialog.openoptions.deliminfo.norecords=Geen rekords
 dialog.openoptions.deliminfo.records=Rekords, met
 dialog.openoptions.deliminfo.fields=velde
 dialog.openoptions.deliminfo.norecords=Geen rekords
-dialog.openoptions.altitudeunits=Hoogte Eenhede
+dialog.openoptions.altitudeunits=Hoogte eenhede
+dialog.open.contentsdoubled=Hierdie leer bevat twee kopie van elke punt,\n once eenkeer as baken en eenkeer as spoor punt
+dialog.selecttracks.intro=Selekteer die spoor of spore om te laai
+dialog.selecttracks.noname=on benaamd
 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.subdirectories=Sluit sub-gidse in
 dialog.jpegload.loadjpegswithoutcoords=Sluit fotos sonder koordinate in
 dialog.jpegload.loadjpegsoutsidearea=Sluit foto buitekant huidige area in
@@ -174,15 +189,18 @@ 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.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.exportsvg.text=Selekteer die parameters vir die SVG uitvoer
+dialog.exportsvg.phi=Azimuth hoek \u03d5
+dialog.exportsvg.theta=Opstandings angle \u03b8
 dialog.pointtype.desc=Stoor die volgende punt tipes
 dialog.pointtype.track=Spoor punte
 dialog.pointtype.waypoint=Bakens
 dialog.pointtype.photo=Foto punte
 dialog.pointtype.desc=Stoor die volgende punt tipes
 dialog.pointtype.track=Spoor punte
 dialog.pointtype.waypoint=Bakens
 dialog.pointtype.photo=Foto punte
+dialog.pointtype.selection=Net seleksie
 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.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.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
@@ -191,9 +209,12 @@ 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
 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
+dialog.pointedit.text=Selekteer elke veld om te wysig en gebruik die 'Wysig' knoppie om die waarde te verander
 dialog.pointedit.table.field=Veld
 dialog.pointedit.table.value=Waarde
 dialog.pointedit.table.changed=Verander
 dialog.pointedit.table.field=Veld
 dialog.pointedit.table.value=Waarde
 dialog.pointedit.table.changed=Verander
+dialog.pointedit.changevalue.text=Sleutel die nuwe waarde vir hierdie veld.
+dialog.pointedit.changevalue.title=Wysig veld
 dialog.pointnameedit.name=Baken naam
 dialog.pointnameedit.uppercase=Hoof letter
 dialog.pointnameedit.lowercase=Klein letter
 dialog.pointnameedit.name=Baken naam
 dialog.pointnameedit.uppercase=Hoof letter
 dialog.pointnameedit.lowercase=Klein letter
@@ -202,7 +223,204 @@ dialog.addtimeoffset.subtract=Vat tyd weg
 dialog.addtimeoffset.days=Dae
 dialog.addtimeoffset.hours=Ure
 dialog.addtimeoffset.minutes=Minute
 dialog.addtimeoffset.days=Dae
 dialog.addtimeoffset.hours=Ure
 dialog.addtimeoffset.minutes=Minute
+dialog.findwaypoint.intro=Sleutel gedeelte van baken naam
 dialog.findwaypoint.search=Soek
 dialog.saveexif.title=Stoor Exif
 dialog.findwaypoint.search=Soek
 dialog.saveexif.title=Stoor Exif
+dialog.saveexif.table.photoname=Foto naam
 dialog.saveexif.table.status=Status
 dialog.saveexif.table.save=Stoor
 dialog.saveexif.table.status=Status
 dialog.saveexif.table.save=Stoor
+dialog.saveexif.photostatus.connected=Verbind
+dialog.saveexif.photostatus.disconnected=Afgesluit
+dialog.saveexif.photostatus.modified=Verander
+dialog.saveexif.overwrite=Oorskruif leers
+dialog.saveexif.force=Vorseer ten spyte van klein foute
+dialog.charts.xaxis=X as
+dialog.charts.yaxis=Y as
+dialog.charts.output=Uitset
+dialog.charts.screen=Uitset na skerm
+dialog.charts.svg=Uitset na SVG leer
+dialog.charts.svgwidth=SVG wydte
+dialog.charts.svgheight=SVG hoogte
+dialog.charts.needaltitudeortimes=die spoor moet of hoogtes of tyd informasie bevat om grafiek teskep
+dialog.charts.gnuplotnotfound=Kon nie gnuplot find op gegewe pad
+dialog.distances.intro=Reguit lyn afstande tussen punte
+dialog.distances.column.from=Vanaf punt
+dialog.distances.column.to=Na punt
+dialog.distances.currentpoint=Huidige Punt
+dialog.distances.toofewpoints=Hierdie funksie benodig bakens om afstande tussen bakens uit tewerk
+dialog.fullrangedetails.intro=Hier is die besonderhede for die geselekteerde reeks
+dialog.setmapbg.intro=Selekteer een van die kaart bronne, of voeg nuwe een by
+dialog.addmapsource.title=Voeg nuwe kaart bron by
+dialog.addmapsource.sourcename=Naam van bron
+dialog.correlate.notimestamps=Daar is geen tyd stempels in die data punte, so daar is niks om te korreleer met die fotos
+dialog.correlate.nouncorrelatedphotos=Daar is geen ongekorreleerde fotos.\nIs jy seker jy wil voortgaan?
+dialog.correlate.photoselect.intro=Selekteer een van die gekorreleerde fotos om te gebruik as tyd afset
+dialog.correlate.select.photoname=Foto naam
+dialog.correlate.select.timediff=Tyd verskil
+dialog.correlate.select.photolater=Foto later
+dialog.correlate.options.tip=Wenk: Deur een item te verbind, kan die tyd afset bereken word vir jou.
+dialog.correlate.options.intro=Seleketeer die opsies vir automatiese korrelasie
+dialog.correlate.options.offsetpanel=Tyd afset
+dialog.correlate.options.offset=Afset
+dialog.correlate.options.offset.hours=ure,
+dialog.correlate.options.offset.minutes=minute en
+dialog.correlate.options.offset.seconds=sekondes
+dialog.correlate.options.photolater=Foto later as punt
+dialog.correlate.options.pointlaterphoto=Punt later as foto
+dialog.correlate.options.limitspanel=Korrelasie limiete
+dialog.correlate.options.notimelimit=Geen tyd limiet
+dialog.correlate.options.timelimit=Tyd limiet
+dialog.correlate.options.nodistancelimit=Geen afstand limiet
+dialog.correlate.options.distancelimit=Afstand limiet
+dialog.correlate.options.correlate=Korreleer
+dialog.correlate.alloutsiderange=Al die fotos is buitekant die tyd reeks van die spoor, so geen kon gekorreleer word.\nProbeer om afset te stel of omself ten minste een foto te korreleer.
+dialog.correlate.correltimes=Vir korrelasie gebruik:
+dialog.correlate.timestamp.beginning=Begin
+dialog.correlate.timestamp.middle=Middel
+dialog.correlate.timestamp.end=Einde
+dialog.rearrangephotos.tostart=Beweeg na begin
+dialog.rearrangephotos.toend=Beweeg na einde
+dialog.rearrangephotos.nosort=Nie sorteer
+dialog.rearrangephotos.sortbyfilename=Sorteer volgens leernaam
+dialog.rearrangephotos.sortbytime=Sorteer volgens tyd
+dialog.compress.closepoints.title=Naby punt verwydering
+dialog.compress.closepoints.paramdesc=Span faktor
+dialog.compress.wackypoints.title=Gekkige punt verwydering
+dialog.compress.wackypoints.paramdesc=Afstands faktor
+dialog.compress.singletons.paramdesc=Afstand faktor
+dialog.compress.duplicates.title=Duplikaat verwydering
+dialog.compress.douglaspeucker.title=Douglas-Peuker kompressie
+dialog.compress.summarylabel=Punte om te verwyder
+dialog.deletemarked.nonefound=Geen data punt kon verwyder word
+dialog.pastecoordinates.desc=Sleutel of plak die koordinate hier
+dialog.pastecoordinates.coords=Koordinate
+dialog.pastecoordinates.nothingfound=Gaan asseblief koordinate na en probeer weer
+dialog.help.help=Sien asseblief\n http://activityworkshop.net/software/gpsprune/\n vir meer inligting en gebruikers handleidings.
+dialog.about.version=Weergawe
+dialog.about.build=Bou
+dialog.about.summarytext1=GpsPrune is 'n program vir die laai, vertoon en wysiging van data vanaf GPS ontvangers.
+dialog.about.languages=Beskikbare tale
+dialog.about.translatedby=Engelse teks deur activityworkshop
+dialog.about.systeminfo=Stelsel informasie
+dialog.about.systeminfo.os=Beheer Stelsel
+dialog.about.systeminfo.java3d=Java3d geinstalleer
+dialog.about.systeminfo.povray=Povray geinstalleer
+dialog.about.systeminfo.exiftool=Exiftool geinstalleer
+dialog.about.systeminfo.gpsbabel=Gpsbabel geinstalleer
+dialog.about.systeminfo.gnuplot=Gnuplot geinstalleer
+dialog.about.systeminfo.exiflib=Exif biblioteek
+dialog.about.systeminfo.exiflib.internal=Intern
+dialog.about.systeminfo.exiflib.internal.failed=Interne (nie gevind)
+dialog.about.systeminfo.exiflib.external=Ektern
+dialog.about.systeminfo.exiflib.external.failed=Ekstern (nie gevind)
+dialog.about.yes=Ja
+dialog.about.no=Nee
+dialog.about.credits=Krediete
+dialog.about.credits.code=GpsPrune bron kode geskruif deur
+dialog.about.credits.exifcode=Exif bron kode deur
+dialog.about.credits.icons=Somigge ikone gevat vanaf
+dialog.about.credits.translators=Vertalers
+dialog.about.credits.translations=Vertalings gehelp deur
+dialog.about.credits.devtools=Onwikkelings gereedskap
+dialog.about.credits.othertools=Ander gereedskap
+dialog.about.credits.thanks=Dankie aan
+dialog.about.readme=Leesmy
+
+# Field names
+fieldname.latitude=breedtegraad
+fieldname.longitude=lengtegraad
+fieldname.altitude=Hoogte
+fieldname.timestamp=Tyd
+fieldname.time=Tyd
+fieldname.waypointname=Naam
+fieldname.waypointtype=Tipe
+fieldname.newsegment=Segment
+fieldname.custom=Persoonlike
+fieldname.prefix=Veld
+fieldname.distance=Afstand
+fieldname.movingdistance=Beweeg afstand
+fieldname.duration=Tydperk
+fieldname.speed=Spoed
+fieldname.verticalspeed=Vertikale spoed
+fieldname.description=Beskrywing
+
+# Measurement units
+units.original=Oorspronklik
+units.default=Bestek
+units.metres=Meters
+units.metres.short=m
+units.feet=Voet
+units.feet.short=ft
+units.kilometres=Kilo meters
+units.kilometres.short=km
+units.miles=Myl
+units.miles.short=mi
+units.hours=ure
+units.degminsec=Deg-min-sec
+units.degmin=Deg-min
+units.deg=Grade
+units.iso8601=ISO 8601
+
+# Cardinals for 3d plots
+cardinal.n=N
+cardinal.s=S
+cardinal.e=O
+cardinal.w=W
+
+# Undo operations
+undo.load=laai data
+undo.loadphotos=laai fotos
+undo.editpoint=eind punt
+undo.deletepoint=verwyder punt
+undo.removephoto=verwyder foto
+undo.deleterange=verwyder reeks
+undo.insert=voeg punte by
+undo.reverse=keer baan om
+undo.mergetracksegments=smelt baan segmente
+undo.addtimeoffset=voeg tyd afset
+undo.addaltitudeoffset=voeg hoogte afset
+undo.rearrangewaypoints=herrangskik
+undo.cutandmove=beweeg seksie
+undo.connect=verbind
+undo.disconnect=afsluit
+undo.correlatephotos=korreleer fotos
+undo.rearrangephotos=herrangskik fotos
+undo.createpoint=skep punt
+undo.rotatephoto=roteer foto
+undo.convertnamestotimes=skakel name na tye
+undo.lookupsrtm=soek hoogtes vanaf SRTM
+undo.deletefieldvalues=verwyder veld waardes
+
+# Error messages
+error.save.dialogtitle=Fout om data te stoor
+error.save.nodata=Geen data om te stoor
+error.save.failed=Stoor van data na l\u00eaer het misluk
+error.saveexif.filenotfound=Find van foto het misluk
+error.saveexif.cannotoverwrite1=Foto leer
+error.saveexif.cannotoverwrite2=is lees-alleen en kan nie oorskruif word nie. Skyf na kopie?
+error.saveexif.failed1=Stoor het misluk
+error.saveexif.failed2=van die beelde
+error.saveexif.forced2=van die beelde vereis vorsering
+error.load.dialogtitle=Fout met laai van data
+error.load.noread=Kan nie leer lees
+error.load.nopoints=Geen koordinaat informasie gevind in the leer
+error.load.unknownxml=Onherkenbare xml formaat:
+error.load.noxmlinzip=Geen xml leer gevind binne zip leer
+error.jpegload.dialogtitle=Fout met fotos laai
+error.jpegload.nofilesfound=Geen leers gevind
+error.jpegload.nojpegsfound=Geen jpeg leers gevind
+error.jpegload.nogpsfound=Geen GPS informasie gevind
+error.gpsload.unknown=Onbekende fout
+error.function.noop.title=Funksie het geen effek gehad
+error.rearrange.noop=Herrangskikking van punte het geen effek gehad
+error.function.notavailable.title=Funksie nie beskikbaar
+error.3d='n fout het gebeur met die 3d vertoon
+error.readme.notfound=Readme leer nie gevind
+error.osmimage.dialogtitle=Fout met laai van kaart beelde
+error.osmimage.failed=Milsukking met die laai van kaart beelde.Toets internet conneksie
+error.language.wrongfile=Die geselekteerde leer lyk nie soos 'n taal leer vir GpsPrune
+error.convertnamestotimes.nonames=Geen name kon in tye omgeskakel word
+error.lookupsrtm.nonefound=Geen hoogte waardes beskikbaar vir die punte
+error.lookupsrtm.nonerequired=Al die punte het klaar hoogtes, so daar is niks meer om te soek
+error.gpsies.uploadnotok=Die gpsies server het die boodskap terug gestuur
+error.gpsies.uploadfailed=Die oplaai het misluk met die volgende fout boodskap
index 248dfb75b51a74bf0c0bb7a08ecc8e5ad21155d3..17fcadc20d7ab70222bdc3a252efb1fa18672e30 100644 (file)
@@ -10,6 +10,7 @@ menu.file.exit=Konec
 menu.track=Trasa
 menu.track.undo=Undo
 menu.track.clearundo=Vypr\u00e1zdnit pam\u011b\u0165 undo
 menu.track=Trasa
 menu.track.undo=Undo
 menu.track.clearundo=Vypr\u00e1zdnit pam\u011b\u0165 undo
+menu.track.markrectangle=Ozna\u010dit body v obd\u00e9ln\u00edku
 menu.track.deletemarked=Smazat ozna\u010den\u00e9 body
 menu.track.rearrange=P\u0159euspo\u0159\u00e1dat z\u00e1jmov\u00e9 body
 menu.track.rearrange.start=V\u0161e na po\u010d\u00e1tek
 menu.track.deletemarked=Smazat ozna\u010den\u00e9 body
 menu.track.rearrange=P\u0159euspo\u0159\u00e1dat z\u00e1jmov\u00e9 body
 menu.track.rearrange.start=V\u0161e na po\u010d\u00e1tek
@@ -20,8 +21,6 @@ menu.range.all=Vybrat v\u0161e
 menu.range.none=Zru\u0161it v\u00fdb\u011br
 menu.range.start=Nastavit za\u010d\u00e1tek rozmez\u00ed
 menu.range.end=Nastavit konec rozmez\u00ed
 menu.range.none=Zru\u0161it v\u00fdb\u011br
 menu.range.start=Nastavit za\u010d\u00e1tek rozmez\u00ed
 menu.range.end=Nastavit konec rozmez\u00ed
-menu.range.deleterange=Smazat rozmez\u00ed
-menu.range.interpolate=Interpolovat
 menu.range.average=St\u0159ed z v\u00fdb\u011bru
 menu.range.reverse=Obr\u00e1tit rozmez\u00ed
 menu.range.mergetracksegments=Slou\u010dit \u010d\u00e1sti trasy
 menu.range.average=St\u0159ed z v\u00fdb\u011bru
 menu.range.reverse=Obr\u00e1tit rozmez\u00ed
 menu.range.mergetracksegments=Slou\u010dit \u010d\u00e1sti trasy
@@ -54,6 +53,7 @@ menu.map.connect=Propojit body trasy
 menu.map.autopan=Automatika zorn\u00e9ho pole
 menu.map.showmap=Zobrazit mapu
 menu.map.showscalebar=Zobrazit m\u011b\u0159\u00edtko
 menu.map.autopan=Automatika zorn\u00e9ho pole
 menu.map.showmap=Zobrazit mapu
 menu.map.showscalebar=Zobrazit m\u011b\u0159\u00edtko
+menu.map.editmode=Edita\u010dn\u00ed m\u00f3d
 
 # Alt keys for menus
 altkey.menu.file=S
 
 # Alt keys for menus
 altkey.menu.file=S
@@ -86,6 +86,9 @@ function.exportpov=Export POV
 function.exportsvg=Export SVG
 function.editwaypointname=Nastavit n\u00e1zev v\u00fdzna\u010dn\u00e9ho bodu
 function.compress=Komprimovat trasu
 function.exportsvg=Export SVG
 function.editwaypointname=Nastavit n\u00e1zev v\u00fdzna\u010dn\u00e9ho bodu
 function.compress=Komprimovat trasu
+function.deleterange=Smazat rozmez\u00ed
+function.croptrack=O\u0159\u00edznout trasu
+function.interpolate=Interpolovat body
 function.addtimeoffset=P\u0159idat \u010dasov\u00fd posun
 function.addaltitudeoffset=P\u0159idat v\u00fd\u0161kov\u00fd posun
 function.convertnamestotimes=P\u0159ev\u00e9st n\u00e1zvy v\u00fdzna\u010dn\u00fdch bod\u016f na \u010dasy
 function.addtimeoffset=P\u0159idat \u010dasov\u00fd posun
 function.addaltitudeoffset=P\u0159idat v\u00fd\u0161kov\u00fd posun
 function.convertnamestotimes=P\u0159ev\u00e9st n\u00e1zvy v\u00fdzna\u010dn\u00fdch bod\u016f na \u010dasy
@@ -140,6 +143,7 @@ dialog.deletepoint.title=Smazat bod
 dialog.deletepoint.deletephoto=Odebrat fotografii p\u0159ipojenou k tomuto bodu?
 dialog.deletephoto.title=Odebrat fotografii
 dialog.deletephoto.deletepoint=Smazat bod p\u0159ipojen\u00fd k t\u00e9to fotografii?
 dialog.deletepoint.deletephoto=Odebrat fotografii p\u0159ipojenou k tomuto bodu?
 dialog.deletephoto.title=Odebrat fotografii
 dialog.deletephoto.deletepoint=Smazat bod p\u0159ipojen\u00fd k t\u00e9to fotografii?
+dialog.deleteaudio.deletepoint=Smazat bod p\u0159ipojen\u00fd k t\u00e9to audionahr\u00e1vce?
 dialog.openoptions.title=Volby p\u0159i na\u010dten\u00ed
 dialog.openoptions.filesnippet=N\u00e1hled souboru
 dialog.load.table.field=Pole
 dialog.openoptions.title=Volby p\u0159i na\u010dten\u00ed
 dialog.openoptions.filesnippet=N\u00e1hled souboru
 dialog.load.table.field=Pole
@@ -219,8 +223,8 @@ dialog.confirmreversetrack.title=Potvr\u010fte obr\u00e1cen\u00ed
 dialog.confirmreversetrack.text=Tato trasa obsahuje \u010dasov\u00e9 zna\u010dky, jejich\u017e po\u0159ad\u00ed se obr\u00e1cen\u00edm zm\u011bn\u00ed.\nOpravdu chcete obr\u00e1tit v\u00fdb\u011br?
 dialog.confirmcutandmove.title=Potvr\u010fte p\u0159esun
 dialog.confirmcutandmove.text=Tato trasa obsahuje \u010dasov\u00e9 zna\u010dky, jejich\u017e po\u0159ad\u00ed se p\u0159esunem zm\u011bn\u00ed.\nOpravdu chcete v\u00fdb\u011br p\u0159esunout?
 dialog.confirmreversetrack.text=Tato trasa obsahuje \u010dasov\u00e9 zna\u010dky, jejich\u017e po\u0159ad\u00ed se obr\u00e1cen\u00edm zm\u011bn\u00ed.\nOpravdu chcete obr\u00e1tit v\u00fdb\u011br?
 dialog.confirmcutandmove.title=Potvr\u010fte p\u0159esun
 dialog.confirmcutandmove.text=Tato trasa obsahuje \u010dasov\u00e9 zna\u010dky, jejich\u017e po\u0159ad\u00ed se p\u0159esunem zm\u011bn\u00ed.\nOpravdu chcete v\u00fdb\u011br p\u0159esunout?
-dialog.interpolate.title=Interpolovat body
 dialog.interpolate.parameter.text=Po\u010det bod\u016f, kter\u00e9 se maj\u00ed p\u0159idat mezi vybran\u00e9 body
 dialog.interpolate.parameter.text=Po\u010det bod\u016f, kter\u00e9 se maj\u00ed p\u0159idat mezi vybran\u00e9 body
+dialog.interpolate.betweenwaypoints=Vlo\u017eit nov\u00e9 body trasy mezi v\u00fdzna\u010dn\u00fdmi body?
 dialog.undo.title=Vr\u00e1tit akci (akce)
 dialog.undo.pretext=Pros\u00edm vyberte akci (akce) k vr\u00e1cen\u00ed
 dialog.undo.none.title=Nelze vr\u00e1tit
 dialog.undo.title=Vr\u00e1tit akci (akce)
 dialog.undo.pretext=Pros\u00edm vyberte akci (akce) k vr\u00e1cen\u00ed
 dialog.undo.none.title=Nelze vr\u00e1tit
@@ -237,7 +241,7 @@ dialog.pointedit.changevalue.title=Upravit pole
 dialog.pointnameedit.name=N\u00e1zev v\u00fdzna\u010dn\u00e9ho bodu
 dialog.pointnameedit.uppercase=VELK\u00c1 p\u00edsmena
 dialog.pointnameedit.lowercase=mal\u00e1 p\u00edsmena
 dialog.pointnameedit.name=N\u00e1zev v\u00fdzna\u010dn\u00e9ho bodu
 dialog.pointnameedit.uppercase=VELK\u00c1 p\u00edsmena
 dialog.pointnameedit.lowercase=mal\u00e1 p\u00edsmena
-dialog.pointnameedit.sentencecase=Po\u010d\u00e1te\u010dn\u00ed P\u00edsmena Velk\u00e1
+dialog.pointnameedit.titlecase=Po\u010d\u00e1te\u010dn\u00ed P\u00edsmena Velk\u00e1
 dialog.addtimeoffset.add=P\u0159idat \u010das
 dialog.addtimeoffset.subtract=Odebrat \u010das
 dialog.addtimeoffset.days=Dny
 dialog.addtimeoffset.add=P\u0159idat \u010das
 dialog.addtimeoffset.subtract=Odebrat \u010das
 dialog.addtimeoffset.days=Dny
@@ -273,6 +277,8 @@ dialog.distances.column.to=Do bodu
 dialog.distances.currentpoint=Aktu\u00e1ln\u00ed bod
 dialog.distances.toofewpoints=Je t\u0159eba zadat v\u00edce bod\u016f, aby bylo mo\u017en\u00e9 vypo\u010d\u00edst jejich vzd\u00e1lenost
 dialog.fullrangedetails.intro=Zobrazuji detaily vybran\u00e9ho rozmez\u00ed
 dialog.distances.currentpoint=Aktu\u00e1ln\u00ed bod
 dialog.distances.toofewpoints=Je t\u0159eba zadat v\u00edce bod\u016f, aby bylo mo\u017en\u00e9 vypo\u010d\u00edst jejich vzd\u00e1lenost
 dialog.fullrangedetails.intro=Zobrazuji detaily vybran\u00e9ho rozmez\u00ed
+dialog.fullrangedetails.coltotal=V\u010detn\u011b p\u0159eru\u0161en\u00ed
+dialog.fullrangedetails.colsegments=Bez p\u0159eru\u0161en\u00ed
 dialog.setmapbg.intro=Vyberte jeden ze zdroj\u016f map nebo p\u0159idejte nov\u00fd
 dialog.addmapsource.title=P\u0159idat nov\u00fd zdroj map
 dialog.addmapsource.sourcename=N\u00e1zev zdroje
 dialog.setmapbg.intro=Vyberte jeden ze zdroj\u016f map nebo p\u0159idejte nov\u00fd
 dialog.addmapsource.title=P\u0159idat nov\u00fd zdroj map
 dialog.addmapsource.sourcename=N\u00e1zev zdroje
@@ -303,6 +309,7 @@ dialog.wikipedia.column.name=N\u00e1zev \u010dl\u00e1nku
 dialog.wikipedia.column.distance=Vzd\u00e1lenost
 dialog.correlate.notimestamps=U bod\u016f nejsou \u010dasov\u00e9 zna\u010dky, tak\u017ee nen\u00ed s \u010d\u00edm fotografie sladit.
 dialog.correlate.nouncorrelatedphotos=V\u0161echny fotografie jsou slad\u011bn\u00e9.\nOpravdu chcete pokra\u010dovat?
 dialog.wikipedia.column.distance=Vzd\u00e1lenost
 dialog.correlate.notimestamps=U bod\u016f nejsou \u010dasov\u00e9 zna\u010dky, tak\u017ee nen\u00ed s \u010d\u00edm fotografie sladit.
 dialog.correlate.nouncorrelatedphotos=V\u0161echny fotografie jsou slad\u011bn\u00e9.\nOpravdu chcete pokra\u010dovat?
+dialog.correlate.nouncorrelatedaudios=V\u0161echny audionahr\u00e1vky jsou slad\u011bn\u00e9.\nOpravdu chcete pokra\u010dovat?
 dialog.correlate.photoselect.intro=Vyberte jednu z t\u011bchto slad\u011bn\u00fdch fotografi\u00ed pro ur\u010den\u00ed \u010dasov\u00e9ho posunu
 dialog.correlate.select.photoname=N\u00e1zev fotografie
 dialog.correlate.select.timediff=\u010casov\u00fd rozd\u00edl
 dialog.correlate.photoselect.intro=Vyberte jednu z t\u011bchto slad\u011bn\u00fdch fotografi\u00ed pro ur\u010den\u00ed \u010dasov\u00e9ho posunu
 dialog.correlate.select.photoname=N\u00e1zev fotografie
 dialog.correlate.select.timediff=\u010casov\u00fd rozd\u00edl
@@ -340,7 +347,6 @@ dialog.rearrangephotos.toend=P\u0159en\u00e9st na konec
 dialog.rearrangephotos.nosort=Neuspo\u0159\u00e1d\u00e1vat
 dialog.rearrangephotos.sortbyfilename=Uspo\u0159\u00e1dat dle n\u00e1zvu souboru
 dialog.rearrangephotos.sortbytime=Uspo\u0159\u00e1dat dle \u010dasu
 dialog.rearrangephotos.nosort=Neuspo\u0159\u00e1d\u00e1vat
 dialog.rearrangephotos.sortbyfilename=Uspo\u0159\u00e1dat dle n\u00e1zvu souboru
 dialog.rearrangephotos.sortbytime=Uspo\u0159\u00e1dat dle \u010dasu
-dialog.compress.nonefound=Nemohou b\u00fdt odstran\u011bny \u017e\u00e1dn\u00e9 body trasy
 dialog.compress.closepoints.title=Odstran\u011bn\u00ed bl\u00edzk\u00fdch bod\u016f
 dialog.compress.closepoints.paramdesc=Koeficient bl\u00edzkosti
 dialog.compress.wackypoints.title=Odstran\u011bn\u00ed ust\u0159elen\u00fdch bod\u016f
 dialog.compress.closepoints.title=Odstran\u011bn\u00ed bl\u00edzk\u00fdch bod\u016f
 dialog.compress.closepoints.paramdesc=Koeficient bl\u00edzkosti
 dialog.compress.wackypoints.title=Odstran\u011bn\u00ed ust\u0159elen\u00fdch bod\u016f
@@ -351,6 +357,10 @@ dialog.compress.duplicates.title=Odstran\u011bn\u00ed zdvojen\u00fdch bod\u016f
 dialog.compress.douglaspeucker.title=Douglasova-Peuckerova komprese
 dialog.compress.douglaspeucker.paramdesc=Povolen\u00e1 odchylka
 dialog.compress.summarylabel=Bod\u016f ke smaz\u00e1n\u00ed
 dialog.compress.douglaspeucker.title=Douglasova-Peuckerova komprese
 dialog.compress.douglaspeucker.paramdesc=Povolen\u00e1 odchylka
 dialog.compress.summarylabel=Bod\u016f ke smaz\u00e1n\u00ed
+dialog.compress.confirm1=Bylo ozna\u010deno celkem
+dialog.compress.confirm2=bod\u016f.\nBody je mo\u017en\u00e9 smazat volbou Trasa->Smazat ozna\u010den\u00e9 body
+dialog.compress.confirmnone=Nebyly vybr\u00e1ny \u017e\u00e1dn\u00e9 body.
+dialog.deletemarked.nonefound=Nemohou b\u00fdt odstran\u011bny \u017e\u00e1dn\u00e9 body trasy
 dialog.pastecoordinates.desc=Zadejte sou\u0159adnice
 dialog.pastecoordinates.coords=Sou\u0159adnice
 dialog.pastecoordinates.nothingfound=Pros\u00edm ov\u011b\u0159te sou\u0159adnice a zkuste znovu
 dialog.pastecoordinates.desc=Zadejte sou\u0159adnice
 dialog.pastecoordinates.coords=Sou\u0159adnice
 dialog.pastecoordinates.nothingfound=Pros\u00edm ov\u011b\u0159te sou\u0159adnice a zkuste znovu
@@ -406,7 +416,6 @@ dialog.saveconfig.prune.languagefile=Soubor jazyka
 dialog.saveconfig.prune.gpsdevice=Za\u0159\u00edzen\u00ed GPS
 dialog.saveconfig.prune.gpsformat=Form\u00e1t GPS
 dialog.saveconfig.prune.povrayfont=Font Povray
 dialog.saveconfig.prune.gpsdevice=Za\u0159\u00edzen\u00ed GPS
 dialog.saveconfig.prune.gpsformat=Form\u00e1t GPS
 dialog.saveconfig.prune.povrayfont=Font Povray
-dialog.saveconfig.prune.metricunits=Pou\u017e\u00edvat metrick\u00e9 jednotky?
 dialog.saveconfig.prune.gnuplotpath=Cesta k gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Cesta k gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Cesta k exiftool
 dialog.saveconfig.prune.gnuplotpath=Cesta k gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Cesta k gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Cesta k exiftool
@@ -447,6 +456,7 @@ dialog.diskcache.save=Ukl\u00e1dat mapov\u00e9 podklady na disk
 dialog.diskcache.dir=Adres\u00e1\u0159 s cache
 dialog.diskcache.createdir=Vytvo\u0159it adres\u00e1\u0159
 dialog.diskcache.nocreate=Adres\u00e1\u0159 nebyl vytvo\u0159en
 dialog.diskcache.dir=Adres\u00e1\u0159 s cache
 dialog.diskcache.createdir=Vytvo\u0159it adres\u00e1\u0159
 dialog.diskcache.nocreate=Adres\u00e1\u0159 nebyl vytvo\u0159en
+dialog.diskcache.cannotwrite=Neda\u0159\u00ed se ulo\u017eit mapov\u00e9 podklady do zvolen\u00e9ho adres\u00e1\u0159e
 dialog.diskcache.table.path=Cesta
 dialog.diskcache.table.usedby=Pou\u017e\u00edv\u00e1
 dialog.diskcache.table.zoom=Zv\u011bt\u0161en\u00ed
 dialog.diskcache.table.path=Cesta
 dialog.diskcache.table.usedby=Pou\u017e\u00edv\u00e1
 dialog.diskcache.table.zoom=Zv\u011bt\u0161en\u00ed
@@ -485,6 +495,7 @@ confirm.addaltitudeoffset=V\u00fd\u0161kov\u00fd posun zm\u011bn\u011bn
 confirm.rearrangewaypoints=Body p\u0159euspo\u0159\u00e1d\u00e1ny
 confirm.rearrangephotos=Fotografie p\u0159euspo\u0159\u00e1d\u00e1ny
 confirm.cutandmove=V\u00fdb\u011br p\u0159esunut
 confirm.rearrangewaypoints=Body p\u0159euspo\u0159\u00e1d\u00e1ny
 confirm.rearrangephotos=Fotografie p\u0159euspo\u0159\u00e1d\u00e1ny
 confirm.cutandmove=V\u00fdb\u011br p\u0159esunut
+confirm.interpolate=Body p\u0159id\u00e1ny
 confirm.convertnamestotimes=N\u00e1zvy bod\u016f p\u0159evedeny
 confirm.saveexif.ok1=Ulo\u017eeno
 confirm.saveexif.ok2=fotografi\u00ed
 confirm.convertnamestotimes=N\u00e1zvy bod\u016f p\u0159evedeny
 confirm.saveexif.ok1=Ulo\u017eeno
 confirm.saveexif.ok2=fotografi\u00ed
@@ -580,7 +591,6 @@ display.range.time.mins=m
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=Pr\u016fm. rychlost
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=Pr\u016fm. rychlost
-details.range.avemovingspeed=Okam\u017e. rychlost
 details.range.maxspeed=Max. rychlost
 details.range.numsegments=Po\u010det segment\u016f
 details.range.pace=Tempo
 details.range.maxspeed=Max. rychlost
 details.range.numsegments=Po\u010det segment\u016f
 details.range.pace=Tempo
@@ -593,6 +603,7 @@ details.nophoto=Fotografie nevybr\u00e1na
 details.photo.loading=Na\u010d\u00edt\u00e1m
 details.photo.bearing=Azimut
 details.media.connected=P\u0159ipojeno
 details.photo.loading=Na\u010d\u00edt\u00e1m
 details.photo.bearing=Azimut
 details.media.connected=P\u0159ipojeno
+details.media.fullpath=\u00dapln\u00e1 cesta
 details.audiodetails=Detaily audionahr\u00e1vky
 details.noaudio=Audionahr\u00e1vka nevybr\u00e1na
 details.audio.file=Zvukov\u00fd soubor
 details.audiodetails=Detaily audionahr\u00e1vky
 details.noaudio=Audionahr\u00e1vka nevybr\u00e1na
 details.audio.file=Zvukov\u00fd soubor
@@ -626,12 +637,15 @@ units.feet=Stopy
 units.feet.short=stop
 units.kilometres=Kilometry
 units.kilometres.short=km
 units.feet.short=stop
 units.kilometres=Kilometry
 units.kilometres.short=km
-units.kmh=km/h
+units.kilometresperhour.short=km/h
 units.miles=M\u00edle
 units.miles.short=mil
 units.miles=M\u00edle
 units.miles.short=mil
-units.mph=mph
-units.metrespersec=m/s
-units.feetpersec=stop/s
+units.milesperhour.short=mph
+units.nauticalmiles=N\u00e1mo\u0159n\u00ed m\u00edle
+units.nauticalmiles.short=N.m.
+units.nauticalmilesperhour.short=uzly
+units.metrespersec.short=m/s
+units.feetpersec.short=stop/s
 units.hours=hodin
 units.degminsec=Deg-min-sec
 units.degmin=Deg-min
 units.hours=hodin
 units.degminsec=Deg-min-sec
 units.degmin=Deg-min
@@ -657,7 +671,8 @@ undo.deletepoint=smazat bod
 undo.removephoto=odebrat fotografii
 undo.removeaudio=odebrat audionahr\u00e1vku
 undo.deleterange=smazat rozmez\u00ed
 undo.removephoto=odebrat fotografii
 undo.removeaudio=odebrat audionahr\u00e1vku
 undo.deleterange=smazat rozmez\u00ed
-undo.compress=zkomprimovat trasu
+undo.croptrack=o\u0159\u00edznout trasu
+undo.deletemarked=zkomprimovat trasu
 undo.insert=vlo\u017eit body
 undo.reverse=obr\u00e1tit rozmez\u00ed
 undo.mergetracksegments=slou\u010dit \u010d\u00e1sti trasy
 undo.insert=vlo\u017eit body
 undo.reverse=obr\u00e1tit rozmez\u00ed
 undo.mergetracksegments=slou\u010dit \u010d\u00e1sti trasy
@@ -716,7 +731,9 @@ error.lookupsrtm.nonefound=Pro tyto body nen\u00ed k dispozici informace o nadmo
 error.lookupsrtm.nonerequired=U v\u0161ech bod\u016f u\u017e je informaci o v\u00fd\u0161ce, tak\u017ee nen\u00ed co dohled\u00e1vat
 error.gpsies.uploadnotok=Server gpsies vr\u00e1til hl\u00e1\u0161en\u00ed
 error.gpsies.uploadfailed=Chyba - nepoda\u0159ilo se nahr\u00e1t data.
 error.lookupsrtm.nonerequired=U v\u0161ech bod\u016f u\u017e je informaci o v\u00fd\u0161ce, tak\u017ee nen\u00ed co dohled\u00e1vat
 error.gpsies.uploadnotok=Server gpsies vr\u00e1til hl\u00e1\u0161en\u00ed
 error.gpsies.uploadfailed=Chyba - nepoda\u0159ilo se nahr\u00e1t data.
+error.showphoto.failed=Nepoda\u0159ilo se na\u010d\u00edst fotografii
 error.playaudiofailed=Nepoda\u0159ilo se p\u0159ehr\u00e1t zvukov\u00fd soubor.
 error.cache.notthere=Nepoda\u0159ilo se nal\u00e9zt adres\u00e1\u0159 s cache map.
 error.cache.empty=Adres\u00e1\u0159 s cache map je pr\u00e1zdn\u00fd.
 error.cache.cannotdelete=Nelze smazat soubory map.
 error.playaudiofailed=Nepoda\u0159ilo se p\u0159ehr\u00e1t zvukov\u00fd soubor.
 error.cache.notthere=Nepoda\u0159ilo se nal\u00e9zt adres\u00e1\u0159 s cache map.
 error.cache.empty=Adres\u00e1\u0159 s cache map je pr\u00e1zdn\u00fd.
 error.cache.cannotdelete=Nelze smazat soubory map.
+error.interpolate.invalidparameter=Po\u010det bod\u016f mus\u00ed b\u00fdt mezi 1 a 1000
diff --git a/tim/prune/lang/prune-texts_da.properties b/tim/prune/lang/prune-texts_da.properties
new file mode 100644 (file)
index 0000000..b375fe3
--- /dev/null
@@ -0,0 +1,85 @@
+# Text entries for the GpsPrune application
+# Danish translations
+
+# Menu entries
+menu.file=Fil
+menu.file.addphotos=Tilf\u00f8j billeder
+menu.file.recentfiles=Seneste filer
+menu.file.save=Gem som tekst
+menu.file.exit=Afslut
+menu.track.undo=Fortryd
+menu.track.clearundo=Nulstil fortrydelsesliste
+menu.track.deletemarked=Slet markerede punkter
+menu.track.rearrange=Omorganis\u00e9r waypoints
+menu.track.rearrange.nearest=Hvert waypoint til n\u00e6rmeste nabo
+menu.range=Omr\u00e5de
+menu.range.all=V\u00e6lg alle
+menu.range.none=Ingen valgt
+menu.range.start=V\u00e6lg omr\u00e5des startpunkt
+menu.range.end=V\u00e6lg omr\u00e5des slutpunkt
+menu.range.average=Dan gennemsnit af valgte omr\u00e5de
+menu.range.reverse=Dan omvendt r\u00e6kkef\u00f8lge
+menu.range.mergetracksegments=Sammensmelt sporsegmenter
+menu.range.cutandmove=Afsk\u00e6r og flyt valgte omr\u00e5de
+menu.point=Punkt
+menu.point.editpoint=Redig\u00e8r punkt
+menu.point.deletepoint=Fjern punkt
+menu.photo=Foto
+menu.photo.saveexif=Gem Exif-data
+menu.audio=Lyd
+menu.view=Udseende
+menu.view.showsidebars=Vis sidepanel
+menu.view.browser=Kort i browser
+menu.settings=Indstillinger
+menu.settings.onlinemode=Hent kort fra Internettet
+menu.settings.autosave=Gem indstillinger automatisk ved aflutning
+menu.help=Hj\u00e6lp
+# Popup menu for map
+menu.map.zoomin=Zoom ind
+menu.map.zoomout=Zoom ud
+menu.map.newpoint=Skab nyt punkt
+menu.map.drawpoints=Skab serie af punkter
+menu.map.connect=Saml punkter p\u00e5 linie
+menu.map.autopan=Autocentrering
+menu.map.showmap=Vis kort
+menu.map.showscalebar=Vis m\u00e5lestok
+
+# Alt keys for menus
+altkey.menu.file=F
+altkey.menu.track=S
+altkey.menu.range=O
+altkey.menu.point=P
+altkey.menu.view=U
+altkey.menu.photo=T
+altkey.menu.audio=L
+altkey.menu.settings=I
+altkey.menu.help=H
+
+# Functions
+function.open=\u00c5bn fil
+function.importwithgpsbabel=Import\u00e9r fil med GPSBabel
+function.loadfromgps=Hent data fra GPS
+function.sendtogps=Overf\u00f8r data til GPS
+function.exportkml=Eksport\u00e9r KML
+function.exportgpx=Eksport\u00e9r GPX
+function.exportpov=Eksport\u00e9r POV
+function.exportsvg=Eksport\u00e9r SVG
+function.editwaypointname=Ret waypoint-navn
+function.compress=Komprim\u00e9r spor
+function.deleterange=Fjern det valgte omr\u00e5de
+function.croptrack=Afgr\u00e6ns spor
+function.interpolate=Interpol\u00e9r
+function.addtimeoffset=Tilf\u00f8j offset p\u00e5 tiden
+function.addaltitudeoffset=Tilf\u00f8j offset p\u00e5 h\u00f8jde
+function.convertnamestotimes=Ret waypoint-navne til tidspunkter
+function.deletefieldvalues=Fjern feltv\u00e6rdier
+function.findwaypoint=Find waypoint
+function.pastecoordinates=Indf\u00f8j nye koordinater
+function.charts=Kort
+function.show3d=3-D view
+function.distances=Afstande
+function.fullrangedetails=Vis alle detaljer
+function.setmapbg=V\u00e6lg kort som baggrund
+function.setkmzimagesize=V\u00e6lg KMZ billedst\u00f8rrelse
+function.setpaths=V\u00e6lg sti til programmer
+function.getgpsies=Se liste af GPS-spor
index 745331a6c9a8f09e780b41f559559be00d85ba4d..ee57c2152143d5d110b10b8d5e97bd7f3cddb192 100644 (file)
@@ -1,17 +1,18 @@
 # Text entries for the GpsPrune application
 # Text entries for the GpsPrune application
-# German entries as extra
+# German entries
 
 # Menu entries
 menu.file=Datei
 menu.file.addphotos=Fotos laden
 menu.file.recentfiles=Zuletzt verwendete Dateien
 
 # Menu entries
 menu.file=Datei
 menu.file.addphotos=Fotos laden
 menu.file.recentfiles=Zuletzt verwendete Dateien
-menu.file.save=Als Text Speichern
+menu.file.save=Als Text speichern
 menu.file.exit=Beenden
 menu.track=Track
 menu.track.undo=R\u00fcckg\u00e4ngig
 menu.track.clearundo=Liste der letzten \u00c4nderungen l\u00f6schen
 menu.file.exit=Beenden
 menu.track=Track
 menu.track.undo=R\u00fcckg\u00e4ngig
 menu.track.clearundo=Liste der letzten \u00c4nderungen l\u00f6schen
-menu.track.deletemarked=Komprimierte Punkte l\u00f6schen
-menu.track.rearrange=Wegpunkte reorganisieren
+menu.track.markrectangle=Punkte im Viereck markieren
+menu.track.deletemarked=Markierte Punkte l\u00f6schen
+menu.track.rearrange=Wegpunkte neu anordnen
 menu.track.rearrange.start=Alle Wegpunkte zum Anfang
 menu.track.rearrange.end=Alle Wegpunkte ans Ende
 menu.track.rearrange.nearest=Jeden Wegpunkt zum n\u00e4chsten Trackpunkt verschieben
 menu.track.rearrange.start=Alle Wegpunkte zum Anfang
 menu.track.rearrange.end=Alle Wegpunkte ans Ende
 menu.track.rearrange.nearest=Jeden Wegpunkt zum n\u00e4chsten Trackpunkt verschieben
@@ -20,21 +21,24 @@ menu.range.all=Alles markieren
 menu.range.none=Nichts markieren
 menu.range.start=Startpunkt setzen
 menu.range.end=Endpunkt setzen
 menu.range.none=Nichts markieren
 menu.range.start=Startpunkt setzen
 menu.range.end=Endpunkt setzen
-menu.range.deleterange=Bereich l\u00f6schen
-menu.range.interpolate=Interpolieren
 menu.range.average=Durchschnitt berechnen
 menu.range.reverse=Bereich umkehren
 menu.range.mergetracksegments=Trackabschnitte verbinden
 menu.range.average=Durchschnitt berechnen
 menu.range.reverse=Bereich umkehren
 menu.range.mergetracksegments=Trackabschnitte verbinden
-menu.range.cutandmove=Schneiden und verschieben
+menu.range.cutandmove=Auswahl vor den markierten Punkt verschieben
 menu.point=Punkt
 menu.point.editpoint=Punkt bearbeiten
 menu.point.deletepoint=Punkt l\u00f6schen
 menu.photo=Foto
 menu.point=Punkt
 menu.point.editpoint=Punkt bearbeiten
 menu.point.deletepoint=Punkt l\u00f6schen
 menu.photo=Foto
-menu.photo.saveexif=Exif Daten speichern
+menu.photo.saveexif=Exif-Daten speichern
 menu.audio=Audio
 menu.view=Ansicht
 menu.view.showsidebars=Seitenleisten anzeigen
 menu.audio=Audio
 menu.view=Ansicht
 menu.view.showsidebars=Seitenleisten anzeigen
-menu.view.browser=Karte in Browser
+menu.view.browser=Karte in Browser anzeigen
+menu.view.browser.google=Google Maps
+menu.view.browser.openstreetmap=OpenStreetMap
+menu.view.browser.mapquest=Mapquest
+menu.view.browser.yahoo=Yahoo Maps
+menu.view.browser.bing=Bing Maps
 menu.settings=Einstellungen
 menu.settings.onlinemode=Karten aus dem Internet laden
 menu.settings.autosave=Einstellungen automatisch speichern
 menu.settings=Einstellungen
 menu.settings.onlinemode=Karten aus dem Internet laden
 menu.settings.autosave=Einstellungen automatisch speichern
@@ -49,6 +53,7 @@ menu.map.connect=Trackpunkte mit Linie anzeigen
 menu.map.autopan=Autozentrierung
 menu.map.showmap=Karte zeigen
 menu.map.showscalebar=Ma\u00dfstab anzeigen
 menu.map.autopan=Autozentrierung
 menu.map.showmap=Karte zeigen
 menu.map.showscalebar=Ma\u00dfstab anzeigen
+menu.map.editmode=Punkte verschieben
 
 # Alt keys for menus
 altkey.menu.file=D
 
 # Alt keys for menus
 altkey.menu.file=D
@@ -74,19 +79,22 @@ shortcut.menu.help.help=H
 function.open=Datei \u00f6ffnen
 function.importwithgpsbabel=Datei mit GPSBabel importieren
 function.loadfromgps=Vom GPS laden
 function.open=Datei \u00f6ffnen
 function.importwithgpsbabel=Datei mit GPSBabel importieren
 function.loadfromgps=Vom GPS laden
-function.sendtogps=zum GPS schicken
+function.sendtogps=Zum GPS schicken
 function.exportkml=KML exportieren
 function.exportgpx=GPX exportieren
 function.exportpov=POV exportieren
 function.exportsvg=SVG exportieren
 function.exportkml=KML exportieren
 function.exportgpx=GPX exportieren
 function.exportpov=POV exportieren
 function.exportsvg=SVG exportieren
-function.editwaypointname=Wegpunkt Name bearbeiten
+function.editwaypointname=Name des Punkts bearbeiten
 function.compress=Track komprimieren
 function.compress=Track komprimieren
+function.deleterange=Bereich l\u00f6schen
+function.croptrack=Track zuschneiden
+function.interpolate=Punkte interpolieren
 function.addtimeoffset=Zeitverschiebung aufrechnen
 function.addaltitudeoffset=H\u00f6henverschiebung aufrechnen
 function.addtimeoffset=Zeitverschiebung aufrechnen
 function.addaltitudeoffset=H\u00f6henverschiebung aufrechnen
-function.convertnamestotimes=Wegpunktenamen in Zeitstempel umwandeln
+function.convertnamestotimes=Namen der Wegpunkte in Zeitstempel umwandeln
 function.deletefieldvalues=Werte eines Feldes l\u00f6schen
 function.findwaypoint=Wegpunkt finden
 function.deletefieldvalues=Werte eines Feldes l\u00f6schen
 function.findwaypoint=Wegpunkt finden
-function.pastecoordinates=Neue Koordinaten eingeben
+function.pastecoordinates=Neuen Wegpunkt anlegen
 function.charts=Diagramme
 function.show3d=3D Ansicht
 function.distances=Entfernungen
 function.charts=Diagramme
 function.show3d=3D Ansicht
 function.distances=Entfernungen
@@ -94,12 +102,12 @@ function.fullrangedetails=Zus\u00e4tzliche Bereichdetails
 function.setmapbg=Karte Hintergrund setzen
 function.setkmzimagesize=Bildgr\u00f6\u00dfe im KMZ setzen
 function.setpaths=Programmpfade setzen
 function.setmapbg=Karte Hintergrund setzen
 function.setkmzimagesize=Bildgr\u00f6\u00dfe im KMZ setzen
 function.setpaths=Programmpfade setzen
-function.getgpsies=Gpsies Tracks holen
-function.uploadgpsies=Daten zum Gpsies hochladen
-function.lookupsrtm=H\u00f6hendaten von SRTM holen
+function.getgpsies=Tracks bei GPSies.com herunterladen
+function.uploadgpsies=Track zu GPSies.com hochladen
+function.lookupsrtm=H\u00f6hendaten von SRTM herunterladen
 function.getwikipedia=Wikipediaartikel in der N\u00e4he nachschlagen
 function.searchwikipedianames=Wikipedia mit Name durchsuchen
 function.getwikipedia=Wikipediaartikel in der N\u00e4he nachschlagen
 function.searchwikipedianames=Wikipedia mit Name durchsuchen
-function.downloadosm=OSM Daten f\u00fcr dieses Gebiet herunterladen
+function.downloadosm=OSM-Daten f\u00fcr dieses Gebiet herunterladen
 function.duplicatepoint=Punkt verdoppeln
 function.setcolours=Farben einstellen
 function.setlinewidth=Liniendicke einstellen
 function.duplicatepoint=Punkt verdoppeln
 function.setcolours=Farben einstellen
 function.setlinewidth=Liniendicke einstellen
@@ -108,14 +116,14 @@ function.connecttopoint=Mit Punkt verkn\u00fcpfen
 function.disconnectfrompoint=Vom Punkt trennen
 function.removephoto=Foto entfernen
 function.correlatephotos=Fotos korrelieren
 function.disconnectfrompoint=Vom Punkt trennen
 function.removephoto=Foto entfernen
 function.correlatephotos=Fotos korrelieren
-function.rearrangephotos=Fotos reorganisieren
-function.rotatephotoleft=Foto nach Links drehen
-function.rotatephotoright=Foto nach Rechts drehen
+function.rearrangephotos=Fotos neu anordnen
+function.rotatephotoleft=Foto nach links drehen
+function.rotatephotoright=Foto nach rechts drehen
 function.photopopup=Fotofenster anzeigen
 function.photopopup=Fotofenster anzeigen
-function.ignoreexifthumb=Exif Vorschaubild ignorieren
+function.ignoreexifthumb=Exif-Vorschaubild ignorieren
 function.loadaudio=Audiodateien laden
 function.removeaudio=Audiodatei entfernen
 function.loadaudio=Audiodateien laden
 function.removeaudio=Audiodatei entfernen
-function.correlateaudios=Audios korrelieren
+function.correlateaudios=Audiodateien korrelieren
 function.playaudio=Audiodatei abspielen
 function.stopaudio=Abspielen abbrechen
 function.help=Hilfe
 function.playaudio=Audiodatei abspielen
 function.stopaudio=Abspielen abbrechen
 function.help=Hilfe
@@ -135,30 +143,31 @@ dialog.deletepoint.title=Punkt l\u00f6schen
 dialog.deletepoint.deletephoto=Das zu diesem Punkt geh\u00f6rende Foto ebenfalls l\u00f6schen?
 dialog.deletephoto.title=Foto entfernen
 dialog.deletephoto.deletepoint=Den zu diesem Foto geh\u00f6renden Punkt auch l\u00f6schen?
 dialog.deletepoint.deletephoto=Das zu diesem Punkt geh\u00f6rende Foto ebenfalls l\u00f6schen?
 dialog.deletephoto.title=Foto entfernen
 dialog.deletephoto.deletepoint=Den zu diesem Foto geh\u00f6renden Punkt auch l\u00f6schen?
+dialog.deleteaudio.deletepoint=Den zu dieser Audiodatei geh\u00f6renden Punkt auch l\u00f6schen?
 dialog.openoptions.title=\u00d6ffnen
 dialog.openoptions.filesnippet=Dateiausschnitt
 dialog.load.table.field=Feld
 dialog.load.table.datatype=Datentyp
 dialog.load.table.description=Beschreibung
 dialog.openoptions.title=\u00d6ffnen
 dialog.openoptions.filesnippet=Dateiausschnitt
 dialog.load.table.field=Feld
 dialog.load.table.datatype=Datentyp
 dialog.load.table.description=Beschreibung
-dialog.delimiter.label=Feld Trennzeichen
+dialog.delimiter.label=Feld-Trennzeichen
 dialog.delimiter.comma=Komma ,
 dialog.delimiter.comma=Komma ,
-dialog.delimiter.tab=Tab
+dialog.delimiter.tab=Tabulator
 dialog.delimiter.space=Leerzeichen
 dialog.delimiter.semicolon=Strichpunkt ;
 dialog.delimiter.other=Andere
 dialog.openoptions.deliminfo.records=Datens\u00e4tze, mit
 dialog.openoptions.deliminfo.fields=Feldern
 dialog.openoptions.deliminfo.norecords=Keine Datens\u00e4tze
 dialog.delimiter.space=Leerzeichen
 dialog.delimiter.semicolon=Strichpunkt ;
 dialog.delimiter.other=Andere
 dialog.openoptions.deliminfo.records=Datens\u00e4tze, mit
 dialog.openoptions.deliminfo.fields=Feldern
 dialog.openoptions.deliminfo.norecords=Keine Datens\u00e4tze
-dialog.openoptions.altitudeunits=H\u00f6he Ma\u00dfeinheiten
-dialog.open.contentsdoubled=Diese Datei enth\u00e4lt zwei Kopien von jedem Punkt,\neinmal als Waypoint und einmal als Trackpunkt.
+dialog.openoptions.altitudeunits=Ma\u00dfeinheiten f\u00fcr die H\u00f6he
+dialog.open.contentsdoubled=Diese Datei enth\u00e4lt zwei Kopien jedes Punkts,\neinmal als Waypoint und einmal als Trackpunkt.
 dialog.selecttracks.intro=W\u00e4hlen Sie den Track oder die Tracks aus, die Sie laden m\u00f6chten
 dialog.selecttracks.noname=Unbenannt
 dialog.jpegload.subdirectories=Unterordner mit durchsuchen
 dialog.jpegload.loadjpegswithoutcoords=Auch Fotos ohne Koordinaten laden
 dialog.selecttracks.intro=W\u00e4hlen Sie den Track oder die Tracks aus, die Sie laden m\u00f6chten
 dialog.selecttracks.noname=Unbenannt
 dialog.jpegload.subdirectories=Unterordner mit durchsuchen
 dialog.jpegload.loadjpegswithoutcoords=Auch Fotos ohne Koordinaten laden
-dialog.jpegload.loadjpegsoutsidearea=Auch Fotos ausserhalb des Tracks laden
+dialog.jpegload.loadjpegsoutsidearea=Auch Fotos au\u00dferhalb des Tracks laden
 dialog.jpegload.progress.title=Fotos werden geladen
 dialog.jpegload.progress.title=Fotos werden geladen
-dialog.jpegload.progress=Bitte warten w\u00e4hrend die Fotos durchsucht werden
-dialog.gpsload.nogpsbabel=Programm gpsbabel wurde nicht gefunden. Weiter?
+dialog.jpegload.progress=Bitte warten, w\u00e4hrend die Fotos durchsucht werden
+dialog.gpsload.nogpsbabel=Programm GPSBabel wurde nicht gefunden. Weiter?
 dialog.gpsload.device=Ger\u00e4tename
 dialog.gpsload.format=Format
 dialog.gpsload.getwaypoints=Wegpunkte laden
 dialog.gpsload.device=Ger\u00e4tename
 dialog.gpsload.format=Format
 dialog.gpsload.getwaypoints=Wegpunkte laden
@@ -173,25 +182,25 @@ dialog.save.table.field=Feld
 dialog.save.table.hasdata=Enth\u00e4lt Daten
 dialog.save.table.save=Speichern
 dialog.save.headerrow=Titelzeile speichern
 dialog.save.table.hasdata=Enth\u00e4lt Daten
 dialog.save.table.save=Speichern
 dialog.save.headerrow=Titelzeile speichern
-dialog.save.coordinateunits=Koordinaten Ma\u00dfeinheiten
-dialog.save.altitudeunits=H\u00f6he Ma\u00dfeinheiten
+dialog.save.coordinateunits=Format der Koordinaten
+dialog.save.altitudeunits=Ma\u00dfeinheiten f\u00fcr die H\u00f6he
 dialog.save.timestampformat=Zeitstempelformat
 dialog.save.overwrite.title=Datei schon vorhanden
 dialog.save.overwrite.text=Diese Datei gibt es schon. Wollen Sie die vorhandene Datei \u00fcberschreiben?
 dialog.save.notypesselected=Keine Punktetypen sind ausgew\u00e4hlt
 dialog.exportkml.text=Titel f\u00fcr die Daten
 dialog.exportkml.altitude=Absolute H\u00f6heninformation (f\u00fcr Luftfahrt)
 dialog.save.timestampformat=Zeitstempelformat
 dialog.save.overwrite.title=Datei schon vorhanden
 dialog.save.overwrite.text=Diese Datei gibt es schon. Wollen Sie die vorhandene Datei \u00fcberschreiben?
 dialog.save.notypesselected=Keine Punktetypen sind ausgew\u00e4hlt
 dialog.exportkml.text=Titel f\u00fcr die Daten
 dialog.exportkml.altitude=Absolute H\u00f6heninformation (f\u00fcr Luftfahrt)
-dialog.exportkml.kmz=Daten in kmz Datei komprimieren
-dialog.exportkml.exportimages=Vorschaubilder mit in kmz exportieren
+dialog.exportkml.kmz=Daten in KMZ-Datei komprimieren
+dialog.exportkml.exportimages=Vorschaubilder mit in KMZ-Datei exportieren
 dialog.exportkml.trackcolour=Trackfarbe
 dialog.exportgpx.name=Name
 dialog.exportgpx.desc=Beschreibung
 dialog.exportgpx.includetimestamps=Zeitstempel mit exportieren
 dialog.exportkml.trackcolour=Trackfarbe
 dialog.exportgpx.name=Name
 dialog.exportgpx.desc=Beschreibung
 dialog.exportgpx.includetimestamps=Zeitstempel mit exportieren
-dialog.exportgpx.copysource=Xml von Quelle kopieren
+dialog.exportgpx.copysource=XML von Quelle kopieren
 dialog.exportgpx.encoding=Enkodierung
 dialog.exportgpx.encoding.system=System
 dialog.exportgpx.encoding.utf8=UTF-8
 dialog.exportgpx.encoding=Enkodierung
 dialog.exportgpx.encoding.system=System
 dialog.exportgpx.encoding.utf8=UTF-8
-dialog.exportpov.text=Geben Sie die Parameter f\u00fcr den POV Export ein
+dialog.exportpov.text=Geben Sie die Parameter f\u00fcr den POV-Export ein
 dialog.exportpov.font=Font
 dialog.exportpov.camerax=Kamera X
 dialog.exportpov.cameray=Kamera Y
 dialog.exportpov.font=Font
 dialog.exportpov.camerax=Kamera X
 dialog.exportpov.cameray=Kamera Y
@@ -200,7 +209,7 @@ dialog.exportpov.modelstyle=Modellstil
 dialog.exportpov.ballsandsticks=B\u00e4lle und Stangen
 dialog.exportpov.tubesandwalls=R\u00f6hren und W\u00e4nde
 dialog.exportpov.warningtracksize=Dieser Track hat sehr viele Punkte, die Java3D vielleicht nicht bearbeiten kann.\nM\u00f6chten Sie den Vorgang trotzdem fortsetzen?
 dialog.exportpov.ballsandsticks=B\u00e4lle und Stangen
 dialog.exportpov.tubesandwalls=R\u00f6hren und W\u00e4nde
 dialog.exportpov.warningtracksize=Dieser Track hat sehr viele Punkte, die Java3D vielleicht nicht bearbeiten kann.\nM\u00f6chten Sie den Vorgang trotzdem fortsetzen?
-dialog.exportsvg.text=W\u00e4hlen Sie die Parameter f\u00fcr den SVG Export aus
+dialog.exportsvg.text=W\u00e4hlen Sie die Parameter f\u00fcr den SVG-Export aus
 dialog.exportsvg.phi=Richtungswinkel \u03d5
 dialog.exportsvg.theta=Neigungswinkel \u03b8
 dialog.exportsvg.gradients=Farbverl\u00e4ufe verwenden
 dialog.exportsvg.phi=Richtungswinkel \u03d5
 dialog.exportsvg.theta=Neigungswinkel \u03b8
 dialog.exportsvg.gradients=Farbverl\u00e4ufe verwenden
@@ -214,8 +223,8 @@ dialog.confirmreversetrack.title=Umkehrung best\u00e4tigen
 dialog.confirmreversetrack.text=Diese Daten enthalten Zeitangaben, die bei einer Umkehrung in falscher Reihenfolge erscheinen w\u00fcrden.\nSind Sie sicher, dass Sie diesen Bereich umkehren wollen?
 dialog.confirmcutandmove.title=Verschieben best\u00e4tigen
 dialog.confirmcutandmove.text=Diese Daten enthalten Zeitangaben, die nach dem Verschieben in falscher Reihenfolge erscheinen w\u00fcrden.\nSind Sie sicher, dass Sie diesen Bereich verschieben wollen?
 dialog.confirmreversetrack.text=Diese Daten enthalten Zeitangaben, die bei einer Umkehrung in falscher Reihenfolge erscheinen w\u00fcrden.\nSind Sie sicher, dass Sie diesen Bereich umkehren wollen?
 dialog.confirmcutandmove.title=Verschieben best\u00e4tigen
 dialog.confirmcutandmove.text=Diese Daten enthalten Zeitangaben, die nach dem Verschieben in falscher Reihenfolge erscheinen w\u00fcrden.\nSind Sie sicher, dass Sie diesen Bereich verschieben wollen?
-dialog.interpolate.title=Punkte interpolieren
 dialog.interpolate.parameter.text=Anzahl Punkte, die zwischen den gew\u00e4hlten Punkten eingef\u00fcgt werden sollen
 dialog.interpolate.parameter.text=Anzahl Punkte, die zwischen den gew\u00e4hlten Punkten eingef\u00fcgt werden sollen
+dialog.interpolate.betweenwaypoints=Zwischen den Wegpunkten interpolieren?
 dialog.undo.title=Aktionen R\u00fcckg\u00e4ngig
 dialog.undo.pretext=Bitte die Operationen, die r\u00fcckg\u00e4ngig gemacht werden sollen, ausw\u00e4hlen.
 dialog.undo.none.title=Undo nicht m\u00f6glich
 dialog.undo.title=Aktionen R\u00fcckg\u00e4ngig
 dialog.undo.pretext=Bitte die Operationen, die r\u00fcckg\u00e4ngig gemacht werden sollen, ausw\u00e4hlen.
 dialog.undo.none.title=Undo nicht m\u00f6glich
@@ -223,16 +232,16 @@ dialog.undo.none.text=Keine Operationen k\u00f6nnen r\u00fcckg\u00e4ngig gemacht
 dialog.clearundo.title=Undo-Liste l\u00f6schen
 dialog.clearundo.text=Wollen Sie wirklich die Undo-Liste l\u00f6schen?\nAlle Undo- Informationen werden verloren gehen!
 dialog.pointedit.title=Punkt bearbeiten
 dialog.clearundo.title=Undo-Liste l\u00f6schen
 dialog.clearundo.text=Wollen Sie wirklich die Undo-Liste l\u00f6schen?\nAlle Undo- Informationen werden verloren gehen!
 dialog.pointedit.title=Punkt bearbeiten
-dialog.pointedit.text=W\u00e4hlen Sie die Felder aus, die Sie bearbeiten m\u00f6chten, und verwenden Sie den 'Bearbeiten' Knopf, um den Wert zu \u00e4ndern
+dialog.pointedit.text=W\u00e4hlen Sie die Felder aus, die Sie bearbeiten m\u00f6chten, und verwenden Sie den 'Bearbeiten'-Button, um den Wert zu \u00e4ndern
 dialog.pointedit.table.field=Feld
 dialog.pointedit.table.value=Wert
 dialog.pointedit.table.changed=Ge\u00e4ndert
 dialog.pointedit.changevalue.text=Geben Sie den neuen Wert f\u00fcr dieses Feld ein
 dialog.pointedit.changevalue.title=Feld bearbeiten
 dialog.pointedit.table.field=Feld
 dialog.pointedit.table.value=Wert
 dialog.pointedit.table.changed=Ge\u00e4ndert
 dialog.pointedit.changevalue.text=Geben Sie den neuen Wert f\u00fcr dieses Feld ein
 dialog.pointedit.changevalue.title=Feld bearbeiten
-dialog.pointnameedit.name=Wegpunkt Name
-dialog.pointnameedit.uppercase=GRO\u00df geschrieben
+dialog.pointnameedit.name=Name des Wegpunkts
+dialog.pointnameedit.uppercase=GROSS geschrieben
 dialog.pointnameedit.lowercase=klein geschrieben
 dialog.pointnameedit.lowercase=klein geschrieben
-dialog.pointnameedit.sentencecase=Gemischt geschrieben
+dialog.pointnameedit.titlecase=Gemischt geschrieben
 dialog.addtimeoffset.add=Zeit addieren
 dialog.addtimeoffset.subtract=Zeit subtrahieren
 dialog.addtimeoffset.days=Tage
 dialog.addtimeoffset.add=Zeit addieren
 dialog.addtimeoffset.subtract=Zeit subtrahieren
 dialog.addtimeoffset.days=Tage
@@ -244,8 +253,8 @@ dialog.findwaypoint.search=Suche
 dialog.saveexif.title=Exif speichern
 dialog.saveexif.intro=W\u00e4hlen Sie die Fotos zum Speichern aus
 dialog.saveexif.nothingtosave=Koordinaten sind unver\u00e4ndert. Es gibt nichts zu speichern.
 dialog.saveexif.title=Exif speichern
 dialog.saveexif.intro=W\u00e4hlen Sie die Fotos zum Speichern aus
 dialog.saveexif.nothingtosave=Koordinaten sind unver\u00e4ndert. Es gibt nichts zu speichern.
-dialog.saveexif.noexiftool=Kein exiftool Programm gefunden. Trotzdem fortfahren?
-dialog.saveexif.table.photoname=Foto Name
+dialog.saveexif.noexiftool=Kein ExifTool-Programm gefunden. Trotzdem fortfahren?
+dialog.saveexif.table.photoname=Name des Fotos
 dialog.saveexif.table.status=Status
 dialog.saveexif.table.save=Speichern
 dialog.saveexif.photostatus.connected=Verbunden
 dialog.saveexif.table.status=Status
 dialog.saveexif.table.save=Speichern
 dialog.saveexif.photostatus.connected=Verbunden
@@ -253,21 +262,23 @@ dialog.saveexif.photostatus.disconnected=Getrennt
 dialog.saveexif.photostatus.modified=Modifiziert
 dialog.saveexif.overwrite=Dateien \u00fcberschreiben
 dialog.saveexif.force=Erzwingen trotz geringf\u00fcgiger Fehler
 dialog.saveexif.photostatus.modified=Modifiziert
 dialog.saveexif.overwrite=Dateien \u00fcberschreiben
 dialog.saveexif.force=Erzwingen trotz geringf\u00fcgiger Fehler
-dialog.charts.xaxis=X Achse
-dialog.charts.yaxis=Y Achse
+dialog.charts.xaxis=X-Achse
+dialog.charts.yaxis=Y-Achse
 dialog.charts.output=Ausgabe
 dialog.charts.screen=Ausgabe auf Bildschirm
 dialog.charts.output=Ausgabe
 dialog.charts.screen=Ausgabe auf Bildschirm
-dialog.charts.svg=Ausgabe in SVG Datei
-dialog.charts.svgwidth=SVG Breite
-dialog.charts.svgheight=SVG H\u00f6he
-dialog.charts.needaltitudeortimes=Ohne Daten \u00fcber H\u00f6he und Zeit kann kein Diagramm erzeugt werden.
+dialog.charts.svg=Ausgabe in SVG-Datei
+dialog.charts.svgwidth=SVG-Breite
+dialog.charts.svgheight=SVG-H\u00f6he
+dialog.charts.needaltitudeortimes=Ohne Daten zu H\u00f6he und Zeit kann kein Diagramm erzeugt werden.
 dialog.charts.gnuplotnotfound=Gnuplot konnte im angegebenen Pfad nicht gefunden werden
 dialog.distances.intro=Luftlinienentfernung zwischen Punkten
 dialog.distances.column.from=Vom Punkt
 dialog.distances.column.to=Zum Punkt
 dialog.distances.currentpoint=Aktueller Punkt
 dialog.charts.gnuplotnotfound=Gnuplot konnte im angegebenen Pfad nicht gefunden werden
 dialog.distances.intro=Luftlinienentfernung zwischen Punkten
 dialog.distances.column.from=Vom Punkt
 dialog.distances.column.to=Zum Punkt
 dialog.distances.currentpoint=Aktueller Punkt
-dialog.distances.toofewpoints=Diese Funktion braucht Wegpunkte um die Distanzen zu berechnen
-dialog.fullrangedetails.intro=Hier sind die Details des markierten Bereichs
+dialog.distances.toofewpoints=Diese Funktion braucht Wegpunkte, um die Distanzen zu berechnen
+dialog.fullrangedetails.intro=Detaillierte Angaben zum markierten Bereich
+dialog.fullrangedetails.coltotal=Mit L\u00fccken
+dialog.fullrangedetails.colsegments=Ohne L\u00fccken
 dialog.setmapbg.intro=Eine der Quellen ausw\u00e4hlen oder eine neue hinzuf\u00fcgen
 dialog.addmapsource.title=Neue Kartenquelle hinzuf\u00fcgen
 dialog.addmapsource.sourcename=Name der Quelle
 dialog.setmapbg.intro=Eine der Quellen ausw\u00e4hlen oder eine neue hinzuf\u00fcgen
 dialog.addmapsource.title=Neue Kartenquelle hinzuf\u00fcgen
 dialog.addmapsource.sourcename=Name der Quelle
@@ -276,28 +287,29 @@ dialog.addmapsource.layer2url=URL f\u00fcr obere Ebene (falls n\u00f6tig)
 dialog.addmapsource.maxzoom=Maximales Zoom
 dialog.addmapsource.cloudstyle=Stilnummer
 dialog.addmapsource.noname=Unbenannt
 dialog.addmapsource.maxzoom=Maximales Zoom
 dialog.addmapsource.cloudstyle=Stilnummer
 dialog.addmapsource.noname=Unbenannt
-dialog.gpsies.column.name=Track Name
+dialog.gpsies.column.name=Name des Tracks
 dialog.gpsies.column.length=L\u00e4nge
 dialog.gpsies.description=Beschreibung
 dialog.gpsies.nodescription=Keine Beschreibung
 dialog.gpsies.nonefound=Keine Tracks gefunden
 dialog.gpsies.column.length=L\u00e4nge
 dialog.gpsies.description=Beschreibung
 dialog.gpsies.nodescription=Keine Beschreibung
 dialog.gpsies.nonefound=Keine Tracks gefunden
-dialog.gpsies.username=Gpsies Username
-dialog.gpsies.password=Gpsies Passwort
+dialog.gpsies.username=Username bei GPSies.com
+dialog.gpsies.password=Passwort bei GPSies.com
 dialog.gpsies.keepprivate=Track privat halten
 dialog.gpsies.confirmopenpage=Webseite f\u00fcr den hochgeladenen Track \u00f6ffnen?
 dialog.gpsies.activities=Aktivit\u00e4ten
 dialog.gpsies.activity.trekking=Wandern
 dialog.gpsies.activity.walking=Walking
 dialog.gpsies.activity.jogging=Laufen
 dialog.gpsies.keepprivate=Track privat halten
 dialog.gpsies.confirmopenpage=Webseite f\u00fcr den hochgeladenen Track \u00f6ffnen?
 dialog.gpsies.activities=Aktivit\u00e4ten
 dialog.gpsies.activity.trekking=Wandern
 dialog.gpsies.activity.walking=Walking
 dialog.gpsies.activity.jogging=Laufen
-dialog.gpsies.activity.biking=Fahrradtour
-dialog.gpsies.activity.motorbiking=Motorrad
-dialog.gpsies.activity.snowshoe=Schneeschuh
+dialog.gpsies.activity.biking=Fahrradfahren
+dialog.gpsies.activity.motorbiking=Motorradfahren
+dialog.gpsies.activity.snowshoe=Schneeschuhwandern
 dialog.gpsies.activity.sailing=Segeln
 dialog.gpsies.activity.skating=Inline-Skating
 dialog.wikipedia.column.name=Artikelname
 dialog.wikipedia.column.distance=Entfernung
 dialog.correlate.notimestamps=Die Punkte enthalten keine Zeitangaben, deshalb k\u00f6nnen die Fotos nicht zugeordnet werden.
 dialog.correlate.nouncorrelatedphotos=Alle Fotos sind schon zugeordnet.\nWollen Sie trotzdem fortfahren?
 dialog.gpsies.activity.sailing=Segeln
 dialog.gpsies.activity.skating=Inline-Skating
 dialog.wikipedia.column.name=Artikelname
 dialog.wikipedia.column.distance=Entfernung
 dialog.correlate.notimestamps=Die Punkte enthalten keine Zeitangaben, deshalb k\u00f6nnen die Fotos nicht zugeordnet werden.
 dialog.correlate.nouncorrelatedphotos=Alle Fotos sind schon zugeordnet.\nWollen Sie trotzdem fortfahren?
+dialog.correlate.nouncorrelatedaudios=Alle Audiodateien sind schon zugeordnet.\nWollen Sie trotzdem fortfahren?
 dialog.correlate.photoselect.intro=W\u00e4hlen Sie eines dieser Fotos aus, um die Zeitdifferenz zu berechnen
 dialog.correlate.select.photoname=Bezeichnung des Fotos
 dialog.correlate.select.timediff=Zeitdifferenz
 dialog.correlate.photoselect.intro=W\u00e4hlen Sie eines dieser Fotos aus, um die Zeitdifferenz zu berechnen
 dialog.correlate.select.photoname=Bezeichnung des Fotos
 dialog.correlate.select.timediff=Zeitdifferenz
@@ -313,20 +325,20 @@ dialog.correlate.options.photolater=Foto sp\u00e4ter als Punkt
 dialog.correlate.options.pointlaterphoto=Punkt sp\u00e4ter als Foto
 dialog.correlate.options.audiolater=Audio sp\u00e4ter als Punkt
 dialog.correlate.options.pointlateraudio=Punkt sp\u00e4ter als Audio
 dialog.correlate.options.pointlaterphoto=Punkt sp\u00e4ter als Foto
 dialog.correlate.options.audiolater=Audio sp\u00e4ter als Punkt
 dialog.correlate.options.pointlateraudio=Punkt sp\u00e4ter als Audio
-dialog.correlate.options.limitspanel=Korrelation Grenzen
+dialog.correlate.options.limitspanel=Grenzen der Korrelation
 dialog.correlate.options.notimelimit=Keine Zeitgrenzen
 dialog.correlate.options.timelimit=Zeitgrenzen
 dialog.correlate.options.nodistancelimit=Keine Distanzgrenzen
 dialog.correlate.options.distancelimit=Distanzgrenzen
 dialog.correlate.options.correlate=Korrelieren
 dialog.correlate.options.notimelimit=Keine Zeitgrenzen
 dialog.correlate.options.timelimit=Zeitgrenzen
 dialog.correlate.options.nodistancelimit=Keine Distanzgrenzen
 dialog.correlate.options.distancelimit=Distanzgrenzen
 dialog.correlate.options.correlate=Korrelieren
-dialog.correlate.alloutsiderange=Alle Fotos sind au\u00dferhalb des Track Zeitraums. Sie k\u00f6nnen nicht korreliert werden.\nVersuchen Sie es mit einem anderen Offset oder binden Sie manuell mindestens ein Foto ein.
+dialog.correlate.alloutsiderange=Alle Elemente liegen au\u00dferhalb des Track-Zeitraums und k\u00f6nnen deshalb nicht korreliert werden.\nVersuchen Sie es mit einem anderen Offset oder binden Sie manuell mindestens ein Element ein.
 dialog.correlate.filetimes=Die Datei Zeitstempel zeigen:
 dialog.correlate.filetimes2=der Tonspuren
 dialog.correlate.filetimes=Die Datei Zeitstempel zeigen:
 dialog.correlate.filetimes2=der Tonspuren
-dialog.correlate.correltimes=F\u00fcr das Korrelieren, folgendes verwenden:
+dialog.correlate.correltimes=F\u00fcr das Korrelieren Folgendes verwenden:
 dialog.correlate.timestamp.beginning=Anfang
 dialog.correlate.timestamp.middle=Mitte
 dialog.correlate.timestamp.end=Ende
 dialog.correlate.timestamp.beginning=Anfang
 dialog.correlate.timestamp.middle=Mitte
 dialog.correlate.timestamp.end=Ende
-dialog.correlate.audioselect.intro=W\u00e4hlen Sie eines dieser Audios aus, um die Zeitdifferenz zu berechnen
+dialog.correlate.audioselect.intro=W\u00e4hlen Sie eines dieser Audiodateien aus, um die Zeitdifferenz zu berechnen
 dialog.correlate.select.audioname=Audio Name
 dialog.correlate.select.audiolater=Audio sp\u00e4ter
 dialog.rearrangephotos.desc=Setzen Sie das Ziel und die Reihenfolge der Fotopunkte
 dialog.correlate.select.audioname=Audio Name
 dialog.correlate.select.audiolater=Audio sp\u00e4ter
 dialog.rearrangephotos.desc=Setzen Sie das Ziel und die Reihenfolge der Fotopunkte
@@ -335,62 +347,65 @@ dialog.rearrangephotos.toend=Am Ende
 dialog.rearrangephotos.nosort=Nicht sortieren
 dialog.rearrangephotos.sortbyfilename=per Dateiname sortieren
 dialog.rearrangephotos.sortbytime=per Zeitstempel sortieren
 dialog.rearrangephotos.nosort=Nicht sortieren
 dialog.rearrangephotos.sortbyfilename=per Dateiname sortieren
 dialog.rearrangephotos.sortbytime=per Zeitstempel sortieren
-dialog.compress.nonefound=Es konnten keine Punkte entfernt werden
 dialog.compress.closepoints.title=Nahegelegene Punkte entfernen
 dialog.compress.closepoints.title=Nahegelegene Punkte entfernen
-dialog.compress.closepoints.paramdesc=Span Faktor
+dialog.compress.closepoints.paramdesc=Span-Faktor
 dialog.compress.wackypoints.title=Ungew\u00f6hnliche Punkte entfernen
 dialog.compress.wackypoints.paramdesc=Distanzfaktor
 dialog.compress.singletons.title=Singletons (isolierte Punkte) entfernen
 dialog.compress.singletons.paramdesc=Distanzfaktor
 dialog.compress.duplicates.title=Duplikate entfernen
 dialog.compress.wackypoints.title=Ungew\u00f6hnliche Punkte entfernen
 dialog.compress.wackypoints.paramdesc=Distanzfaktor
 dialog.compress.singletons.title=Singletons (isolierte Punkte) entfernen
 dialog.compress.singletons.paramdesc=Distanzfaktor
 dialog.compress.duplicates.title=Duplikate entfernen
-dialog.compress.douglaspeucker.title=Douglas-Peucker Komprimierung
-dialog.compress.douglaspeucker.paramdesc=Span Faktor
-dialog.compress.summarylabel=Punkte zu entfernen
-dialog.pastecoordinates.desc=Geben Sie die Koordinaten ein
+dialog.compress.douglaspeucker.title=Douglas-Peucker-Komprimierung
+dialog.compress.douglaspeucker.paramdesc=Span-Faktor
+dialog.compress.summarylabel=Zu entfernende Punkte
+dialog.compress.confirm1=Es wurden
+dialog.compress.confirm2=Punkte markiert.\nMit Track->Markierte Punkte l\u00f6schen werden sie gel\u00f6scht
+dialog.compress.confirmnone=es wurden keine Punkte markiert
+dialog.deletemarked.nonefound=Es konnten keine Punkte entfernt werden
+dialog.pastecoordinates.desc=Koordinaten eingeben oder einf\u00fcgen
 dialog.pastecoordinates.coords=Koordinaten
 dialog.pastecoordinates.nothingfound=Bitte pr\u00fcfen Sie die Koordinaten und versuchen Sie es nochmals
 dialog.help.help=Weitere Informationen und Benutzeranleitungen finden Sie unter\n http://activityworkshop.net/software/gpsprune/
 dialog.about.version=Version
 dialog.about.build=Build
 dialog.pastecoordinates.coords=Koordinaten
 dialog.pastecoordinates.nothingfound=Bitte pr\u00fcfen Sie die Koordinaten und versuchen Sie es nochmals
 dialog.help.help=Weitere Informationen und Benutzeranleitungen finden Sie unter\n http://activityworkshop.net/software/gpsprune/
 dialog.about.version=Version
 dialog.about.build=Build
-dialog.about.summarytext1=GpsPrune ist ein Programm zum Laden, Darstellen und Editieren von Daten von GPS Ger\u00e4ten.
-dialog.about.summarytext2=Es wird unter der Gnu GPL zur Verf\u00fcgung gestellt, zum freien, kostenlosen und offenen Gebrauch und zur Weiterentwicklung.<br>Kopieren, Weiterverbreitung und Ver\u00e4nderungen sind erlaubt und willkommen<br>unter den in der <code>license.txt</code> Datei enthaltenen Bedingungen.
+dialog.about.summarytext1=GpsPrune ist ein Programm zum Laden, Darstellen und Editieren der Daten von GPS- Ger\u00e4ten.
+dialog.about.summarytext2=Es wird unter der Gnu GPL zur Verf\u00fcgung gestellt zum freien, kostenlosen und offenen Gebrauch und zur Weiterentwicklung.<br>Das Kopieren, Weiterverbreiten und Ver\u00e4ndern ist erlaubt und willkommen<br>unter den in der Datei <code>license.txt</code> enthaltenen Bedingungen.
 dialog.about.summarytext3=Auf der Seite <code style="font-weight:bold">http://activityworkshop.net/</code> finden Sie weitere Informationen und Bedienungsanleitungen.
 dialog.about.languages=Verf\u00fcgbare Sprachen
 dialog.about.translatedby=Deutsche \u00dcbersetzung von activityworkshop.
 dialog.about.summarytext3=Auf der Seite <code style="font-weight:bold">http://activityworkshop.net/</code> finden Sie weitere Informationen und Bedienungsanleitungen.
 dialog.about.languages=Verf\u00fcgbare Sprachen
 dialog.about.translatedby=Deutsche \u00dcbersetzung von activityworkshop.
-dialog.about.systeminfo=System Informationen
+dialog.about.systeminfo=System-Informationen
 dialog.about.systeminfo.os=Betriebssystem
 dialog.about.systeminfo.java=Java Runtime
 dialog.about.systeminfo.java3d=Java3d installiert
 dialog.about.systeminfo.povray=Povray installiert
 dialog.about.systeminfo.os=Betriebssystem
 dialog.about.systeminfo.java=Java Runtime
 dialog.about.systeminfo.java3d=Java3d installiert
 dialog.about.systeminfo.povray=Povray installiert
-dialog.about.systeminfo.exiftool=Exiftool installiert
-dialog.about.systeminfo.gpsbabel=Gpsbabel installiert
+dialog.about.systeminfo.exiftool=ExifTool installiert
+dialog.about.systeminfo.gpsbabel=GPSBabel installiert
 dialog.about.systeminfo.gnuplot=Gnuplot installiert
 dialog.about.systeminfo.gnuplot=Gnuplot installiert
-dialog.about.systeminfo.exiflib=Exif Bibliothek
+dialog.about.systeminfo.exiflib=Exif-Bibliothek
 dialog.about.systeminfo.exiflib.internal=Intern
 dialog.about.systeminfo.exiflib.internal.failed=Intern (nicht gefunden)
 dialog.about.systeminfo.exiflib.external=Extern
 dialog.about.systeminfo.exiflib.external.failed=Extern (nicht gefunden)
 dialog.about.yes=Ja
 dialog.about.no=Nein
 dialog.about.systeminfo.exiflib.internal=Intern
 dialog.about.systeminfo.exiflib.internal.failed=Intern (nicht gefunden)
 dialog.about.systeminfo.exiflib.external=Extern
 dialog.about.systeminfo.exiflib.external.failed=Extern (nicht gefunden)
 dialog.about.yes=Ja
 dialog.about.no=Nein
-dialog.about.credits=Credits
-dialog.about.credits.code=GpsPrune Code geschrieben von
-dialog.about.credits.exifcode=Exif Code von
+dialog.about.credits=Danksagung
+dialog.about.credits.code=GpsPrune-Code geschrieben von
+dialog.about.credits.exifcode=Exif-Code von
 dialog.about.credits.icons=Einige Bilder von
 dialog.about.credits.translators=Dolmetscher
 dialog.about.credits.translations=\u00dcbersetzungen mit Hilfe von
 dialog.about.credits.devtools=Entwicklungsprogramme
 dialog.about.credits.othertools=Andere Programme
 dialog.about.credits.thanks=Dank an
 dialog.about.credits.icons=Einige Bilder von
 dialog.about.credits.translators=Dolmetscher
 dialog.about.credits.translations=\u00dcbersetzungen mit Hilfe von
 dialog.about.credits.devtools=Entwicklungsprogramme
 dialog.about.credits.othertools=Andere Programme
 dialog.about.credits.thanks=Dank an
-dialog.about.readme=Liesmich
-dialog.checkversion.error=Die Versionnummer konnte nicht ermittelt werden.\nBitte pr\u00fcfen Sie die Internet Verbindung.
+dialog.about.readme=Lies mich
+dialog.checkversion.error=Die Versionnummer konnte nicht ermittelt werden.\nBitte pr\u00fcfen Sie die Internet-Verbindung.
 dialog.checkversion.uptodate=Sie haben schon die neueste Version von GpsPrune.
 dialog.checkversion.uptodate=Sie haben schon die neueste Version von GpsPrune.
-dialog.checkversion.newversion1=Eine neue Version vom GpsPrune ist jetzt verf\u00fcgbar! Die neue Version ist Version
+dialog.checkversion.newversion1=Eine neue Version von GpsPrune ist jetzt verf\u00fcgbar! Die neue Version ist Version
 dialog.checkversion.newversion2=.
 dialog.checkversion.releasedate1=Diese neue Version ist am
 dialog.checkversion.releasedate2=ver\u00f6ffentlicht worden.
 dialog.checkversion.download=Um die neue Version herunterzuladen, gehen Sie zu http://activityworkshop.net/software/gpsprune/download.html.
 dialog.keys.intro=Anstelle der Maus k\u00f6nnen Sie folgende Tastenkombinationen nutzen
 dialog.checkversion.newversion2=.
 dialog.checkversion.releasedate1=Diese neue Version ist am
 dialog.checkversion.releasedate2=ver\u00f6ffentlicht worden.
 dialog.checkversion.download=Um die neue Version herunterzuladen, gehen Sie zu http://activityworkshop.net/software/gpsprune/download.html.
 dialog.keys.intro=Anstelle der Maus k\u00f6nnen Sie folgende Tastenkombinationen nutzen
-dialog.keys.keylist=<table><tr><td>Pfeil Tasten</td><td>Karte verschieben</td></tr><tr><td>Strg + links, rechts Pfeil</td><td>Vorherigen oder n\u00e4chsten Punkt markieren</td></tr><tr><td>Strg + auf, abw\u00e4rts Pfeil</td><td>Ein- oder Auszoomen</td></tr><tr><td>Strg + Bild auf, ab</td><td>Vorherigen oder n\u00e4chsten Segment markieren</td></tr><tr><td>Strg + Pos1, Ende</td><td>Ersten oder letzten Punkt markieren</td></tr><tr><td>Entf</td><td>Aktuellen Punkt entfernen</td></tr></table>
+dialog.keys.keylist=<table><tr><td>Pfeil Tasten</td><td>Karte verschieben</td></tr><tr><td>Strg + Links-, Rechts-Pfeil</td><td>Vorherigen oder n\u00e4chsten Punkt markieren</td></tr><tr><td>Strg + Auf-, Abw\u00e4rts-Pfeil</td><td>Ein- oder Auszoomen</td></tr><tr><td>Strg + Bild auf, ab</td><td>Vorheriges oder n\u00e4chstes Segment markieren</td></tr><tr><td>Strg + Pos1, Ende</td><td>Ersten oder letzten Punkt markieren</td></tr><tr><td>Entf</td><td>Aktuellen Punkt entfernen</td></tr></table>
 dialog.keys.normalmodifier=Strg
 dialog.keys.macmodifier=Kommando
 dialog.saveconfig.desc=Die folgende Einstellungen k\u00f6nnen gespeichert werden:
 dialog.keys.normalmodifier=Strg
 dialog.keys.macmodifier=Kommando
 dialog.saveconfig.desc=Die folgende Einstellungen k\u00f6nnen gespeichert werden:
@@ -398,33 +413,32 @@ dialog.saveconfig.prune.trackdirectory=Datenverzeichnis
 dialog.saveconfig.prune.photodirectory=Fotoverzeichnis
 dialog.saveconfig.prune.languagecode=Sprachcode (DE)
 dialog.saveconfig.prune.languagefile=Sprachdatei
 dialog.saveconfig.prune.photodirectory=Fotoverzeichnis
 dialog.saveconfig.prune.languagecode=Sprachcode (DE)
 dialog.saveconfig.prune.languagefile=Sprachdatei
-dialog.saveconfig.prune.gpsdevice=GPS Ger\u00e4tename
-dialog.saveconfig.prune.gpsformat=GPS Format
-dialog.saveconfig.prune.povrayfont=Povray Font
-dialog.saveconfig.prune.metricunits=Metrische Einheiten verwenden?
-dialog.saveconfig.prune.gnuplotpath=Gnuplot Pfad
-dialog.saveconfig.prune.gpsbabelpath=Gpsbabel Pfad
-dialog.saveconfig.prune.exiftoolpath=Exiftool Pfad
-dialog.saveconfig.prune.mapsource=Kartenserver Index
+dialog.saveconfig.prune.gpsdevice=GPS-Ger\u00e4tename
+dialog.saveconfig.prune.gpsformat=GPS-Format
+dialog.saveconfig.prune.povrayfont=Povray-Font
+dialog.saveconfig.prune.gnuplotpath=Gnuplot-Pfad
+dialog.saveconfig.prune.gpsbabelpath=GPSBabel-Pfad
+dialog.saveconfig.prune.exiftoolpath=ExifTool-Pfad
+dialog.saveconfig.prune.mapsource=Kartenserver-Index
 dialog.saveconfig.prune.mapsourcelist=Kartenserver
 dialog.saveconfig.prune.diskcache=Kartenordner
 dialog.saveconfig.prune.kmzimagewidth=Bildbreite in KMZ
 dialog.saveconfig.prune.kmzimageheight=Bildh\u00f6he in KMZ
 dialog.saveconfig.prune.colourscheme=Farbschema
 dialog.saveconfig.prune.linewidth=Liniedicke
 dialog.saveconfig.prune.mapsourcelist=Kartenserver
 dialog.saveconfig.prune.diskcache=Kartenordner
 dialog.saveconfig.prune.kmzimagewidth=Bildbreite in KMZ
 dialog.saveconfig.prune.kmzimageheight=Bildh\u00f6he in KMZ
 dialog.saveconfig.prune.colourscheme=Farbschema
 dialog.saveconfig.prune.linewidth=Liniedicke
-dialog.saveconfig.prune.kmltrackcolour=KML Trackfarbe
+dialog.saveconfig.prune.kmltrackcolour=KML-Trackfarbe
 dialog.saveconfig.prune.autosavesettings=Einstellungen speichern
 dialog.saveconfig.prune.autosavesettings=Einstellungen speichern
-dialog.setpaths.intro=Sie k\u00f6nnen hier die Pfade f\u00fcr externe Applikationen setzen:
+dialog.setpaths.intro=Sie k\u00f6nnen hier die Pfade f\u00fcr externe Programme setzen:
 dialog.setpaths.found=Pfad gefunden?
 dialog.addaltitude.noaltitudes=Der markierte Bereich enth\u00e4lt keine H\u00f6henangaben
 dialog.addaltitude.desc=Hinzuzurechnende H\u00f6henverschiebung
 dialog.lookupsrtm.overwritezeros=H\u00f6henangaben von null \u00fcberschreiben?
 dialog.setpaths.found=Pfad gefunden?
 dialog.addaltitude.noaltitudes=Der markierte Bereich enth\u00e4lt keine H\u00f6henangaben
 dialog.addaltitude.desc=Hinzuzurechnende H\u00f6henverschiebung
 dialog.lookupsrtm.overwritezeros=H\u00f6henangaben von null \u00fcberschreiben?
-dialog.setcolours.intro=Klicken Sie auf eine Farbe um sie zu \u00e4ndern
+dialog.setcolours.intro=Klicken Sie auf eine Farbe, um sie zu \u00e4ndern
 dialog.setcolours.background=Hintergrund
 dialog.setcolours.borders=Umrandungen
 dialog.setcolours.lines=Linien
 dialog.setcolours.primary=Prim\u00e4r
 dialog.setcolours.background=Hintergrund
 dialog.setcolours.borders=Umrandungen
 dialog.setcolours.lines=Linien
 dialog.setcolours.primary=Prim\u00e4r
-dialog.setcolours.secondary=Second\u00e4r
+dialog.setcolours.secondary=Sekund\u00e4r
 dialog.setcolours.point=Punkte
 dialog.setcolours.selection=Bereich
 dialog.setcolours.text=Texte
 dialog.setcolours.point=Punkte
 dialog.setcolours.selection=Bereich
 dialog.setcolours.text=Texte
@@ -433,15 +447,16 @@ dialog.colourchooser.red=Rot
 dialog.colourchooser.green=Gr\u00fcn
 dialog.colourchooser.blue=Blau
 dialog.setlanguage.firstintro=Sie k\u00f6nnen entweder eine von den mitgelieferten Sprachen<p>oder eine Text-Datei ausw\u00e4hlen.
 dialog.colourchooser.green=Gr\u00fcn
 dialog.colourchooser.blue=Blau
 dialog.setlanguage.firstintro=Sie k\u00f6nnen entweder eine von den mitgelieferten Sprachen<p>oder eine Text-Datei ausw\u00e4hlen.
-dialog.setlanguage.secondintro=Sie m\u00fcssen Ihre Einstellungen speichern und dann<p>GpsPrune neu starten um die Sprache zu \u00e4ndern.
+dialog.setlanguage.secondintro=Sie m\u00fcssen Ihre Einstellungen speichern und dann<p>GpsPrune neu starten, um die Sprache zu \u00e4ndern.
 dialog.setlanguage.language=Sprache
 dialog.setlanguage.languagefile=Sprachdatei
 dialog.setlanguage.language=Sprache
 dialog.setlanguage.languagefile=Sprachdatei
-dialog.setlanguage.endmessage=Speichern Sie nun Ihre Einstellungen und starten Sie GpsPrune neu\num die neue Sprache zu verwenden.
-dialog.setlanguage.endmessagewithautosave=Starten Sie GpsPrune neu um die neue Sprache zu verwenden.
+dialog.setlanguage.endmessage=Speichern Sie nun Ihre Einstellungen und starten Sie GpsPrune neu,\num die neue Sprache zu verwenden.
+dialog.setlanguage.endmessagewithautosave=Starten Sie GpsPrune neu, um die neue Sprache zu verwenden.
 dialog.diskcache.save=Karten auf Festplatte speichern
 dialog.diskcache.dir=Kartenordner
 dialog.diskcache.createdir=Ordner anlegen
 dialog.diskcache.nocreate=Ordner wurde nicht angelegt
 dialog.diskcache.save=Karten auf Festplatte speichern
 dialog.diskcache.dir=Kartenordner
 dialog.diskcache.createdir=Ordner anlegen
 dialog.diskcache.nocreate=Ordner wurde nicht angelegt
+dialog.diskcache.cannotwrite=Kacheln k\u00f6nnen nicht im Ordner gespeichert werden
 dialog.diskcache.table.path=Pfad
 dialog.diskcache.table.usedby=Anwender
 dialog.diskcache.table.zoom=Zoom
 dialog.diskcache.table.path=Pfad
 dialog.diskcache.table.usedby=Anwender
 dialog.diskcache.table.zoom=Zoom
@@ -454,15 +469,16 @@ dialog.diskcache.maximumage=Maximales Alter (Tage)
 dialog.diskcache.deleteall=Alle Kacheln l\u00f6schen
 dialog.diskcache.deleted1=Es wurden
 dialog.diskcache.deleted2=Dateien aus dem Ordner gel\u00f6scht
 dialog.diskcache.deleteall=Alle Kacheln l\u00f6schen
 dialog.diskcache.deleted1=Es wurden
 dialog.diskcache.deleted2=Dateien aus dem Ordner gel\u00f6scht
-dialog.deletefieldvalues.intro=W\u00e4hlen Sie das Feld aus, die Sie l\u00f6schen m\u00f6chten
+dialog.deletefieldvalues.intro=W\u00e4hlen Sie das Feld aus, das Sie l\u00f6schen m\u00f6chten
+dialog.deletefieldvalues.nofields=Es sind keine Felder zu l\u00f6schen f\u00fcr diesen Bereich
 dialog.setlinewidth.text=Geben Sie die Dicke der Linien ein (1-4)
 dialog.setlinewidth.text=Geben Sie die Dicke der Linien ein (1-4)
-dialog.downloadosm.desc=Best\u00e4tigen um rohe OSM Daten f\u00fcr den Gebiet herunterzuladen:
+dialog.downloadosm.desc=Die OpenStreetMap-Daten f\u00fcr das folgende Gebiet werden heruntergeladen (.osm-Datei):
 dialog.searchwikipedianames.search=Suche nach:
 
 # 3d window
 dialog.searchwikipedianames.search=Suche nach:
 
 # 3d window
-dialog.3d.title=GpsPrune 3D Ansicht
+dialog.3d.title=GpsPrune-3D-Ansicht
 dialog.3d.altitudefactor=Vervielfachungsfaktor f\u00fcr H\u00f6hen
 dialog.3d.altitudefactor=Vervielfachungsfaktor f\u00fcr H\u00f6hen
-dialog.3dlines.title=GpsPrune Gitterlinien
+dialog.3dlines.title=GpsPrune-Gitterlinien
 dialog.3dlines.empty=Keine Linien zum Anzeigen!
 dialog.3dlines.intro=Hier sind die Linien f\u00fcr die 3D Ansicht
 
 dialog.3dlines.empty=Keine Linien zum Anzeigen!
 dialog.3dlines.intro=Hier sind die Linien f\u00fcr die 3D Ansicht
 
@@ -477,9 +493,10 @@ confirm.mergetracksegments=Trackabschnitte verbunden
 confirm.reverserange=Bereich umgekehrt
 confirm.addtimeoffset=Zeitverschiebung aufgerechnet
 confirm.addaltitudeoffset=H\u00f6henverschiebung aufgerechnet
 confirm.reverserange=Bereich umgekehrt
 confirm.addtimeoffset=Zeitverschiebung aufgerechnet
 confirm.addaltitudeoffset=H\u00f6henverschiebung aufgerechnet
-confirm.rearrangewaypoints=Wegpunkte reorganisiert
-confirm.rearrangephotos=Fotos reorganisiert
+confirm.rearrangewaypoints=Wegpunkte neu angeordnet
+confirm.rearrangephotos=Fotos neu angeordnet
 confirm.cutandmove=Bereich verschoben
 confirm.cutandmove=Bereich verschoben
+confirm.interpolate=Punkte eingef\u00fcgt
 confirm.convertnamestotimes=Wegpunktnamen umgewandelt
 confirm.saveexif.ok1=Es wurden
 confirm.saveexif.ok2=Fotodateien geschrieben
 confirm.convertnamestotimes=Wegpunktnamen umgewandelt
 confirm.saveexif.ok1=Es wurden
 confirm.saveexif.ok2=Fotodateien geschrieben
@@ -506,7 +523,7 @@ confirm.correlateaudios.multi=Audios wurden korreliert
 # Buttons
 button.ok=OK
 button.back=Zur\u00fcck
 # Buttons
 button.ok=OK
 button.back=Zur\u00fcck
-button.next=Vorw\u00e4rts
+button.next=Weiter
 button.finish=Fertig
 button.cancel=Abbrechen
 button.overwrite=\u00dcberschreiben
 button.finish=Fertig
 button.cancel=Abbrechen
 button.overwrite=\u00dcberschreiben
@@ -537,15 +554,15 @@ button.delete=Entfernen
 button.manage=Verwalten
 
 # File types
 button.manage=Verwalten
 
 # File types
-filetype.txt=TXT Dateien
-filetype.jpeg=JPG Dateien
-filetype.kmlkmz=KML, KMZ Dateien
-filetype.kml=KML Dateien
-filetype.kmz=KMZ Dateien
-filetype.gpx=GPX Dateien
-filetype.pov=POV Dateien
-filetype.svg=SVG Dateien
-filetype.audio=MP3, OGG, WAV Dateien
+filetype.txt=TXT-Dateien
+filetype.jpeg=JPG-Dateien
+filetype.kmlkmz=KML-, KMZ-Dateien
+filetype.kml=KML-Dateien
+filetype.kmz=KMZ-Dateien
+filetype.gpx=GPX-Dateien
+filetype.pov=POV-Dateien
+filetype.svg=SVG-Dateien
+filetype.audio=MP3-, OGG-, WAV-Dateien
 
 # Display components
 display.nodata=Keine Daten geladen
 
 # Display components
 display.nodata=Keine Daten geladen
@@ -559,7 +576,7 @@ details.track.numfiles=Anzahl Dateien
 details.pointdetails=Details des Punkts
 details.index.selected=Index
 details.index.of=von
 details.pointdetails=Details des Punkts
 details.index.selected=Index
 details.index.of=von
-details.nopointselection=Nichts selektiert
+details.nopointselection=Nichts ausgew\u00e4hlt
 details.photofile=Fotodatei
 details.norangeselection=Kein Bereich ausgew\u00e4hlt
 details.rangedetails=Details der Auswahl
 details.photofile=Fotodatei
 details.norangeselection=Kein Bereich ausgew\u00e4hlt
 details.rangedetails=Details der Auswahl
@@ -575,7 +592,6 @@ display.range.time.mins=m
 display.range.time.hours=h
 display.range.time.days=T
 details.range.avespeed=Durchschnittsgeschwindigkeit
 display.range.time.hours=h
 display.range.time.days=T
 details.range.avespeed=Durchschnittsgeschwindigkeit
-details.range.avemovingspeed=Durchschnittsgeschwindigkeit gleitend
 details.range.maxspeed=H\u00f6chstgeschwindigkeit
 details.range.numsegments=Anzahl Abschnitte
 details.range.pace=Tempo
 details.range.maxspeed=H\u00f6chstgeschwindigkeit
 details.range.numsegments=Anzahl Abschnitte
 details.range.pace=Tempo
@@ -583,11 +599,12 @@ details.range.gradient=Gef\u00e4lle
 details.lists.waypoints=Wegpunkte
 details.lists.photos=Fotos
 details.lists.audio=Audio
 details.lists.waypoints=Wegpunkte
 details.lists.photos=Fotos
 details.lists.audio=Audio
-details.photodetails=Fotodetails
+details.photodetails=Details des Fotos
 details.nophoto=Kein Foto ausgew\u00e4hlt
 details.photo.loading=Laden
 details.photo.bearing=Richtung
 details.media.connected=Verbunden
 details.nophoto=Kein Foto ausgew\u00e4hlt
 details.photo.loading=Laden
 details.photo.bearing=Richtung
 details.media.connected=Verbunden
+details.media.fullpath=Ganzer Pfad
 details.audiodetails=Audiodetails
 details.noaudio=Keine Audiodatei ausgew\u00e4hlt
 details.audio.file=Audiodatei
 details.audiodetails=Audiodetails
 details.noaudio=Keine Audiodatei ausgew\u00e4hlt
 details.audio.file=Audiodatei
@@ -616,11 +633,15 @@ fieldname.description=Beschreibung
 units.original=Original
 units.default=Standard
 units.metres=Meter
 units.original=Original
 units.default=Standard
 units.metres=Meter
+units.metres.short=m
 units.kilometres=Kilometer
 units.kilometres.short=km
 units.kilometres=Kilometer
 units.kilometres.short=km
-units.kmh=km/h
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.kilometresperhour.short=km/h
+units.nauticalmiles=Seemeilen
+units.nauticalmiles.short=sm
+units.nauticalmilesperhour.short=kn
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=Std
 units.degminsec=Grad-Min-Sek
 units.degmin=Grad-Min
 units.hours=Std
 units.degminsec=Grad-Min-Sek
 units.degmin=Grad-Min
@@ -646,18 +667,19 @@ undo.deletepoint=Punkt l\u00f6schen
 undo.removephoto=Foto entfernen
 undo.removeaudio=Audiodatei entfernen
 undo.deleterange=Bereich l\u00f6schen
 undo.removephoto=Foto entfernen
 undo.removeaudio=Audiodatei entfernen
 undo.deleterange=Bereich l\u00f6schen
-undo.compress=Track komprimieren
+undo.croptrack=Track zuschneiden
+undo.deletemarked=Punkte l\u00f6schen
 undo.insert=Punkte hinzuf\u00fcgen
 undo.reverse=Bereich umdrehen
 undo.mergetracksegments=Trackabschnitte verbinden
 undo.addtimeoffset=Zeitverschiebung aufrechnen
 undo.addaltitudeoffset=H\u00f6henverschiebung aufrechnen
 undo.insert=Punkte hinzuf\u00fcgen
 undo.reverse=Bereich umdrehen
 undo.mergetracksegments=Trackabschnitte verbinden
 undo.addtimeoffset=Zeitverschiebung aufrechnen
 undo.addaltitudeoffset=H\u00f6henverschiebung aufrechnen
-undo.rearrangewaypoints=Wegpunkte reorganisieren
+undo.rearrangewaypoints=Wegpunkte neu anordnen
 undo.cutandmove=Bereich verschieben
 undo.connect=verbinden
 undo.disconnect=trennen
 undo.correlatephotos=Fotos korrelieren
 undo.cutandmove=Bereich verschieben
 undo.connect=verbinden
 undo.disconnect=trennen
 undo.correlatephotos=Fotos korrelieren
-undo.rearrangephotos=Fotos reorganisieren
+undo.rearrangephotos=Fotos neu anordnen
 undo.createpoint=Punkt erzeugen
 undo.rotatephoto=Foto umdrehen
 undo.convertnamestotimes=Namen in Zeitstempel umwandeln
 undo.createpoint=Punkt erzeugen
 undo.rotatephoto=Foto umdrehen
 undo.convertnamestotimes=Namen in Zeitstempel umwandeln
@@ -669,8 +691,8 @@ undo.correlateaudios=Audios korrelieren
 error.save.dialogtitle=Fehler beim Speichern
 error.save.nodata=Keine Daten zum Speichern vorhanden
 error.save.failed=Speichern von Daten in Datei fehlgeschlagen
 error.save.dialogtitle=Fehler beim Speichern
 error.save.nodata=Keine Daten zum Speichern vorhanden
 error.save.failed=Speichern von Daten in Datei fehlgeschlagen
-error.saveexif.filenotfound=Foto Datei nicht gefunden
-error.saveexif.cannotoverwrite1=Foto Datei
+error.saveexif.filenotfound=Bilddatei nicht gefunden
+error.saveexif.cannotoverwrite1=Bilddatei
 error.saveexif.cannotoverwrite2=ist schreibgesch\u00fctzt. Als Kopie speichern?
 error.saveexif.failed1=
 error.saveexif.failed2=Bilder konnten nicht gespeichert werden
 error.saveexif.cannotoverwrite2=ist schreibgesch\u00fctzt. Als Kopie speichern?
 error.saveexif.failed1=
 error.saveexif.failed2=Bilder konnten nicht gespeichert werden
@@ -679,24 +701,24 @@ error.saveexif.forced2=der Bilder musste das Speichern erzwungen werden
 error.load.dialogtitle=Fehler beim Laden
 error.load.noread=Datei konnte nicht gelesen werden
 error.load.nopoints=Keine g\u00fcltigen Daten in Datei gefunden
 error.load.dialogtitle=Fehler beim Laden
 error.load.noread=Datei konnte nicht gelesen werden
 error.load.nopoints=Keine g\u00fcltigen Daten in Datei gefunden
-error.load.unknownxml=Unbekanntes xml Format:
-error.load.noxmlinzip=Keine xml Datei in Zip Datei gefunden
+error.load.unknownxml=Unbekanntes XML-Format:
+error.load.noxmlinzip=Keine XML-Datei in Zip-Datei gefunden
 error.load.othererror=Fehler beim Lesen der Datei:
 error.jpegload.dialogtitle=Fehler beim Laden von Fotos
 error.jpegload.nofilesfound=Keine Dateien gefunden
 error.load.othererror=Fehler beim Lesen der Datei:
 error.jpegload.dialogtitle=Fehler beim Laden von Fotos
 error.jpegload.nofilesfound=Keine Dateien gefunden
-error.jpegload.nojpegsfound=Keine Jpeg Dateien gefunden
-error.jpegload.nogpsfound=Keine GPS Information gefunden
-error.jpegload.exifreadfailed=EXIF Aufruf fehlgeschlagen. Keine EXIF Information k\u00f6nnen gelesen werden\nohne einen internen oder externen Bibliothek.
+error.jpegload.nojpegsfound=Keine JPG-Dateien gefunden
+error.jpegload.nogpsfound=Keine GPS-Information gefunden
+error.jpegload.exifreadfailed=Exif-Aufruf fehlgeschlagen. Exif-Information k\u00f6nnen nicht gelesen werden\nwenn nicht eine interne oder externe Bibliothek vorhanden ist.
 error.audioload.nofilesfound=Keine Audiodateien gefunden
 error.gpsload.unknown=Unbekannter Fehler
 error.undofailed.title=Undo fehlgeschlagen
 error.undofailed.text=Operation konnte nicht r\u00fcckg\u00e4ngig gemacht werden
 error.function.noop.title=Funktion hat nichts bewirkt
 error.audioload.nofilesfound=Keine Audiodateien gefunden
 error.gpsload.unknown=Unbekannter Fehler
 error.undofailed.title=Undo fehlgeschlagen
 error.undofailed.text=Operation konnte nicht r\u00fcckg\u00e4ngig gemacht werden
 error.function.noop.title=Funktion hat nichts bewirkt
-error.rearrange.noop=Die Punkte zu reorganisieren hatte keinen Effekt
+error.rearrange.noop=Die Neuanordnung der Punkte hatte keinen Effekt
 error.function.notavailable.title=Funktion nicht verf\u00fcgbar
 error.function.notavailable.title=Funktion nicht verf\u00fcgbar
-error.function.nojava3d=Diese Funktion ben\u00f6tigt die Java3d Library,\nvon Sun.com erh\u00e4ltlich.
+error.function.nojava3d=Diese Funktion ben\u00f6tigt die Java3d-Library,\ndie bei Sun.com erh\u00e4ltlich ist.
 error.3d=Ein Fehler ist bei der 3D Darstellung aufgetreten
 error.3d=Ein Fehler ist bei der 3D Darstellung aufgetreten
-error.readme.notfound=Liesmich Datei nicht gefunden
+error.readme.notfound=Liesmich-Datei nicht gefunden
 error.osmimage.dialogtitle=Laden von Karten-Bildern fehlgeschlagen
 error.osmimage.failed=Laden von Karten-Bildern fehlgeschlagen. Bitte pr\u00fcfen Sie die Internetverbindung.
 error.language.wrongfile=Die ausgew\u00e4hlte Datei scheint keine Sprachdatei f\u00fcr GpsPrune zu sein
 error.osmimage.dialogtitle=Laden von Karten-Bildern fehlgeschlagen
 error.osmimage.failed=Laden von Karten-Bildern fehlgeschlagen. Bitte pr\u00fcfen Sie die Internetverbindung.
 error.language.wrongfile=Die ausgew\u00e4hlte Datei scheint keine Sprachdatei f\u00fcr GpsPrune zu sein
@@ -705,7 +727,9 @@ error.lookupsrtm.nonefound=Keine H\u00f6hendaten verf\u00fcgbar f\u00fcr diese P
 error.lookupsrtm.nonerequired=Alle Punkte haben schon H\u00f6hendaten
 error.gpsies.uploadnotok=Der Gpsies Server hat geantwortet
 error.gpsies.uploadfailed=Das Hochladen ist fehlgeschlagen
 error.lookupsrtm.nonerequired=Alle Punkte haben schon H\u00f6hendaten
 error.gpsies.uploadnotok=Der Gpsies Server hat geantwortet
 error.gpsies.uploadfailed=Das Hochladen ist fehlgeschlagen
+error.showphoto.failed=Das Foto konnte nicht geladen werden
 error.playaudiofailed=Das Abspielen der Audiodatei ist fehlgeschlagen
 error.cache.notthere=Der Ordner wurde nicht gefunden
 error.cache.empty=Der Ordner ist leer
 error.cache.cannotdelete=Es konnte keine Kacheln gel\u00f6scht werden
 error.playaudiofailed=Das Abspielen der Audiodatei ist fehlgeschlagen
 error.cache.notthere=Der Ordner wurde nicht gefunden
 error.cache.empty=Der Ordner ist leer
 error.cache.cannotdelete=Es konnte keine Kacheln gel\u00f6scht werden
+error.interpolate.invalidparameter=Die Anzahl der Punkte muss zwischen 1 und 1000 liegen
index 38f0538b5599cc58b37b35a6ec830946fbcfc466..caa5bd6a17faadb83a67042c2f89dbdaa999929a 100644 (file)
@@ -3,37 +3,37 @@
 
 # Menu entries
 menu.file=File
 
 # Menu entries
 menu.file=File
-menu.file.addphotos=Fötelis innätue
+menu.file.addphotos=F\u00f6telis inn\u00e4tue
 menu.file.recentfiles=Letzschti aagluegte Files
 menu.file.save=Als Text Speichere
 menu.file.recentfiles=Letzschti aagluegte Files
 menu.file.save=Als Text Speichere
-menu.file.exit=Beände
+menu.file.exit=Be\u00e4nde
 menu.track=Track
 menu.track.undo=Undo
 menu.track=Track
 menu.track.undo=Undo
-menu.track.clearundo=Undo-Liste lösche
-menu.track.deletemarked=Komprimierte Punkte lösche
+menu.track.clearundo=Undo-Liste l\u00f6sche
+menu.track.markrectangle=P\u00fcnkte inem Viereck markiere
+menu.track.deletemarked=Markierte P\u00fcnkte l\u00f6sche
 menu.track.rearrange=Waypoints reorganisiere
 menu.track.rearrange.start=Alli zum Aafang
 menu.track.rearrange.end=Alli zum Ã„nde
 menu.track.rearrange=Waypoints reorganisiere
 menu.track.rearrange.start=Alli zum Aafang
 menu.track.rearrange.end=Alli zum Ã„nde
-menu.track.rearrange.nearest=Jede zum nöchsti Trackpunkt
+menu.track.rearrange.nearest=Jede zum n\u00f6chsti Trackpunkt
 menu.range=Beriich
 menu.range.all=Alles selektiere
 menu.range=Beriich
 menu.range.all=Alles selektiere
-menu.range.none=Nüüt selektiere
-menu.range.start=Start setzä
-menu.range.end=Stopp setzä
-menu.range.deleterange=Beriich lösche
-menu.range.interpolate=Interpoliere
-menu.range.average=Durchschnitt uusrächne
-menu.range.reverse=Beriich umdrähie
-menu.range.mergetracksegments=Track Segmänte merge
+menu.range.none=N\u00fc\u00fct selektiere
+menu.range.start=Start setz\u00e4
+menu.range.end=Stopp setz\u00e4
+function.interpolate=P\u00fcnkte interpoliere
+menu.range.average=Durchschnitt uusr\u00e4chne
+menu.range.reverse=Beriich umdr\u00e4hie
+menu.range.mergetracksegments=Track Segm\u00e4nte merge
 menu.range.cutandmove=Schniide und move
 menu.point=Punkt
 menu.point.editpoint=Punkt editiere
 menu.range.cutandmove=Schniide und move
 menu.point=Punkt
 menu.point.editpoint=Punkt editiere
-menu.point.deletepoint=Punkt lösche
-menu.photo=Föteli
-menu.photo.saveexif=Exif Date speicherä
-function.connecttopoint=Mitem Punkt verbindä
-function.disconnectfrompoint=Vonem Punkt trännä
-function.removephoto=Föteli entfernä
+menu.point.deletepoint=Punkt l\u00f6sche
+menu.photo=F\u00f6teli
+menu.photo.saveexif=Exif Date speicher\u00e4
+function.connecttopoint=Mitem Punkt verbind\u00e4
+function.disconnectfrompoint=Vonem Punkt tr\u00e4nn\u00e4
+function.removephoto=F\u00f6teli entfern\u00e4
 menu.audio=Audio
 menu.view=Aasicht
 menu.view.showsidebars=Seiteleischten aazeige
 menu.audio=Audio
 menu.view=Aasicht
 menu.view.showsidebars=Seiteleischten aazeige
@@ -47,11 +47,12 @@ menu.map.zoomin=Innezoome
 menu.map.zoomout=Uusezoome
 menu.map.zoomfull=Zoome zum ganzes Bild
 menu.map.newpoint=Noii Punkt
 menu.map.zoomout=Uusezoome
 menu.map.zoomfull=Zoome zum ganzes Bild
 menu.map.newpoint=Noii Punkt
-menu.map.drawpoints=Noii Punkte uufzeichnä
-menu.map.connect=Trackpünktli verbindä
+menu.map.drawpoints=Noii P\u00fcnktli uufzeichn\u00e4
+menu.map.connect=Trackp\u00fcnktli verbind\u00e4
 menu.map.autopan=Autopan
 menu.map.autopan=Autopan
-menu.map.showmap=Karte zeigä
+menu.map.showmap=Karte zeig\u00e4
 menu.map.showscalebar=Massstab aazeige
 menu.map.showscalebar=Massstab aazeige
+menu.map.editmode=P\u00fcnkte verschiebe
 
 # Alt keys for menus
 altkey.menu.file=F
 
 # Alt keys for menus
 altkey.menu.file=F
@@ -59,7 +60,7 @@ altkey.menu.track=T
 altkey.menu.range=B
 altkey.menu.point=P
 altkey.menu.view=A
 altkey.menu.range=B
 altkey.menu.point=P
 altkey.menu.view=A
-altkey.menu.photo=F
+altkey.menu.photo=L
 altkey.menu.audio=U
 altkey.menu.settings=I
 altkey.menu.help=H
 altkey.menu.audio=U
 altkey.menu.settings=I
 altkey.menu.help=H
@@ -74,50 +75,52 @@ shortcut.menu.range.all=A
 shortcut.menu.help.help=H
 
 # Functions
 shortcut.menu.help.help=H
 
 # Functions
-function.open=File Ã¶ffne
+function.open=File \u00f6ffne
 function.importwithgpsbabel=mit GPSBabel importiere
 function.loadfromgps=uusem GPS lade
 function.sendtogps=zum GPS schicke
 function.importwithgpsbabel=mit GPSBabel importiere
 function.loadfromgps=uusem GPS lade
 function.sendtogps=zum GPS schicke
-function.exportkml=KML exportierä
-function.exportgpx=GPX exportierä
-function.exportpov=POV exportierä
-function.exportsvg=SVG exportierä
+function.exportkml=KML exportier\u00e4
+function.exportgpx=GPX exportier\u00e4
+function.exportpov=POV exportier\u00e4
+function.exportsvg=SVG exportier\u00e4
 function.editwaypointname=Waypoint Name editiere
 function.editwaypointname=Waypoint Name editiere
-function.compress=Track komprimierä
+function.compress=Track komprimier\u00e4
+function.deleterange=Beriich l\u00f6sche
+function.croptrack=Track zuschniide
 function.addtimeoffset=Ziitverschiebig zutue
 function.addtimeoffset=Ziitverschiebig zutue
-function.addaltitudeoffset=Höchiverschiebig zutue
-function.findwaypoint=Waypoint suechä
-function.convertnamestotimes=Waypointname ins Ziitstämple verwondle
-function.deletefieldvalues=Werte von nem Fäld lösche
+function.addaltitudeoffset=H\u00f6chiverschiebig zutue
+function.findwaypoint=Waypoint suech\u00e4
+function.convertnamestotimes=Waypointname ins Ziitst\u00e4mple verwondle
+function.deletefieldvalues=Werte von nem F\u00e4ld l\u00f6sche
 function.pastecoordinates=Noii Koordinaten iigebe
 function.charts=Diagramme
 function.pastecoordinates=Noii Koordinaten iigebe
 function.charts=Diagramme
-function.show3d=Drüü-D Aasicht
-function.distances=Entfärnige
-function.fullrangedetails=Zuesätzlichi Beriichinfos
-function.setmapbg=Karte Hintegrund setzä
-function.getgpsies=Gpsies Tracks holä
-function.uploadgpsies=Date zum Gpsies uufaladä
-function.lookupsrtm=Höhendate vonem SRTM hole
-function.getwikipedia=Im Wikipedia in dr Nöchi naaluege
+function.show3d=Dr\u00fc\u00fc-D Aasicht
+function.distances=Entf\u00e4rnige
+function.fullrangedetails=Zues\u00e4tzlichi Beriichinfos
+function.setmapbg=Karte Hintegrund setz\u00e4
+function.getgpsies=Gpsies Tracks hol\u00e4
+function.uploadgpsies=Date zum Gpsies uufalad\u00e4
+function.lookupsrtm=H\u00f6hendate vonem SRTM hole
+function.getwikipedia=Im Wikipedia in dr N\u00f6chi naaluege
 function.searchwikipedianames=Wikipedia mit Name durasueche
 function.searchwikipedianames=Wikipedia mit Name durasueche
-function.downloadosm=OSM-Date für dere Gebiet abaladä
-function.duplicatepoint=Punkt verdopplä
-function.correlatephotos=Fötelis korrelierä
-function.rearrangephotos=Fötelis reorganisierä
-function.rotatephotoleft=Föteli nach Links dräyä
-function.rotatephotoright=Föteli nach Rächts dräyä
-function.photopopup=Fötelifänschter aazeigä
-function.ignoreexifthumb=Exif Vorschaubildli ignorierä
+function.downloadosm=OSM-Date f\u00fcr dere Gebiet abalad\u00e4
+function.duplicatepoint=Punkt verdoppl\u00e4
+function.correlatephotos=F\u00f6telis korrelier\u00e4
+function.rearrangephotos=F\u00f6telis reorganisier\u00e4
+function.rotatephotoleft=F\u00f6teli nach Links dr\u00e4y\u00e4
+function.rotatephotoright=F\u00f6teli nach R\u00e4chts dr\u00e4y\u00e4
+function.photopopup=F\u00f6telif\u00e4nschter aazeig\u00e4
+function.ignoreexifthumb=Exif Vorschaubildli ignorier\u00e4
 function.loadaudio=Audiofiles lade
 function.loadaudio=Audiofiles lade
-function.removeaudio=Audiodatei entfernä
-function.correlateaudios=Audios korrelierä
-function.playaudio=Audiofile abspielä
-function.stopaudio=Abspielen abbrächä
-function.setkmzimagesize=Bildligrösse inem KMZ setzä
-function.setpaths=Programmepfade setzä
-function.setcolours=Farben setzä
-function.setlinewidth=Liniedicke setzä
-function.setlanguage=Sproch setzä
+function.removeaudio=Audiodatei entfern\u00e4
+function.correlateaudios=Audios korrelier\u00e4
+function.playaudio=Audiofile abspiel\u00e4
+function.stopaudio=Abspielen abbr\u00e4ch\u00e4
+function.setkmzimagesize=Bildligr\u00f6sse inem KMZ setz\u00e4
+function.setpaths=Programmepfade setz\u00e4
+function.setcolours=Farben setz\u00e4
+function.setlinewidth=Liniedicke setz\u00e4
+function.setlanguage=Sproch setz\u00e4
 function.help=Hilfe
 function.showkeys=Tastekombinatione aazeige
 function.about=Ãœber GpsPrune
 function.help=Hilfe
 function.showkeys=Tastekombinatione aazeige
 function.about=Ãœber GpsPrune
@@ -127,164 +130,167 @@ function.diskcache=Karten uufem Disk speichere
 function.managetilecache=Kartebildli verwolte
 
 # Dialogs
 function.managetilecache=Kartebildli verwolte
 
 # Dialogs
-dialog.exit.confirm.title=GpsPrune beände
-dialog.exit.confirm.text=Ihri Date sind nonig gspeicheret worde. Wend Sie trotzdem s Programm beände?
-dialog.openappend.title=Date aahänge oder ersätze
-dialog.openappend.text=Häng diese Date zur aktuelli Daten aa?
-dialog.deletepoint.title=Punkt löschä
-dialog.deletepoint.deletephoto=s Föteli vonem Punkt au löschä?
-dialog.deletephoto.title=Föteli entfernä
-dialog.deletephoto.deletepoint=Punkt vonem Föteli au löschä?
+dialog.exit.confirm.title=GpsPrune be\u00e4nde
+dialog.exit.confirm.text=Ihri Date sind nonig gspeicheret worde. Wend Sie trotzdem s Programm be\u00e4nde?
+dialog.openappend.title=Date aah\u00e4nge oder ers\u00e4tze
+dialog.openappend.text=H\u00e4ng diese Date zur aktuelli Daten aa?
+dialog.deletepoint.title=Punkt l\u00f6sch\u00e4
+dialog.deletepoint.deletephoto=s F\u00f6teli vonem Punkt au l\u00f6sch\u00e4?
+dialog.deletephoto.title=F\u00f6teli entfern\u00e4
+dialog.deletephoto.deletepoint=Punkt vonem F\u00f6teli au l\u00f6sch\u00e4?
+dialog.deleteaudio.deletepoint=Punkt vonem Audio au l\u00f6sch\u00e4?
 dialog.openoptions.title=Öffne Optionen
 dialog.openoptions.filesnippet=Extrakt vom File
 dialog.openoptions.title=Öffne Optionen
 dialog.openoptions.filesnippet=Extrakt vom File
-dialog.load.table.field=Fäld
+dialog.load.table.field=F\u00e4ld
 dialog.load.table.datatype=Date Typ
 dialog.load.table.description=Beschriibig
 dialog.load.table.datatype=Date Typ
 dialog.load.table.description=Beschriibig
-dialog.delimiter.label=Fäld Trennzeiche
+dialog.delimiter.label=F\u00e4ld Trennzeiche
 dialog.delimiter.comma=Komma ,
 dialog.delimiter.tab=Tab
 dialog.delimiter.space=Abstand
 dialog.delimiter.semicolon=Strichpunkt ;
 dialog.delimiter.other=Andere
 dialog.openoptions.deliminfo.records=Rekords, mit
 dialog.delimiter.comma=Komma ,
 dialog.delimiter.tab=Tab
 dialog.delimiter.space=Abstand
 dialog.delimiter.semicolon=Strichpunkt ;
 dialog.delimiter.other=Andere
 dialog.openoptions.deliminfo.records=Rekords, mit
-dialog.openoptions.deliminfo.fields=Fäldere
+dialog.openoptions.deliminfo.fields=F\u00e4ldere
 dialog.openoptions.deliminfo.norecords=Kei Rekords
 dialog.openoptions.deliminfo.norecords=Kei Rekords
-dialog.openoptions.altitudeunits=Höchi Masseiheite
-dialog.open.contentsdoubled=Dieses File hät zwei Kopien von jädem Punkt,\neimol als Waypoint und eimol als Trackpunkt.
-dialog.selecttracks.intro=Wählet Sie die Tracks uus zum ladä
+dialog.openoptions.altitudeunits=H\u00f6chi Masseiheite
+dialog.open.contentsdoubled=Dieses File h\u00e4t zwei Kopien von j\u00e4dem Punkt,\neimol als Waypoint und eimol als Trackpunkt.
+dialog.selecttracks.intro=W\u00e4hlet Sie die Tracks uus zum lad\u00e4
 dialog.selecttracks.noname=Unbenannt
 dialog.jpegload.subdirectories=Subordnern au
 dialog.selecttracks.noname=Unbenannt
 dialog.jpegload.subdirectories=Subordnern au
-dialog.jpegload.loadjpegswithoutcoords=Au Fötelis ohni Koordinate
-dialog.jpegload.loadjpegsoutsidearea=Au Fötelis uuserhalb vonem Track
-dialog.jpegload.progress.title=Fötelis lade
-dialog.jpegload.progress=Bitte warte während die Fötelis durägsucht werde
+dialog.jpegload.loadjpegswithoutcoords=Au F\u00f6telis ohni Koordinate
+dialog.jpegload.loadjpegsoutsidearea=Au F\u00f6telis uuserhalb vonem Track
+dialog.jpegload.progress.title=F\u00f6telis lade
+dialog.jpegload.progress=Bitte warte w\u00e4hrend die F\u00f6telis dur\u00e4gsucht werde
 dialog.gpsload.nogpsbabel=Kei gpsbabel Programm gfunde. Wiiter?
 dialog.gpsload.device=Device Name
 dialog.gpsload.format=Format
 dialog.gpsload.getwaypoints=Waypoints lade
 dialog.gpsload.gettracks=Tracks lade
 dialog.gpsload.nogpsbabel=Kei gpsbabel Programm gfunde. Wiiter?
 dialog.gpsload.device=Device Name
 dialog.gpsload.format=Format
 dialog.gpsload.getwaypoints=Waypoints lade
 dialog.gpsload.gettracks=Tracks lade
-dialog.gpsload.save=nach nem File speicherä
+dialog.gpsload.save=nach nem File speicher\u00e4
 dialog.gpssend.sendwaypoints=Waypoints schicke
 dialog.gpssend.sendtracks=Tracks schicke
 dialog.gpssend.trackname=Track Name
 dialog.gpssend.sendwaypoints=Waypoints schicke
 dialog.gpssend.sendtracks=Tracks schicke
 dialog.gpssend.trackname=Track Name
-dialog.saveoptions.title=File speicherä
-dialog.save.fieldstosave=Fälder zu speicherä
-dialog.save.table.field=Fäld
+dialog.saveoptions.title=File speicher\u00e4
+dialog.save.fieldstosave=F\u00e4lder zu speicher\u00e4
+dialog.save.table.field=F\u00e4ld
 dialog.save.table.hasdata=Het Date
 dialog.save.table.hasdata=Het Date
-dialog.save.table.save=Speicherä
-dialog.save.headerrow=Titel Ziile speicherä
+dialog.save.table.save=Speicher\u00e4
+dialog.save.headerrow=Titel Ziile speicher\u00e4
 dialog.save.coordinateunits=Koordinate Massiiheite
 dialog.save.coordinateunits=Koordinate Massiiheite
-dialog.save.altitudeunits=Höchi Massiiheite
-dialog.save.timestampformat=Ziitstämpelformat
+dialog.save.altitudeunits=H\u00f6chi Massiiheite
+dialog.save.timestampformat=Ziitst\u00e4mpelformat
 dialog.save.overwrite.title=s'File existiert scho
 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.save.notypesselected=Kei Punktetype sin uusgewählt worde
-dialog.exportkml.text=Titel für die Date
-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.save.overwrite.text=s'File existiert scho. Sind Sie sicher, Sie wend s'File \u00fcberschriibe?
+dialog.save.notypesselected=Kei Punktetype sin uusgew\u00e4hlt worde
+dialog.exportkml.text=Titel f\u00fcr die Date
+dialog.exportkml.altitude=Absolut H\u00f6chiinformation (f\u00fcrs Fliege)
+dialog.exportkml.kmz=Date ins kmz File komprimier\u00e4
+dialog.exportkml.exportimages=Bildli ins Kmz exportier\u00e4
 dialog.exportkml.trackcolour=Trackfarb
 dialog.exportgpx.name=Name
 dialog.exportgpx.desc=Beschriibig
 dialog.exportkml.trackcolour=Trackfarb
 dialog.exportgpx.name=Name
 dialog.exportgpx.desc=Beschriibig
-dialog.exportgpx.includetimestamps=Au Ziitstämpel
-dialog.exportgpx.copysource=Xml-Quälle kopierä
+dialog.exportgpx.includetimestamps=Au Ziitst\u00e4mpel
+dialog.exportgpx.copysource=Xml-Qu\u00e4lle kopier\u00e4
 dialog.exportgpx.encoding=Enkodierig
 dialog.exportgpx.encoding.system=System
 dialog.exportgpx.encoding.utf8=UTF-8
 dialog.exportgpx.encoding=Enkodierig
 dialog.exportgpx.encoding.system=System
 dialog.exportgpx.encoding.utf8=UTF-8
-dialog.exportpov.text=Gäbet Sie die Parameter ii fürs POV Export
+dialog.exportpov.text=G\u00e4bet Sie die Parameter ii f\u00fcrs POV Export
 dialog.exportpov.font=Font
 dialog.exportpov.camerax=Kamera X
 dialog.exportpov.cameray=Kamera Y
 dialog.exportpov.cameraz=Kamera Z
 dialog.exportpov.modelstyle=Modellstil
 dialog.exportpov.font=Font
 dialog.exportpov.camerax=Kamera X
 dialog.exportpov.cameray=Kamera Y
 dialog.exportpov.cameraz=Kamera Z
 dialog.exportpov.modelstyle=Modellstil
-dialog.exportpov.ballsandsticks=Bälle und Schtange
-dialog.exportpov.tubesandwalls=Röhre und Wände
-dialog.exportpov.warningtracksize=Dieser Track hät mega viele Punkte, die Java3D villiicht nöd chann bearbeite.\nSind Sie sicher, Sie wend trotzdem fortsetze?
-dialog.exportsvg.text=Wählet Sie die Parameter fürs SVG Export uus
+dialog.exportpov.ballsandsticks=B\u00e4lle und Schtange
+dialog.exportpov.tubesandwalls=R\u00f6hre und W\u00e4nde
+dialog.exportpov.warningtracksize=Dieser Track h\u00e4t mega viele P\u00fcnkte, die Java3D villiicht n\u00f6d chann bearbeite.\nSind Sie sicher, Sie wend trotzdem fortsetze?
+dialog.exportsvg.text=W\u00e4hlet Sie die Parameter f\u00fcrs SVG Export uus
 dialog.exportsvg.phi=Richtigswinkel \u03D5
 dialog.exportsvg.theta=Neigigswinkel \u03B8
 dialog.exportsvg.phi=Richtigswinkel \u03D5
 dialog.exportsvg.theta=Neigigswinkel \u03B8
-dialog.exportsvg.gradients=Farbeverläufe verwände
+dialog.exportsvg.gradients=Farbeverl\u00e4ufe verw\u00e4nde
 dialog.pointtype.desc=Folgende Punkttype speichere:
 dialog.pointtype.desc=Folgende Punkttype speichere:
-dialog.pointtype.track=Trackpunkte
+dialog.pointtype.track=Trackp\u00fcnkte
 dialog.pointtype.waypoint=Waypoints
 dialog.pointtype.waypoint=Waypoints
-dialog.pointtype.photo=Fötelipunkte
-dialog.pointtype.audio=Audiopunkte
+dialog.pointtype.photo=F\u00f6telip\u00fcnkte
+dialog.pointtype.audio=Audiop\u00fcnkte
 dialog.pointtype.selection=Nur aktuelli Beriich
 dialog.pointtype.selection=Nur aktuelli Beriich
-dialog.confirmreversetrack.title=Umdrehig bestätige
-dialog.confirmreversetrack.text=Diese Daten enthalte Ziitstämpel Informatione, die bei dr Umkehrig usser Reihefolge erschiene würdi.\nSind Sie sicher, Sie wend dn Beriich umkehre?
-dialog.confirmcutandmove.title=Move bestätige
-dialog.confirmcutandmove.text=Diese Daten enthalte Ziitstämpel Informatione, die bei dr Move usser Reihefolge erschiene würdi.\nSind Sie sicher, Sie wend dn Beriich move?
-dialog.interpolate.title=Punkte interpoliere
-dialog.interpolate.parameter.text=Aazahl Punkte zum innätue zwüschet den selektierten Punkten
+dialog.confirmreversetrack.title=Umdrehig best\u00e4tige
+dialog.confirmreversetrack.text=Diese Daten enthalte Ziitst\u00e4mpel Informatione, die bei dr Umkehrig usser Reihefolge erschiene w\u00fcrdi.\nSind Sie sicher, Sie wend dn Beriich umkehre?
+dialog.confirmcutandmove.title=Move best\u00e4tige
+dialog.confirmcutandmove.text=Diese Daten enthalte Ziitst\u00e4mpel Informatione, die bei dr Move usser Reihefolge erschiene w\u00fcrdi.\nSind Sie sicher, Sie wend dn Beriich move?
+dialog.interpolate.parameter.text=Aazahl P\u00fcnkte zum inn\u00e4tue zw\u00fcschet den selektierten P\u00fcnkten
+dialog.interpolate.betweenwaypoints=Zw\u00fcschet d Waypoints interpoliere?
 dialog.undo.title=Undo Operation(e)
 dialog.undo.title=Undo Operation(e)
-dialog.undo.pretext=Selektiere die Operatione die rückgängig gmacht söllti werde.
-dialog.undo.none.title=Undo nöd möglich
-dialog.undo.none.text=Keini Operatione könne rückgängig gmacht werde.
-dialog.clearundo.title=Undo-Liste löschä
-dialog.clearundo.text=Sind Sie sicher, Sie wend die Undo-Liste lösche?\nAlle Undo Infos werdet verlore gah!
-dialog.pointedit.title=Punkt editierä
-dialog.pointedit.text=Wählet Sie jäden Fäld uus zu editiere, und mitem 'Editierä' Chnopf den Wert Ã¤ndere
-dialog.pointedit.table.field=Fäld
+dialog.undo.pretext=Selektiere die Operatione die r\u00fcckg\u00e4ngig gmacht s\u00f6llti werde.
+dialog.undo.none.title=Undo n\u00f6d m\u00f6glich
+dialog.undo.none.text=Keini Operatione k\u00f6nne r\u00fcckg\u00e4ngig gmacht werde.
+dialog.clearundo.title=Undo-Liste l\u00f6sch\u00e4
+dialog.clearundo.text=Sind Sie sicher, Sie wend die Undo-Liste l\u00f6sche?\nAlle Undo Infos werdet verlore gah!
+dialog.pointedit.title=Punkt editier\u00e4
+dialog.pointedit.text=W\u00e4hlet Sie j\u00e4den F\u00e4ld uus zu editiere, und mitem 'Editier\u00e4' Chnopf den Wert \u00e4ndere
+dialog.pointedit.table.field=F\u00e4ld
 dialog.pointedit.table.value=Wert
 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.pointedit.table.changed=Ge\u00e4ndert
+dialog.pointedit.changevalue.text=Gebet Sie den neuen Wert f\u00fcr diesen F\u00e4ld ina
+dialog.pointedit.changevalue.title=F\u00e4ld editiere
 dialog.pointnameedit.name=Waypoint Name
 dialog.pointnameedit.uppercase=GROSS gschriebe
 dialog.pointnameedit.lowercase=chli gschriebe
 dialog.pointnameedit.name=Waypoint Name
 dialog.pointnameedit.uppercase=GROSS gschriebe
 dialog.pointnameedit.lowercase=chli gschriebe
-dialog.pointnameedit.sentencecase=Gmischt Gschriebe
+dialog.pointnameedit.titlecase=Gmischt Gschriebe
 dialog.addtimeoffset.add=Ziit zutue
 dialog.addtimeoffset.subtract=Ziit davo neh
 dialog.addtimeoffset.days=Tage
 dialog.addtimeoffset.hours=Schtunde
 dialog.addtimeoffset.minutes=Minute
 dialog.addtimeoffset.add=Ziit zutue
 dialog.addtimeoffset.subtract=Ziit davo neh
 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.addtimeoffset.notimestamps=Ziitverschiebig n\u00f6d m\u00f6glech wil dr Beriich kei Ziitinfo h\u00e4t
 dialog.findwaypoint.intro=Gebet Sie en Teil vonem Namen ina
 dialog.findwaypoint.search=Sueche
 dialog.findwaypoint.intro=Gebet Sie en Teil vonem Namen ina
 dialog.findwaypoint.search=Sueche
-dialog.saveexif.title=Exif go speicherä
-dialog.saveexif.intro=Wählet Sie die Fötelis uus zum speicherä
-dialog.saveexif.nothingtosave=Koordinaten sin nöd geänderet, nüüt zum speicherä
+dialog.saveexif.title=Exif go speicher\u00e4
+dialog.saveexif.intro=W\u00e4hlet Sie die F\u00f6telis uus zum speicher\u00e4
+dialog.saveexif.nothingtosave=Koordinaten sin n\u00f6d ge\u00e4nderet, n\u00fc\u00fct zum speicher\u00e4
 dialog.saveexif.noexiftool=Kei exiftool Programm gfunde. Wiiter?
 dialog.saveexif.noexiftool=Kei exiftool Programm gfunde. Wiiter?
-dialog.saveexif.table.photoname=Föteli Name
+dialog.saveexif.table.photoname=F\u00f6teli Name
 dialog.saveexif.table.status=Status
 dialog.saveexif.table.status=Status
-dialog.saveexif.table.save=Speicherä
-dialog.saveexif.photostatus.connected=Verbundä
-dialog.saveexif.photostatus.disconnected=Gtrännt
-dialog.saveexif.photostatus.modified=Gänderet
-dialog.saveexif.overwrite=Files Ã¼berschriebä
-dialog.saveexif.force=Forzierä trotz Warnige
+dialog.saveexif.table.save=Speicher\u00e4
+dialog.saveexif.photostatus.connected=Verbund\u00e4
+dialog.saveexif.photostatus.disconnected=Gtr\u00e4nnt
+dialog.saveexif.photostatus.modified=G\u00e4nderet
+dialog.saveexif.overwrite=Files \u00fcberschrieb\u00e4
+dialog.saveexif.force=Forzier\u00e4 trotz Warnige
 dialog.charts.xaxis=X Achse
 dialog.charts.yaxis=Y Achse
 dialog.charts.output=Uusgabe
 dialog.charts.screen=Bildschirm
 dialog.charts.svg=SVG File
 dialog.charts.svgwidth=SVG Breiti
 dialog.charts.xaxis=X Achse
 dialog.charts.yaxis=Y Achse
 dialog.charts.output=Uusgabe
 dialog.charts.screen=Bildschirm
 dialog.charts.svg=SVG File
 dialog.charts.svgwidth=SVG Breiti
-dialog.charts.svgheight=SVG Höhi
-dialog.charts.needaltitudeortimes=Ohni Höhi Date und au ohne Ziit, isch es nöd möglech, Diagramme z zeigä.
-dialog.charts.gnuplotnotfound=Gnuplot isch mit dem Pfad nöd gfunde worde
-dialog.distances.intro=Entfärnige per Luftlinie zwüschet Punkte
+dialog.charts.svgheight=SVG H\u00f6hi
+dialog.charts.needaltitudeortimes=Ohni H\u00f6hi Date und au ohne Ziit, isch es n\u00f6d m\u00f6glech, Diagramme z zeig\u00e4.
+dialog.charts.gnuplotnotfound=Gnuplot isch mit dem Pfad n\u00f6d gfunde worde
+dialog.distances.intro=Entf\u00e4rnige per Luftlinie zw\u00fcschet P\u00fcnkte
 dialog.distances.column.from=Vom Punkt
 dialog.distances.column.to=Zum Punkt
 dialog.distances.currentpoint=Aktuelli Punkt
 dialog.distances.column.from=Vom Punkt
 dialog.distances.column.to=Zum Punkt
 dialog.distances.currentpoint=Aktuelli Punkt
-dialog.distances.toofewpoints=d'Funktion bruucht Waypoints um die Dischtanze z berächne
+dialog.distances.toofewpoints=d'Funktion bruucht Waypoints um die Dischtanze z ber\u00e4chne
 dialog.fullrangedetails.intro=Hier sind die Infos vonem aktuelli Beriich
 dialog.fullrangedetails.intro=Hier sind die Infos vonem aktuelli Beriich
-dialog.setmapbg.intro=Eini von den Quällen uuswähle, oder eini neui hinzuefüge
-dialog.addmapsource.title=Neui Kartequälle hinzuefüge
+dialog.fullrangedetails.coltotal=Inklusiv L\u00fccke
+dialog.fullrangedetails.colsegments=Ohni L\u00fccke
+dialog.setmapbg.intro=Eini von den Qu\u00e4llen uusw\u00e4hle, oder eini neui hinzuef\u00fcge
+dialog.addmapsource.title=Neui Kartequ\u00e4lle hinzuef\u00fcge
 dialog.addmapsource.sourcename=Sourcename
 dialog.addmapsource.sourcename=Sourcename
-dialog.addmapsource.layer1url=URL für erschti Ebene
-dialog.addmapsource.layer2url=URL für oberi Ebene (falls nötig)
+dialog.addmapsource.layer1url=URL f\u00fcr erschti Ebene
+dialog.addmapsource.layer2url=URL f\u00fcr oberi Ebene (falls n\u00f6tig)
 dialog.addmapsource.maxzoom=Maximali Zoom
 dialog.addmapsource.cloudstyle=Stilnummere
 dialog.addmapsource.noname=Unbenannt
 dialog.gpsies.column.name=Track Name
 dialog.addmapsource.maxzoom=Maximali Zoom
 dialog.addmapsource.cloudstyle=Stilnummere
 dialog.addmapsource.noname=Unbenannt
 dialog.gpsies.column.name=Track Name
-dialog.gpsies.column.length=Länge
+dialog.gpsies.column.length=L\u00e4nge
 dialog.gpsies.description=Beschriebig
 dialog.gpsies.nodescription=Kei Beschriebig
 dialog.gpsies.nonefound=Kei Tracks gfunde
 dialog.gpsies.username=Gpsies Username
 dialog.gpsies.password=Gpsies Passwort
 dialog.gpsies.keepprivate=Track privat halte
 dialog.gpsies.description=Beschriebig
 dialog.gpsies.nodescription=Kei Beschriebig
 dialog.gpsies.nonefound=Kei Tracks gfunde
 dialog.gpsies.username=Gpsies Username
 dialog.gpsies.password=Gpsies Passwort
 dialog.gpsies.keepprivate=Track privat halte
-dialog.gpsies.confirmopenpage=Websiite fürn uufageladenen Track Ã¶ffne?
+dialog.gpsies.confirmopenpage=Websiite f\u00fcrn uufageladenen Track \u00f6ffne?
 dialog.gpsies.activities=Aktivit\u00e4ten
 dialog.gpsies.activity.trekking=Wandere
 dialog.gpsies.activity.walking=Z'Fuess gah
 dialog.gpsies.activities=Aktivit\u00e4ten
 dialog.gpsies.activity.trekking=Wandere
 dialog.gpsies.activity.walking=Z'Fuess gah
@@ -295,68 +301,72 @@ dialog.gpsies.activity.snowshoe=Schneeschuh
 dialog.gpsies.activity.sailing=Segle
 dialog.gpsies.activity.skating=Inline-Skate
 dialog.wikipedia.column.name=Artikelname
 dialog.gpsies.activity.sailing=Segle
 dialog.gpsies.activity.skating=Inline-Skate
 dialog.wikipedia.column.name=Artikelname
-dialog.wikipedia.column.distance=Entfärnig
-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.select.photoname=Föteli Name
-dialog.correlate.select.timediff=Ziitdifferänz
-dialog.correlate.select.photolater=Föteli spöter
-dialog.correlate.options.tip=Tipp: Mit mindeschtens einem verbundenen Elemänt kann die Ziitdifferänz automatisch berächnet werdä.
-dialog.correlate.options.intro=Wählet Sie die Optione uus für die Korrelierig
+dialog.wikipedia.column.distance=Entf\u00e4rnig
+dialog.correlate.notimestamps=Es h\u00e4t kei Ziitst\u00e4mpel inem Track inn\u00e4, so s'isch n\u00f6d m\u00f6glech die F\u00f6telis zu korrelier\u00e4.
+dialog.correlate.nouncorrelatedphotos=Alle F\u00f6telis sin scho korreliert.\nWend Sie trotzdem fortsetz\u00e4?
+dialog.correlate.nouncorrelatedaudios=Alle Audios sin scho korreliert.\nWend Sie trotzdem fortsetz\u00e4?
+dialog.correlate.photoselect.intro=W\u00e4hlet Sie eini vo deren F\u00f6teli uus, um die Ziitdiffer\u00e4nz zu ber\u00e4chn\u00e4
+dialog.correlate.select.photoname=F\u00f6teli Name
+dialog.correlate.select.timediff=Ziitdiffer\u00e4nz
+dialog.correlate.select.photolater=F\u00f6teli sp\u00f6ter
+dialog.correlate.options.tip=Tipp: Mit mindeschtens einem verbundenen Elem\u00e4nt kann die Ziitdiffer\u00e4nz automatisch ber\u00e4chnet werd\u00e4.
+dialog.correlate.options.intro=W\u00e4hlet Sie die Optione uus f\u00fcr die Korrelierig
 dialog.correlate.options.offsetpanel=Ziitunterschied
 dialog.correlate.options.offset=Unterschied
 dialog.correlate.options.offsetpanel=Ziitunterschied
 dialog.correlate.options.offset=Unterschied
-dialog.correlate.options.offset.hours=Schtundä,
-dialog.correlate.options.offset.minutes=Minutä und
-dialog.correlate.options.offset.seconds=Sekundä
-dialog.correlate.options.photolater=Föteli spöter alsem Punkt
-dialog.correlate.options.pointlaterphoto=Punkt spöter alsem Föteli
-dialog.correlate.options.audiolater=Audio spöter alsem Punkt
-dialog.correlate.options.pointlateraudio=Punkt spöter alsem Audio
-dialog.correlate.options.limitspanel=Korrelation Gränzä
-dialog.correlate.options.notimelimit=Kei Ziitgränzä
-dialog.correlate.options.timelimit=Ziitgränzä
-dialog.correlate.options.nodistancelimit=Kei Distanzgränzä
-dialog.correlate.options.distancelimit=Distanzgränzä
-dialog.correlate.options.correlate=Korrelierä
-dialog.correlate.alloutsiderange=Alli Fötelis sin uusserhalb vonem Track Ziitruum, so chönne nöd korreliert werdä.\nVersuechet Sie mitenem anderen Offset oder verbindet Sie manuell mindeschtens eis Föteli.
+dialog.correlate.options.offset.hours=Schtund\u00e4,
+dialog.correlate.options.offset.minutes=Minut\u00e4 und
+dialog.correlate.options.offset.seconds=Sekund\u00e4
+dialog.correlate.options.photolater=F\u00f6teli sp\u00f6ter alsem Punkt
+dialog.correlate.options.pointlaterphoto=Punkt sp\u00f6ter alsem F\u00f6teli
+dialog.correlate.options.audiolater=Audio sp\u00f6ter alsem Punkt
+dialog.correlate.options.pointlateraudio=Punkt sp\u00f6ter alsem Audio
+dialog.correlate.options.limitspanel=Korrelation Gr\u00e4nz\u00e4
+dialog.correlate.options.notimelimit=Kei Ziitgr\u00e4nz\u00e4
+dialog.correlate.options.timelimit=Ziitgr\u00e4nz\u00e4
+dialog.correlate.options.nodistancelimit=Kei Distanzgr\u00e4nz\u00e4
+dialog.correlate.options.distancelimit=Distanzgr\u00e4nz\u00e4
+dialog.correlate.options.correlate=Korrelier\u00e4
+dialog.correlate.alloutsiderange=Alli Elem\u00e4nte sin uusserhalb vonem Track Ziitruum, so ch\u00f6nne n\u00f6d korreliert werd\u00e4.\nVersuechet Sie mitenem anderen Offset oder verbindet Sie manuell mindeschtens eis Elem\u00e4nt.
 dialog.correlate.filetimes=Die Datei Zeitstempel zeigen:
 dialog.correlate.filetimes2=der Tonspuren
 dialog.correlate.filetimes=Die Datei Zeitstempel zeigen:
 dialog.correlate.filetimes2=der Tonspuren
-dialog.correlate.correltimes=Fürs Korreliere, folgendes verwände:
+dialog.correlate.correltimes=F\u00fcrs Korreliere, folgendes verw\u00e4nde:
 dialog.correlate.timestamp.beginning=Aafang
 dialog.correlate.timestamp.middle=Mitti
 dialog.correlate.timestamp.end=Ände
 dialog.correlate.timestamp.beginning=Aafang
 dialog.correlate.timestamp.middle=Mitti
 dialog.correlate.timestamp.end=Ände
-dialog.correlate.audioselect.intro=Wählet Sie eini vo deren Audios uus, um die Ziitdifferänz zu berächnä
+dialog.correlate.audioselect.intro=W\u00e4hlet Sie eini vo deren Audios uus, um die Ziitdiffer\u00e4nz zu ber\u00e4chn\u00e4
 dialog.correlate.select.audioname=Audio Name
 dialog.correlate.select.audioname=Audio Name
-dialog.correlate.select.audiolater=Audio spöter
-dialog.rearrangephotos.desc=Bitte Ziel und Reihefolge von den Punkten setze
+dialog.correlate.select.audiolater=Audio sp\u00f6ter
+dialog.rearrangephotos.desc=Bitte Ziel und Reihefolge von d P\u00fcnkte setze
 dialog.rearrangephotos.tostart=zum Aafang
 dialog.rearrangephotos.toend=zum Ã„nde
 dialog.rearrangephotos.tostart=zum Aafang
 dialog.rearrangephotos.toend=zum Ã„nde
-dialog.rearrangephotos.nosort=Nöd sortiere
+dialog.rearrangephotos.nosort=N\u00f6d sortiere
 dialog.rearrangephotos.sortbyfilename=per Filename sortiere
 dialog.rearrangephotos.sortbytime=per Ziit sortiere
 dialog.rearrangephotos.sortbyfilename=per Filename sortiere
 dialog.rearrangephotos.sortbytime=per Ziit sortiere
-dialog.compress.nonefound=Kei Punkte hätte gelöscht werde könne
-dialog.compress.duplicates.title=Duplikate entfärnä
-dialog.compress.closepoints.title=Nöchiglägeni Punkte entfärnä
+dialog.compress.duplicates.title=Duplikate entf\u00e4rn\u00e4
+dialog.compress.closepoints.title=N\u00f6chigl\u00e4geni P\u00fcnkte entf\u00e4rn\u00e4
 dialog.compress.closepoints.paramdesc=Span Faktor
 dialog.compress.closepoints.paramdesc=Span Faktor
-dialog.compress.wackypoints.title=Komischi Punkte entfärnä
+dialog.compress.wackypoints.title=Komischi P\u00fcnkte entf\u00e4rn\u00e4
 dialog.compress.wackypoints.paramdesc=Distanz Faktor
 dialog.compress.wackypoints.paramdesc=Distanz Faktor
-dialog.compress.singletons.title=Singletons entfärnä
+dialog.compress.singletons.title=Singletons entf\u00e4rn\u00e4
 dialog.compress.singletons.paramdesc=Distanz faktor
 dialog.compress.douglaspeucker.title=Douglas-Peucker Komprimierig
 dialog.compress.douglaspeucker.paramdesc=Span Faktor
 dialog.compress.singletons.paramdesc=Distanz faktor
 dialog.compress.douglaspeucker.title=Douglas-Peucker Komprimierig
 dialog.compress.douglaspeucker.paramdesc=Span Faktor
-dialog.compress.summarylabel=Punkte zu entfärnä
-dialog.pastecoordinates.desc=Gäbet Sie hier die Koordinaten innä
+dialog.compress.summarylabel=P\u00fcnkte zu entf\u00e4rn\u00e4
+dialog.compress.confirm1=Es sin
+dialog.compress.confirm2=P\u00fcnkt markiert.\nMit Track->Markierte P\u00fcnkte l\u00f6sche werdet sie gl\u00f6scht
+dialog.compress.confirmnone=es sin kei P\u00fcnkte markiert worde
+dialog.deletemarked.nonefound=Kei P\u00fcnkte h\u00e4tte gel\u00f6scht werde k\u00f6nne
+dialog.pastecoordinates.desc=G\u00e4bet Sie hier die Koordinaten inn\u00e4
 dialog.pastecoordinates.coords=Koordinate
 dialog.pastecoordinates.coords=Koordinate
-dialog.pastecoordinates.nothingfound=Prüefet Sie die Koordinate und versuechet nomal
-dialog.help.help=Bitte lueg na\n http://activityworkshop.net/software/gpsprune/\nfür wiitere Information und Benutzeraaleitige.
+dialog.pastecoordinates.nothingfound=Pr\u00fcefet Sie die Koordinate und versuechet nomal
+dialog.help.help=Bitte lueg na\n http://activityworkshop.net/software/gpsprune/\nf\u00fcr wiitere Information und Benutzeraaleitige.
 dialog.about.version=Version
 dialog.about.build=Build
 dialog.about.version=Version
 dialog.about.build=Build
-dialog.about.summarytext1=GpsPrune isch s Programm fürs Lade, Darstelle und Editiere vo Date von GPS Geräte.
-dialog.about.summarytext2=Es isch unter den Gnu GPL zur Verfüegig gstellt,für frei, gratis und offen Gebruuch und Wiiterentwicklig.<br>Kopiere, Wiiterverbreitig und Veränderige sin erlaubt und willkomme<br>unter die Bedingige im enthaltene <code>license.txt</code> File.
-dialog.about.summarytext3=Bitte lueget Sie na <code style="font-weight:bold">http://activityworkshop.net/</code> für wiitere Informatione und Benutzeraaleitige.
-dialog.about.languages=Verfüegbare Sproche
-dialog.about.translatedby=Schwiizerdüütschi Ãœbersetzig vo activityworkshop.
+dialog.about.summarytext1=GpsPrune isch s Programm f\u00fcrs Lade, Darstelle und Editiere vo Date von GPS Ger\u00e4te.
+dialog.about.summarytext2=Es isch unter den Gnu GPL zur Verf\u00fcegig gstellt,f\u00fcr frei, gratis und offen Gebruuch und Wiiterentwicklig.<br>Kopiere, Wiiterverbreitig und Ver\u00e4nderige sin erlaubt und willkomme<br>unter die Bedingige im enthaltene <code>license.txt</code> File.
+dialog.about.summarytext3=Bitte lueget Sie na <code style="font-weight:bold">http://activityworkshop.net/</code> f\u00fcr wiitere Informatione und Benutzeraaleitige.
+dialog.about.languages=Verf\u00fcegbare Sproche
+dialog.about.translatedby=Schwiizerd\u00fc\u00fctschi Ãœbersetzig vo activityworkshop.
 dialog.about.systeminfo=Syschtem Info
 dialog.about.systeminfo.os=Betriebsyschtem
 dialog.about.systeminfo.java=Version vonem Java
 dialog.about.systeminfo=Syschtem Info
 dialog.about.systeminfo.os=Betriebsyschtem
 dialog.about.systeminfo.java=Version vonem Java
@@ -367,41 +377,40 @@ dialog.about.systeminfo.gpsbabel=Gpsbabel inschtalliert
 dialog.about.systeminfo.gnuplot=Gnuplot inschtalliert
 dialog.about.systeminfo.exiflib=Exif Bibliothek
 dialog.about.systeminfo.exiflib.internal=Intern
 dialog.about.systeminfo.gnuplot=Gnuplot inschtalliert
 dialog.about.systeminfo.exiflib=Exif Bibliothek
 dialog.about.systeminfo.exiflib.internal=Intern
-dialog.about.systeminfo.exiflib.internal.failed=Intern (nöd gfunde)
-dialog.about.systeminfo.exiflib.external=Extärn
-dialog.about.systeminfo.exiflib.external.failed=Extärn (nöd gfunde)
+dialog.about.systeminfo.exiflib.internal.failed=Intern (n\u00f6d gfunde)
+dialog.about.systeminfo.exiflib.external=Ext\u00e4rn
+dialog.about.systeminfo.exiflib.external.failed=Ext\u00e4rn (n\u00f6d gfunde)
 dialog.about.yes=Ja
 dialog.about.no=Nei
 dialog.about.credits=Credits
 dialog.about.yes=Ja
 dialog.about.no=Nei
 dialog.about.credits=Credits
-dialog.about.credits.code=GpsPrune Code gschriebä vo
+dialog.about.credits.code=GpsPrune Code gschrieb\u00e4 vo
 dialog.about.credits.exifcode=Exif Code vo
 dialog.about.credits.icons=Einigi Bilder vo
 dialog.about.credits.exifcode=Exif Code vo
 dialog.about.credits.icons=Einigi Bilder vo
-dialog.about.credits.translators=Dolmätscher
+dialog.about.credits.translators=Dolm\u00e4tscher
 dialog.about.credits.translations=Ãœbersetzige mit dr Hilfe vo
 dialog.about.credits.translations=Ãœbersetzige mit dr Hilfe vo
-dialog.about.credits.devtools=Entwicklungswärkzüüge
-dialog.about.credits.othertools=Anderi Wärkzüüge
+dialog.about.credits.devtools=Entwicklungsw\u00e4rkz\u00fc\u00fcge
+dialog.about.credits.othertools=Anderi W\u00e4rkz\u00fc\u00fcge
 dialog.about.credits.thanks=Danke an
 dialog.about.credits.thanks=Danke an
-dialog.about.readme=Läsmi
-dialog.checkversion.error=Die Versionnummer könne nöd gefprüft werdä.\nGits ne internet Verbindig?
+dialog.about.readme=L\u00e4smi
+dialog.checkversion.error=Die Versionnummer k\u00f6nne n\u00f6d gefpr\u00fcft werd\u00e4.\nGits ne internet Verbindig?
 dialog.checkversion.uptodate=Sie han die noischti Version vonem GpsPrune scho.
 dialog.checkversion.newversion1=Ne noii Version vonem GpsPrune isch jetzt usse! Die heisst jetzt Version
 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/gpsprune/download.html.
 dialog.checkversion.uptodate=Sie han die noischti Version vonem GpsPrune scho.
 dialog.checkversion.newversion1=Ne noii Version vonem GpsPrune isch jetzt usse! Die heisst jetzt Version
 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/gpsprune/download.html.
-dialog.keys.intro=Aastatt d'Muus könnet Sie diese Tastekombinationen nutze
-dialog.keys.keylist=<table><tr><td>Pfiil Taste</td><td>Karte verschiebe</td></tr><tr><td>Strg + links, rächts Pfiil</td><td>Vorherigi oder nöchsti Punkt markiere</td></tr><tr><td>Strg + uuf, aba Pfiil</td><td>Ii- oder Uusezoome</td></tr><tr><td>Strg + Bild uuf, ab</td><td>Vorherigi oder nöchsti Segmänt markiere</td></tr><tr><td>Strg + Pos1, Ã„nde</td><td>Erschti oder letschti Punkt markiere</td></tr><tr><td>Entf</td><td>Aktuelli Punkt lösche</td></tr></table>
+dialog.keys.intro=Aastatt d'Muus k\u00f6nnet Sie diese Tastekombinationen nutze
+dialog.keys.keylist=<table><tr><td>Pfiil Taste</td><td>Karte verschiebe</td></tr><tr><td>Strg + links, r\u00e4chts Pfiil</td><td>Vorherigi oder n\u00f6chsti Punkt markiere</td></tr><tr><td>Strg + uuf, aba Pfiil</td><td>Ii- oder Uusezoome</td></tr><tr><td>Strg + Bild uuf, ab</td><td>Vorherigi oder n\u00f6chsti Segm\u00e4nt markiere</td></tr><tr><td>Strg + Pos1, Ã„nde</td><td>Erschti oder letschti Punkt markiere</td></tr><tr><td>Entf</td><td>Aktuelli Punkt l\u00f6sche</td></tr></table>
 dialog.keys.normalmodifier=Strg
 dialog.keys.macmodifier=Kommando
 dialog.keys.normalmodifier=Strg
 dialog.keys.macmodifier=Kommando
-dialog.saveconfig.desc=Die folgendi Iinstellige könne gspeicheret werde :
+dialog.saveconfig.desc=Die folgendi Iinstellige k\u00f6nne gspeicheret werde :
 dialog.saveconfig.prune.trackdirectory=Trackverzeichnis
 dialog.saveconfig.prune.trackdirectory=Trackverzeichnis
-dialog.saveconfig.prune.photodirectory=Föteliverzeichnis
+dialog.saveconfig.prune.photodirectory=F\u00f6teliverzeichnis
 dialog.saveconfig.prune.languagecode=Sprochecode (DE_ch)
 dialog.saveconfig.prune.languagefile=Sprochedatei
 dialog.saveconfig.prune.languagecode=Sprochecode (DE_ch)
 dialog.saveconfig.prune.languagefile=Sprochedatei
-dialog.saveconfig.prune.gpsdevice=GPS Gerätename
+dialog.saveconfig.prune.gpsdevice=GPS Ger\u00e4tename
 dialog.saveconfig.prune.gpsformat=GPS Format
 dialog.saveconfig.prune.povrayfont=Povray Font
 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.gnuplotpath=Gnuplot Pfad
 dialog.saveconfig.prune.gpsbabelpath=Gpsbabel Pfad
 dialog.saveconfig.prune.exiftoolpath=Exiftool Pfad
@@ -409,41 +418,42 @@ dialog.saveconfig.prune.mapsource=Kartenserver Index
 dialog.saveconfig.prune.mapsourcelist=Kartenservers
 dialog.saveconfig.prune.diskcache=Kartenordner
 dialog.saveconfig.prune.kmzimagewidth=Bildbreiti im KMZ
 dialog.saveconfig.prune.mapsourcelist=Kartenservers
 dialog.saveconfig.prune.diskcache=Kartenordner
 dialog.saveconfig.prune.kmzimagewidth=Bildbreiti im KMZ
-dialog.saveconfig.prune.kmzimageheight=Bildhöchi im KMZ
+dialog.saveconfig.prune.kmzimageheight=Bildh\u00f6chi im KMZ
 dialog.saveconfig.prune.colourscheme=Farbeschema
 dialog.saveconfig.prune.linewidth=Liniedicke
 dialog.saveconfig.prune.kmltrackcolour=KML Trackfarb
 dialog.saveconfig.prune.autosavesettings=Iistellige speichere
 dialog.saveconfig.prune.colourscheme=Farbeschema
 dialog.saveconfig.prune.linewidth=Liniedicke
 dialog.saveconfig.prune.kmltrackcolour=KML Trackfarb
 dialog.saveconfig.prune.autosavesettings=Iistellige speichere
-dialog.setpaths.intro=Sie könnet dann die Pfade für dia Applikatione setzä:
+dialog.setpaths.intro=Sie k\u00f6nnet dann die Pfade f\u00fcr dia Applikatione setz\u00e4:
 dialog.setpaths.found=Pfad gfunde?
 dialog.setpaths.found=Pfad gfunde?
-dialog.addaltitude.noaltitudes=Dr seläktierte Beriich hät keini Höchiinformation
-dialog.addaltitude.desc=Höchiverschiebig zuzutue
-dialog.lookupsrtm.overwritezeros=Höchiwärte von null Ã¼berschriebä?
-dialog.setcolours.intro=Klicket Sie uuf ne Farb um sie z'verändere
+dialog.addaltitude.noaltitudes=Dr sel\u00e4ktierte Beriich h\u00e4t keini H\u00f6chiinformation
+dialog.addaltitude.desc=H\u00f6chiverschiebig zuzutue
+dialog.lookupsrtm.overwritezeros=H\u00f6chiw\u00e4rte von null \u00fcberschrieb\u00e4?
+dialog.setcolours.intro=Klicket Sie uuf ne Farb um sie z'ver\u00e4ndere
 dialog.setcolours.background=Hintergrund
 dialog.setcolours.borders=Rande
 dialog.setcolours.lines=Linie
 dialog.setcolours.background=Hintergrund
 dialog.setcolours.borders=Rande
 dialog.setcolours.lines=Linie
-dialog.setcolours.primary=Primär
-dialog.setcolours.secondary=Secondär
-dialog.setcolours.point=Punkte
+dialog.setcolours.primary=Prim\u00e4r
+dialog.setcolours.secondary=Second\u00e4r
+dialog.setcolours.point=P\u00fcnkte
 dialog.setcolours.selection=Beriich
 dialog.setcolours.text=Texte
 dialog.setcolours.selection=Beriich
 dialog.setcolours.text=Texte
-dialog.colourchooser.title=Farbe uuswähle
+dialog.colourchooser.title=Farbe uusw\u00e4hle
 dialog.colourchooser.red=Rot
 dialog.colourchooser.red=Rot
-dialog.colourchooser.green=Grüen
+dialog.colourchooser.green=Gr\u00fcen
 dialog.colourchooser.blue=Blau
 dialog.colourchooser.blue=Blau
-dialog.setlanguage.firstintro=Sie könnet entweder eini vo den iigebouti Sproche<p>oder ne Text-Datei uuswähle.
-dialog.setlanguage.secondintro=Sie münt Ihri Iistellige speichere und dann<p>GpsPrune wieder neustarte um die Sproch z'ändere.
+dialog.setlanguage.firstintro=Sie k\u00f6nnet entweder eini vo den iigebouti Sproche<p>oder ne Text-Datei uusw\u00e4hle.
+dialog.setlanguage.secondintro=Sie m\u00fcnt Ihri Iistellige speichere und dann<p>GpsPrune wieder neustarte um die Sproch z'\u00e4ndere.
 dialog.setlanguage.language=Sproch
 dialog.setlanguage.languagefile=Sproch Datei
 dialog.setlanguage.language=Sproch
 dialog.setlanguage.languagefile=Sproch Datei
-dialog.setlanguage.endmessage=Jetze speicheret Sie Ihri Iistellige und startet Sie GpsPrune neu\num t noii Sproch z' verwände.
-dialog.setlanguage.endmessagewithautosave=Startet Sie GpsPrune neu um t noii Sproch z' verwände.
+dialog.setlanguage.endmessage=Jetze speicheret Sie Ihri Iistellige und startet Sie GpsPrune neu\num t noii Sproch z' verw\u00e4nde.
+dialog.setlanguage.endmessagewithautosave=Startet Sie GpsPrune neu um t noii Sproch z' verw\u00e4nde.
 dialog.diskcache.save=Karten uufem Disk speichere
 dialog.diskcache.dir=Kartenordner
 dialog.diskcache.createdir=Ordner kreiere
 dialog.diskcache.save=Karten uufem Disk speichere
 dialog.diskcache.dir=Kartenordner
 dialog.diskcache.createdir=Ordner kreiere
-dialog.diskcache.nocreate=Ordner isch nöd kreiert worde
+dialog.diskcache.nocreate=Ordner isch n\u00f6d kreiert worde
+dialog.diskcache.cannotwrite=Kachle k\u00f6nned n\u00f6d im Ordner gspeicheret werde
 dialog.diskcache.table.path=Pfad
 dialog.diskcache.table.path=Pfad
-dialog.diskcache.table.usedby=Aawänder
+dialog.diskcache.table.usedby=Aaw\u00e4nder
 dialog.diskcache.table.zoom=Zoom
 dialog.diskcache.table.tiles=Kachle
 dialog.diskcache.table.megabytes=Megabytes
 dialog.diskcache.table.zoom=Zoom
 dialog.diskcache.table.tiles=Kachle
 dialog.diskcache.table.megabytes=Megabytes
@@ -454,87 +464,90 @@ dialog.diskcache.maximumage=Maximali Alter (Tag)
 dialog.diskcache.deleteall=Alli Kachle l\u00f6sche
 dialog.diskcache.deleted1=Es sin
 dialog.diskcache.deleted2=Files uusem Ordner gl\u00f6scht worde
 dialog.diskcache.deleteall=Alli Kachle l\u00f6sche
 dialog.diskcache.deleted1=Es sin
 dialog.diskcache.deleted2=Files uusem Ordner gl\u00f6scht worde
-dialog.deletefieldvalues.intro=Wählet Sie s Fäld uus zum lösche
-dialog.setlinewidth.text=Gäbet Sie die Dicke vonen Linien ii (1-4)
-dialog.downloadosm.desc=Best\ätige um rohi OSM Date fürn Gebiet aba zlade:
+dialog.deletefieldvalues.intro=W\u00e4hlet Sie s F\u00e4ld uus zum l\u00f6sche
+dialog.deletefieldvalues.nofields=Es sin kei F\u00e4lder z'l\u00f6sche f\u00fcr dere Beriich
+dialog.setlinewidth.text=G\u00e4bet Sie die Dicke vonen Linien ii (1-4)
+dialog.downloadosm.desc=Best\u00e4tige um rohi OSM Date f\u00fcrn Gebiet aba zlade:
 dialog.searchwikipedianames.search=Sueche na:
 
 # 3d window
 dialog.searchwikipedianames.search=Sueche na:
 
 # 3d window
-dialog.3d.title=GpsPrune Drüü-d Aasicht
-dialog.3d.altitudefactor=Höchivervilfachigsfaktor
+dialog.3d.title=GpsPrune Dr\u00fc\u00fc-d Aasicht
+dialog.3d.altitudefactor=H\u00f6chivervilfachigsfaktor
 dialog.3dlines.title=GpsPrune Gitterlinie
 dialog.3dlines.title=GpsPrune Gitterlinie
-dialog.3dlines.empty=Kei Linie zum aazeigä!
-dialog.3dlines.intro=Hier sin die Linie für die drüü-D Aasicht
+dialog.3dlines.empty=Kei Linie zum aazeig\u00e4!
+dialog.3dlines.intro=Hier sin die Linie f\u00fcr die dr\u00fc\u00fc-D Aasicht
 
 # Confirm messages
 confirm.loadfile=Date glade vom
 confirm.save.ok1=Es sin
 
 # Confirm messages
 confirm.loadfile=Date glade vom
 confirm.save.ok1=Es sin
-confirm.save.ok2=Punkte gspeicheret worde na
+confirm.save.ok2=P\u00fcnkte gspeicheret worde na
 confirm.deletepoint.single=Punkt isch entfernt worde
 confirm.deletepoint.single=Punkt isch entfernt worde
-confirm.deletepoint.multi=Punkte sin entfernt worde
+confirm.deletepoint.multi=P\u00fcnkte sin entfernt worde
 confirm.point.edit=Punkt editiert
 confirm.point.edit=Punkt editiert
-confirm.mergetracksegments=Segmänte gmerged
-confirm.reverserange=Beriich umgdrähet
+confirm.mergetracksegments=Segm\u00e4nte gmerged
+confirm.reverserange=Beriich umgdr\u00e4het
 confirm.addtimeoffset=Ziitverschiebig zutue
 confirm.addtimeoffset=Ziitverschiebig zutue
-confirm.addaltitudeoffset=Höchiverschiebig zutue
+confirm.addaltitudeoffset=H\u00f6chiverschiebig zutue
 confirm.rearrangewaypoints=Waypoints umorganisiert
 confirm.rearrangephotos=Fotos umorganisiert
 confirm.cutandmove=Beriich gmoved
 confirm.rearrangewaypoints=Waypoints umorganisiert
 confirm.rearrangephotos=Fotos umorganisiert
 confirm.cutandmove=Beriich gmoved
+confirm.interpolate=P\u00fcnkte iigf\u00fcgt worde
 confirm.convertnamestotimes=Waypointname verwondlet
 confirm.saveexif.ok1=Es sin
 confirm.convertnamestotimes=Waypointname verwondlet
 confirm.saveexif.ok1=Es sin
-confirm.saveexif.ok2=Fötelis gschriebe worde
-confirm.undo.single=Operation rückgängig gmacht worde.
-confirm.undo.multi=Operatione rückgängig gmacht worde.
-confirm.jpegload.single=Föteli isch glade worde
-confirm.jpegload.multi=Fötelis sin glade worde
-confirm.media.connect=Media verbundä
-confirm.photo.disconnect=Föteli gtrännt
-confirm.audio.disconnect=Audio gtrännt
-confirm.correlatephotos.single=Föteli isch korreliert worde
-confirm.correlatephotos.multi=Fötelis sin korreliert worde
+confirm.saveexif.ok2=F\u00f6telis gschriebe worde
+confirm.undo.single=Operation r\u00fcckg\u00e4ngig gmacht worde.
+confirm.undo.multi=Operatione r\u00fcckg\u00e4ngig gmacht worde.
+confirm.jpegload.single=F\u00f6teli isch glade worde
+confirm.jpegload.multi=F\u00f6telis sin glade worde
+confirm.media.connect=Media verbund\u00e4
+details.media.fullpath=Ganzi Pfad
+confirm.photo.disconnect=F\u00f6teli gtr\u00e4nnt
+confirm.audio.disconnect=Audio gtr\u00e4nnt
+confirm.correlatephotos.single=F\u00f6teli isch korreliert worde
+confirm.correlatephotos.multi=F\u00f6telis sin korreliert worde
 confirm.createpoint=Punkt kreiert worde
 confirm.createpoint=Punkt kreiert worde
-confirm.rotatephoto=Föteli umgedräit worde
+confirm.rotatephoto=F\u00f6teli umgedr\u00e4it worde
 confirm.running=Am Laufe ...
 confirm.lookupsrtm1=Es sin
 confirm.running=Am Laufe ...
 confirm.lookupsrtm1=Es sin
-confirm.lookupsrtm2=Höhenwerte gfunde
-confirm.deletefieldvalues=Feldwärte glöscht worde
+confirm.lookupsrtm2=H\u00f6henwerte gfunde
+confirm.deletefieldvalues=Feldw\u00e4rte gl\u00f6scht worde
 confirm.audioload=Audiofiles glade worde
 confirm.audioload=Audiofiles glade worde
-confirm.media.removed=entfärnt
+confirm.media.removed=entf\u00e4rnt
 confirm.correlateaudios.single=Audiofile isch korreliert worde
 confirm.correlateaudios.multi=Audiofiles sin korreliert worde
 
 # Buttons
 button.ok=OK
 button.back=Zrugg
 confirm.correlateaudios.single=Audiofile isch korreliert worde
 confirm.correlateaudios.multi=Audiofiles sin korreliert worde
 
 # Buttons
 button.ok=OK
 button.back=Zrugg
-button.next=Nöchstä
+button.next=N\u00f6chst\u00e4
 button.finish=Fertig
 button.finish=Fertig
-button.cancel=Abbrächä
-button.overwrite=Überschriibä
-button.moveup=Uufä schiebä
-button.movedown=Aba schiebä
-button.showlines=Linie aazeigä
-button.edit=Editierä
-button.exit=Beändä
-button.close=Schliessä
-button.continue=Fortsetzä
+button.cancel=Abbr\u00e4ch\u00e4
+button.overwrite=Ãœberschriib\u00e4
+button.moveup=Uuf\u00e4 schieb\u00e4
+button.movedown=Aba schieb\u00e4
+button.showlines=Linie aazeig\u00e4
+button.edit=Editier\u00e4
+button.exit=Be\u00e4nd\u00e4
+button.close=Schliess\u00e4
+button.continue=Fortsetz\u00e4
 button.yes=Ja
 button.no=Nei
 button.yes=Ja
 button.no=Nei
-button.yestoall=Ja für alli
-button.notoall=Nei für alli
-button.select=Uuswähle
-button.selectall=Alli uuswähle
-button.selectnone=Nüüt uuswähle
-button.preview=Vorschauä
-button.load=Ladä
-button.upload=Uufaladä
-button.guessfields=Fälde erratä
-button.showwebpage=Websiite aazeigä
-button.check=Prüefa
-button.resettodefaults=Zurücksetzä
-button.browse=Durasuechä...
-button.addnew=Hinzuefügä
-button.delete=Entfärnä
-button.manage=Verwoltä
+button.yestoall=Ja f\u00fcr alli
+button.notoall=Nei f\u00fcr alli
+button.select=Uusw\u00e4hle
+button.selectall=Alli uusw\u00e4hle
+button.selectnone=N\u00fc\u00fct uusw\u00e4hle
+button.preview=Vorschau\u00e4
+button.load=Lad\u00e4
+button.upload=Uufalad\u00e4
+button.guessfields=F\u00e4lde errat\u00e4
+button.showwebpage=Websiite aazeig\u00e4
+button.check=Pr\u00fcefa
+button.resettodefaults=Zur\u00fccksetz\u00e4
+button.browse=Durasuech\u00e4...
+button.addnew=Hinzuef\u00fcg\u00e4
+button.delete=Entf\u00e4rn\u00e4
+button.manage=Verwolt\u00e4
 
 # File types
 filetype.txt=TXT Dateie
 
 # File types
 filetype.txt=TXT Dateie
@@ -549,19 +562,19 @@ filetype.audio=MP3, OGG, WAV Dateie
 
 # Display components
 display.nodata=Kei Date glade worde
 
 # Display components
 display.nodata=Kei Date glade worde
-display.noaltitudes=Track hät kei Höhi Date
-display.notimestamps=Track hät kei Ziitstämple
+display.noaltitudes=Track h\u00e4t kei H\u00f6hi Date
+display.notimestamps=Track h\u00e4t kei Ziitst\u00e4mple
 details.trackdetails=Details vom Track
 details.notrack=Kei Track glade worde
 details.trackdetails=Details vom Track
 details.notrack=Kei Track glade worde
-details.track.points=Punkte
+details.track.points=P\u00fcnkte
 details.track.file=Datei
 details.track.numfiles=Anzahl Dateie
 details.pointdetails=Details vonem Punkt
 details.index.selected=Index
 details.index.of=vo
 details.track.file=Datei
 details.track.numfiles=Anzahl Dateie
 details.pointdetails=Details vonem Punkt
 details.index.selected=Index
 details.index.of=vo
-details.nopointselection=Nüüt selektiert
-details.photofile=Föteli Datei
-details.norangeselection=Nüüt selektiert
+details.nopointselection=N\u00fc\u00fct selektiert
+details.photofile=F\u00f6teli Datei
+details.norangeselection=N\u00fc\u00fct selektiert
 details.rangedetails=Details vonem Beriich
 details.range.selected=Selektiert
 details.range.to=bis
 details.rangedetails=Details vonem Beriich
 details.range.selected=Selektiert
 details.range.to=bis
@@ -575,39 +588,38 @@ display.range.time.mins=Min
 display.range.time.hours=Std
 display.range.time.days=T
 details.range.avespeed=Gschwindikeit
 display.range.time.hours=Std
 display.range.time.days=T
 details.range.avespeed=Gschwindikeit
-details.range.avemovingspeed=Gschwindikeit ufem Wäg
-details.range.maxspeed=Höchstgschwindikeit
-details.range.numsegments=Aazahl Segmänte
+details.range.maxspeed=H\u00f6chstgschwindikeit
+details.range.numsegments=Aazahl Segm\u00e4nte
 details.range.pace=Tempo
 details.range.pace=Tempo
-details.range.gradient=Gefälle
+details.range.gradient=Gef\u00e4lle
 details.lists.waypoints=Waypoints
 details.lists.waypoints=Waypoints
-details.lists.photos=Fötelis
-details.photodetails=Details vonem Föteli
-details.nophoto=Kei föteli selektiert
-details.photo.loading=Ladä
+details.lists.photos=F\u00f6telis
+details.photodetails=Details vonem F\u00f6teli
+details.nophoto=Kei f\u00f6teli selektiert
+details.photo.loading=Lad\u00e4
 details.photo.bearing=Richtig
 details.photo.bearing=Richtig
-details.media.connected=Verbundä
+details.media.connected=Verbund\u00e4
 details.lists.audio=Audio
 details.audiodetails=Audiodetails
 details.noaudio=Kei Audiofile selektiert
 details.audio.file=Audiofile
 details.lists.audio=Audio
 details.audiodetails=Audiodetails
 details.noaudio=Kei Audiofile selektiert
 details.audio.file=Audiofile
-details.audio.playing=am abschpielä...
+details.audio.playing=am abschpiel\u00e4...
 map.overzoom=Kei Karte mit diesem Zoom
 
 # Field names
 fieldname.latitude=Breitegrad
 map.overzoom=Kei Karte mit diesem Zoom
 
 # Field names
 fieldname.latitude=Breitegrad
-fieldname.longitude=Längegrad
-fieldname.altitude=Höchi
-fieldname.timestamp=Ziitstämpel
+fieldname.longitude=L\u00e4ngegrad
+fieldname.altitude=H\u00f6chi
+fieldname.timestamp=Ziitst\u00e4mpel
 fieldname.time=Ziit
 fieldname.waypointname=Name
 fieldname.waypointtype=Typ
 fieldname.time=Ziit
 fieldname.waypointname=Name
 fieldname.waypointtype=Typ
-fieldname.newsegment=Segmänt
+fieldname.newsegment=Segm\u00e4nt
 fieldname.custom=Custom
 fieldname.custom=Custom
-fieldname.prefix=Fäld
-fieldname.distance=Längi
-fieldname.movingdistance=Weglängi
-fieldname.duration=Ziitlängi
+fieldname.prefix=F\u00e4ld
+fieldname.distance=L\u00e4ngi
+fieldname.movingdistance=Wegl\u00e4ngi
+fieldname.duration=Ziitl\u00e4ngi
 fieldname.speed=Gschwindikeit
 fieldname.verticalspeed=Uf/Ab Gschwindikeit
 fieldname.description=Bschriibig
 fieldname.speed=Gschwindikeit
 fieldname.verticalspeed=Uf/Ab Gschwindikeit
 fieldname.description=Bschriibig
@@ -616,11 +628,15 @@ fieldname.description=Bschriibig
 units.original=Original
 units.default=Default
 units.metres=Meter
 units.original=Original
 units.default=Default
 units.metres=Meter
+units.metres.short=m
 units.kilometres=Kilometer
 units.kilometres.short=km
 units.kilometres=Kilometer
 units.kilometres.short=km
-units.kmh=km/h
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.kilometresperhour.short=kmh
+units.nauticalmiles=Seemeile
+units.nauticalmiles.short=sm
+units.nauticalmilesperhour.short=kn
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=Std
 units.degminsec=Grad-Min-Sek
 units.degmin=Grad-Min
 units.hours=Std
 units.degminsec=Grad-Min-Sek
 units.degmin=Grad-Min
@@ -638,74 +654,77 @@ cardinal.e=O
 cardinal.w=W
 
 # Undo operations
 cardinal.w=W
 
 # Undo operations
-undo.load=Date ladä
-undo.loadphotos=Fötelis ladä
-undo.loadaudios=Audiofiles ladä
-undo.editpoint=Punkt editierä
-undo.deletepoint=Punkt löschä
-undo.removephoto=Föteli entfärnä
-undo.removeaudio=Audiofile entfärnä
-undo.deleterange=Beriich löschä
-undo.compress=Track komprimierä
-undo.insert=Punkte innätuä
-undo.reverse=Beriich umdrähie
-undo.mergetracksegments=track segmänte merge
+undo.load=Date lad\u00e4
+undo.loadphotos=F\u00f6telis lad\u00e4
+undo.loadaudios=Audiofiles lad\u00e4
+undo.editpoint=Punkt editier\u00e4
+undo.deletepoint=Punkt l\u00f6sch\u00e4
+undo.removephoto=F\u00f6teli entf\u00e4rn\u00e4
+undo.removeaudio=Audiofile entf\u00e4rn\u00e4
+undo.deleterange=Beriich l\u00f6sch\u00e4
+undo.croptrack=Track zuschniid\u00e4
+undo.deletemarked=P\u00fcnkte l\u00f6sch\u00e4
+undo.insert=P\u00fcnkte inn\u00e4tu\u00e4
+undo.reverse=Beriich umdr\u00e4hie
+undo.mergetracksegments=track segm\u00e4nte merge
 undo.addtimeoffset=ziitverschiebig zutue
 undo.addtimeoffset=ziitverschiebig zutue
-undo.addaltitudeoffset=höchiverschiebig zutue
-undo.rearrangewaypoints=Waypoints reorganisierä
-undo.cutandmove=Selektion movä
-undo.connect=verbindä
-undo.disconnect=trännä
-undo.correlatephotos=Fötelis korrelierä
-undo.rearrangephotos=Fötelis reorganisierä
-undo.createpoint=Punkt kreierä
-undo.rotatephoto=Föteli umadräya
-undo.convertnamestotimes=Name ins Ziitstämple verwondlä
-undo.lookupsrtm=Höhendate vonem SRTM holä
-undo.deletefieldvalues=Feldwärte löschä
-undo.correlateaudios=Audios korrelierä
+undo.addaltitudeoffset=h\u00f6chiverschiebig zutue
+undo.rearrangewaypoints=Waypoints reorganisier\u00e4
+undo.cutandmove=Selektion mov\u00e4
+undo.connect=verbind\u00e4
+undo.disconnect=tr\u00e4nn\u00e4
+undo.correlatephotos=F\u00f6telis korrelier\u00e4
+undo.rearrangephotos=F\u00f6telis reorganisier\u00e4
+undo.createpoint=Punkt kreier\u00e4
+undo.rotatephoto=F\u00f6teli umadr\u00e4ya
+undo.convertnamestotimes=Name ins Ziitst\u00e4mple verwondl\u00e4
+undo.lookupsrtm=H\u00f6hendate vonem SRTM hol\u00e4
+undo.deletefieldvalues=Feldw\u00e4rte l\u00f6sch\u00e4
+undo.correlateaudios=Audios korrelier\u00e4
 
 # Error messages
 
 # Error messages
-error.save.dialogtitle=Fähle bim Speichere
+error.save.dialogtitle=F\u00e4hle bim Speichere
 error.save.nodata=Kei Date zum speichere
 error.save.failed=Speichere vom File fehlgschlage
 error.save.nodata=Kei Date zum speichere
 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?
+error.saveexif.filenotfound=F\u00f6teli File n\u00f6d gfunde
+error.saveexif.cannotoverwrite1=F\u00f6teli File
+error.saveexif.cannotoverwrite2=isch n\u00f6d schriibbar. Speichere na einer Kopie?
 error.saveexif.failed1=
 error.saveexif.failed1=
-error.saveexif.failed2=von d Bilder han i nöd speichere könne
+error.saveexif.failed2=von d Bilder han i n\u00f6d k\u00f6nne speichere
 error.saveexif.forced1=
 error.saveexif.forced1=
-error.saveexif.forced2=von d Bilder han i müsse forziere
-error.load.dialogtitle=Fähle bim Lade
-error.load.noread=File cha nöd glase werde
-error.load.nopoints=Kei gültigi Information inem File gfunde
+error.saveexif.forced2=von d Bilder han i m\u00fcsse forziere
+error.load.dialogtitle=F\u00e4hle bim Lade
+error.load.noread=File cha n\u00f6d glase werde
+error.load.nopoints=Kei g\u00fcltigi Information inem File gfunde
 error.load.unknownxml=Unbekanntes xml Format:
 error.load.noxmlinzip=Kei xml im Zip File gfunde
 error.load.unknownxml=Unbekanntes xml Format:
 error.load.noxmlinzip=Kei xml im Zip File gfunde
-error.load.othererror=Fähle bim Läse:
-error.jpegload.dialogtitle=Fähle bim Lade von Fötelis
+error.load.othererror=F\u00e4hle bim L\u00e4se:
+error.jpegload.dialogtitle=F\u00e4hle bim Lade von F\u00f6telis
 error.jpegload.nofilesfound=Kei Files gfunde
 error.jpegload.nojpegsfound=Kei Jpegs gfunde
 error.jpegload.nogpsfound=Kei GPS Information gfunde
 error.jpegload.nofilesfound=Kei Files gfunde
 error.jpegload.nojpegsfound=Kei Jpegs gfunde
 error.jpegload.nogpsfound=Kei GPS Information gfunde
-error.jpegload.exifreadfailed=EXIF Uufruef isch fehlgschlage. Kei EXIF Infos könnet gläse werde\nohni nen interni oder extärni Bibliothek.
+error.jpegload.exifreadfailed=EXIF Uufruef isch fehlgschlage. Kei EXIF Infos k\u00f6nnet gl\u00e4se werde\nohni nen interni oder ext\u00e4rni Bibliothek.
 error.audioload.nofilesfound=Kei Audiofiles gfunde
 error.audioload.nofilesfound=Kei Audiofiles gfunde
-error.gpsload.unknown=Unbekannts Fähler
+error.gpsload.unknown=Unbekannts F\u00e4hler
 error.undofailed.title=Undo isch fehlgschlage worde
 error.undofailed.title=Undo isch fehlgschlage worde
-error.undofailed.text=Operation kann nöd rückgängig gmacht werde
-error.function.noop.title=Funktion hät gar nüüt gmacht
-error.rearrange.noop=Punkte Reorganisierig hät kei Effäkt gha
-error.function.notavailable.title=Funktion nöd verfüegbar
-error.function.nojava3d=Sorry, d'Funktion brucht d Java3d Library,\nvo Sun.com erhältlech.
-error.3d=N Fähler isch mitere 3d Darstellig ufgträte
-error.readme.notfound=Läs mi File nöd gfunde
-error.osmimage.dialogtitle=Fähle bim Bildli-Lade
-error.osmimage.failed=Map Bildli könne nöd glade werde.  Gits ne Internet Verbindig?
-error.language.wrongfile=Die uusgewählti Datei scheint kei Sproch-Datei für GpsPrune z'sii
-error.convertnamestotimes.nonames=Kei Namen han könnet verwondlet werde
-error.lookupsrtm.nonefound=Kei Höhendate verfüegbar für d'Punkte
-error.lookupsrtm.nonerequired=Alle Punkte han die Höhendate scho.  Nüüt z'tue.
-error.gpsies.uploadnotok=Der Gpsies Server hät gseit gha
+error.undofailed.text=Operation kann n\u00f6d r\u00fcckg\u00e4ngig gmacht werde
+error.function.noop.title=Funktion h\u00e4t gar n\u00fc\u00fct gmacht
+error.rearrange.noop=P\u00fcnkte Reorganisierig h\u00e4t kei Eff\u00e4kt gha
+error.function.notavailable.title=Funktion n\u00f6d verf\u00fcegbar
+error.function.nojava3d=Sorry, d'Funktion brucht d Java3d Library,\nvo Sun.com erh\u00e4ltlech.
+error.3d=N F\u00e4hler isch mitere 3d Darstellig ufgtr\u00e4te
+error.readme.notfound=L\u00e4s mi File n\u00f6d gfunde
+error.osmimage.dialogtitle=F\u00e4hle bim Bildli-Lade
+error.osmimage.failed=Map Bildli k\u00f6nne n\u00f6d glade werde.  Gits ne Internet Verbindig?
+error.language.wrongfile=Die uusgew\u00e4hlti Datei scheint kei Sproch-Datei f\u00fcr GpsPrune z'sii
+error.convertnamestotimes.nonames=Kei Namen han k\u00f6nnet verwondlet werde
+error.lookupsrtm.nonefound=Kei H\u00f6hendate verf\u00fcegbar f\u00fcr d'P\u00fcnkte
+error.lookupsrtm.nonerequired=Alle P\u00fcnkte han die H\u00f6hendate scho.  N\u00fc\u00fct z'tue.
+error.gpsies.uploadnotok=Der Gpsies Server h\u00e4t gseit gha
 error.gpsies.uploadfailed=S Uufalade isch fehlgschlage
 error.gpsies.uploadfailed=S Uufalade isch fehlgschlage
+error.showphoto.failed=S F\u00f6teli han i n\u00f6d k\u00f6nne lade
 error.playaudiofailed=S Abschpiele vonem File isch fehlgschlage
 error.playaudiofailed=S Abschpiele vonem File isch fehlgschlage
-error.cache.notthere=D Ordner isch nöd gfunde worde
-error.cache.empty=D Ordner hät nüüt drinne
+error.cache.notthere=D Ordner isch n\u00f6d gfunde worde
+error.cache.empty=D Ordner h\u00e4t n\u00fc\u00fct drinne
 error.cache.cannotdelete=Es sin kei Kachle gl\u00f6scht worde
 error.cache.cannotdelete=Es sin kei Kachle gl\u00f6scht worde
+error.interpolate.invalidparameter=D'Aazahl P\u00fcnkt muess zw\u00fcschet 1 und 1000 sii
index 003593b58a1700e52024f28c72651110294d095f..f2e70e1d9a6ba94f8a8c7d92dafa36985d9e3426 100644 (file)
@@ -1,5 +1,5 @@
 # Text entries for the GpsPrune application
 # Text entries for the GpsPrune application
-# English entries as default - others can be added
+# English entries as default
 
 # Menu entries
 menu.file=File
 
 # Menu entries
 menu.file=File
@@ -10,6 +10,7 @@ menu.file.exit=Exit
 menu.track=Track
 menu.track.undo=Undo
 menu.track.clearundo=Clear undo list
 menu.track=Track
 menu.track.undo=Undo
 menu.track.clearundo=Clear undo list
+menu.track.markrectangle=Mark points in rectangle
 menu.track.deletemarked=Delete marked points
 menu.track.rearrange=Rearrange waypoints
 menu.track.rearrange.start=All to start of file
 menu.track.deletemarked=Delete marked points
 menu.track.rearrange=Rearrange waypoints
 menu.track.rearrange.start=All to start of file
@@ -20,8 +21,6 @@ menu.range.all=Select all
 menu.range.none=Select none
 menu.range.start=Set range start
 menu.range.end=Set range end
 menu.range.none=Select none
 menu.range.start=Set range start
 menu.range.end=Set range end
-menu.range.deleterange=Delete range
-menu.range.interpolate=Interpolate
 menu.range.average=Average selection
 menu.range.reverse=Reverse range
 menu.range.mergetracksegments=Merge track segments
 menu.range.average=Average selection
 menu.range.reverse=Reverse range
 menu.range.mergetracksegments=Merge track segments
@@ -54,6 +53,7 @@ menu.map.connect=Connect track points
 menu.map.autopan=Autopan
 menu.map.showmap=Show map
 menu.map.showscalebar=Show scalebar
 menu.map.autopan=Autopan
 menu.map.showmap=Show map
 menu.map.showscalebar=Show scalebar
+menu.map.editmode=Edit mode
 
 # Alt keys for menus
 altkey.menu.file=F
 
 # Alt keys for menus
 altkey.menu.file=F
@@ -86,6 +86,9 @@ function.exportpov=Export POV
 function.exportsvg=Export SVG
 function.editwaypointname=Edit waypoint name
 function.compress=Compress track
 function.exportsvg=Export SVG
 function.editwaypointname=Edit waypoint name
 function.compress=Compress track
+function.deleterange=Delete range
+function.croptrack=Crop track
+function.interpolate=Interpolate points
 function.addtimeoffset=Add time offset
 function.addaltitudeoffset=Add altitude offset
 function.findwaypoint=Find waypoint
 function.addtimeoffset=Add time offset
 function.addaltitudeoffset=Add altitude offset
 function.findwaypoint=Find waypoint
@@ -140,6 +143,7 @@ dialog.deletepoint.title=Delete Point
 dialog.deletepoint.deletephoto=Delete photo attached to this point?
 dialog.deletephoto.title=Delete Photo
 dialog.deletephoto.deletepoint=Delete point attached to this photo?
 dialog.deletepoint.deletephoto=Delete photo attached to this point?
 dialog.deletephoto.title=Delete Photo
 dialog.deletephoto.deletepoint=Delete point attached to this photo?
+dialog.deleteaudio.deletepoint=Delete point attached to this audio clip?
 dialog.openoptions.title=Open options
 dialog.openoptions.filesnippet=Extract of file
 dialog.load.table.field=Field
 dialog.openoptions.title=Open options
 dialog.openoptions.filesnippet=Extract of file
 dialog.load.table.field=Field
@@ -219,8 +223,8 @@ dialog.confirmreversetrack.title=Confirm reversal
 dialog.confirmreversetrack.text=This track contains timestamp information, which will be out of sequence after a reversal.\nAre you sure you want to reverse this section?
 dialog.confirmcutandmove.title=Confirm cut and move
 dialog.confirmcutandmove.text=This track contains timestamp information, which will be out of sequence after a move.\nAre you sure you want to move this section?
 dialog.confirmreversetrack.text=This track contains timestamp information, which will be out of sequence after a reversal.\nAre you sure you want to reverse this section?
 dialog.confirmcutandmove.title=Confirm cut and move
 dialog.confirmcutandmove.text=This track contains timestamp information, which will be out of sequence after a move.\nAre you sure you want to move this section?
-dialog.interpolate.title=Interpolate points
-dialog.interpolate.parameter.text=Number of points to insert between selected points
+dialog.interpolate.parameter.text=Number of points to insert between each pair of points
+dialog.interpolate.betweenwaypoints=Interpolate between waypoints?
 dialog.undo.title=Undo action(s)
 dialog.undo.pretext=Please select the action(s) to undo
 dialog.undo.none.title=Cannot undo
 dialog.undo.title=Undo action(s)
 dialog.undo.pretext=Please select the action(s) to undo
 dialog.undo.none.title=Cannot undo
@@ -237,7 +241,7 @@ dialog.pointedit.changevalue.title=Edit field
 dialog.pointnameedit.name=Waypoint name
 dialog.pointnameedit.uppercase=UPPER case
 dialog.pointnameedit.lowercase=lower case
 dialog.pointnameedit.name=Waypoint name
 dialog.pointnameedit.uppercase=UPPER case
 dialog.pointnameedit.lowercase=lower case
-dialog.pointnameedit.sentencecase=Sentence Case
+dialog.pointnameedit.titlecase=Title Case
 dialog.addtimeoffset.add=Add time
 dialog.addtimeoffset.subtract=Subtract time
 dialog.addtimeoffset.days=Days
 dialog.addtimeoffset.add=Add time
 dialog.addtimeoffset.subtract=Subtract time
 dialog.addtimeoffset.days=Days
@@ -273,6 +277,8 @@ dialog.distances.column.to=To point
 dialog.distances.currentpoint=Current point
 dialog.distances.toofewpoints=This function needs waypoints in order to calculate the distances between them
 dialog.fullrangedetails.intro=Here are the details for the selected range
 dialog.distances.currentpoint=Current point
 dialog.distances.toofewpoints=This function needs waypoints in order to calculate the distances between them
 dialog.fullrangedetails.intro=Here are the details for the selected range
+dialog.fullrangedetails.coltotal=Including gaps
+dialog.fullrangedetails.colsegments=Without gaps
 dialog.setmapbg.intro=Select one of the map sources, or add a new one
 dialog.addmapsource.title=Add new map source
 dialog.addmapsource.sourcename=Name of source
 dialog.setmapbg.intro=Select one of the map sources, or add a new one
 dialog.addmapsource.title=Add new map source
 dialog.addmapsource.sourcename=Name of source
@@ -303,6 +309,7 @@ dialog.wikipedia.column.name=Article name
 dialog.wikipedia.column.distance=Distance
 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.wikipedia.column.distance=Distance
 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.nouncorrelatedaudios=There are no uncorrelated audios.\nAre you sure you want to continue?
 dialog.correlate.photoselect.intro=Select one of these correlated photos to use as the time offset
 dialog.correlate.select.photoname=Photo name
 dialog.correlate.select.timediff=Time difference
 dialog.correlate.photoselect.intro=Select one of these correlated photos to use as the time offset
 dialog.correlate.select.photoname=Photo name
 dialog.correlate.select.timediff=Time difference
@@ -324,7 +331,7 @@ dialog.correlate.options.timelimit=Time limit
 dialog.correlate.options.nodistancelimit=No distance limit
 dialog.correlate.options.distancelimit=Distance limit
 dialog.correlate.options.correlate=Correlate
 dialog.correlate.options.nodistancelimit=No distance limit
 dialog.correlate.options.distancelimit=Distance limit
 dialog.correlate.options.correlate=Correlate
-dialog.correlate.alloutsiderange=All photos are outside the time range of the track, so none can be correlated.\nTry changing the offset or manually correlating at least one photo.
+dialog.correlate.alloutsiderange=All the items are outside the time range of the track, so none can be correlated.\nTry changing the offset or manually correlating at least one item.
 dialog.correlate.filetimes=File timestamps denote:
 dialog.correlate.filetimes2=of audio clip
 dialog.correlate.correltimes=For correlation, use:
 dialog.correlate.filetimes=File timestamps denote:
 dialog.correlate.filetimes2=of audio clip
 dialog.correlate.correltimes=For correlation, use:
@@ -340,7 +347,6 @@ dialog.rearrangephotos.toend=Move to end
 dialog.rearrangephotos.nosort=Don't sort
 dialog.rearrangephotos.sortbyfilename=Sort by filename
 dialog.rearrangephotos.sortbytime=Sort by time
 dialog.rearrangephotos.nosort=Don't sort
 dialog.rearrangephotos.sortbyfilename=Sort by filename
 dialog.rearrangephotos.sortbytime=Sort by time
-dialog.compress.nonefound=No data points could be removed
 dialog.compress.duplicates.title=Duplicate removal
 dialog.compress.closepoints.title=Nearby point removal
 dialog.compress.closepoints.paramdesc=Span factor
 dialog.compress.duplicates.title=Duplicate removal
 dialog.compress.closepoints.title=Nearby point removal
 dialog.compress.closepoints.paramdesc=Span factor
@@ -351,15 +357,19 @@ dialog.compress.singletons.paramdesc=Distance factor
 dialog.compress.douglaspeucker.title=Douglas-Peucker compression
 dialog.compress.douglaspeucker.paramdesc=Span factor
 dialog.compress.summarylabel=Points to delete
 dialog.compress.douglaspeucker.title=Douglas-Peucker compression
 dialog.compress.douglaspeucker.paramdesc=Span factor
 dialog.compress.summarylabel=Points to delete
+dialog.compress.confirm1=
+dialog.compress.confirm2=points have been marked.\nUse Track->Delete marked points to delete them
+dialog.compress.confirmnone=no points have been marked
+dialog.deletemarked.nonefound=No data points could be removed
 dialog.pastecoordinates.desc=Enter or paste the coordinates here
 dialog.pastecoordinates.coords=Coordinates
 dialog.pastecoordinates.nothingfound=Please check the coordinates and try again
 dialog.pastecoordinates.desc=Enter or paste the coordinates here
 dialog.pastecoordinates.coords=Coordinates
 dialog.pastecoordinates.nothingfound=Please check the coordinates and try again
-dialog.help.help=Please see\n http://activityworkshop.net/software/gpsprune/\nfor more information and user guides.
+dialog.help.help=Please see\n http://gpsprune.activityworkshop.net/\nfor more information and tips,\nincluding a new PDF user guide you can buy.
 dialog.about.version=Version
 dialog.about.build=Build
 dialog.about.summarytext1=GpsPrune is a program for loading, displaying and editing data from GPS receivers.
 dialog.about.summarytext2=It is released under the Gnu GPL for free, open, worldwide use and enhancement.<br>Copying, redistribution and modification are permitted and encouraged<br>according to the conditions in the included <code>license.txt</code> file.
 dialog.about.version=Version
 dialog.about.build=Build
 dialog.about.summarytext1=GpsPrune is a program for loading, displaying and editing data from GPS receivers.
 dialog.about.summarytext2=It is released under the Gnu GPL for free, open, worldwide use and enhancement.<br>Copying, redistribution and modification are permitted and encouraged<br>according to the conditions in the included <code>license.txt</code> file.
-dialog.about.summarytext3=Please see <code style="font-weight:bold">http://activityworkshop.net/</code> for more information and user guides.
+dialog.about.summarytext3=Please see <code style="font-weight:bold">http://activityworkshop.net/</code> for more information and tips, including<br>a new PDF user guide you can buy.
 dialog.about.languages=Available languages
 dialog.about.translatedby=English text by activityworkshop.
 dialog.about.systeminfo=System info
 dialog.about.languages=Available languages
 dialog.about.translatedby=English text by activityworkshop.
 dialog.about.systeminfo=System info
@@ -406,7 +416,6 @@ dialog.saveconfig.prune.languagefile=Language file
 dialog.saveconfig.prune.gpsdevice=GPS device
 dialog.saveconfig.prune.gpsformat=GPS format
 dialog.saveconfig.prune.povrayfont=Povray font
 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.gnuplotpath=Path to gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Path to gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Path to exiftool
@@ -447,6 +456,7 @@ dialog.diskcache.save=Save map images to disk
 dialog.diskcache.dir=Cache directory
 dialog.diskcache.createdir=Create directory
 dialog.diskcache.nocreate=Cache directory not created
 dialog.diskcache.dir=Cache directory
 dialog.diskcache.createdir=Create directory
 dialog.diskcache.nocreate=Cache directory not created
+dialog.diskcache.cannotwrite=Map tiles cannot be saved in the selected directory
 dialog.diskcache.table.path=Path
 dialog.diskcache.table.usedby=Used by
 dialog.diskcache.table.zoom=Zoom
 dialog.diskcache.table.path=Path
 dialog.diskcache.table.usedby=Used by
 dialog.diskcache.table.zoom=Zoom
@@ -460,6 +470,7 @@ dialog.diskcache.deleteall=Delete all tiles
 dialog.diskcache.deleted1=Deleted
 dialog.diskcache.deleted2=files from the cache
 dialog.deletefieldvalues.intro=Select the field to delete for the current range
 dialog.diskcache.deleted1=Deleted
 dialog.diskcache.deleted2=files from the cache
 dialog.deletefieldvalues.intro=Select the field to delete for the current range
+dialog.deletefieldvalues.nofields=There are no fields to delete for this range
 dialog.setlinewidth.text=Enter the thickness of lines to draw for the tracks (1-4)
 dialog.downloadosm.desc=Confirm to download the raw OSM data for the specified area:
 dialog.searchwikipedianames.search=Search for:
 dialog.setlinewidth.text=Enter the thickness of lines to draw for the tracks (1-4)
 dialog.downloadosm.desc=Confirm to download the raw OSM data for the specified area:
 dialog.searchwikipedianames.search=Search for:
@@ -485,6 +496,7 @@ confirm.addaltitudeoffset=Altitude offset added
 confirm.rearrangewaypoints=Waypoints rearranged
 confirm.rearrangephotos=Photos rearranged
 confirm.cutandmove=Selection moved
 confirm.rearrangewaypoints=Waypoints rearranged
 confirm.rearrangephotos=Photos rearranged
 confirm.cutandmove=Selection moved
+confirm.interpolate=Points added
 confirm.convertnamestotimes=Waypoint names converted
 confirm.saveexif.ok1=Saved
 confirm.saveexif.ok2=photo files
 confirm.convertnamestotimes=Waypoint names converted
 confirm.saveexif.ok1=Saved
 confirm.saveexif.ok2=photo files
@@ -580,7 +592,6 @@ display.range.time.mins=m
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=Ave speed
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=Ave speed
-details.range.avemovingspeed=Moving average
 details.range.maxspeed=Maximum speed
 details.range.numsegments=Number of segments
 details.range.pace=Pace
 details.range.maxspeed=Maximum speed
 details.range.numsegments=Number of segments
 details.range.pace=Pace
@@ -593,6 +604,7 @@ details.nophoto=No photo selected
 details.photo.loading=Loading
 details.photo.bearing=Bearing
 details.media.connected=Connected
 details.photo.loading=Loading
 details.photo.bearing=Bearing
 details.media.connected=Connected
+details.media.fullpath=Full path
 details.audiodetails=Audio details
 details.noaudio=No audio clip selected
 details.audio.file=Audio file
 details.audiodetails=Audio details
 details.noaudio=No audio clip selected
 details.audio.file=Audio file
@@ -626,12 +638,15 @@ units.feet=Feet
 units.feet.short=ft
 units.kilometres=Kilometres
 units.kilometres.short=km
 units.feet.short=ft
 units.kilometres=Kilometres
 units.kilometres.short=km
-units.kmh=km/h
+units.kilometresperhour.short=km/h
 units.miles=Miles
 units.miles.short=mi
 units.miles=Miles
 units.miles.short=mi
-units.mph=mph
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.milesperhour.short=mph
+units.nauticalmiles=Nautical miles
+units.nauticalmiles.short=N.m.
+units.nauticalmilesperhour.short=kts
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=hours
 units.degminsec=Deg-min-sec
 units.degmin=Deg-min
 units.hours=hours
 units.degminsec=Deg-min-sec
 units.degmin=Deg-min
@@ -657,7 +672,8 @@ undo.deletepoint=delete point
 undo.removephoto=remove photo
 undo.removeaudio=remove audio clip
 undo.deleterange=delete range
 undo.removephoto=remove photo
 undo.removeaudio=remove audio clip
 undo.deleterange=delete range
-undo.compress=compress track
+undo.croptrack=crop track
+undo.deletemarked=delete points
 undo.insert=insert points
 undo.reverse=reverse range
 undo.mergetracksegments=merge track segments
 undo.insert=insert points
 undo.reverse=reverse range
 undo.mergetracksegments=merge track segments
@@ -716,7 +732,9 @@ error.lookupsrtm.nonefound=No altitude values available for these points
 error.lookupsrtm.nonerequired=All points already have altitudes, so there's nothing to lookup
 error.gpsies.uploadnotok=The gpsies server returned the message
 error.gpsies.uploadfailed=The upload failed with the error
 error.lookupsrtm.nonerequired=All points already have altitudes, so there's nothing to lookup
 error.gpsies.uploadnotok=The gpsies server returned the message
 error.gpsies.uploadfailed=The upload failed with the error
+error.showphoto.failed=Failed to load photo
 error.playaudiofailed=Failed to play audio clip
 error.cache.notthere=The tile cache directory was not found
 error.cache.empty=The tile cache directory is empty
 error.cache.cannotdelete=No tiles could be deleted
 error.playaudiofailed=Failed to play audio clip
 error.cache.notthere=The tile cache directory was not found
 error.cache.empty=The tile cache directory is empty
 error.cache.cannotdelete=No tiles could be deleted
+error.interpolate.invalidparameter=The number of points must be between 1 and 1000
index 49bc392e06a2fae6168b18d9f8b4d0b4e38441f9..77f889328b5b00cbab166c52346afb72f1873181 100644 (file)
@@ -20,8 +20,8 @@ menu.range.all=Seleccionar todo
 menu.range.none=No seleccionar nada
 menu.range.start=Fijar comienzo
 menu.range.end=Fijar final
 menu.range.none=No seleccionar nada
 menu.range.start=Fijar comienzo
 menu.range.end=Fijar final
-menu.range.deleterange=Eliminar rango
-menu.range.interpolate=Interpolar
+function.deleterange=Eliminar rango
+function.interpolate=Interpolar puntos
 menu.range.average=Crear punto a la media del rango
 menu.range.reverse=Invertir rango
 menu.range.mergetracksegments=Unir los segmentos de track
 menu.range.average=Crear punto a la media del rango
 menu.range.reverse=Invertir rango
 menu.range.mergetracksegments=Unir los segmentos de track
@@ -219,7 +219,6 @@ 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. \u00bfEst\u00e1 seguro que desea invertir esta secci\u00f3n?
 dialog.confirmcutandmove.title=Confirmar accion cortar/pegar
 dialog.confirmcutandmove.text=Este track contiene informaci\u00f3n sobre la fecha, que estar\u00e1 fuera de secuencia despu\u00e9s de mover.\n\u00bfEsta seguro que desea mover esta secci\u00f3n?
 dialog.confirmreversetrack.text=Este track contiene informaci\u00f3n sobre la fecha, que estar\u00e1 fuera de secuencia despu\u00e9s de la inversi\u00f3n. \u00bfEst\u00e1 seguro que desea invertir esta secci\u00f3n?
 dialog.confirmcutandmove.title=Confirmar accion cortar/pegar
 dialog.confirmcutandmove.text=Este track contiene informaci\u00f3n sobre la fecha, que estar\u00e1 fuera de secuencia despu\u00e9s de mover.\n\u00bfEsta seguro que desea mover esta secci\u00f3n?
-dialog.interpolate.title=Interpolar puntos
 dialog.interpolate.parameter.text=N\u00famero de los puntos a insertar entre los puntos elegidos
 dialog.undo.title=Deshacer
 dialog.undo.pretext=Por favor, seleccione la operaci\u00f3n(es) a deshacer
 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\u00f3n(es) a deshacer
@@ -237,7 +236,7 @@ dialog.pointedit.changevalue.title=Editar campo
 dialog.pointnameedit.name=Nombre de waypoint
 dialog.pointnameedit.uppercase=May\u00fasculas
 dialog.pointnameedit.lowercase=min\u00fasculas
 dialog.pointnameedit.name=Nombre de waypoint
 dialog.pointnameedit.uppercase=May\u00fasculas
 dialog.pointnameedit.lowercase=min\u00fasculas
-dialog.pointnameedit.sentencecase=Mezcla
+dialog.pointnameedit.titlecase=Mezcla
 dialog.addtimeoffset.add=A\u00f1adir tiempo
 dialog.addtimeoffset.subtract=Sustraer tiempo
 dialog.addtimeoffset.days=Dias
 dialog.addtimeoffset.add=A\u00f1adir tiempo
 dialog.addtimeoffset.subtract=Sustraer tiempo
 dialog.addtimeoffset.days=Dias
@@ -340,7 +339,7 @@ dialog.rearrangephotos.toend=Mover al final
 dialog.rearrangephotos.nosort=No sortear
 dialog.rearrangephotos.sortbyfilename=Sortear por nombre del archivo
 dialog.rearrangephotos.sortbytime=Sortear por tiempo
 dialog.rearrangephotos.nosort=No sortear
 dialog.rearrangephotos.sortbyfilename=Sortear por nombre del archivo
 dialog.rearrangephotos.sortbytime=Sortear por tiempo
-dialog.compress.nonefound=Ning\u00fan punto eliminado
+dialog.deletemarked.nonefound=Ning\u00fan punto eliminado
 dialog.compress.closepoints.title=remover puntos cercanos
 dialog.compress.closepoints.paramdesc=Factor de extensi\u00f3n
 dialog.compress.wackypoints.title=Eliminar puntos an\u00f3malos
 dialog.compress.closepoints.title=remover puntos cercanos
 dialog.compress.closepoints.paramdesc=Factor de extensi\u00f3n
 dialog.compress.wackypoints.title=Eliminar puntos an\u00f3malos
@@ -406,7 +405,6 @@ dialog.saveconfig.prune.languagefile=Archivo de lenguaje
 dialog.saveconfig.prune.gpsdevice=Dispositivo GPS
 dialog.saveconfig.prune.gpsformat=Formato GPS
 dialog.saveconfig.prune.povrayfont=Fuente povray
 dialog.saveconfig.prune.gpsdevice=Dispositivo GPS
 dialog.saveconfig.prune.gpsformat=Formato GPS
 dialog.saveconfig.prune.povrayfont=Fuente povray
-dialog.saveconfig.prune.metricunits=\u00bfUsar unidades m\u00e9tricas?
 dialog.saveconfig.prune.gnuplotpath=Ruta a gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Ruta a gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Ruta a exiftool
 dialog.saveconfig.prune.gnuplotpath=Ruta a gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Ruta a gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Ruta a exiftool
@@ -580,7 +578,6 @@ display.range.time.mins=m
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=Velocidad media
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=Velocidad media
-details.range.avemovingspeed=Moviendo promedio
 details.range.maxspeed=Velocidad m\u00e1xima
 details.range.numsegments=N\u00famero de segmentos
 details.range.pace=Ritmo
 details.range.maxspeed=Velocidad m\u00e1xima
 details.range.numsegments=N\u00famero de segmentos
 details.range.pace=Ritmo
@@ -626,12 +623,11 @@ units.feet=Pies
 units.feet.short=ft
 units.kilometres=Kil\u00f3metros
 units.kilometres.short=km
 units.feet.short=ft
 units.kilometres=Kil\u00f3metros
 units.kilometres.short=km
-units.kmh=km/h
 units.miles=Millas
 units.miles.short=mi
 units.miles=Millas
 units.miles.short=mi
-units.mph=mi/h
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.milesperhour.short=mi/h
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=horas
 units.degminsec=Gra-min-seg
 units.degmin=Gra-min
 units.hours=horas
 units.degminsec=Gra-min-seg
 units.degmin=Gra-min
@@ -651,13 +647,13 @@ cardinal.w=O
 # Undo operations
 undo.load=cargar datos
 undo.loadphotos=cargar fotos
 # Undo operations
 undo.load=cargar datos
 undo.loadphotos=cargar fotos
-undo.loadaudios=Cargar archivos de audio
+undo.loadaudios=cargar archivos de audio
 undo.editpoint=editar punto
 undo.deletepoint=eliminar punto
 undo.removephoto=eliminar foto
 undo.editpoint=editar punto
 undo.deletepoint=eliminar punto
 undo.removephoto=eliminar foto
-undo.removeaudio=Eliminar archivos de audio
+undo.removeaudio=eliminar archivos de audio
 undo.deleterange=eliminar rango
 undo.deleterange=eliminar rango
-undo.compress=comprimir track
+undo.deletemarked=eliminar puntos
 undo.insert=insertar puntos
 undo.reverse=invertir rango
 undo.mergetracksegments=unir los segmentos de track
 undo.insert=insertar puntos
 undo.reverse=invertir rango
 undo.mergetracksegments=unir los segmentos de track
@@ -665,16 +661,16 @@ undo.addtimeoffset=a\u00f1adir margen de tiempo
 undo.addaltitudeoffset=a\u00f1adir margen de altitud
 undo.rearrangewaypoints=reordenar waypoints
 undo.cutandmove=mover secci\u00f3n
 undo.addaltitudeoffset=a\u00f1adir margen de altitud
 undo.rearrangewaypoints=reordenar waypoints
 undo.cutandmove=mover secci\u00f3n
-undo.connect=Conectar
-undo.disconnect=Desconectar
+undo.connect=conectar
+undo.disconnect=desconectar
 undo.correlatephotos=correlacionar fotos
 undo.rearrangephotos=reordenar fotos
 undo.createpoint=crear punto
 undo.rotatephoto=girar foto
 undo.convertnamestotimes=convertir nombres a tiempo
 undo.lookupsrtm=obtener altitudes de SRTM
 undo.correlatephotos=correlacionar fotos
 undo.rearrangephotos=reordenar fotos
 undo.createpoint=crear punto
 undo.rotatephoto=girar foto
 undo.convertnamestotimes=convertir nombres a tiempo
 undo.lookupsrtm=obtener altitudes de SRTM
-undo.deletefieldvalues=Eliminar valores de campo
-undo.correlateaudios=Correlacionar audios
+undo.deletefieldvalues=eliminar valores de campo
+undo.correlateaudios=correlacionar audios
 
 # Error messages
 error.save.dialogtitle=Fallo al guardar datos
 
 # Error messages
 error.save.dialogtitle=Fallo al guardar datos
index 2e9d558f0e63fca59936e87a219b8884a75d745f..960330d4f8a44c25dbca8c9fb7df2e56799cb868 100644 (file)
@@ -19,8 +19,8 @@ menu.range.all=\u0627\u0646\u062a\u062e\u0627\u0628 \u0647\u0645\u0647 \u0646\u0
 menu.range.none=\u0627\u0646\u062a\u062e\u0627\u0628 \u0647\u064a\u0686 \u064a\u06a9 \u0627\u0632 \u0646\u0642\u0627\u0637
 menu.range.start=\u062a\u0646\u0638\u064a\u0645 \u0634\u0631\u0648\u0639 \u0686\u064a\u0646\u0634
 menu.range.end=\u062a\u0646\u0638\u064a\u0645 \u0627\u0646\u062a\u0647\u0627\u06cc \u0686\u064a\u0646\u0634
 menu.range.none=\u0627\u0646\u062a\u062e\u0627\u0628 \u0647\u064a\u0686 \u064a\u06a9 \u0627\u0632 \u0646\u0642\u0627\u0637
 menu.range.start=\u062a\u0646\u0638\u064a\u0645 \u0634\u0631\u0648\u0639 \u0686\u064a\u0646\u0634
 menu.range.end=\u062a\u0646\u0638\u064a\u0645 \u0627\u0646\u062a\u0647\u0627\u06cc \u0686\u064a\u0646\u0634
-menu.range.deleterange=\u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u0686\u064a\u0646\u0634
-menu.range.interpolate=\u062f\u0631\u0648\u0646\u064a\u0627\u0628\u06cc
+function.deleterange=\u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u0686\u064a\u0646\u0634
+function.interpolate=\u062f\u0631\u0648\u0646\u064a\u0627\u0628\u06cc
 menu.range.average=\u0645\u06cc\u0627\u0646\u06af\u064a\u0646 \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647 \u0647\u0627
 menu.range.reverse=\u0686\u064a\u0646\u0634 \u0645\u0639\u06a9\u0648\u0633
 menu.range.mergetracksegments=\u0627\u062a\u0635\u0627\u0644 \u0642\u0633\u0645\u062a \u0647\u0627\u06cc \u0645\u0633\u064a\u0631
 menu.range.average=\u0645\u06cc\u0627\u0646\u06af\u064a\u0646 \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647 \u0647\u0627
 menu.range.reverse=\u0686\u064a\u0646\u0634 \u0645\u0639\u06a9\u0648\u0633
 menu.range.mergetracksegments=\u0627\u062a\u0635\u0627\u0644 \u0642\u0633\u0645\u062a \u0647\u0627\u06cc \u0645\u0633\u064a\u0631
index 1e0164b3a87def438f01c537164dbee4792e64cb..1b0364ce8e600bd0a2c263fc43f9dbe0be6e56fd 100644 (file)
@@ -1,10 +1,10 @@
 # Text entries for the GpsPrune application
 # Text entries for the GpsPrune application
-# French entries as extra
+# French entries
 
 # Menu entries
 menu.file=Fichier
 menu.file.addphotos=Ajouter photos
 
 # Menu entries
 menu.file=Fichier
 menu.file.addphotos=Ajouter photos
-menu.file.recentfiles=Derniers Fichiers utilis\u00e9s
+menu.file.recentfiles=Fichiers r\u00e9cents
 menu.file.save=Enregistrer
 menu.file.exit=Quitter
 menu.track=Trace
 menu.file.save=Enregistrer
 menu.file.exit=Quitter
 menu.track=Trace
@@ -20,8 +20,6 @@ menu.range.all=Tout s\u00e9lectionner
 menu.range.none=Rien s\u00e9lectionner
 menu.range.start=D\u00e9finir le d\u00e9but de l'\u00e9tendue
 menu.range.end=D\u00e9finir la fin de l'\u00e9tendue
 menu.range.none=Rien s\u00e9lectionner
 menu.range.start=D\u00e9finir le d\u00e9but de l'\u00e9tendue
 menu.range.end=D\u00e9finir la fin de l'\u00e9tendue
-menu.range.deleterange=Supprimer l'\u00e9tendue
-menu.range.interpolate=Interpoler
 menu.range.average=Cr\u00e9er un point pour la s\u00e9lection
 menu.range.reverse=Inverser l'\u00e9tendue
 menu.range.mergetracksegments=Fusionner les segments de trace
 menu.range.average=Cr\u00e9er un point pour la s\u00e9lection
 menu.range.reverse=Inverser l'\u00e9tendue
 menu.range.mergetracksegments=Fusionner les segments de trace
@@ -77,6 +75,7 @@ shortcut.menu.help.help=A
 
 # Functions
 function.open=Ouvrir fichier
 
 # Functions
 function.open=Ouvrir fichier
+function.importwithgpsbabel=Importer fichier avec GPSBabel
 function.loadfromgps=T\u00e9l\u00e9charger donn\u00e9es du GPS
 function.sendtogps=Envoyer donn\u00e9es au GPS
 function.exportkml=Exporter en KML
 function.loadfromgps=T\u00e9l\u00e9charger donn\u00e9es du GPS
 function.sendtogps=Envoyer donn\u00e9es au GPS
 function.exportkml=Exporter en KML
@@ -85,6 +84,8 @@ function.exportpov=Exporter en POV
 function.exportsvg=Exporter en SVG
 function.editwaypointname=\u00c9diter le nom du waypoint
 function.compress=Compresser la trace
 function.exportsvg=Exporter en SVG
 function.editwaypointname=\u00c9diter le nom du waypoint
 function.compress=Compresser la trace
+function.deleterange=Supprimer l'\u00e9tendue
+function.interpolate=Interpoler les points
 function.addtimeoffset=Ajouter un d\u00e9calage d'horaire
 function.addaltitudeoffset=Ajouter un d\u00e9calage d'altitude
 function.convertnamestotimes=Convertir les noms de waypoints en horodatages
 function.addtimeoffset=Ajouter un d\u00e9calage d'horaire
 function.addaltitudeoffset=Ajouter un d\u00e9calage d'altitude
 function.convertnamestotimes=Convertir les noms de waypoints en horodatages
@@ -128,6 +129,7 @@ function.about=\u00c0 propos de GpsPrune
 function.checkversion=Chercher une mise \u00e0 jour
 function.saveconfig=Enregistrer les pr\u00e9f\u00e9rences
 function.diskcache=Enregistrer les cartes sur le disque
 function.checkversion=Chercher une mise \u00e0 jour
 function.saveconfig=Enregistrer les pr\u00e9f\u00e9rences
 function.diskcache=Enregistrer les cartes sur le disque
+function.managetilecache=Gestion du cache des tuiles de cartes
 
 # Dialogs
 dialog.exit.confirm.title=Quitter GpsPrune
 
 # Dialogs
 dialog.exit.confirm.title=Quitter GpsPrune
@@ -191,7 +193,8 @@ dialog.exportgpx.name=Nom
 dialog.exportgpx.desc=L\u00e9gende
 dialog.exportgpx.includetimestamps=Inclure l'heure pour chaque point
 dialog.exportgpx.copysource=Copier la source xml
 dialog.exportgpx.desc=L\u00e9gende
 dialog.exportgpx.includetimestamps=Inclure l'heure pour chaque point
 dialog.exportgpx.copysource=Copier la source xml
-dialog.exportgpx.encoding.system=Syst\u00e8me
+dialog.exportgpx.encoding=Encodage
+dialog.exportgpx.encoding.system=Encodage syst\u00e8me
 dialog.exportgpx.encoding.utf8=UTF-8
 dialog.exportpov.text=Entrez les param\u00e8tres pour l'export POV
 dialog.exportpov.font=Police
 dialog.exportgpx.encoding.utf8=UTF-8
 dialog.exportpov.text=Entrez les param\u00e8tres pour l'export POV
 dialog.exportpov.font=Police
@@ -216,7 +219,6 @@ dialog.confirmreversetrack.title=Confirmer l'inversion
 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.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 \u00e0 ins\u00e9rer entre les points s\u00e9lectionn\u00e9s
 dialog.undo.title=Annuler les actions
 dialog.undo.pretext=S\u00e9lectionnez les actions \u00e0 annuler
 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\u00e9lectionnez les actions \u00e0 annuler
@@ -234,7 +236,7 @@ dialog.pointedit.changevalue.title=\u00c9diter le champ
 dialog.pointnameedit.name=Nom de waypoint
 dialog.pointnameedit.uppercase=CASSE MAJUSCULES
 dialog.pointnameedit.lowercase=casse minuscules
 dialog.pointnameedit.name=Nom de waypoint
 dialog.pointnameedit.uppercase=CASSE MAJUSCULES
 dialog.pointnameedit.lowercase=casse minuscules
-dialog.pointnameedit.sentencecase=Casse Phrase
+dialog.pointnameedit.titlecase=Casse Phrase
 dialog.addtimeoffset.add=Retarder l'heure
 dialog.addtimeoffset.subtract=Avancer l'heure
 dialog.addtimeoffset.days=Jours
 dialog.addtimeoffset.add=Retarder l'heure
 dialog.addtimeoffset.subtract=Avancer l'heure
 dialog.addtimeoffset.days=Jours
@@ -337,7 +339,6 @@ dialog.rearrangephotos.toend=Aller \u00e0 la fin
 dialog.rearrangephotos.nosort=Ne pas trier
 dialog.rearrangephotos.sortbyfilename=Trier par nom de fichier
 dialog.rearrangephotos.sortbytime=Trier par horodatage
 dialog.rearrangephotos.nosort=Ne pas trier
 dialog.rearrangephotos.sortbyfilename=Trier par nom de fichier
 dialog.rearrangephotos.sortbytime=Trier par horodatage
-dialog.compress.nonefound=Pas de donn\u00e9es \u00e0 effacer
 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.closepoints.title=Suppression des points voisins
 dialog.compress.closepoints.paramdesc=Taille du voisinage
 dialog.compress.wackypoints.title=Suppression des points anormaux
@@ -348,6 +349,7 @@ dialog.compress.duplicates.title=Suppression des doublons
 dialog.compress.douglaspeucker.title=Compression Douglas-Peucker
 dialog.compress.douglaspeucker.paramdesc=Taille du voisinage
 dialog.compress.summarylabel=Points \u00e0 supprimer
 dialog.compress.douglaspeucker.title=Compression Douglas-Peucker
 dialog.compress.douglaspeucker.paramdesc=Taille du voisinage
 dialog.compress.summarylabel=Points \u00e0 supprimer
+dialog.deletemarked.nonefound=Pas de donn\u00e9es \u00e0 effacer
 dialog.pastecoordinates.desc=Entrez ou collez les coordonn\u00e9es ici
 dialog.pastecoordinates.coords=Coordonn\u00e9es
 dialog.pastecoordinates.nothingfound=V\u00e9rifier les coordonn\u00e9es et essayez \u00e0 nouveau
 dialog.pastecoordinates.desc=Entrez ou collez les coordonn\u00e9es ici
 dialog.pastecoordinates.coords=Coordonn\u00e9es
 dialog.pastecoordinates.nothingfound=V\u00e9rifier les coordonn\u00e9es et essayez \u00e0 nouveau
@@ -403,7 +405,6 @@ dialog.saveconfig.prune.languagefile=Fichier de langue
 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.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.gnuplotpath=Chemin gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Chemin gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Chemin exiftool
@@ -444,6 +445,16 @@ dialog.diskcache.save=Enregistrer les images de carte sur le disque
 dialog.diskcache.dir=R\u00e9pertoire cache
 dialog.diskcache.createdir=Cr\u00e9er r\u00e9pertoire
 dialog.diskcache.nocreate=Le r\u00e9pertoire cache n'est pas cr\u00e9\u00e9
 dialog.diskcache.dir=R\u00e9pertoire cache
 dialog.diskcache.createdir=Cr\u00e9er r\u00e9pertoire
 dialog.diskcache.nocreate=Le r\u00e9pertoire cache n'est pas cr\u00e9\u00e9
+dialog.diskcache.table.path=Chemin
+dialog.diskcache.table.usedby=Utilis\u00e9 par
+dialog.diskcache.table.zoom=Amplitude du zoom
+dialog.diskcache.table.tiles=Tuiles
+dialog.diskcache.table.megabytes=Megabytes
+dialog.diskcache.tileset.multiple=multiple
+dialog.diskcache.deleteold=Efface vieilles tuiles
+dialog.diskcache.deleteall=Efface toute les tuiles
+dialog.diskcache.deleted1=Effac\u00e9
+dialog.diskcache.deleted2=tuiles du cache
 dialog.deletefieldvalues.intro=Choisir le champ \u00e0 effacer pour l'\u00e9tendue actuelle
 dialog.setlinewidth.text=Entrer l'\u00e9paisseur des lignes des traces (1-4)
 dialog.downloadosm.desc=Confirmer le t\u00e9l\u00e9chargement des donn\u00e9es OSM brutes pour la zone indiqu\u00e9e :
 dialog.deletefieldvalues.intro=Choisir le champ \u00e0 effacer pour l'\u00e9tendue actuelle
 dialog.setlinewidth.text=Entrer l'\u00e9paisseur des lignes des traces (1-4)
 dialog.downloadosm.desc=Confirmer le t\u00e9l\u00e9chargement des donn\u00e9es OSM brutes pour la zone indiqu\u00e9e :
@@ -524,6 +535,7 @@ button.resettodefaults=Revenir aux valeurs par d\u00e9faut
 button.browse=Naviguer...
 button.addnew=Ajouter nouveau...
 button.delete=Supprimer
 button.browse=Naviguer...
 button.addnew=Ajouter nouveau...
 button.delete=Supprimer
+button.manage=G\u00e9rer
 
 # File types
 filetype.txt=Fichiers TXT
 
 # File types
 filetype.txt=Fichiers TXT
@@ -564,7 +576,6 @@ display.range.time.mins=m
 display.range.time.hours=h
 display.range.time.days=j
 details.range.avespeed=Vitesse moyenne
 display.range.time.hours=h
 display.range.time.days=j
 details.range.avespeed=Vitesse moyenne
-details.range.avemovingspeed=Moyenne continue
 details.range.maxspeed=Vitesse maximum
 details.range.numsegments=Nombre de segments
 details.range.pace=Allure
 details.range.maxspeed=Vitesse maximum
 details.range.numsegments=Nombre de segments
 details.range.pace=Allure
@@ -575,6 +586,7 @@ details.lists.audio=Audio
 details.photodetails=D\u00e9tails de la photo
 details.nophoto=Pas de photo
 details.photo.loading=Chargement
 details.photodetails=D\u00e9tails de la photo
 details.nophoto=Pas de photo
 details.photo.loading=Chargement
+details.photo.bearing=Direction
 details.media.connected=Reli\u00e9e
 details.audiodetails=D\u00e9tails de l'audio
 details.noaudio=Pas de fichier audio s\u00e9lectionner
 details.media.connected=Reli\u00e9e
 details.audiodetails=D\u00e9tails de l'audio
 details.noaudio=Pas de fichier audio s\u00e9lectionner
@@ -609,12 +621,12 @@ units.feet=pieds
 units.feet.short=p
 units.kilometres=Kilom\u00e8tres
 units.kilometres.short=km
 units.feet.short=p
 units.kilometres=Kilom\u00e8tres
 units.kilometres.short=km
-units.kmh=km/h
+units.kilometresperhour.short=km/h
 units.miles=Miles
 units.miles.short=mi
 units.miles=Miles
 units.miles.short=mi
-units.mph=mi/h
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.milesperhour.short=mi/h
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=heures
 units.degminsec=Deg-min-sec
 units.degmin=Deg-min
 units.hours=heures
 units.degminsec=Deg-min-sec
 units.degmin=Deg-min
@@ -640,7 +652,7 @@ undo.deletepoint=effacer le point
 undo.removephoto=retirer la photo
 undo.removeaudio=retirer le fichier audio
 undo.deleterange=effacer l'\u00e9tendue
 undo.removephoto=retirer la photo
 undo.removeaudio=retirer le fichier audio
 undo.deleterange=effacer l'\u00e9tendue
-undo.compress=compresser la trace
+undo.deletemarked=effacer les points
 undo.insert=ins\u00e9rer les points
 undo.reverse=inverser l'\u00e9tendue
 undo.mergetracksegments=fusionner les segments de trace
 undo.insert=ins\u00e9rer les points
 undo.reverse=inverser l'\u00e9tendue
 undo.mergetracksegments=fusionner les segments de trace
@@ -700,3 +712,6 @@ error.lookupsrtm.nonerequired=Tous les points ont d\u00e9j\u00e0 une altitude, i
 error.gpsies.uploadnotok=Le serveur de Gpsies \u00e0 renvoy\u00e9 le message
 error.gpsies.uploadfailed=L'envoi a \u00e9chou\u00e9 avec l'erreur
 error.playaudiofailed=\u00c9chec de la lecture du fichier audio
 error.gpsies.uploadnotok=Le serveur de Gpsies \u00e0 renvoy\u00e9 le message
 error.gpsies.uploadfailed=L'envoi a \u00e9chou\u00e9 avec l'erreur
 error.playaudiofailed=\u00c9chec de la lecture du fichier audio
+error.cache.notthere=Le dossier du cache n'a pas \u00e9t\u00e9 trouv\u00e9
+error.cache.empty=Le dossier du cache est vide
+error.cache.cannotdelete=Ne peux pas effac\u00e9 les tuiles
index da5b1b6e5a554af35f1fba17e6911ea691f862cd..837f9d9decf02318d9d028089261b6e4612f684b 100644 (file)
@@ -20,8 +20,8 @@ menu.range.all=Mindet kijel\u00f6l
 menu.range.none=Kijel\u00f6l\u00e9s megsz\u00fcntet\u00e9se
 menu.range.start=Tartom\u00e1ny kezdet\u00e9nek be\u00e1ll\u00edt\u00e1sa
 menu.range.end=Tartom\u00e1ny v\u00e9g\u00e9nek be\u00e1ll\u00edt\u00e1sa
 menu.range.none=Kijel\u00f6l\u00e9s megsz\u00fcntet\u00e9se
 menu.range.start=Tartom\u00e1ny kezdet\u00e9nek be\u00e1ll\u00edt\u00e1sa
 menu.range.end=Tartom\u00e1ny v\u00e9g\u00e9nek be\u00e1ll\u00edt\u00e1sa
-menu.range.deleterange=Tartom\u00e1ny t\u00f6rl\u00e9se
-menu.range.interpolate=Interpol\u00e1ci\u00f3
+function.deleterange=Tartom\u00e1ny t\u00f6rl\u00e9se
+function.interpolate=Pontok interpol\u00e1l\u00e1sa
 menu.range.average=Kijel\u00f6l\u00e9s \u00e1tlaga
 menu.range.reverse=Tartom\u00e1ny megford\u00edt\u00e1sa
 menu.range.mergetracksegments=Nyomvonalszakaszok egyes\u00edt\u00e9se
 menu.range.average=Kijel\u00f6l\u00e9s \u00e1tlaga
 menu.range.reverse=Tartom\u00e1ny megford\u00edt\u00e1sa
 menu.range.mergetracksegments=Nyomvonalszakaszok egyes\u00edt\u00e9se
@@ -219,7 +219,6 @@ dialog.confirmreversetrack.title=Megford\u00edt\u00e1s meger\u0151s\u00edt\u00e9
 dialog.confirmreversetrack.text=Ez a nyomvonal id\u0151b\u00e9lyeg-inform\u00e1ci\u00f3t tartalmaz, amely sorrendje megford\u00edt\u00e1s ut\u00e1n megv\u00e1ltozik.\n Biztos benne, hogy megford\u00edtja a kijel\u00f6l\u00e9st?
 dialog.confirmcutandmove.title=Kiv\u00e1g\u00e1s \u00e9s mozgat\u00e1s meger\u0151s\u00edt\u00e9se
 dialog.confirmcutandmove.text=Ez a nyomvonal id\u0151b\u00e9lyeg-inform\u00e1ci\u00f3t tartalmaz, amely sorrendje mozgat\u00e1s ut\u00e1n megv\u00e1ltozik.\n Biztos benne, hogy mozgatja a kijel\u00f6l\u00e9st?
 dialog.confirmreversetrack.text=Ez a nyomvonal id\u0151b\u00e9lyeg-inform\u00e1ci\u00f3t tartalmaz, amely sorrendje megford\u00edt\u00e1s ut\u00e1n megv\u00e1ltozik.\n Biztos benne, hogy megford\u00edtja a kijel\u00f6l\u00e9st?
 dialog.confirmcutandmove.title=Kiv\u00e1g\u00e1s \u00e9s mozgat\u00e1s meger\u0151s\u00edt\u00e9se
 dialog.confirmcutandmove.text=Ez a nyomvonal id\u0151b\u00e9lyeg-inform\u00e1ci\u00f3t tartalmaz, amely sorrendje mozgat\u00e1s ut\u00e1n megv\u00e1ltozik.\n Biztos benne, hogy mozgatja a kijel\u00f6l\u00e9st?
-dialog.interpolate.title=Pontok interpol\u00e1l\u00e1sa
 dialog.interpolate.parameter.text=Pontok sz\u00e1ma, amely a k\u00e9t kiv\u00e1lasztott pont k\u00f6z\u00e9 besz\u00farand\u00f3
 dialog.undo.title=M\u0171velet(ek) visszavon\u00e1sa
 dialog.undo.pretext=V\u00e1lassza ki a visszavonand\u00f3 m\u0171velet(ek)et
 dialog.interpolate.parameter.text=Pontok sz\u00e1ma, amely a k\u00e9t kiv\u00e1lasztott pont k\u00f6z\u00e9 besz\u00farand\u00f3
 dialog.undo.title=M\u0171velet(ek) visszavon\u00e1sa
 dialog.undo.pretext=V\u00e1lassza ki a visszavonand\u00f3 m\u0171velet(ek)et
@@ -237,7 +236,7 @@ dialog.pointedit.changevalue.title=Mez\u0151 szerkeszt\u00e9se
 dialog.pointnameedit.name=\u00datpont neve
 dialog.pointnameedit.uppercase=NAGYBET\u0170S
 dialog.pointnameedit.lowercase=kisbet\u0171s
 dialog.pointnameedit.name=\u00datpont neve
 dialog.pointnameedit.uppercase=NAGYBET\u0170S
 dialog.pointnameedit.lowercase=kisbet\u0171s
-dialog.pointnameedit.sentencecase=Nagy Kezd\u0151bet\u0171s
+dialog.pointnameedit.titlecase=Nagy Kezd\u0151bet\u0171s
 dialog.addtimeoffset.add=Id\u0151 hozz\u00e1ad\u00e1sa
 dialog.addtimeoffset.subtract=Id\u0151 kivon\u00e1sa
 dialog.addtimeoffset.days=Nap
 dialog.addtimeoffset.add=Id\u0151 hozz\u00e1ad\u00e1sa
 dialog.addtimeoffset.subtract=Id\u0151 kivon\u00e1sa
 dialog.addtimeoffset.days=Nap
@@ -340,7 +339,7 @@ dialog.rearrangephotos.toend=Mozgat\u00e1s a v\u00e9g\u00e9hez
 dialog.rearrangephotos.nosort=Ne rendezze
 dialog.rearrangephotos.sortbyfilename=Rendez\u00e9s f\u00e1jln\u00e9v szerint
 dialog.rearrangephotos.sortbytime=Rendez\u00e9s id\u0151 szerint
 dialog.rearrangephotos.nosort=Ne rendezze
 dialog.rearrangephotos.sortbyfilename=Rendez\u00e9s f\u00e1jln\u00e9v szerint
 dialog.rearrangephotos.sortbytime=Rendez\u00e9s id\u0151 szerint
-dialog.compress.nonefound=Nem t\u00e1vol\u00edthat\u00f3 el adatpont
+dialog.deletemarked.nonefound=Nem t\u00e1vol\u00edthat\u00f3 el adatpont
 dialog.compress.closepoints.title=K\u00f6zeli pontok elt\u00e1vol\u00edt\u00e1sa
 dialog.compress.closepoints.paramdesc=Hat\u00f3t\u00e1vols\u00e1g
 dialog.compress.wackypoints.title=Kisz\u00e1m\u00edthatatlan pontok elt\u00e1vol\u00edt\u00e1sa
 dialog.compress.closepoints.title=K\u00f6zeli pontok elt\u00e1vol\u00edt\u00e1sa
 dialog.compress.closepoints.paramdesc=Hat\u00f3t\u00e1vols\u00e1g
 dialog.compress.wackypoints.title=Kisz\u00e1m\u00edthatatlan pontok elt\u00e1vol\u00edt\u00e1sa
@@ -406,7 +405,6 @@ dialog.saveconfig.prune.languagefile=Nyelvi f\u00e1jl
 dialog.saveconfig.prune.gpsdevice=GPS eszk\u00f6z
 dialog.saveconfig.prune.gpsformat=GPS form\u00e1tum
 dialog.saveconfig.prune.povrayfont=Povray bet\u0171t\u00edpus
 dialog.saveconfig.prune.gpsdevice=GPS eszk\u00f6z
 dialog.saveconfig.prune.gpsformat=GPS form\u00e1tum
 dialog.saveconfig.prune.povrayfont=Povray bet\u0171t\u00edpus
-dialog.saveconfig.prune.metricunits=Metrikus m\u00e9rt\u00e9krendszer haszn\u00e1lata?
 dialog.saveconfig.prune.gnuplotpath=\u00datvonal a gnuplothoz
 dialog.saveconfig.prune.gpsbabelpath=\u00datvonal a gpsbabelhez
 dialog.saveconfig.prune.exiftoolpath=\u00datvonal az exiftoolhoz
 dialog.saveconfig.prune.gnuplotpath=\u00datvonal a gnuplothoz
 dialog.saveconfig.prune.gpsbabelpath=\u00datvonal a gpsbabelhez
 dialog.saveconfig.prune.exiftoolpath=\u00datvonal az exiftoolhoz
@@ -580,7 +578,6 @@ display.range.time.mins=p
 display.range.time.hours=\u00f3
 display.range.time.days=n
 details.range.avespeed=\u00c1tlagsebess\u00e9g
 display.range.time.hours=\u00f3
 display.range.time.days=n
 details.range.avespeed=\u00c1tlagsebess\u00e9g
-details.range.avemovingspeed=Mozg\u00e1si \u00e1tlag
 details.range.maxspeed=Maxim\u00e1lis sebess\u00e9g
 details.range.numsegments=Szakaszok sz\u00e1ma
 details.range.pace=Iram
 details.range.maxspeed=Maxim\u00e1lis sebess\u00e9g
 details.range.numsegments=Szakaszok sz\u00e1ma
 details.range.pace=Iram
@@ -626,12 +623,11 @@ units.feet=l\u00e1b
 units.feet.short=ft
 units.kilometres=kilom\u00e9ter
 units.kilometres.short=km
 units.feet.short=ft
 units.kilometres=kilom\u00e9ter
 units.kilometres.short=km
-units.kmh=km/h
 units.miles=m\u00e9rf\u00f6ld
 units.miles.short=mi
 units.miles=m\u00e9rf\u00f6ld
 units.miles.short=mi
-units.mph=mph
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.milesperhour.short=mph
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=\u00f3ra
 units.degminsec=Sz\u00f6g-sz\u00f6gperc-sz\u00f6gm\u00e1sodperc
 units.degmin=Sz\u00f6g-sz\u00f6gperc
 units.hours=\u00f3ra
 units.degminsec=Sz\u00f6g-sz\u00f6gperc-sz\u00f6gm\u00e1sodperc
 units.degmin=Sz\u00f6g-sz\u00f6gperc
@@ -657,7 +653,7 @@ undo.deletepoint=pont t\u00f6rl\u00e9se
 undo.removephoto=f\u00e9nyk\u00e9p elt\u00e1vol\u00edt\u00e1sa
 undo.removeaudio=hangf\u00e1jl elt\u00e1vol\u00edt\u00e1sa
 undo.deleterange=tartom\u00e1ny t\u00f6rl\u00e9se
 undo.removephoto=f\u00e9nyk\u00e9p elt\u00e1vol\u00edt\u00e1sa
 undo.removeaudio=hangf\u00e1jl elt\u00e1vol\u00edt\u00e1sa
 undo.deleterange=tartom\u00e1ny t\u00f6rl\u00e9se
-undo.compress=nyomvonal t\u00f6m\u00f6r\u00edt\u00e9se
+undo.deletemarked=nyomvonal t\u00f6m\u00f6r\u00edt\u00e9se
 undo.insert=pontok besz\u00far\u00e1sa
 undo.reverse=tartom\u00e1ny megford\u00edt\u00e1sa
 undo.mergetracksegments=nyomvonalszakaszok egyes\u00edt\u00e9se
 undo.insert=pontok besz\u00far\u00e1sa
 undo.reverse=tartom\u00e1ny megford\u00edt\u00e1sa
 undo.mergetracksegments=nyomvonalszakaszok egyes\u00edt\u00e9se
index ec4bc255e678a54492e37ce5fb00999801161e98..c0b42460bfa8c0918b824be473990e4c53807c22 100644 (file)
@@ -10,7 +10,7 @@ menu.track=Track
 menu.track.undo=Batal
 menu.point.editpoint=Perbaiki titik
 menu.point.deletepoint=Hapus titik
 menu.track.undo=Batal
 menu.point.editpoint=Perbaiki titik
 menu.point.deletepoint=Hapus titik
-menu.range.deleterange=Hapus jarak
+function.deleterange=Hapus jarak
 menu.range=Jangkauan
 menu.point=Titik
 menu.range.all=Pilih semua
 menu.range=Jangkauan
 menu.point=Titik
 menu.range.all=Pilih semua
index a15ceb19fb7289cb5390fa8eb13c94a4d39d4497..989110a6b4820a0fce93565e81bb02004b86aa96 100644 (file)
@@ -1,5 +1,5 @@
 # Text entries for the GpsPrune application
 # Text entries for the GpsPrune application
-# Italian entries thanks to josatoc and others
+# Italian entries thanks to josatoc, denisov
 
 # Menu entries
 menu.file=File
 
 # Menu entries
 menu.file=File
@@ -10,6 +10,7 @@ menu.file.exit=Esci
 menu.track=Traccia
 menu.track.undo=Annulla
 menu.track.clearundo=Cancella lista annulla
 menu.track=Traccia
 menu.track.undo=Annulla
 menu.track.clearundo=Cancella lista annulla
+menu.track.markrectangle=Segnare i punti nel rettangolo
 menu.track.deletemarked=Cancella punti marcati
 menu.track.rearrange=Riorganizza waypoint
 menu.track.rearrange.start=Tutti all'inizio del file
 menu.track.deletemarked=Cancella punti marcati
 menu.track.rearrange=Riorganizza waypoint
 menu.track.rearrange.start=Tutti all'inizio del file
@@ -20,8 +21,6 @@ menu.range.all=Seleziona tutto
 menu.range.none=Deseleziona tutto
 menu.range.start=Imposta inizio serie
 menu.range.end=Imposta fine serie
 menu.range.none=Deseleziona tutto
 menu.range.start=Imposta inizio serie
 menu.range.end=Imposta fine serie
-menu.range.deleterange=Cancella la serie
-menu.range.interpolate=Interpola
 menu.range.average=Crea punto medio della selezione
 menu.range.reverse=Inverti la serie
 menu.range.mergetracksegments=Unisci segmenti traccia
 menu.range.average=Crea punto medio della selezione
 menu.range.reverse=Inverti la serie
 menu.range.mergetracksegments=Unisci segmenti traccia
@@ -54,6 +53,7 @@ menu.map.connect=Aggancia ai punti
 menu.map.autopan=Autopan
 menu.map.showmap=Mostra sulla mappa
 menu.map.showscalebar=Mostra scala
 menu.map.autopan=Autopan
 menu.map.showmap=Mostra sulla mappa
 menu.map.showscalebar=Mostra scala
+menu.map.editmode=Modifica
 
 # Alt keys for menus
 altkey.menu.file=F
 
 # Alt keys for menus
 altkey.menu.file=F
@@ -86,6 +86,9 @@ function.exportpov=Esporta in POV
 function.exportsvg=Esporta in SVG
 function.editwaypointname=Modifica nome waypoint
 function.compress=Comprimi la traccia
 function.exportsvg=Esporta in SVG
 function.editwaypointname=Modifica nome waypoint
 function.compress=Comprimi la traccia
+function.deleterange=Cancella la serie
+function.croptrack=Cima la traccia
+function.interpolate=Interpola i punti
 function.addtimeoffset=Aggiungi uno scarto temporale
 function.addaltitudeoffset=Aggiungi uno scarto di altitudine
 function.convertnamestotimes=Converti nomi dei waypoint in orari
 function.addtimeoffset=Aggiungi uno scarto temporale
 function.addaltitudeoffset=Aggiungi uno scarto di altitudine
 function.convertnamestotimes=Converti nomi dei waypoint in orari
@@ -140,6 +143,7 @@ dialog.deletepoint.title=Cancella Punto
 dialog.deletepoint.deletephoto=Cancella la foto collegata a questo punto?
 dialog.deletephoto.title=Cancella Foto
 dialog.deletephoto.deletepoint=Cancella il punto collegato a questa foto?
 dialog.deletepoint.deletephoto=Cancella la foto collegata a questo punto?
 dialog.deletephoto.title=Cancella Foto
 dialog.deletephoto.deletepoint=Cancella il punto collegato a questa foto?
+dialog.deleteaudio.deletepoint=Elimina il punto collegato a questo file audio?
 dialog.openoptions.title=Apri opzioni
 dialog.openoptions.filesnippet=Estrai dal file
 dialog.load.table.field=Campo
 dialog.openoptions.title=Apri opzioni
 dialog.openoptions.filesnippet=Estrai dal file
 dialog.load.table.field=Campo
@@ -219,8 +223,8 @@ dialog.confirmreversetrack.title=Conferma l'inversione
 dialog.confirmreversetrack.text=Questa traccia contiene informazioni sull'orario di scatto che possono essere messe fuori sequenza dopo l'inversione.\nSei sicuro di voler invertire questa sezione?
 dialog.confirmcutandmove.title=Conferma il taglio e lo spostamento
 dialog.confirmcutandmove.text=Questa traccia contiene informazioni sull'orario di scatto che possono essere messe fuori sequenza dopo lo spostamento\nSei sicuro di voler spostare questa sezione?
 dialog.confirmreversetrack.text=Questa traccia contiene informazioni sull'orario di scatto che possono essere messe fuori sequenza dopo l'inversione.\nSei sicuro di voler invertire questa sezione?
 dialog.confirmcutandmove.title=Conferma il taglio e lo spostamento
 dialog.confirmcutandmove.text=Questa traccia contiene informazioni sull'orario di scatto che possono essere messe fuori sequenza dopo lo spostamento\nSei sicuro di voler spostare questa sezione?
-dialog.interpolate.title=Interpola i punti
 dialog.interpolate.parameter.text=Numero di punti da inserire tra i punti selezionati
 dialog.interpolate.parameter.text=Numero di punti da inserire tra i punti selezionati
+dialog.interpolate.betweenwaypoints=Interpolazione tra waypoint?
 dialog.undo.title=Annulla l'azione(i)
 dialog.undo.pretext=Per favore seleziona l'azione(i) da annullare
 dialog.undo.none.title=Non \u00e8 possibile annullare
 dialog.undo.title=Annulla l'azione(i)
 dialog.undo.pretext=Per favore seleziona l'azione(i) da annullare
 dialog.undo.none.title=Non \u00e8 possibile annullare
@@ -237,7 +241,7 @@ dialog.pointedit.changevalue.title=Modifica il campo
 dialog.pointnameedit.name=Nome del waypoint
 dialog.pointnameedit.uppercase=MAIUSCOLE
 dialog.pointnameedit.lowercase=minuscole
 dialog.pointnameedit.name=Nome del waypoint
 dialog.pointnameedit.uppercase=MAIUSCOLE
 dialog.pointnameedit.lowercase=minuscole
-dialog.pointnameedit.sentencecase=Iniziali Maiuscole
+dialog.pointnameedit.titlecase=Iniziali Maiuscole
 dialog.addtimeoffset.add=Scarto in aggiunta
 dialog.addtimeoffset.subtract=Scarto in sottrazione
 dialog.addtimeoffset.days=Giorni
 dialog.addtimeoffset.add=Scarto in aggiunta
 dialog.addtimeoffset.subtract=Scarto in sottrazione
 dialog.addtimeoffset.days=Giorni
@@ -273,6 +277,8 @@ dialog.distances.column.to=Al punto
 dialog.distances.currentpoint=Punto attuale
 dialog.distances.toofewpoints=Questa funzione necessita di waypoints per calcolare le distanze tra loro
 dialog.fullrangedetails.intro=Qui i dettagli della selezione
 dialog.distances.currentpoint=Punto attuale
 dialog.distances.toofewpoints=Questa funzione necessita di waypoints per calcolare le distanze tra loro
 dialog.fullrangedetails.intro=Qui i dettagli della selezione
+dialog.fullrangedetails.coltotal=Includere le lacune
+dialog.fullrangedetails.colsegments=Senza lacune
 dialog.setmapbg.intro=Selezione una fonte delle mappe o aggiungine una nuova
 dialog.addmapsource.title=Aggiungi nuova fonte delle mappa
 dialog.addmapsource.sourcename=Nome della fonte
 dialog.setmapbg.intro=Selezione una fonte delle mappe o aggiungine una nuova
 dialog.addmapsource.title=Aggiungi nuova fonte delle mappa
 dialog.addmapsource.sourcename=Nome della fonte
@@ -303,6 +309,7 @@ dialog.wikipedia.column.name=Titolo articolo
 dialog.wikipedia.column.distance=Distanza
 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.wikipedia.column.distance=Distanza
 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.nouncorrelatedaudios=Non ci sono audio non correlati. \nSei sicuro di voler continuare?
 dialog.correlate.photoselect.intro=Selezione una delle foto correlate da usare come scarto dell'orario
 dialog.correlate.select.photoname=Nome della foto
 dialog.correlate.select.timediff=Differenza di orario
 dialog.correlate.photoselect.intro=Selezione una delle foto correlate da usare come scarto dell'orario
 dialog.correlate.select.photoname=Nome della foto
 dialog.correlate.select.timediff=Differenza di orario
@@ -340,7 +347,6 @@ dialog.rearrangephotos.toend=Sposta alla fine
 dialog.rearrangephotos.nosort=Non mettere in ordine
 dialog.rearrangephotos.sortbyfilename=Metti in ordine di nome del file
 dialog.rearrangephotos.sortbytime=Metti in ordine di tempo
 dialog.rearrangephotos.nosort=Non mettere in ordine
 dialog.rearrangephotos.sortbyfilename=Metti in ordine di nome del file
 dialog.rearrangephotos.sortbytime=Metti in ordine di tempo
-dialog.compress.nonefound=Nessun punto rimosso
 dialog.compress.closepoints.title=Cancella punti vicini
 dialog.compress.closepoints.paramdesc=Fattore vicinanza
 dialog.compress.wackypoints.title=Cancella punti strani
 dialog.compress.closepoints.title=Cancella punti vicini
 dialog.compress.closepoints.paramdesc=Fattore vicinanza
 dialog.compress.wackypoints.title=Cancella punti strani
@@ -349,7 +355,12 @@ dialog.compress.singletons.title=Cancella solitari
 dialog.compress.singletons.paramdesc=Fattore distanza
 dialog.compress.duplicates.title=Cancella duplicati
 dialog.compress.douglaspeucker.title=Compressione con algoritmo Douglas-Peucker
 dialog.compress.singletons.paramdesc=Fattore distanza
 dialog.compress.duplicates.title=Cancella duplicati
 dialog.compress.douglaspeucker.title=Compressione con algoritmo Douglas-Peucker
+dialog.compress.douglaspeucker.paramdesc=Fattore di apertura
 dialog.compress.summarylabel=Punti da cancellare
 dialog.compress.summarylabel=Punti da cancellare
+dialog.compress.confirm1=
+dialog.compress.confirm2=punti sono stati contrassegnati.\nUsa traccia-> Elimina i punti segnati per eliminarle
+dialog.compress.confirmnone=I punti non sono stati marcati
+dialog.deletemarked.nonefound=Nessun punto rimosso
 dialog.pastecoordinates.desc=Inserisci o incolla qui le coordinate
 dialog.pastecoordinates.coords=Coordinate
 dialog.pastecoordinates.nothingfound=Per favore, controlla le coordinate e riprova
 dialog.pastecoordinates.desc=Inserisci o incolla qui le coordinate
 dialog.pastecoordinates.coords=Coordinate
 dialog.pastecoordinates.nothingfound=Per favore, controlla le coordinate e riprova
@@ -405,7 +416,6 @@ dialog.saveconfig.prune.languagefile=File lingua
 dialog.saveconfig.prune.gpsdevice=Nome del Dispositivo GPS
 dialog.saveconfig.prune.gpsformat=Formato GPS
 dialog.saveconfig.prune.povrayfont=Font povray
 dialog.saveconfig.prune.gpsdevice=Nome del Dispositivo GPS
 dialog.saveconfig.prune.gpsformat=Formato GPS
 dialog.saveconfig.prune.povrayfont=Font povray
-dialog.saveconfig.prune.metricunits=Utilizza unita' metrica?
 dialog.saveconfig.prune.gnuplotpath=Path gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Path gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Path exiftool
 dialog.saveconfig.prune.gnuplotpath=Path gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Path gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Path exiftool
@@ -446,6 +456,7 @@ dialog.diskcache.save=Salva la mappa sul disco
 dialog.diskcache.dir=Cartella della cache
 dialog.diskcache.createdir=Crea cartella
 dialog.diskcache.nocreate=Cartella della cache non creata
 dialog.diskcache.dir=Cartella della cache
 dialog.diskcache.createdir=Crea cartella
 dialog.diskcache.nocreate=Cartella della cache non creata
+dialog.diskcache.cannotwrite=Il titolo della mappa non pu\u00f2 essere salvato nella cartella selezionata
 dialog.diskcache.table.path=Percorso (Path)
 dialog.diskcache.table.usedby=Utilizzato da
 dialog.diskcache.table.zoom=Zoom
 dialog.diskcache.table.path=Percorso (Path)
 dialog.diskcache.table.usedby=Utilizzato da
 dialog.diskcache.table.zoom=Zoom
@@ -484,6 +495,7 @@ confirm.addaltitudeoffset=Scarto altitudine aggiunto
 confirm.rearrangewaypoints=Waypoint riorganizzati
 confirm.rearrangephotos=Foto riorganizzate
 confirm.cutandmove=Selezione spostata
 confirm.rearrangewaypoints=Waypoint riorganizzati
 confirm.rearrangephotos=Foto riorganizzate
 confirm.cutandmove=Selezione spostata
+confirm.interpolate=Aggiungi punto
 confirm.convertnamestotimes=Nome del waypoint convertito
 confirm.saveexif.ok1=Salvato
 confirm.saveexif.ok2=foto
 confirm.convertnamestotimes=Nome del waypoint convertito
 confirm.saveexif.ok1=Salvato
 confirm.saveexif.ok2=foto
@@ -579,7 +591,6 @@ display.range.time.mins=m
 display.range.time.hours=h
 display.range.time.days=g
 details.range.avespeed=Velocit\u00e0 media
 display.range.time.hours=h
 display.range.time.days=g
 details.range.avespeed=Velocit\u00e0 media
-details.range.avemovingspeed=Velocit\u00e0 media in movimento
 details.range.maxspeed=Velocit\u00e0 massima
 details.range.numsegments=Numero di segmenti
 details.range.pace=Passo
 details.range.maxspeed=Velocit\u00e0 massima
 details.range.numsegments=Numero di segmenti
 details.range.pace=Passo
@@ -592,6 +603,7 @@ details.nophoto=Nessuna foto selezionata
 details.photo.loading=Caricamento
 details.photo.bearing=Direzione
 details.media.connected=Collegata
 details.photo.loading=Caricamento
 details.photo.bearing=Direzione
 details.media.connected=Collegata
+details.media.fullpath=Percorso completo
 details.audiodetails=Dettagli ripresa audio
 details.noaudio=Nessuna ripresa audio selezionata
 details.audio.file=Ripresa audio
 details.audiodetails=Dettagli ripresa audio
 details.noaudio=Nessuna ripresa audio selezionata
 details.audio.file=Ripresa audio
@@ -625,12 +637,15 @@ units.feet=Feet
 units.feet.short=ft
 units.kilometres=Kilometri
 units.kilometres.short=km
 units.feet.short=ft
 units.kilometres=Kilometri
 units.kilometres.short=km
-units.kmh=km/h
+units.kilometresperhour.short=km/h
 units.miles=Miglia
 units.miles.short=mi
 units.miles=Miglia
 units.miles.short=mi
-units.mph=mph
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.milesperhour.short=mph
+units.nauticalmiles=Miglia nautiche
+units.nauticalmiles.short=N.m
+units.nauticalmilesperhour.short=Miglia nautiche all'ora
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=Ore
 units.degminsec=Deg-min-sec
 units.degmin=Deg-min
 units.hours=Ore
 units.degminsec=Deg-min-sec
 units.degmin=Deg-min
@@ -656,7 +671,8 @@ undo.deletepoint=cancella punto
 undo.removephoto=rimuovi foto
 undo.removeaudio=rimuovi riprese audio
 undo.deleterange=cancella l'intervallo
 undo.removephoto=rimuovi foto
 undo.removeaudio=rimuovi riprese audio
 undo.deleterange=cancella l'intervallo
-undo.compress=comprimi traccia
+undo.croptrack=taglia la traccia
+undo.deletemarked=
 undo.insert=inserisci punti
 undo.reverse=inverti l'intervallo
 undo.mergetracksegments=unisci segmenti traccia
 undo.insert=inserisci punti
 undo.reverse=inverti l'intervallo
 undo.mergetracksegments=unisci segmenti traccia
@@ -715,7 +731,9 @@ error.lookupsrtm.nonefound=Valori di quota non trovati
 error.lookupsrtm.nonerequired=Tutti i punti hanno gi\u00e0 una quota, non c'\u00e8 niente da cercare
 error.gpsies.uploadnotok=Il server Gpsies ha riportato il messaggio
 error.gpsies.uploadfailed=Il caricamento \u00e8 fallito con l'errore
 error.lookupsrtm.nonerequired=Tutti i punti hanno gi\u00e0 una quota, non c'\u00e8 niente da cercare
 error.gpsies.uploadnotok=Il server Gpsies ha riportato il messaggio
 error.gpsies.uploadfailed=Il caricamento \u00e8 fallito con l'errore
+error.showphoto.failed=Caricamento foto fallito
 error.playaudiofailed=Ripresa audio non riprodotta
 error.cache.notthere=Directory del cache di tasselli non trovato
 error.cache.empty=Directory del cache di tasselli \u00e8 vuoto
 error.cache.cannotdelete=Impossibile cancellare tasselli
 error.playaudiofailed=Ripresa audio non riprodotta
 error.cache.notthere=Directory del cache di tasselli non trovato
 error.cache.empty=Directory del cache di tasselli \u00e8 vuoto
 error.cache.cannotdelete=Impossibile cancellare tasselli
+error.interpolate.invalidparameter=Il numero di punti deve essere tra 1 e 1000
index 30c3556bcb3a9be9f014e4605807b080a81dcfc9..ada2387cb5afb88bc81b4dee346ca4213d104720 100644 (file)
@@ -1,52 +1,51 @@
 # Text entries for the GpsPrune application
 # Text entries for the GpsPrune application
-# Japanese entries as extra
+# Japanese entries
 
 # Menu entries
 
 # Menu entries
-menu.file=\u30d5\u30a1\u30a4\u30eb
+menu.file=\u30d5\u30a1\u30a4\u30eb(F)
 menu.file.addphotos=\u5199\u771f\u3092\u8ffd\u52a0
 menu.file.save=\u4fdd\u5b58
 menu.file.exit=\u7d42\u4e86
 menu.file.addphotos=\u5199\u771f\u3092\u8ffd\u52a0
 menu.file.save=\u4fdd\u5b58
 menu.file.exit=\u7d42\u4e86
-menu.track=\u30c8\u30e9\u30c3\u30af
+menu.track=\u30c8\u30e9\u30c3\u30af(T)
 menu.track.undo=\u30a2\u30f3\u30c9\u30a5
 menu.track.clearundo=\u30a2\u30f3\u30c9\u30a5\u30ea\u30b9\u30c8\u3092\u7a7a\u306b\u3059\u308b
 menu.track.undo=\u30a2\u30f3\u30c9\u30a5
 menu.track.clearundo=\u30a2\u30f3\u30c9\u30a5\u30ea\u30b9\u30c8\u3092\u7a7a\u306b\u3059\u308b
-menu.point.editpoint=\u70b9\u3092\u7de8\u96c6
-menu.point.deletepoint=\u70b9\u3092\u524a\u9664
-menu.range.deleterange=\u7bc4\u56f2\u3092\u524a\u9664
 menu.track.deletemarked=\u5370\u306e\u4ed8\u3044\u305f\u70b9\u3092\u524a\u9664
 menu.track.deletemarked=\u5370\u306e\u4ed8\u3044\u305f\u70b9\u3092\u524a\u9664
-menu.range.interpolate=\u88dc\u5b8c
-menu.range.average=\u9078\u629e\u7bc4\u56f2\u3092\u5e73\u5747\u5316
-menu.range.reverse=\u7bc4\u56f2\u3092\u53cd\u8ee2
-menu.range.mergetracksegments=\u30c8\u30e9\u30c3\u30af\u30bb\u30b0\u30e1\u30f3\u30c8\u3092\u7d71\u5408
 menu.track.rearrange=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u4e26\u3079\u66ff\u3048
 menu.track.rearrange.start=\u5168\u3066\u3092\u30d5\u30a1\u30a4\u30eb\u306e\u59cb\u70b9\u306b
 menu.track.rearrange.end=\u5168\u3066\u3092\u30d5\u30a1\u30a4\u30eb\u306e\u7d42\u70b9\u306b
 menu.track.rearrange.nearest=\u305d\u308c\u305e\u308c\u3092\u6700\u8fd1\u306e\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8\u306b
 menu.track.rearrange=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u4e26\u3079\u66ff\u3048
 menu.track.rearrange.start=\u5168\u3066\u3092\u30d5\u30a1\u30a4\u30eb\u306e\u59cb\u70b9\u306b
 menu.track.rearrange.end=\u5168\u3066\u3092\u30d5\u30a1\u30a4\u30eb\u306e\u7d42\u70b9\u306b
 menu.track.rearrange.nearest=\u305d\u308c\u305e\u308c\u3092\u6700\u8fd1\u306e\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8\u306b
-menu.range.cutandmove=\u9078\u629e\u7bc4\u56f2\u3092\u79fb\u52d5
-menu.range=\u7bc4\u56f2
-menu.point=\u70b9
+menu.range=\u7bc4\u56f2(R)
 menu.range.all=\u5168\u3066\u9078\u629e
 menu.range.none=\u9078\u629e\u89e3\u9664
 menu.range.all=\u5168\u3066\u9078\u629e
 menu.range.none=\u9078\u629e\u89e3\u9664
-menu.range.start=\u958b\u59cb\u70b9\u3092\u7f6e\u304f
-menu.range.end=\u7d42\u4e86\u70b9\u3092\u7f6e\u304f
+menu.range.start=\u958b\u59cb\u70b9\u3092\u8a2d\u5b9a
+menu.range.end=\u7d42\u4e86\u70b9\u3092\u8a2d\u5b9a
+menu.range.average=\u9078\u629e\u7bc4\u56f2\u3092\u5e73\u5747\u5316
+menu.range.reverse=\u7bc4\u56f2\u3092\u53cd\u8ee2
+menu.range.mergetracksegments=\u30c8\u30e9\u30c3\u30af\u30bb\u30b0\u30e1\u30f3\u30c8\u3092\u7d71\u5408
+menu.range.cutandmove=\u9078\u629e\u7bc4\u56f2\u3092\u79fb\u52d5
+menu.point=\u70b9(P)
+menu.point.editpoint=\u70b9\u3092\u7de8\u96c6
+menu.point.deletepoint=\u70b9\u3092\u524a\u9664
 menu.photo=\u5199\u771f
 menu.photo.saveexif=Exif\u306b\u4fdd\u5b58
 menu.photo=\u5199\u771f
 menu.photo.saveexif=Exif\u306b\u4fdd\u5b58
-function.connecttopoint=\u70b9\u306b\u63a5\u7d9a
-function.disconnectfrompoint=\u70b9\u304b\u3089\u63a5\u7d9a\u89e3\u9664
-function.removephoto=\u5199\u771f\u3092\u53d6\u308a\u9664\u304f
-menu.view=\u30d3\u30e5\u30fc
+menu.audio=\u30aa\u30fc\u30c7\u30a3\u30aa(A)
+menu.view=\u30d3\u30e5\u30fc(V)
+menu.view.showsidebars=\u30b5\u30a4\u30c9\u30d0\u30fc\u3092\u8868\u793a
 menu.view.browser=\u5730\u56f3\u3092\u30d6\u30e9\u30a6\u30b6\u30fc\u3067\u898b\u308b
 menu.view.browser.google=Google \u30de\u30c3\u30d7
 menu.view.browser.openstreetmap=OpenStreetMap
 menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Yahoo \u5730\u56f3
 menu.view.browser.bing=Bing \u5730\u56f3
 menu.view.browser=\u5730\u56f3\u3092\u30d6\u30e9\u30a6\u30b6\u30fc\u3067\u898b\u308b
 menu.view.browser.google=Google \u30de\u30c3\u30d7
 menu.view.browser.openstreetmap=OpenStreetMap
 menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Yahoo \u5730\u56f3
 menu.view.browser.bing=Bing \u5730\u56f3
-menu.settings=\u8a2d\u5b9a
-menu.help=\u30d8\u30eb\u30d7
+menu.settings=\u8a2d\u5b9a(S)
+menu.settings.onlinemode=\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u304b\u3089\u5730\u56f3\u3092\u30ed\u30fc\u30c9
+menu.help=\u30d8\u30eb\u30d7(H)
 # Popup menu for map
 menu.map.zoomin=\u62e1\u5927
 menu.map.zoomout=\u7e2e\u5c0f
 menu.map.zoomfull=\u6700\u5927\u62e1\u5927
 menu.map.newpoint=\u70b9\u3092\u4f5c\u308b
 # Popup menu for map
 menu.map.zoomin=\u62e1\u5927
 menu.map.zoomout=\u7e2e\u5c0f
 menu.map.zoomfull=\u6700\u5927\u62e1\u5927
 menu.map.newpoint=\u70b9\u3092\u4f5c\u308b
+menu.map.drawpoints=\u9023\u7d9a\u3057\u305f\u70b9\u3092\u4f5c\u308b
 menu.map.connect=\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8\u306b\u63a5\u7d9a
 menu.map.autopan=\u81ea\u52d5\u79fb\u52d5
 menu.map.showmap=\u5730\u56f3\u3092\u8868\u793a
 menu.map.connect=\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8\u306b\u63a5\u7d9a
 menu.map.autopan=\u81ea\u52d5\u79fb\u52d5
 menu.map.showmap=\u5730\u56f3\u3092\u8868\u793a
@@ -59,11 +58,15 @@ function.sendtogps=GPS\u3078\u4fdd\u5b58
 function.exportkml=KML\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
 function.exportgpx=GPX\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
 function.exportpov=POV\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
 function.exportkml=KML\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
 function.exportgpx=GPX\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
 function.exportpov=POV\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
+function.exportsvg=SVG\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
 function.editwaypointname=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u306e\u540d\u524d\u3092\u7de8\u96c6
 function.editwaypointname=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u306e\u540d\u524d\u3092\u7de8\u96c6
+function.deleterange=\u7bc4\u56f2\u3092\u524a\u9664
+function.interpolate=\u70b9\u3092\u88dc\u5b8c\u3059\u308b
 function.compress=\u30c8\u30e9\u30c3\u30af\u3092\u5727\u7e2e
 function.addtimeoffset=\u6642\u9593\u306e\u504f\u4f4d\u3092\u52a0\u3048\u308b
 function.addaltitudeoffset=\u9ad8\u5ea6\u306b\u504f\u4f4d\u3092\u52a0\u3048\u308b
 function.convertnamestotimes=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u540d\u3092\u6642\u9593\u306b\u5909\u63db
 function.compress=\u30c8\u30e9\u30c3\u30af\u3092\u5727\u7e2e
 function.addtimeoffset=\u6642\u9593\u306e\u504f\u4f4d\u3092\u52a0\u3048\u308b
 function.addaltitudeoffset=\u9ad8\u5ea6\u306b\u504f\u4f4d\u3092\u52a0\u3048\u308b
 function.convertnamestotimes=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u540d\u3092\u6642\u9593\u306b\u5909\u63db
+function.deletefieldvalues=\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u5024\u3092\u524a\u9664\u3059\u308b
 function.findwaypoint=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u63a2\u3059
 function.pastecoordinates=\u65b0\u3057\u3044\u5ea7\u6a19\u3092\u5165\u529b
 function.charts=\u9ad8\u5ea6\u901f\u5ea6\u30c1\u30e3\u30fc\u30c8
 function.findwaypoint=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u63a2\u3059
 function.pastecoordinates=\u65b0\u3057\u3044\u5ea7\u6a19\u3092\u5165\u529b
 function.charts=\u9ad8\u5ea6\u901f\u5ea6\u30c1\u30e3\u30fc\u30c8
@@ -74,19 +77,35 @@ function.setmapbg=\u80cc\u666f\u5730\u56f3
 function.setkmzimagesize=KML \u30a4\u30e1\u30fc\u30b8\u30b5\u30a4\u30ba
 function.setpaths=\u5916\u90e8\u30d7\u30ed\u30b0\u30e9\u30e0\u30d1\u30b9\u3092\u8a2d\u5b9a
 function.getgpsies=Gpsies\u30c8\u30e9\u30c3\u30af\u3092\u5f97\u308b
 function.setkmzimagesize=KML \u30a4\u30e1\u30fc\u30b8\u30b5\u30a4\u30ba
 function.setpaths=\u5916\u90e8\u30d7\u30ed\u30b0\u30e9\u30e0\u30d1\u30b9\u3092\u8a2d\u5b9a
 function.getgpsies=Gpsies\u30c8\u30e9\u30c3\u30af\u3092\u5f97\u308b
+function.uploadgpsies=Gpsies\u306b\u30c8\u30e9\u30c3\u30af\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9
+function.lookupsrtm=SRTM\u304b\u3089\u6a19\u9ad8\u3092\u53d6\u5f97\u3059\u308b
+function.getwikipedia=Wikipedia\u304b\u3089\u5468\u56f2\u306e\u8a18\u4e8b\u3092\u53d6\u5f97\u3059\u308b
+function.searchwikipedianames=\u540d\u524d\u3067Wikipedia\u3092\u691c\u7d22
+function.downloadosm=\u30a8\u30ea\u30a2\u306eOSM\u30c7\u30fc\u30bf\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9
 function.duplicatepoint=\u91cd\u8907\u70b9
 function.setcolours=\u8272\u3092\u8a2d\u5b9a
 function.duplicatepoint=\u91cd\u8907\u70b9
 function.setcolours=\u8272\u3092\u8a2d\u5b9a
+function.setlinewidth=\u884c\u306e\u5e45\u3092\u8a2d\u5b9a
 function.setlanguage=\u8a00\u8a9e\u8a2d\u5b9a
 function.setlanguage=\u8a00\u8a9e\u8a2d\u5b9a
+function.connecttopoint=\u70b9\u306b\u63a5\u7d9a
+function.disconnectfrompoint=\u70b9\u304b\u3089\u63a5\u7d9a\u89e3\u9664
+function.removephoto=\u5199\u771f\u3092\u53d6\u308a\u9664\u304f
 function.correlatephotos=\u5199\u771f\u3068\u95a2\u9023\u3055\u305b\u308b
 function.rearrangephotos=\u5199\u771f\u306e\u4e26\u3079\u76f4\u3057
 function.rotatephotoleft=\u5199\u771f\u3092\u5de6\u306b\u56de\u3059
 function.rotatephotoright=\u5199\u771f\u3092\u53f3\u306b\u56de\u3059
 function.correlatephotos=\u5199\u771f\u3068\u95a2\u9023\u3055\u305b\u308b
 function.rearrangephotos=\u5199\u771f\u306e\u4e26\u3079\u76f4\u3057
 function.rotatephotoleft=\u5199\u771f\u3092\u5de6\u306b\u56de\u3059
 function.rotatephotoright=\u5199\u771f\u3092\u53f3\u306b\u56de\u3059
+function.photopopup=\u5199\u771f\u306e\u30dd\u30c3\u30d7\u30a2\u30c3\u30d7\u3092\u8868\u793a
 function.ignoreexifthumb=EXIF\u30b5\u30e0\u30cd\u30a4\u30eb\u3092\u7121\u8996
 function.ignoreexifthumb=EXIF\u30b5\u30e0\u30cd\u30a4\u30eb\u3092\u7121\u8996
+function.loadaudio=\u30aa\u30fc\u30c7\u30a3\u30aa\u30d5\u30a1\u30a4\u30eb\u3092\u8ffd\u52a0
+function.removeaudio=\u4e00\u89a7\u304b\u3089\u73fe\u5728\u306e\u30aa\u30fc\u30c7\u30a3\u30aa\u30d5\u30a1\u30a4\u30eb\u3092\u524a\u9664
+function.correlateaudios=\u30aa\u30fc\u30c7\u30a3\u30aa\u3092\u95a2\u9023\u4ed8\u3051\u308b
+function.playaudio=\u518d\u751f
+function.stopaudio=\u505c\u6b62
 function.help=\u30d8\u30eb\u30d7
 function.showkeys=\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8\u30ad\u30fc\u3092\u8868\u793a
 function.about=GpsPrune \u306b\u3064\u3044\u3066
 function.checkversion=\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u8868\u793a
 function.saveconfig=\u8a2d\u5b9a\u3092\u4fdd\u5b58
 function.help=\u30d8\u30eb\u30d7
 function.showkeys=\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8\u30ad\u30fc\u3092\u8868\u793a
 function.about=GpsPrune \u306b\u3064\u3044\u3066
 function.checkversion=\u65b0\u3057\u3044\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u8868\u793a
 function.saveconfig=\u8a2d\u5b9a\u3092\u4fdd\u5b58
+function.diskcache=\u30c7\u30a3\u30b9\u30af\u306b\u30de\u30c3\u30d7\u3092\u4fdd\u5b58
 
 # Dialogs
 dialog.exit.confirm.title=GpsPrune \u3092\u7d42\u4e86
 
 # Dialogs
 dialog.exit.confirm.title=GpsPrune \u3092\u7d42\u4e86
@@ -112,6 +131,7 @@ dialog.openoptions.deliminfo.records=\u8a18\u9332\uff0c
 dialog.openoptions.deliminfo.fields=\u30d5\u30a3\u30fc\u30eb\u30c9
 dialog.openoptions.deliminfo.norecords=\u8a18\u9332\u306a\u3057
 dialog.openoptions.altitudeunits=\u9ad8\u5ea6\u5358\u4f4d
 dialog.openoptions.deliminfo.fields=\u30d5\u30a3\u30fc\u30eb\u30c9
 dialog.openoptions.deliminfo.norecords=\u8a18\u9332\u306a\u3057
 dialog.openoptions.altitudeunits=\u9ad8\u5ea6\u5358\u4f4d
+dialog.selecttracks.noname=\u540d\u524d\u306a\u3057
 dialog.jpegload.subdirectories=\u30b5\u30d6\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u542b\u3081\u308b
 dialog.jpegload.loadjpegswithoutcoords=\u5ea7\u6a19\u3092\u542b\u307e\u306a\u3044\u5199\u771f\u3092\u542b\u3081\u308b
 dialog.jpegload.loadjpegsoutsidearea=\u73fe\u5728\u898b\u3066\u3044\u308b\u5730\u57df\u5916\u306e\u5199\u771f\u3092\u542b\u3081\u308b
 dialog.jpegload.subdirectories=\u30b5\u30d6\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u30fc\u3092\u542b\u3081\u308b
 dialog.jpegload.loadjpegswithoutcoords=\u5ea7\u6a19\u3092\u542b\u307e\u306a\u3044\u5199\u771f\u3092\u542b\u3081\u308b
 dialog.jpegload.loadjpegsoutsidearea=\u73fe\u5728\u898b\u3066\u3044\u308b\u5730\u57df\u5916\u306e\u5199\u771f\u3092\u542b\u3081\u308b
@@ -160,12 +180,12 @@ dialog.pointtype.desc=\u6b21\u306e\u70b9\u3092\u4fdd\u5b58\u3057\u307e\u3059\uff
 dialog.pointtype.track=\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8
 dialog.pointtype.waypoint=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8
 dialog.pointtype.photo=\u5199\u771f\u70b9
 dialog.pointtype.track=\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8
 dialog.pointtype.waypoint=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8
 dialog.pointtype.photo=\u5199\u771f\u70b9
+dialog.pointtype.audio=\u30aa\u30fc\u30c7\u30a3\u30aa\u30dd\u30a4\u30f3\u30c8
 dialog.pointtype.selection=\u9078\u629e\u7bc4\u56f2\u306e\u307f
 dialog.confirmreversetrack.title=\u53cd\u8ee2\u306e\u78ba\u8a8d
 dialog.confirmreversetrack.text=\u3053\u306e\u30c8\u30e9\u30c3\u30af\u306f\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u3092\u542b\u3093\u3067\u3044\u3066\u3001\u53cd\u8ee2\u3059\u308b\u3068\u306a\u304f\u306a\u308a\u307e\u3059\u3002\n\u672c\u5f53\u306b\u53cd\u8ee2\u3055\u305b\u307e\u3059\u304b\uff1f
 dialog.confirmcutandmove.title=\u5207\u308a\u53d6\u308a\u3068\u79fb\u52d5\u306e\u78ba\u8a8d
 dialog.confirmcutandmove.text=\u3053\u306e\u30c8\u30e9\u30c3\u30af\u306f\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u3092\u542b\u3093\u3067\u3044\u3066\u3001\u79fb\u52d5\u3059\u308b\u3068\u306a\u304f\u306a\u308a\u307e\u3059\u3002\n\u672c\u5f53\u306b\u53cd\u8ee2\u3055\u305b\u307e\u3059\u304b\uff1f
 dialog.pointtype.selection=\u9078\u629e\u7bc4\u56f2\u306e\u307f
 dialog.confirmreversetrack.title=\u53cd\u8ee2\u306e\u78ba\u8a8d
 dialog.confirmreversetrack.text=\u3053\u306e\u30c8\u30e9\u30c3\u30af\u306f\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u3092\u542b\u3093\u3067\u3044\u3066\u3001\u53cd\u8ee2\u3059\u308b\u3068\u306a\u304f\u306a\u308a\u307e\u3059\u3002\n\u672c\u5f53\u306b\u53cd\u8ee2\u3055\u305b\u307e\u3059\u304b\uff1f
 dialog.confirmcutandmove.title=\u5207\u308a\u53d6\u308a\u3068\u79fb\u52d5\u306e\u78ba\u8a8d
 dialog.confirmcutandmove.text=\u3053\u306e\u30c8\u30e9\u30c3\u30af\u306f\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u3092\u542b\u3093\u3067\u3044\u3066\u3001\u79fb\u52d5\u3059\u308b\u3068\u306a\u304f\u306a\u308a\u307e\u3059\u3002\n\u672c\u5f53\u306b\u53cd\u8ee2\u3055\u305b\u307e\u3059\u304b\uff1f
-dialog.interpolate.title=\u70b9\u3092\u88dc\u5b8c\u3059\u308b
 dialog.interpolate.parameter.text=\u9078\u629e\u3057\u305f\u70b9\u306e\u9593\u306b\u633f\u5165\u3055\u308c\u308b\u70b9\u306e\u6570
 dialog.undo.title=\u4f5c\u696d\u3092\u30a2\u30f3\u30c9\u30a5
 dialog.undo.pretext=\u30a2\u30f3\u30c9\u30a5\u3059\u308b\u4f5c\u696d\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002
 dialog.interpolate.parameter.text=\u9078\u629e\u3057\u305f\u70b9\u306e\u9593\u306b\u633f\u5165\u3055\u308c\u308b\u70b9\u306e\u6570
 dialog.undo.title=\u4f5c\u696d\u3092\u30a2\u30f3\u30c9\u30a5
 dialog.undo.pretext=\u30a2\u30f3\u30c9\u30a5\u3059\u308b\u4f5c\u696d\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002
@@ -183,7 +203,7 @@ dialog.pointedit.changevalue.title=\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u7de8\u9
 dialog.pointnameedit.name=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u540d
 dialog.pointnameedit.uppercase=\u5927\u6587\u5b57
 dialog.pointnameedit.lowercase=\u5c0f\u6587\u5b57
 dialog.pointnameedit.name=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u540d
 dialog.pointnameedit.uppercase=\u5927\u6587\u5b57
 dialog.pointnameedit.lowercase=\u5c0f\u6587\u5b57
-dialog.pointnameedit.sentencecase=\u982d\u6587\u5b57\u306e\u307f\u5927\u6587\u5b57
+dialog.pointnameedit.titlecase=\u982d\u6587\u5b57\u306e\u307f\u5927\u6587\u5b57
 dialog.addtimeoffset.add=\u6642\u9593\u3092\u8db3\u3059
 dialog.addtimeoffset.subtract=\u6642\u9593\u3092\u5f15\u304f
 dialog.addtimeoffset.days=\u65e5
 dialog.addtimeoffset.add=\u6642\u9593\u3092\u8db3\u3059
 dialog.addtimeoffset.subtract=\u6642\u9593\u3092\u5f15\u304f
 dialog.addtimeoffset.days=\u65e5
@@ -219,24 +239,29 @@ dialog.distances.column.to=\u7d42\u70b9
 dialog.distances.currentpoint=\u73fe\u5728\u306e\u70b9
 dialog.distances.toofewpoints=\u3053\u306e\u6a5f\u80fd\u306f\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u9593\u306e\u8ddd\u96e2\u3092\u8a08\u7b97\u3059\u308b\u305f\u3081\u306b\u3001\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u304c\u5fc5\u8981\u3067\u3059\u3002
 dialog.fullrangedetails.intro=\u9078\u629e\u7bc4\u56f2\u306b\u306f\u8a73\u7d30\u304c\u3042\u308a\u307e\u3059\u3002
 dialog.distances.currentpoint=\u73fe\u5728\u306e\u70b9
 dialog.distances.toofewpoints=\u3053\u306e\u6a5f\u80fd\u306f\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u9593\u306e\u8ddd\u96e2\u3092\u8a08\u7b97\u3059\u308b\u305f\u3081\u306b\u3001\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u304c\u5fc5\u8981\u3067\u3059\u3002
 dialog.fullrangedetails.intro=\u9078\u629e\u7bc4\u56f2\u306b\u306f\u8a73\u7d30\u304c\u3042\u308a\u307e\u3059\u3002
-dialog.setmapbg.mapnik=Mapnik(\u521d\u671f\u5024)
-dialog.setmapbg.osma=Osma
-dialog.setmapbg.cyclemap=Cyclemap
-dialog.setmapbg.other=\u305d\u306e\u4ed6(URL\u306b\u5165\u529b)
-dialog.setmapbg.server=\u5730\u56f3\u30b5\u30fc\u30d0\u30fcURL
+dialog.addmapsource.title=\u65b0\u3057\u3044\u30de\u30c3\u30d7\u30fb\u30bd\u30fc\u30b9\u3092\u8ffd\u52a0
+dialog.addmapsource.sourcename=\u30bd\u30fc\u30b9\u306e\u540d\u524d
+dialog.addmapsource.maxzoom=\u6700\u5927\u30ba\u30fc\u30e0\u30ec\u30d9\u30eb
+dialog.addmapsource.cloudstyle=\u30b9\u30bf\u30a4\u30eb\u756a\u53f7
+dialog.addmapsource.noname=\u540d\u524d\u306a\u3057
 dialog.gpsies.column.name=\u30c8\u30e9\u30c3\u30af\u540d
 dialog.gpsies.column.length=\u9577\u3055
 dialog.gpsies.description=\u8a18\u8ff0
 dialog.gpsies.nodescription=\u8a18\u8ff0\u304c\u3042\u308a\u307e\u305b\u3093
 dialog.gpsies.nonefound=\u30c8\u30e9\u30c3\u30af\u304c\u3042\u308a\u307e\u305b\u3093
 dialog.gpsies.column.name=\u30c8\u30e9\u30c3\u30af\u540d
 dialog.gpsies.column.length=\u9577\u3055
 dialog.gpsies.description=\u8a18\u8ff0
 dialog.gpsies.nodescription=\u8a18\u8ff0\u304c\u3042\u308a\u307e\u305b\u3093
 dialog.gpsies.nonefound=\u30c8\u30e9\u30c3\u30af\u304c\u3042\u308a\u307e\u305b\u3093
+dialog.gpsies.username=Gpsies\u306e\u30e6\u30fc\u30b6\u30fc\u540d
+dialog.gpsies.password=Gpsies\u306e\u30d1\u30b9\u30ef\u30fc\u30c9
 dialog.gpsies.activities=\u6d3b\u52d5\u306b\u9069\u3057\u3066
 dialog.gpsies.activity.trekking=\u30cf\u30a4\u30ad\u30f3\u30b0
 dialog.gpsies.activity.walking=\u30a6\u30a9\u30fc\u30ad\u30f3\u30b0
 dialog.gpsies.activity.jogging=\u5b9f\u884c\u4e2d
 dialog.gpsies.activity.biking=\u30b5\u30a4\u30af\u30ea\u30f3\u30b0
 dialog.gpsies.activities=\u6d3b\u52d5\u306b\u9069\u3057\u3066
 dialog.gpsies.activity.trekking=\u30cf\u30a4\u30ad\u30f3\u30b0
 dialog.gpsies.activity.walking=\u30a6\u30a9\u30fc\u30ad\u30f3\u30b0
 dialog.gpsies.activity.jogging=\u5b9f\u884c\u4e2d
 dialog.gpsies.activity.biking=\u30b5\u30a4\u30af\u30ea\u30f3\u30b0
+dialog.gpsies.activity.motorbiking=\u30e2\u30fc\u30bf\u30fc\u30d0\u30a4\u30af
 dialog.gpsies.activity.snowshoe=\u30b9\u30ce\u30fc\u30b7\u30e5\u30fc\u30a4\u30f3\u30b0
 dialog.gpsies.activity.sailing=\u30bb\u30fc\u30ea\u30f3\u30b0
 dialog.gpsies.activity.skating=\u30d5\u30a3\u30ae\u30e5\u30a2\u30b9\u30b1\u30fc\u30c8
 dialog.gpsies.activity.snowshoe=\u30b9\u30ce\u30fc\u30b7\u30e5\u30fc\u30a4\u30f3\u30b0
 dialog.gpsies.activity.sailing=\u30bb\u30fc\u30ea\u30f3\u30b0
 dialog.gpsies.activity.skating=\u30d5\u30a3\u30ae\u30e5\u30a2\u30b9\u30b1\u30fc\u30c8
+dialog.wikipedia.column.name=Wikipedia\u8a18\u4e8b\u540d
+dialog.wikipedia.column.distance=\u8ddd\u96e2
 dialog.correlate.notimestamps=\u30c7\u30fc\u30bf\u30dd\u30a4\u30f3\u30c8\u306b\u306f\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u304c\u306a\u3044\u306e\u3067\u3001\u5199\u771f\u3092\u95a2\u9023\u4ed8\u3051\u3089\u308c\u308b\u7269\u304c\u3042\u308a\u307e\u305b\u3093\u3002
 dialog.correlate.nouncorrelatedphotos=\u95a2\u9023\u4ed8\u3051\u3089\u308c\u306a\u304b\u3063\u305f\u5199\u771f\u306f\u3042\u308a\u307e\u305b\u3093\u3002\n\u7d9a\u3051\u307e\u3059\u304b\uff1f
 dialog.correlate.photoselect.intro=\u6642\u9593\u504f\u4f4d\u3092\u4f5c\u308b\u305f\u3081\u306e\u5199\u771f\u3092\u4e00\u3064\u9078\u3093\u3067\u304f\u3060\u3055\u3044\u3002
 dialog.correlate.notimestamps=\u30c7\u30fc\u30bf\u30dd\u30a4\u30f3\u30c8\u306b\u306f\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u304c\u306a\u3044\u306e\u3067\u3001\u5199\u771f\u3092\u95a2\u9023\u4ed8\u3051\u3089\u308c\u308b\u7269\u304c\u3042\u308a\u307e\u305b\u3093\u3002
 dialog.correlate.nouncorrelatedphotos=\u95a2\u9023\u4ed8\u3051\u3089\u308c\u306a\u304b\u3063\u305f\u5199\u771f\u306f\u3042\u308a\u307e\u305b\u3093\u3002\n\u7d9a\u3051\u307e\u3059\u304b\uff1f
 dialog.correlate.photoselect.intro=\u6642\u9593\u504f\u4f4d\u3092\u4f5c\u308b\u305f\u3081\u306e\u5199\u771f\u3092\u4e00\u3064\u9078\u3093\u3067\u304f\u3060\u3055\u3044\u3002
@@ -259,13 +284,19 @@ dialog.correlate.options.nodistancelimit=\u8ddd\u96e2\u5236\u9650\u306a\u3057
 dialog.correlate.options.distancelimit=\u8ddd\u96e2\u5236\u9650
 dialog.correlate.options.correlate=\u95a2\u9023\u4ed8\u3051
 dialog.correlate.alloutsiderange=\u5168\u3066\u306e\u5199\u771f\u304c\u30c8\u30e9\u30c3\u30af\u306e\u7bc4\u56f2\u5916\u3067\u3059\u3002\u3060\u304b\u3089\u3001\u4f55\u3082\u95a2\u9023\u4ed8\u3051\u3089\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002\n\u6642\u9593\u504f\u4f4d\u3092\u5909\u3048\u308b\u304b\u3001\u5c11\u306a\u304f\u3068\u3082\u4e00\u3064\u306e\u5199\u771f\u3092\u624b\u52d5\u95a2\u9023\u4ed8\u3051\u3092\u3059\u308b\u306a\u3069\u3057\u3066\u898b\u3066\u304f\u3060\u3055\u3044\u3002
 dialog.correlate.options.distancelimit=\u8ddd\u96e2\u5236\u9650
 dialog.correlate.options.correlate=\u95a2\u9023\u4ed8\u3051
 dialog.correlate.alloutsiderange=\u5168\u3066\u306e\u5199\u771f\u304c\u30c8\u30e9\u30c3\u30af\u306e\u7bc4\u56f2\u5916\u3067\u3059\u3002\u3060\u304b\u3089\u3001\u4f55\u3082\u95a2\u9023\u4ed8\u3051\u3089\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002\n\u6642\u9593\u504f\u4f4d\u3092\u5909\u3048\u308b\u304b\u3001\u5c11\u306a\u304f\u3068\u3082\u4e00\u3064\u306e\u5199\u771f\u3092\u624b\u52d5\u95a2\u9023\u4ed8\u3051\u3092\u3059\u308b\u306a\u3069\u3057\u3066\u898b\u3066\u304f\u3060\u3055\u3044\u3002
+dialog.correlate.filetimes=\u30d5\u30a1\u30a4\u30eb\u306e\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u3092\u8868\u793a\uff1a
+dialog.correlate.filetimes2=\u30aa\u30fc\u30c7\u30a3\u30aa\u30af\u30ea\u30c3\u30d7\u306e
+dialog.correlate.timestamp.beginning=\u958b\u59cb
+dialog.correlate.timestamp.middle=\u4e2d\u9593\u70b9
+dialog.correlate.timestamp.end=\u7d42\u70b9
+dialog.correlate.select.audioname=\u30aa\u30fc\u30c7\u30a3\u30aa\u540d
 dialog.rearrangephotos.desc=\u5411\u304b\u3046\u5148\u3092\u9078\u629e\u3057\u3066\u3001\u5199\u771f\u306e\u70b9\u3092\u4e26\u3079\u76f4\u3059\u3002
 dialog.rearrangephotos.tostart=\u79fb\u52d5\u958b\u59cb
 dialog.rearrangephotos.toend=\u79fb\u52d5\u7d42\u4e86
 dialog.rearrangephotos.nosort=\u4e26\u3079\u66ff\u3048\u306a\u3044
 dialog.rearrangephotos.sortbyfilename=\u30d5\u30a1\u30a4\u30eb\u540d\u3067\u4e26\u3079\u66ff\u3048
 dialog.rearrangephotos.sortbytime=\u6642\u9593\u3067\u4e26\u3079\u66ff\u3048
 dialog.rearrangephotos.desc=\u5411\u304b\u3046\u5148\u3092\u9078\u629e\u3057\u3066\u3001\u5199\u771f\u306e\u70b9\u3092\u4e26\u3079\u76f4\u3059\u3002
 dialog.rearrangephotos.tostart=\u79fb\u52d5\u958b\u59cb
 dialog.rearrangephotos.toend=\u79fb\u52d5\u7d42\u4e86
 dialog.rearrangephotos.nosort=\u4e26\u3079\u66ff\u3048\u306a\u3044
 dialog.rearrangephotos.sortbyfilename=\u30d5\u30a1\u30a4\u30eb\u540d\u3067\u4e26\u3079\u66ff\u3048
 dialog.rearrangephotos.sortbytime=\u6642\u9593\u3067\u4e26\u3079\u66ff\u3048
-dialog.compress.nonefound=\u9664\u304f\u3053\u3068\u304c\u3067\u304d\u308b\u30c7\u30fc\u30bf\u30dd\u30a4\u30f3\u30c8\u304c\u3042\u308a\u307e\u305b\u3093\u3002
+dialog.deletemarked.nonefound=\u9664\u304f\u3053\u3068\u304c\u3067\u304d\u308b\u30c7\u30fc\u30bf\u30dd\u30a4\u30f3\u30c8\u304c\u3042\u308a\u307e\u305b\u3093\u3002
 dialog.compress.closepoints.title=\u8fd1\u508d\u70b9\u3092\u524a\u9664
 dialog.compress.closepoints.paramdesc=\u8fd1\u508d\u4fc2\u6570
 dialog.compress.wackypoints.title=\u304a\u304b\u3057\u306a\u70b9\u306e\u524a\u9664
 dialog.compress.closepoints.title=\u8fd1\u508d\u70b9\u3092\u524a\u9664
 dialog.compress.closepoints.paramdesc=\u8fd1\u508d\u4fc2\u6570
 dialog.compress.wackypoints.title=\u304a\u304b\u3057\u306a\u70b9\u306e\u524a\u9664
@@ -293,6 +324,7 @@ dialog.about.systeminfo.povray=Povray \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u6e08
 dialog.about.systeminfo.exiftool=Exiftool \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u6e08
 dialog.about.systeminfo.gpsbabel=Gpsbabel \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u6e08
 dialog.about.systeminfo.gnuplot=Gnuplot \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u6e08
 dialog.about.systeminfo.exiftool=Exiftool \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u6e08
 dialog.about.systeminfo.gpsbabel=Gpsbabel \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u6e08
 dialog.about.systeminfo.gnuplot=Gnuplot \u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u6e08
+dialog.about.systeminfo.exiflib=Exif\u30e9\u30a4\u30d6\u30e9\u30ea
 dialog.about.yes=\u306f\u3044
 dialog.about.no=\u3044\u3044\u3048
 dialog.about.credits=\u30af\u30ec\u30b8\u30c3\u30c8
 dialog.about.yes=\u306f\u3044
 dialog.about.no=\u3044\u3044\u3048
 dialog.about.credits=\u30af\u30ec\u30b8\u30c3\u30c8
@@ -314,6 +346,8 @@ dialog.checkversion.releasedate2=\u306b\u30ea\u30ea\u30fc\u30b9\u3057\u307e\u305
 dialog.checkversion.download=\u65b0\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u306b\u306f\u3001 http://activityworkshop.net/software/gpsprune/download.html \u3078\u884c\u3063\u3066\u304f\u3060\u3055\u3044\u3002
 dialog.keys.intro=\u30de\u30a6\u30b9\u306e\u4ee3\u308f\u308a\u306b\u6b21\u306e\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8\u30ad\u30fc\u3092\u4f7f\u3046\u4e8b\u304c\u3067\u304d\u307e\u3059\u3002
 dialog.keys.keylist=<table><tr><td>\u77e2\u5370\u30ad\u30fc</td><td>\u5730\u56f3\u3092\u4e0a\u4e0b\u5de6\u53f3\u306b\u79fb\u52d5</td></tr><tr><td>Ctrl + \u5de6\u30fb\u53f3\u77e2\u5370</td><td>\u524d\u30fb\u6b21\u306e\u70b9\u3092\u9078\u629e</td></tr><tr><td>Ctrl + \u4e0a\u30fb\u4e0b\u77e2\u5370</td><td>\u62e1\u5927\u30fb\u7e2e\u5c0f</td></tr><tr><td>Del</td><td>\u73fe\u5728\u306e\u70b9\u3092\u524a\u9664</td></tr></table>
 dialog.checkversion.download=\u65b0\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u306b\u306f\u3001 http://activityworkshop.net/software/gpsprune/download.html \u3078\u884c\u3063\u3066\u304f\u3060\u3055\u3044\u3002
 dialog.keys.intro=\u30de\u30a6\u30b9\u306e\u4ee3\u308f\u308a\u306b\u6b21\u306e\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8\u30ad\u30fc\u3092\u4f7f\u3046\u4e8b\u304c\u3067\u304d\u307e\u3059\u3002
 dialog.keys.keylist=<table><tr><td>\u77e2\u5370\u30ad\u30fc</td><td>\u5730\u56f3\u3092\u4e0a\u4e0b\u5de6\u53f3\u306b\u79fb\u52d5</td></tr><tr><td>Ctrl + \u5de6\u30fb\u53f3\u77e2\u5370</td><td>\u524d\u30fb\u6b21\u306e\u70b9\u3092\u9078\u629e</td></tr><tr><td>Ctrl + \u4e0a\u30fb\u4e0b\u77e2\u5370</td><td>\u62e1\u5927\u30fb\u7e2e\u5c0f</td></tr><tr><td>Del</td><td>\u73fe\u5728\u306e\u70b9\u3092\u524a\u9664</td></tr></table>
+dialog.keys.normalmodifier=Ctrl\u30ad\u30fc
+dialog.keys.macmodifier=Command\u30ad\u30fc
 dialog.saveconfig.desc=\u4e0b\u8a18\u306e\u8a2d\u5b9a\u304c\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58\u3055\u308c\u307e\u3059
 dialog.saveconfig.prune.trackdirectory=\u30c8\u30e9\u30c3\u30af\u30c7\u30a3\u30ec\u30af\u30c8\u30ea
 dialog.saveconfig.prune.photodirectory=\u5199\u771f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea
 dialog.saveconfig.desc=\u4e0b\u8a18\u306e\u8a2d\u5b9a\u304c\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58\u3055\u308c\u307e\u3059
 dialog.saveconfig.prune.trackdirectory=\u30c8\u30e9\u30c3\u30af\u30c7\u30a3\u30ec\u30af\u30c8\u30ea
 dialog.saveconfig.prune.photodirectory=\u5199\u771f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea
@@ -322,15 +356,16 @@ dialog.saveconfig.prune.languagefile=\u8a00\u8a9e\u30d5\u30a1\u30a4\u30eb
 dialog.saveconfig.prune.gpsdevice=GPS\u30c7\u30d0\u30a4\u30b9
 dialog.saveconfig.prune.gpsformat=GPS\u30d5\u30a9\u30fc\u30de\u30c3\u30c8
 dialog.saveconfig.prune.povrayfont=Povray \u30d5\u30a9\u30f3\u30c8
 dialog.saveconfig.prune.gpsdevice=GPS\u30c7\u30d0\u30a4\u30b9
 dialog.saveconfig.prune.gpsformat=GPS\u30d5\u30a9\u30fc\u30de\u30c3\u30c8
 dialog.saveconfig.prune.povrayfont=Povray \u30d5\u30a9\u30f3\u30c8
-dialog.saveconfig.prune.metricunits=\u30e1\u30fc\u30c8\u30eb\u6cd5\u3092\u4f7f\u3046\uff1f
 dialog.saveconfig.prune.gnuplotpath=gnuplot\u3078\u306e\u30d1\u30b9
 dialog.saveconfig.prune.gpsbabelpath=gpsbabel\u3078\u306e\u30d1\u30b9
 dialog.saveconfig.prune.exiftoolpath=exiftool\u3078\u306e\u30d1\u30b9
 dialog.saveconfig.prune.gnuplotpath=gnuplot\u3078\u306e\u30d1\u30b9
 dialog.saveconfig.prune.gpsbabelpath=gpsbabel\u3078\u306e\u30d1\u30b9
 dialog.saveconfig.prune.exiftoolpath=exiftool\u3078\u306e\u30d1\u30b9
-dialog.saveconfig.prune.mapserverindex=\u80cc\u666f\u5730\u56f3\u30b5\u30fc\u30d0\u30fc\u306e\u7d22\u5f15(1-4)
-dialog.saveconfig.prune.mapserverurl=\u5730\u56f3\u30b5\u30fc\u30d0\u30fc\u306eURL
+dialog.saveconfig.prune.mapsource=\u30de\u30c3\u30d7\u30fb\u30bd\u30fc\u30b9\u3092\u9078\u629e
+dialog.saveconfig.prune.mapsourcelist=\u30de\u30c3\u30d7\u30fb\u30bd\u30fc\u30b9
+dialog.saveconfig.prune.diskcache=\u30de\u30c3\u30d7\u306e\u30ad\u30e3\u30c3\u30b7\u30e5
 dialog.saveconfig.prune.kmzimagewidth=KML \u753b\u50cf\u5e45
 dialog.saveconfig.prune.kmzimageheight=KML \u753b\u50cf\u9ad8
 dialog.saveconfig.prune.colourscheme=\u8272\u306e\u30b9\u30ad\u30fc\u30e0
 dialog.saveconfig.prune.kmzimagewidth=KML \u753b\u50cf\u5e45
 dialog.saveconfig.prune.kmzimageheight=KML \u753b\u50cf\u9ad8
 dialog.saveconfig.prune.colourscheme=\u8272\u306e\u30b9\u30ad\u30fc\u30e0
+dialog.saveconfig.prune.linewidth=\u7dda\u306e\u5e45
 dialog.saveconfig.prune.kmltrackcolour=KML \u30c8\u30e9\u30c3\u30af\u306e\u8272
 dialog.setpaths.intro=\u5fc5\u8981\u306a\u3089\u3001\u5916\u90e8\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30d1\u30b9\u3092\u9078\u3076\u4e8b\u304c\u3067\u304d\u307e\u3059
 dialog.addaltitude.noaltitudes=\u9078\u629e\u7bc4\u56f2\u306f\u3001\u9ad8\u5ea6\u3092\u542b\u3093\u3067\u307e\u305b\u3093\u3002
 dialog.saveconfig.prune.kmltrackcolour=KML \u30c8\u30e9\u30c3\u30af\u306e\u8272
 dialog.setpaths.intro=\u5fc5\u8981\u306a\u3089\u3001\u5916\u90e8\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30d1\u30b9\u3092\u9078\u3076\u4e8b\u304c\u3067\u304d\u307e\u3059
 dialog.addaltitude.noaltitudes=\u9078\u629e\u7bc4\u56f2\u306f\u3001\u9ad8\u5ea6\u3092\u542b\u3093\u3067\u307e\u305b\u3093\u3002
@@ -354,13 +389,20 @@ dialog.setlanguage.language=\u8a00\u8a9e
 dialog.setlanguage.languagefile=\u8a00\u8a9e\u30d5\u30a1\u30a4\u30eb
 dialog.setlanguage.endmessage=\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3057\u3001\u8a00\u8a9e\u306e\u5909\u66f4\u3092\u6709\u52b9\u306b\u3059\u308b\u305f\u3081\u306b\nGpsPrune \u3092\u518d\u8d77\u52d5\u3057\u3066\u304f\u3060\u3055\u3044\u3002
 
 dialog.setlanguage.languagefile=\u8a00\u8a9e\u30d5\u30a1\u30a4\u30eb
 dialog.setlanguage.endmessage=\u8a2d\u5b9a\u3092\u4fdd\u5b58\u3057\u3001\u8a00\u8a9e\u306e\u5909\u66f4\u3092\u6709\u52b9\u306b\u3059\u308b\u305f\u3081\u306b\nGpsPrune \u3092\u518d\u8d77\u52d5\u3057\u3066\u304f\u3060\u3055\u3044\u3002
 
+dialog.diskcache.save=\u30c7\u30a3\u30b9\u30af\u306b\u30a4\u30e1\u30fc\u30b8\u3092\u4fdd\u5b58
+dialog.diskcache.dir=\u30ad\u30e3\u30c3\u30b7\u30e5\u30c7\u30a3\u30ec\u30af\u30c8\u30ea
+dialog.diskcache.createdir=\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u4f5c\u6210
+dialog.diskcache.nocreate=\u30ad\u30e3\u30c3\u30b7\u30e5\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u4f5c\u6210\u3055\u308c\u306a\u304b\u3063\u305f\u3002
+dialog.setlinewidth.text=\u30c8\u30e9\u30c3\u30af\u63cf\u753b\u306e\u7dda\u5e45\u30921-4\u306e\u7bc4\u56f2\u3067\u5165\u529b
+dialog.searchwikipedianames.search=\u53f3\u8a18\u3092\u691c\u7d22:
+
 # 3d window
 dialog.3d.title=GpsPrune 3D \u8868\u793a
 dialog.3dlines.title=GpsPrune \u683c\u5b50\u7dda
 dialog.3dlines.empty=\u683c\u5b50\u7dda\u304c\u8868\u793a\u3055\u308c\u307e\u305b\u3093
 dialog.3dlines.intro=\u3053\u308c\u3089\u304c 3D \u8868\u793a\u7528\u306e\u683c\u5b50\u7dda\u3067\u3059\u3002
 
 # 3d window
 dialog.3d.title=GpsPrune 3D \u8868\u793a
 dialog.3dlines.title=GpsPrune \u683c\u5b50\u7dda
 dialog.3dlines.empty=\u683c\u5b50\u7dda\u304c\u8868\u793a\u3055\u308c\u307e\u305b\u3093
 dialog.3dlines.intro=\u3053\u308c\u3089\u304c 3D \u8868\u793a\u7528\u306e\u683c\u5b50\u7dda\u3067\u3059\u3002
 
-# Confirm messages || These are displayed as confirmation in the status bar
+# Confirm messages
 confirm.loadfile=\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u3080
 confirm.save.ok1=\u4fdd\u5b58\u6210\u529f
 confirm.save.ok2=\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u70b9
 confirm.loadfile=\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u3080
 confirm.save.ok1=\u4fdd\u5b58\u6210\u529f
 confirm.save.ok2=\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u70b9
@@ -381,14 +423,23 @@ confirm.undo.single=\u64cd\u4f5c\u306f\u30a2\u30f3\u30c9\u30a5\u3055\u308c\u305f
 confirm.undo.multi=\u64cd\u4f5c\u306f\u30a2\u30f3\u30c9\u30a5\u3055\u308c\u305f
 confirm.jpegload.single=\u5199\u771f\u304c\u52a0\u3048\u3089\u308c\u305f
 confirm.jpegload.multi=\u5199\u771f\u304c\u52a0\u3048\u3089\u308c\u305f
 confirm.undo.multi=\u64cd\u4f5c\u306f\u30a2\u30f3\u30c9\u30a5\u3055\u308c\u305f
 confirm.jpegload.single=\u5199\u771f\u304c\u52a0\u3048\u3089\u308c\u305f
 confirm.jpegload.multi=\u5199\u771f\u304c\u52a0\u3048\u3089\u308c\u305f
-confirm.photo.disconnect=\u5199\u771f\u304c\u63a5\u7d9a\u3055\u308c\u305f
+confirm.media.connect=\u30e1\u30c7\u30a3\u30a2\u304c\u63a5\u7d9a\u3055\u308c\u305f
+confirm.photo.disconnect=\u5199\u771f\u304c\u5207\u65ad\u3055\u308c\u305f
+confirm.audio.disconnect=\u30aa\u30fc\u30c7\u30a3\u30aa\u304c\u5207\u65ad\u3055\u308c\u305f
+confirm.media.removed=\u524a\u9664\u3055\u308c\u305f
 confirm.correlatephotos.single=\u5199\u771f\u304c\u95a2\u9023\u4ed8\u3051\u3089\u308c\u305f
 confirm.correlatephotos.multi=\u5199\u771f\u304c\u95a2\u9023\u4ed8\u3051\u3089\u308c\u305f
 confirm.createpoint=\u70b9\u304c\u4f5c\u3089\u308c\u305f
 confirm.rotatephoto=\u5199\u771f\u3092\u56de\u8ee2\u3057\u305f
 confirm.running=\u5b9f\u884c\u4e2d...
 confirm.correlatephotos.single=\u5199\u771f\u304c\u95a2\u9023\u4ed8\u3051\u3089\u308c\u305f
 confirm.correlatephotos.multi=\u5199\u771f\u304c\u95a2\u9023\u4ed8\u3051\u3089\u308c\u305f
 confirm.createpoint=\u70b9\u304c\u4f5c\u3089\u308c\u305f
 confirm.rotatephoto=\u5199\u771f\u3092\u56de\u8ee2\u3057\u305f
 confirm.running=\u5b9f\u884c\u4e2d...
+confirm.lookupsrtm1=
+confirm.lookupsrtm2=\u6a19\u9ad8\u5024
+confirm.deletefieldvalues=\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u5024\u304c\u524a\u9664\u3055\u308c\u305f
+confirm.audioload=\u30aa\u30fc\u30c7\u30a3\u30aa\u30d5\u30a1\u30a4\u30eb\u304c\u8ffd\u52a0\u3055\u308c\u305f
+confirm.correlateaudios.single=\u30aa\u30fc\u30c7\u30a3\u30aa\u304c\u95a2\u9023\u4ed8\u3051\u3089\u308c\u305f
+confirm.correlateaudios.multi=\u8907\u6570\u306e\u30aa\u30fc\u30c7\u30a3\u30aa\u304c\u95a2\u9023\u4ed8\u3051\u3089\u308c\u305f
 
 
-# Buttons || These are all the texts for buttons
+# Buttons
 button.ok=\u6c7a\u5b9a
 button.back=\u623b\u308b
 button.next=\u6b21
 button.ok=\u6c7a\u5b9a
 button.back=\u623b\u308b
 button.next=\u6b21
@@ -411,11 +462,14 @@ button.selectall=\u5168\u9078\u629e
 button.selectnone=\u9078\u629e\u89e3\u9664
 button.preview=\u30d7\u30ec\u30d3\u30e5\u30fc
 button.load=\u8aad\u307f\u8fbc\u307f
 button.selectnone=\u9078\u629e\u89e3\u9664
 button.preview=\u30d7\u30ec\u30d3\u30e5\u30fc
 button.load=\u8aad\u307f\u8fbc\u307f
+button.upload=\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9
 button.guessfields=\u30d5\u30a3\u30fc\u30eb\u30c9\u4e88\u6e2c
 button.showwebpage=\u30a6\u30a7\u30d6\u30da\u30fc\u30b8\u3092\u8868\u793a
 button.check=\u691c\u67fb
 button.resettodefaults=\u521d\u671f\u5024\u306b\u623b\u3059
 button.browse=\u95b2\u89a7...
 button.guessfields=\u30d5\u30a3\u30fc\u30eb\u30c9\u4e88\u6e2c
 button.showwebpage=\u30a6\u30a7\u30d6\u30da\u30fc\u30b8\u3092\u8868\u793a
 button.check=\u691c\u67fb
 button.resettodefaults=\u521d\u671f\u5024\u306b\u623b\u3059
 button.browse=\u95b2\u89a7...
+button.addnew=\u65b0\u3057\u304f\u8ffd\u52a0
+button.delete=\u524a\u9664
 
 # File types
 filetype.txt=TXT\u30d5\u30a1\u30a4\u30eb
 
 # File types
 filetype.txt=TXT\u30d5\u30a1\u30a4\u30eb
@@ -426,10 +480,12 @@ filetype.kmz=KMZ\u30d5\u30a1\u30a4\u30eb
 filetype.gpx=GPX\u30d5\u30a1\u30a4\u30eb
 filetype.pov=POV\u30d5\u30a1\u30a4\u30eb
 filetype.svg=SVG\u30d5\u30a1\u30a4\u30eb
 filetype.gpx=GPX\u30d5\u30a1\u30a4\u30eb
 filetype.pov=POV\u30d5\u30a1\u30a4\u30eb
 filetype.svg=SVG\u30d5\u30a1\u30a4\u30eb
+filetype.audio=MP3,OGG,WAV\u30d5\u30a1\u30a4\u30eb
 
 
-# Display components || These are all for the side panels showing point/range details
+# Display components
 display.nodata=\u8aad\u307f\u8fbc\u307e\u308c\u305f\u30c7\u30fc\u30bf\u306a\u3057
 display.noaltitudes=\u30c8\u30e9\u30c3\u30af\u30c7\u30fc\u30bf\u306f\u9ad8\u5ea6\u3092\u542b\u307f\u307e\u305b\u3093
 display.nodata=\u8aad\u307f\u8fbc\u307e\u308c\u305f\u30c7\u30fc\u30bf\u306a\u3057
 display.noaltitudes=\u30c8\u30e9\u30c3\u30af\u30c7\u30fc\u30bf\u306f\u9ad8\u5ea6\u3092\u542b\u307f\u307e\u305b\u3093
+display.notimestamps=\u30c8\u30e9\u30c3\u30af\u30c7\u30fc\u30bf\u306f\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u3092\u542b\u3093\u3067\u3044\u307e\u305b\u3093
 details.trackdetails=\u30c8\u30e9\u30c3\u30af\u8a73\u7d30
 details.notrack=\u8aad\u307f\u8fbc\u307e\u308c\u305f\u30c8\u30e9\u30c3\u30af\u306a\u3057
 details.track.points=\u70b9
 details.trackdetails=\u30c8\u30e9\u30c3\u30af\u8a73\u7d30
 details.notrack=\u8aad\u307f\u8fbc\u307e\u308c\u305f\u30c8\u30e9\u30c3\u30af\u306a\u3057
 details.track.points=\u70b9
@@ -454,16 +510,21 @@ display.range.time.mins=\u5206
 display.range.time.hours=\u6642
 display.range.time.days=\u65e5
 details.range.avespeed=\u5e73\u5747\u901f\u5ea6
 display.range.time.hours=\u6642
 display.range.time.days=\u65e5
 details.range.avespeed=\u5e73\u5747\u901f\u5ea6
-details.range.avemovingspeed=\u5e73\u5747\u79fb\u52d5
+details.range.maxspeed=\u6700\u9ad8\u901f\u5ea6
 details.range.numsegments=\u30bb\u30b0\u30e1\u30f3\u30c8\u6570
 details.range.pace=\u30da\u30fc\u30b9
 details.range.gradient=\u52fe\u914d
 details.lists.waypoints=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8
 details.lists.photos=\u5199\u771f
 details.range.numsegments=\u30bb\u30b0\u30e1\u30f3\u30c8\u6570
 details.range.pace=\u30da\u30fc\u30b9
 details.range.gradient=\u52fe\u914d
 details.lists.waypoints=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8
 details.lists.photos=\u5199\u771f
+details.lists.audio=\u30aa\u30fc\u30c7\u30a3\u30aa
 details.photodetails=\u5199\u771f\u8a73\u7d30
 details.nophoto=\u5199\u771f\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093
 details.photo.loading=\u8aad\u307f\u8fbc\u307f\u4e2d
 details.media.connected=\u63a5\u7d9a\u6e08
 details.photodetails=\u5199\u771f\u8a73\u7d30
 details.nophoto=\u5199\u771f\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u307e\u305b\u3093
 details.photo.loading=\u8aad\u307f\u8fbc\u307f\u4e2d
 details.media.connected=\u63a5\u7d9a\u6e08
+details.audiodetails=\u30aa\u30fc\u30c7\u30a3\u30aa\u306e\u8a73\u7d30
+details.noaudio=\u30aa\u30fc\u30c7\u30a3\u30aa\u30d5\u30a1\u30a4\u30eb\u304c\u672a\u9078\u629e
+details.audio.file=\u30aa\u30fc\u30c7\u30a3\u30aa\u30d5\u30a1\u30a4\u30eb
+details.audio.playing=\u518d\u751f...
 map.overzoom=\u3053\u306e\u30ba\u30fc\u30e0\u30ec\u30d9\u30eb\u3067\u306f\u5730\u56f3\u304c\u5165\u624b\u3067\u304d\u307e\u305b\u3093\u3002
 
 # Field names
 map.overzoom=\u3053\u306e\u30ba\u30fc\u30e0\u30ec\u30d9\u30eb\u3067\u306f\u5730\u56f3\u304c\u5165\u624b\u3067\u304d\u307e\u305b\u3093\u3002
 
 # Field names
@@ -492,12 +553,12 @@ units.feet=\u30d5\u30a3\u30fc\u30c8
 units.feet.short=ft
 units.kilometres=\u30ad\u30ed\u30e1\u30fc\u30c8\u30eb
 units.kilometres.short=km
 units.feet.short=ft
 units.kilometres=\u30ad\u30ed\u30e1\u30fc\u30c8\u30eb
 units.kilometres.short=km
-units.kmh=km/h
+units.kilometresperhour.short=km/h
 units.miles=\u30de\u30a4\u30eb
 units.miles.short=mi
 units.miles=\u30de\u30a4\u30eb
 units.miles.short=mi
-units.mph=mph
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.milesperhour.short=mph
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=\u6642\u9593
 units.degminsec=\u5ea6-\u5206-\u79d2
 units.degmin=\u5ea6-\u5206
 units.hours=\u6642\u9593
 units.degminsec=\u5ea6-\u5206-\u79d2
 units.degmin=\u5ea6-\u5206
@@ -514,14 +575,16 @@ cardinal.s=S
 cardinal.e=E
 cardinal.w=W
 
 cardinal.e=E
 cardinal.w=W
 
-# Undo operations || These will be displayed in the undo list after you've performed the operation, to tell you what you did
+# Undo operations
 undo.load=\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u307f
 undo.loadphotos=\u5199\u771f\u306e\u8aad\u307f\u8fbc\u307f
 undo.load=\u30c7\u30fc\u30bf\u3092\u8aad\u307f\u8fbc\u307f
 undo.loadphotos=\u5199\u771f\u306e\u8aad\u307f\u8fbc\u307f
+undo.loadaudios=\u30aa\u30fc\u30c7\u30a3\u30aa\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f
 undo.editpoint=\u70b9\u306e\u7de8\u96c6
 undo.deletepoint=\u70b9\u306e\u524a\u9664
 undo.editpoint=\u70b9\u306e\u7de8\u96c6
 undo.deletepoint=\u70b9\u306e\u524a\u9664
-undo.removephoto=\u5199\u771f\u306e\u53d6\u308a\u9664\u304d
+undo.removephoto=\u5199\u771f\u306e\u524a\u9664
+undo.removeaudio=\u30aa\u30fc\u30c7\u30a3\u30aa\u306e\u524a\u9664
 undo.deleterange=\u7bc4\u56f2\u306e\u524a\u9664
 undo.deleterange=\u7bc4\u56f2\u306e\u524a\u9664
-undo.compress=\u30c8\u30e9\u30c3\u30af\u306e\u5727\u7e2e
+undo.deletemarked=\u30c8\u30e9\u30c3\u30af\u306e\u5727\u7e2e
 undo.insert=\u70b9\u306e\u633f\u5165
 undo.reverse=\u7bc4\u56f2\u306e\u53cd\u8ee2
 undo.mergetracksegments=\u30c8\u30e9\u30c3\u30af\u30bb\u30b0\u30e1\u30f3\u30c8\u306e\u7d71\u5408
 undo.insert=\u70b9\u306e\u633f\u5165
 undo.reverse=\u7bc4\u56f2\u306e\u53cd\u8ee2
 undo.mergetracksegments=\u30c8\u30e9\u30c3\u30af\u30bb\u30b0\u30e1\u30f3\u30c8\u306e\u7d71\u5408
@@ -529,13 +592,16 @@ undo.addtimeoffset=\u6642\u9593\u504f\u4f4d\u3092\u52a0\u3048\u308b
 undo.addaltitudeoffset=\u9ad8\u5ea6\u504f\u4f4d\u3092\u52a0\u3048\u308b
 undo.rearrangewaypoints=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u633f\u5165
 undo.cutandmove=\u30bb\u30af\u30b7\u30e7\u30f3\u306e\u79fb\u52d5
 undo.addaltitudeoffset=\u9ad8\u5ea6\u504f\u4f4d\u3092\u52a0\u3048\u308b
 undo.rearrangewaypoints=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u633f\u5165
 undo.cutandmove=\u30bb\u30af\u30b7\u30e7\u30f3\u306e\u79fb\u52d5
-undo.connect=\u5199\u771f\u306e\u63a5\u7d9a
-undo.disconnect=\u5199\u771f\u306e\u63a5\u7d9a\u89e3\u9664
+undo.connect=\u63a5\u7d9a
+undo.disconnect=\u5207\u65ad
 undo.correlatephotos=\u5199\u771f\u306e\u95a2\u9023\u4ed8\u3051
 undo.rearrangephotos=\u5199\u771f\u306e\u4e26\u3079\u66ff\u3048
 undo.createpoint=\u70b9\u306e\u4f5c\u6210
 undo.rotatephoto=\u5199\u771f\u306e\u56de\u8ee2
 undo.convertnamestotimes=\u540d\u524d\u3092\u6642\u9593\u306b\u5909\u63db\u3059\u308b
 undo.correlatephotos=\u5199\u771f\u306e\u95a2\u9023\u4ed8\u3051
 undo.rearrangephotos=\u5199\u771f\u306e\u4e26\u3079\u66ff\u3048
 undo.createpoint=\u70b9\u306e\u4f5c\u6210
 undo.rotatephoto=\u5199\u771f\u306e\u56de\u8ee2
 undo.convertnamestotimes=\u540d\u524d\u3092\u6642\u9593\u306b\u5909\u63db\u3059\u308b
+undo.lookupsrtm=SRTM\u304b\u3089\u6a19\u9ad8\u3092\u691c\u7d22
+undo.deletefieldvalues=\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u5024\u3092\u524a\u9664
+undo.correlateaudios=\u30aa\u30fc\u30c7\u30a3\u30aa\u3092\u95a2\u9023\u4ed8\u3051
 
 # Error messages
 error.save.dialogtitle=\u30c7\u30fc\u30bf\u4fdd\u5b58\u306e\u30a8\u30e9\u30fc
 
 # Error messages
 error.save.dialogtitle=\u30c7\u30fc\u30bf\u4fdd\u5b58\u306e\u30a8\u30e9\u30fc
@@ -558,6 +624,7 @@ error.jpegload.dialogtitle=\u5199\u771f\u306e\u8aad\u307f\u8fbc\u307f\u30a8\u30e
 error.jpegload.nofilesfound=\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
 error.jpegload.nojpegsfound=Jpeg\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
 error.jpegload.nogpsfound=GPS\u60c5\u5831\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
 error.jpegload.nofilesfound=\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
 error.jpegload.nojpegsfound=Jpeg\u30d5\u30a1\u30a4\u30eb\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
 error.jpegload.nogpsfound=GPS\u60c5\u5831\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093
+error.audioload.nofilesfound=\u30aa\u30fc\u30c7\u30a3\u30aa\u30d5\u30a1\u30a4\u30eb\u304c\u672a\u9078\u629e
 error.gpsload.unknown=\u4e0d\u660e\u306a\u30a8\u30e9\u30fc
 error.undofailed.title=\u30a2\u30f3\u30c9\u30a5\u5931\u6557
 error.undofailed.text=\u30a2\u30f3\u30c9\u30a5\u64cd\u4f5c\u306e\u5931\u6557
 error.gpsload.unknown=\u4e0d\u660e\u306a\u30a8\u30e9\u30fc
 error.undofailed.title=\u30a2\u30f3\u30c9\u30a5\u5931\u6557
 error.undofailed.text=\u30a2\u30f3\u30c9\u30a5\u64cd\u4f5c\u306e\u5931\u6557
@@ -571,3 +638,8 @@ error.osmimage.dialogtitle=\u5730\u56f3\u753b\u50cf\u3092\u8aad\u307f\u8fbc\u307
 error.osmimage.failed=\u5730\u56f3\u753b\u50cf\u3092\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u63a5\u7d9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002
 error.language.wrongfile=\u9078\u629e\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u306fGpsPrune \u7528\u306e\u8a00\u8a9e\u30d5\u30a1\u30a4\u30eb\u306b\u898b\u3048\u307e\u305b\u3093\u3002
 error.convertnamestotimes.nonames=\u3069\u306e\u540d\u524d\u3082\u6642\u9593\u306b\u5909\u63db\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
 error.osmimage.failed=\u5730\u56f3\u753b\u50cf\u3092\u8aad\u307f\u8fbc\u307f\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u63a5\u7d9a\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002
 error.language.wrongfile=\u9078\u629e\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u306fGpsPrune \u7528\u306e\u8a00\u8a9e\u30d5\u30a1\u30a4\u30eb\u306b\u898b\u3048\u307e\u305b\u3093\u3002
 error.convertnamestotimes.nonames=\u3069\u306e\u540d\u524d\u3082\u6642\u9593\u306b\u5909\u63db\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
+error.lookupsrtm.nonefound=\u3069\u306e\u6a19\u9ad8\u5024\u3082\u3053\u308c\u3089\u306e\u30dd\u30a4\u30f3\u30c8\u304b\u3089\u53d6\u5f97\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002
+error.lookupsrtm.nonerequired=\u5168\u3066\u306e\u30dd\u30a4\u30f3\u30c8\u306f\u6a19\u9ad8\u5024\u3092\u6301\u3063\u3066\u3044\u308b\u305f\u3081\u3001\u691c\u7d22\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002
+error.gpsies.uploadnotok=Gpsies\u30b5\u30fc\u30d0\u30fc\u304c\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u8fd4\u3057\u307e\u3057\u305f\u3002
+error.gpsies.uploadfailed=\u30a8\u30e9\u30fc\u306e\u305f\u3081\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u306b\u5931\u6557\u3057\u307e\u3057\u305f
+error.playaudiofailed=\u30aa\u30fc\u30c7\u30a3\u30aa\u30d5\u30a1\u30a4\u30eb\u306e\u518d\u751f\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
index be9b40e0669226c3b91d701233c7d4fca40d28e6..68c5cd7910fe837cbfdba48a039cb9a7c9c6b6ea 100644 (file)
@@ -19,8 +19,8 @@ menu.range.all=\ubaa8\ub450 \uc120\ud0dd
 menu.range.none=\uc120\ud0dd\ud558\uc9c0 \uc54a\uae30
 menu.range.start=\uc2dc\uc791 \uc9c0\uc810\uc73c\ub85c \uc9c0\uc815
 menu.range.end=\ub05d\uc9c0\uc810\uc73c\ub85c \uc9c0\uc815
 menu.range.none=\uc120\ud0dd\ud558\uc9c0 \uc54a\uae30
 menu.range.start=\uc2dc\uc791 \uc9c0\uc810\uc73c\ub85c \uc9c0\uc815
 menu.range.end=\ub05d\uc9c0\uc810\uc73c\ub85c \uc9c0\uc815
-menu.range.deleterange=\uc5f0\uacb0\uc120 \uc0ad\uc81c
-menu.range.interpolate=\uc911\uac04\uc5d0 \ub123\uae30
+function.deleterange=\uc5f0\uacb0\uc120 \uc0ad\uc81c
+function.interpolate=\uc0bd\uc785\ud55c \uc9c0\uc810
 menu.range.average=\ud3c9\uade0\uc9c0\uc810\uc120\ud0dd
 menu.range.reverse=\ucc98\uc74c\uacfc \ub05d \ubc14\uafb8\uae30
 menu.range.mergetracksegments=\ud2b8\ub799 \ubd80\ubd84 \ubcd1\ud569
 menu.range.average=\ud3c9\uade0\uc9c0\uc810\uc120\ud0dd
 menu.range.reverse=\ucc98\uc74c\uacfc \ub05d \ubc14\uafb8\uae30
 menu.range.mergetracksegments=\ud2b8\ub799 \ubd80\ubd84 \ubcd1\ud569
@@ -212,7 +212,6 @@ dialog.confirmreversetrack.title=\ubc18\uc804\uc778\uc9c0 \ud655\uc778
 dialog.confirmreversetrack.text=\uc774 \ud2b8\ub799\uc740 \ubc18\uc804\ud6c4 \uc21c\uc11c\uac00 \ubc14\uafe8\uc744 \uc218\ub3c4 \uc788\ub294\uc2dc\uac04\uc815\ubcf4\ub97c \ud3ec\ud568\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4. /n \uadf8\ub798\ub3c4 \uc774\uc601\uc5ed\uc744 \ubc18\uc804\uc2dc\ud0a4\uc2dc\ub824\ub098\uc694?
 dialog.confirmcutandmove.title=\uc790\ub974\uace0 \uc62e\uae30\uae30 \ud655\uc778
 dialog.confirmcutandmove.text=\uc774 \ud2b8\ub799\uc740 \uc774\ub3d9\ud6c4 \uc21c\uc11c\uac00 \ubc14\uafe7\uc744 \uc218\ub3c4 \uc788\ub294 \uc2dc\uac04\uc815\ubcf4\ub97c \ud3ec\ud568\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4. /n \uadf8\ub798\ub3c4 \uc774 \uc601\uc5ed\uc744 \uc62e\uae30\uc2dc\ub824\ub098\uc694?
 dialog.confirmreversetrack.text=\uc774 \ud2b8\ub799\uc740 \ubc18\uc804\ud6c4 \uc21c\uc11c\uac00 \ubc14\uafe8\uc744 \uc218\ub3c4 \uc788\ub294\uc2dc\uac04\uc815\ubcf4\ub97c \ud3ec\ud568\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4. /n \uadf8\ub798\ub3c4 \uc774\uc601\uc5ed\uc744 \ubc18\uc804\uc2dc\ud0a4\uc2dc\ub824\ub098\uc694?
 dialog.confirmcutandmove.title=\uc790\ub974\uace0 \uc62e\uae30\uae30 \ud655\uc778
 dialog.confirmcutandmove.text=\uc774 \ud2b8\ub799\uc740 \uc774\ub3d9\ud6c4 \uc21c\uc11c\uac00 \ubc14\uafe7\uc744 \uc218\ub3c4 \uc788\ub294 \uc2dc\uac04\uc815\ubcf4\ub97c \ud3ec\ud568\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4. /n \uadf8\ub798\ub3c4 \uc774 \uc601\uc5ed\uc744 \uc62e\uae30\uc2dc\ub824\ub098\uc694?
-dialog.interpolate.title=\uc0bd\uc785\ud55c \uc9c0\uc810
 dialog.interpolate.parameter.text=\uc120\ud0dd\ud55c \uc9c0\uc810 \uc0ac\uc774\uc5d0 \ub123\uc744 \uc9c0\uc810\uc758 \uc218
 dialog.undo.title=\uc791\uc5c5 \ub418\ub3cc\ub9ac\uae30
 dialog.undo.pretext=\ub418\ub3cc\ub9b4 \uc791\uc5c5\uc744 \uc120\ud0dd\ud574\uc8fc\uc138\uc694
 dialog.interpolate.parameter.text=\uc120\ud0dd\ud55c \uc9c0\uc810 \uc0ac\uc774\uc5d0 \ub123\uc744 \uc9c0\uc810\uc758 \uc218
 dialog.undo.title=\uc791\uc5c5 \ub418\ub3cc\ub9ac\uae30
 dialog.undo.pretext=\ub418\ub3cc\ub9b4 \uc791\uc5c5\uc744 \uc120\ud0dd\ud574\uc8fc\uc138\uc694
@@ -230,7 +229,7 @@ dialog.pointedit.changevalue.title=\ud544\ub4dc \uc218\uc815
 dialog.pointnameedit.name=\uacbd\uc720\uc9c0 \uc774\ub984
 dialog.pointnameedit.uppercase=\ub300\ubb38\uc790\ub85c
 dialog.pointnameedit.lowercase=\uc18c\ubb38\uc790\ub85c
 dialog.pointnameedit.name=\uacbd\uc720\uc9c0 \uc774\ub984
 dialog.pointnameedit.uppercase=\ub300\ubb38\uc790\ub85c
 dialog.pointnameedit.lowercase=\uc18c\ubb38\uc790\ub85c
-dialog.pointnameedit.sentencecase=\uccab\uae00\uc790\ub9cc \ub300\ubb38\uc790\ub85c
+dialog.pointnameedit.titlecase=\uccab\uae00\uc790\ub9cc \ub300\ubb38\uc790\ub85c
 dialog.addtimeoffset.add=\uc2dc\uac04 \ucd94\uac00
 dialog.addtimeoffset.subtract=\uc2dc\uac04 \ube7c\uae30
 dialog.addtimeoffset.days=\uc77c
 dialog.addtimeoffset.add=\uc2dc\uac04 \ucd94\uac00
 dialog.addtimeoffset.subtract=\uc2dc\uac04 \ube7c\uae30
 dialog.addtimeoffset.days=\uc77c
@@ -333,7 +332,7 @@ dialog.rearrangephotos.toend=\ub05d\uc73c\ub85c
 dialog.rearrangephotos.nosort=\uc815\ub82c\ud558\uc9c0 \uc54a\uae30
 dialog.rearrangephotos.sortbyfilename=\ud30c\uc77c \uc774\ub984\uc73c\ub85c \uc815\ub82c
 dialog.rearrangephotos.sortbytime=\uc2dc\uac04\uc73c\ub85c \uc815\ub82c
 dialog.rearrangephotos.nosort=\uc815\ub82c\ud558\uc9c0 \uc54a\uae30
 dialog.rearrangephotos.sortbyfilename=\ud30c\uc77c \uc774\ub984\uc73c\ub85c \uc815\ub82c
 dialog.rearrangephotos.sortbytime=\uc2dc\uac04\uc73c\ub85c \uc815\ub82c
-dialog.compress.nonefound=\uc9c0\uc810 \ub370\uc774\ud130\uac00 \uc81c\uac70\ub420 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
+dialog.deletemarked.nonefound=\uc9c0\uc810 \ub370\uc774\ud130\uac00 \uc81c\uac70\ub420 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.
 dialog.compress.closepoints.title=\uc8fc\ubcc0 \ud3ec\uc778\ud2b8 \uc81c\uac70
 dialog.compress.closepoints.paramdesc=\ud655\uc7a5 \uacc4\uc218
 dialog.compress.wackypoints.title=\uc5c9\ub6b1\ud558\uac70\ub098 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uc9c0\uc810 \uc81c\uac70
 dialog.compress.closepoints.title=\uc8fc\ubcc0 \ud3ec\uc778\ud2b8 \uc81c\uac70
 dialog.compress.closepoints.paramdesc=\ud655\uc7a5 \uacc4\uc218
 dialog.compress.wackypoints.title=\uc5c9\ub6b1\ud558\uac70\ub098 \uc0ac\uc6a9\ud558\uc9c0 \uc54a\ub294 \uc9c0\uc810 \uc81c\uac70
@@ -397,7 +396,6 @@ dialog.saveconfig.prune.languagefile=\uc5b8\uc5b4\ud30c\uc77c
 dialog.saveconfig.prune.gpsdevice=GPS\uc7a5\uce58
 dialog.saveconfig.prune.gpsformat=GPS \ud615\uc2dd
 dialog.saveconfig.prune.povrayfont=Povray \uae00\uaf34
 dialog.saveconfig.prune.gpsdevice=GPS\uc7a5\uce58
 dialog.saveconfig.prune.gpsformat=GPS \ud615\uc2dd
 dialog.saveconfig.prune.povrayfont=Povray \uae00\uaf34
-dialog.saveconfig.prune.metricunits=\ubbf8\ud130\ubc95 \ub2e8\uc704\ub97c \uc0ac\uc6a9\ud558\uc2dc\ub098\uc694?
 dialog.saveconfig.prune.gnuplotpath=gnjuplot \uacbd\ub85c
 dialog.saveconfig.prune.gpsbabelpath=gpsbabel \uacbd\ub85c
 dialog.saveconfig.prune.exiftoolpath=exiftool \uacbd\ub85c
 dialog.saveconfig.prune.gnuplotpath=gnjuplot \uacbd\ub85c
 dialog.saveconfig.prune.gpsbabelpath=gpsbabel \uacbd\ub85c
 dialog.saveconfig.prune.exiftoolpath=exiftool \uacbd\ub85c
@@ -556,7 +554,6 @@ display.range.time.mins=\ubd84
 display.range.time.hours=\uc2dc\uac04
 display.range.time.days=\uc77c
 details.range.avespeed=\ud3c9\uade0 \uc18d\ub3c4
 display.range.time.hours=\uc2dc\uac04
 display.range.time.days=\uc77c
 details.range.avespeed=\ud3c9\uade0 \uc18d\ub3c4
-details.range.avemovingspeed=\ud3c9\uade0 \uc774\ub3d9
 details.range.maxspeed=\ucd5c\uace0 \uc18d\ub3c4
 details.range.numsegments=\ubd80\ubd84\ub4e4\uc758 \uc218
 details.range.pace=\ud398\uc774\uc2a4(1km\ub098 1mile\uc774\ub3d9 \uc2dc\uac04)
 details.range.maxspeed=\ucd5c\uace0 \uc18d\ub3c4
 details.range.numsegments=\ubd80\ubd84\ub4e4\uc758 \uc218
 details.range.pace=\ud398\uc774\uc2a4(1km\ub098 1mile\uc774\ub3d9 \uc2dc\uac04)
@@ -600,12 +597,12 @@ units.feet=\ud53c\ud2b8
 units.feet.short=\ud53c\ud2b8
 units.kilometres=\ud0ac\ub85c\ubbf8\ud130
 units.kilometres.short=\ud0ac\ub85c\ubbf8\ud130
 units.feet.short=\ud53c\ud2b8
 units.kilometres=\ud0ac\ub85c\ubbf8\ud130
 units.kilometres.short=\ud0ac\ub85c\ubbf8\ud130
-units.kmh=\ud0ac\ub85c\ubbf8\ud130-\uc2dc\uc18d
+units.kilometresperhour.short=\ud0ac\ub85c\ubbf8\ud130-\uc2dc\uc18d
 units.miles=\ub9c8\uc77c
 units.miles.short=\ub9c8\uc77c
 units.miles=\ub9c8\uc77c
 units.miles.short=\ub9c8\uc77c
-units.mph=\ub9c8\uc77c-\uc2dc\uc18d
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.milesperhour.short=\ub9c8\uc77c-\uc2dc\uc18d
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=\uc2dc\uac04
 units.degminsec=\ub3c4-\ubd84-\ucd08
 units.degmin=\ub3c4-\ubd84
 units.hours=\uc2dc\uac04
 units.degminsec=\ub3c4-\ubd84-\ucd08
 units.degmin=\ub3c4-\ubd84
@@ -631,7 +628,7 @@ undo.deletepoint=\uc9c0\uc810 \uc0ad\uc81c
 undo.removephoto=\uc0ac\uc9c4 \uc81c\uac70
 undo.removeaudio=\uc18c\ub9ac\ud30c\uc77c \uc81c\uac70
 undo.deleterange=\ubc94\uc704 \uc0ad\uc81c
 undo.removephoto=\uc0ac\uc9c4 \uc81c\uac70
 undo.removeaudio=\uc18c\ub9ac\ud30c\uc77c \uc81c\uac70
 undo.deleterange=\ubc94\uc704 \uc0ad\uc81c
-undo.compress=\ud2b8\ub799 \uc555\ucd95
+undo.deletemarked=\ud2b8\ub799 \uc555\ucd95
 undo.insert=\uc9c0\uc810\ub4e4 \uc0bd\uc785
 undo.reverse=\ubc94\uc704 \ubc18\uc804
 undo.mergetracksegments=\ud2b8\ub799 \ubd80\ubd84 \ubcd1\ud569
 undo.insert=\uc9c0\uc810\ub4e4 \uc0bd\uc785
 undo.reverse=\ubc94\uc704 \ubc18\uc804
 undo.mergetracksegments=\ud2b8\ub799 \ubd80\ubd84 \ubcd1\ud569
index 6b92a569691076d2ee9de0f2e85ab31cbc16be7f..5a75c2aac89438ac98a6d2f8bcea647f4a44a4d9 100644 (file)
@@ -10,6 +10,7 @@ menu.file.exit=Afsluiten
 menu.track=Route
 menu.track.undo=Ongedaan maken
 menu.track.clearundo=Ongedaan-maken lijst wissen
 menu.track=Route
 menu.track.undo=Ongedaan maken
 menu.track.clearundo=Ongedaan-maken lijst wissen
+menu.track.markrectangle=Makeer alle punten in een vierkant
 menu.track.deletemarked=Verwijderen gemarkeerde punten
 menu.track.rearrange=Rangschikken waypoints
 menu.track.rearrange.start=Alles naar begin route
 menu.track.deletemarked=Verwijderen gemarkeerde punten
 menu.track.rearrange=Rangschikken waypoints
 menu.track.rearrange.start=Alles naar begin route
@@ -20,8 +21,6 @@ menu.range.all=Selecteer alles
 menu.range.none=Selecteer geen
 menu.range.start=Start van reeks
 menu.range.end=Einde van reeks
 menu.range.none=Selecteer geen
 menu.range.start=Start van reeks
 menu.range.end=Einde van reeks
-menu.range.deleterange=Verwijder reeks
-menu.range.interpolate=Interpoleren
 menu.range.average=Cre\u00eber punt obv gemiddelde van reeks
 menu.range.reverse=Reeks omkeren
 menu.range.mergetracksegments=Samenvoegen route segmenten
 menu.range.average=Cre\u00eber punt obv gemiddelde van reeks
 menu.range.reverse=Reeks omkeren
 menu.range.mergetracksegments=Samenvoegen route segmenten
@@ -54,6 +53,7 @@ menu.map.connect=Verbind route punten
 menu.map.autopan=Autopan
 menu.map.showmap=Toon kaart
 menu.map.showscalebar=Toon schaal
 menu.map.autopan=Autopan
 menu.map.showmap=Toon kaart
 menu.map.showscalebar=Toon schaal
+menu.map.editmode=Wijzigen
 
 # Alt keys for menus
 altkey.menu.file=F
 
 # Alt keys for menus
 altkey.menu.file=F
@@ -86,6 +86,9 @@ function.exportpov=Export POV
 function.exportsvg=Export SVG
 function.editwaypointname=Hernoem waypoint
 function.compress=Route comprimeren
 function.exportsvg=Export SVG
 function.editwaypointname=Hernoem waypoint
 function.compress=Route comprimeren
+function.deleterange=Verwijder reeks
+function.croptrack=Route bijknippen
+function.interpolate=Interpoleer punten
 function.addtimeoffset=Tijdsverschil toevoegen
 function.addaltitudeoffset=Hoogteverschil toevoegen
 function.convertnamestotimes=Converteer waypointnamen naar tijden
 function.addtimeoffset=Tijdsverschil toevoegen
 function.addaltitudeoffset=Hoogteverschil toevoegen
 function.convertnamestotimes=Converteer waypointnamen naar tijden
@@ -140,6 +143,7 @@ dialog.deletepoint.title=Verwijder punt
 dialog.deletepoint.deletephoto=Wilt u de foto die aan dit punt is gekoppeld verwijderen?
 dialog.deletephoto.title=Verwijder foto
 dialog.deletephoto.deletepoint=Wilt u het punt dat aan deze foto is gekoppeld verwijderen?
 dialog.deletepoint.deletephoto=Wilt u de foto die aan dit punt is gekoppeld verwijderen?
 dialog.deletephoto.title=Verwijder foto
 dialog.deletephoto.deletepoint=Wilt u het punt dat aan deze foto is gekoppeld verwijderen?
+dialog.deleteaudio.deletepoint=Wilt u het punt dat aan dit geluidsbestand is gekoppeld verwijderen?
 dialog.openoptions.title=Instellingen openen
 dialog.openoptions.filesnippet=Samenvatting van bestand
 dialog.load.table.field=Veld
 dialog.openoptions.title=Instellingen openen
 dialog.openoptions.filesnippet=Samenvatting van bestand
 dialog.load.table.field=Veld
@@ -219,8 +223,8 @@ dialog.confirmreversetrack.title=Bevestig omkering
 dialog.confirmreversetrack.text=Deze route bevat tijd-informatie die niet meer klopt na een omkering.\nWeet u zeker dat u deze sectie wilt omkeren?
 dialog.confirmcutandmove.title=Bevestig knip en verplaats
 dialog.confirmcutandmove.text=Deze route bevat tijd-informatie die niet meer klopt na een verplaatsing.\nWeet u zeker dat u de sectie wilt verplaatsen?
 dialog.confirmreversetrack.text=Deze route bevat tijd-informatie die niet meer klopt na een omkering.\nWeet u zeker dat u deze sectie wilt omkeren?
 dialog.confirmcutandmove.title=Bevestig knip en verplaats
 dialog.confirmcutandmove.text=Deze route bevat tijd-informatie die niet meer klopt na een verplaatsing.\nWeet u zeker dat u de sectie wilt verplaatsen?
-dialog.interpolate.title=Interpoleer punten
 dialog.interpolate.parameter.text=Aantal punten om in te voegen tussen de geselecteerde punten
 dialog.interpolate.parameter.text=Aantal punten om in te voegen tussen de geselecteerde punten
+dialog.interpolate.betweenwaypoints=Interpoleren tussen waypoints?
 dialog.undo.title=Actie(s) ongedaan maken
 dialog.undo.pretext=Selecteer de acties die u ongedaan wilt maken.
 dialog.undo.none.title=Kan niet ongedaan gemaakt worden.
 dialog.undo.title=Actie(s) ongedaan maken
 dialog.undo.pretext=Selecteer de acties die u ongedaan wilt maken.
 dialog.undo.none.title=Kan niet ongedaan gemaakt worden.
@@ -237,7 +241,7 @@ dialog.pointedit.changevalue.title=Wijzig veld
 dialog.pointnameedit.name=Naam van het waypoint
 dialog.pointnameedit.uppercase=HOOFDLETTERS
 dialog.pointnameedit.lowercase=kleine letters
 dialog.pointnameedit.name=Naam van het waypoint
 dialog.pointnameedit.uppercase=HOOFDLETTERS
 dialog.pointnameedit.lowercase=kleine letters
-dialog.pointnameedit.sentencecase=Ieder woord begint met hoofdletter
+dialog.pointnameedit.titlecase=Ieder woord begint met hoofdletter
 dialog.addtimeoffset.add=Tijd toevoegen
 dialog.addtimeoffset.subtract=Tijd aftrekken
 dialog.addtimeoffset.days=Dagen
 dialog.addtimeoffset.add=Tijd toevoegen
 dialog.addtimeoffset.subtract=Tijd aftrekken
 dialog.addtimeoffset.days=Dagen
@@ -273,6 +277,8 @@ dialog.distances.column.to=Naar punt
 dialog.distances.currentpoint=Huidige punt
 dialog.distances.toofewpoints=Deze functie heeft waypoints nodig om de afstand ertussen te berekenen
 dialog.fullrangedetails.intro=Dit zijn de details van de geselecteerde reeks
 dialog.distances.currentpoint=Huidige punt
 dialog.distances.toofewpoints=Deze functie heeft waypoints nodig om de afstand ertussen te berekenen
 dialog.fullrangedetails.intro=Dit zijn de details van de geselecteerde reeks
+dialog.fullrangedetails.coltotal=Inclusief hiaten
+dialog.fullrangedetails.colsegments=Zonder hiaten
 dialog.setmapbg.intro=Selecteer een kaart-bron, of voeg een nieuwe bron toe.
 dialog.addmapsource.title=Nieuwe kaart-bron toevoegen
 dialog.addmapsource.sourcename=Naam van de bron
 dialog.setmapbg.intro=Selecteer een kaart-bron, of voeg een nieuwe bron toe.
 dialog.addmapsource.title=Nieuwe kaart-bron toevoegen
 dialog.addmapsource.sourcename=Naam van de bron
@@ -303,6 +309,7 @@ dialog.wikipedia.column.name=Artikelnaam
 dialog.wikipedia.column.distance=Afstand
 dialog.correlate.notimestamps=Er zit geen tijdinformatie in de punten, dus kunnen ze niet aan foto's gekoppeld worden.
 dialog.correlate.nouncorrelatedphotos=Er zijn geen ongekoppelde foto's.\nWeet u zeker dat u wilt doorgaan?
 dialog.wikipedia.column.distance=Afstand
 dialog.correlate.notimestamps=Er zit geen tijdinformatie in de punten, dus kunnen ze niet aan foto's gekoppeld worden.
 dialog.correlate.nouncorrelatedphotos=Er zijn geen ongekoppelde foto's.\nWeet u zeker dat u wilt doorgaan?
+dialog.correlate.nouncorrelatedaudios=Er zijn geen ongekoppelde geluidsbestanden.\nWeet u zeker dat u wilt doorgaan?
 dialog.correlate.photoselect.intro=Selecteer \u00e9\u00e9n van deze gekoppelde foto's om het tijdsverschil te gebruiken
 dialog.correlate.select.photoname=Fotonaam
 dialog.correlate.select.timediff=Tijdsverschil
 dialog.correlate.photoselect.intro=Selecteer \u00e9\u00e9n van deze gekoppelde foto's om het tijdsverschil te gebruiken
 dialog.correlate.select.photoname=Fotonaam
 dialog.correlate.select.timediff=Tijdsverschil
@@ -340,7 +347,6 @@ dialog.rearrangephotos.toend=Naar einde
 dialog.rearrangephotos.nosort=Niet sorteren
 dialog.rearrangephotos.sortbyfilename=Sorteren op bestandsnaam
 dialog.rearrangephotos.sortbytime=Sorteren op tijd
 dialog.rearrangephotos.nosort=Niet sorteren
 dialog.rearrangephotos.sortbyfilename=Sorteren op bestandsnaam
 dialog.rearrangephotos.sortbytime=Sorteren op tijd
-dialog.compress.nonefound=Er konden geen punten verwijderd worden
 dialog.compress.closepoints.title=Verwijder nabijliggende punten
 dialog.compress.closepoints.paramdesc=Bereik
 dialog.compress.wackypoints.title=Vreemde punten verwijderen
 dialog.compress.closepoints.title=Verwijder nabijliggende punten
 dialog.compress.closepoints.paramdesc=Bereik
 dialog.compress.wackypoints.title=Vreemde punten verwijderen
@@ -351,6 +357,10 @@ dialog.compress.duplicates.title=Verwijderen duplicaten
 dialog.compress.douglaspeucker.title=Douglas-Peucker compressie
 dialog.compress.douglaspeucker.paramdesc=Span factor
 dialog.compress.summarylabel=Te verwijderen punten
 dialog.compress.douglaspeucker.title=Douglas-Peucker compressie
 dialog.compress.douglaspeucker.paramdesc=Span factor
 dialog.compress.summarylabel=Te verwijderen punten
+dialog.compress.confirm1=Er zijn
+dialog.compress.confirm2=punten zijn gemarkeerd.\nGebruik Track - Verwijder gemarkeerde punten om ze te verwijderen
+dialog.compress.confirmnone=er zijn geen punten gemarkeerd
+dialog.deletemarked.nonefound=Er konden geen punten verwijderd worden
 dialog.pastecoordinates.desc=Geef co\u00f6rdinaten in
 dialog.pastecoordinates.coords=Co\u00f6rdinaten
 dialog.pastecoordinates.nothingfound=Controleer de co\u00f6rdinaten en probeer het nogmaals
 dialog.pastecoordinates.desc=Geef co\u00f6rdinaten in
 dialog.pastecoordinates.coords=Co\u00f6rdinaten
 dialog.pastecoordinates.nothingfound=Controleer de co\u00f6rdinaten en probeer het nogmaals
@@ -406,7 +416,6 @@ dialog.saveconfig.prune.languagefile=Taal bestand
 dialog.saveconfig.prune.gpsdevice=GPS apparaat
 dialog.saveconfig.prune.gpsformat=GPS formaat
 dialog.saveconfig.prune.povrayfont=Povray lettertype
 dialog.saveconfig.prune.gpsdevice=GPS apparaat
 dialog.saveconfig.prune.gpsformat=GPS formaat
 dialog.saveconfig.prune.povrayfont=Povray lettertype
-dialog.saveconfig.prune.metricunits=Metrisch systeem gebruiken?
 dialog.saveconfig.prune.gnuplotpath=Pad naar gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Pad naar gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Pad naar exiftool
 dialog.saveconfig.prune.gnuplotpath=Pad naar gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Pad naar gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Pad naar exiftool
@@ -447,6 +456,7 @@ dialog.diskcache.save=Kaartafbeeldingen opslaan op schijf
 dialog.diskcache.dir=Cache map
 dialog.diskcache.createdir=Cre\u00eber map
 dialog.diskcache.nocreate=Cache map niet aangemaakt
 dialog.diskcache.dir=Cache map
 dialog.diskcache.createdir=Cre\u00eber map
 dialog.diskcache.nocreate=Cache map niet aangemaakt
+dialog.diskcache.cannotwrite=Kaarttegels kunnen niet in de geselecteerde map worden opgeslagen
 dialog.diskcache.table.path=Pad
 dialog.diskcache.table.usedby=Gebruikt door
 dialog.diskcache.table.zoom=Zoom
 dialog.diskcache.table.path=Pad
 dialog.diskcache.table.usedby=Gebruikt door
 dialog.diskcache.table.zoom=Zoom
@@ -460,6 +470,7 @@ dialog.diskcache.deleteall=Verwijder alle tegels
 dialog.diskcache.deleted1=
 dialog.diskcache.deleted2=bestanden uit de cache verwijderd
 dialog.deletefieldvalues.intro=Selecteer het te verwijderen veld voor de huidige reeks
 dialog.diskcache.deleted1=
 dialog.diskcache.deleted2=bestanden uit de cache verwijderd
 dialog.deletefieldvalues.intro=Selecteer het te verwijderen veld voor de huidige reeks
+dialog.deletefieldvalues.nofields=Er zijn geen velden in deze reeks om te verwijderen
 dialog.setlinewidth.text=Geef lijndikte voor routes (1-4)
 dialog.downloadosm.desc=Bevestig het downloaden van ruwe OSM data voor dit gebied:
 dialog.searchwikipedianames.search=Zoeken naar:
 dialog.setlinewidth.text=Geef lijndikte voor routes (1-4)
 dialog.downloadosm.desc=Bevestig het downloaden van ruwe OSM data voor dit gebied:
 dialog.searchwikipedianames.search=Zoeken naar:
@@ -485,6 +496,7 @@ confirm.addaltitudeoffset=Hoogteverschil toegevoegd
 confirm.rearrangewaypoints=Waypoints herschikt
 confirm.rearrangephotos=Foto herschikt
 confirm.cutandmove=Selectie verplaatst
 confirm.rearrangewaypoints=Waypoints herschikt
 confirm.rearrangephotos=Foto herschikt
 confirm.cutandmove=Selectie verplaatst
+confirm.interpolate=Punten toegevoegd
 confirm.convertnamestotimes=Namen waypoint geconverteerd
 confirm.saveexif.ok1=Opgeslagen
 confirm.saveexif.ok2=foto bestanden
 confirm.convertnamestotimes=Namen waypoint geconverteerd
 confirm.saveexif.ok1=Opgeslagen
 confirm.saveexif.ok2=foto bestanden
@@ -580,7 +592,6 @@ display.range.time.mins=m
 display.range.time.hours=u
 display.range.time.days=d
 details.range.avespeed=Gem snelheid
 display.range.time.hours=u
 display.range.time.days=d
 details.range.avespeed=Gem snelheid
-details.range.avemovingspeed=Gem snelheid in beweging
 details.range.maxspeed=Max snelheid
 details.range.numsegments=Aantal segmenten
 details.range.pace=Tempo
 details.range.maxspeed=Max snelheid
 details.range.numsegments=Aantal segmenten
 details.range.pace=Tempo
@@ -593,6 +604,7 @@ details.nophoto=Geen foto geselecteerd
 details.photo.loading=Bezig met laden
 details.photo.bearing=Richting
 details.media.connected=Geconnecteerd
 details.photo.loading=Bezig met laden
 details.photo.bearing=Richting
 details.media.connected=Geconnecteerd
+details.media.fullpath=Volledig pad
 details.audiodetails=Audio details
 details.noaudio=Geen audiobestand geselecteerd
 details.audio.file=Audiobestand
 details.audiodetails=Audio details
 details.noaudio=Geen audiobestand geselecteerd
 details.audio.file=Audiobestand
@@ -626,12 +638,15 @@ units.feet=Voet
 units.feet.short=ft
 units.kilometres=Kilometers
 units.kilometres.short=km
 units.feet.short=ft
 units.kilometres=Kilometers
 units.kilometres.short=km
-units.kmh=km/u
+units.kilometresperhour.short=km/u
 units.miles=Mijlen
 units.miles.short=mi
 units.miles=Mijlen
 units.miles.short=mi
-units.mph=mph
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.milesperhour.short=mph
+units.nauticalmiles=Nautische mijlen
+units.nauticalmiles.short=N.m.
+units.nauticalmilesperhour.short=Kn
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=uren
 units.degminsec=Grd-min-sec
 units.degmin=Grd-min
 units.hours=uren
 units.degminsec=Grd-min-sec
 units.degmin=Grd-min
@@ -657,14 +672,15 @@ undo.deletepoint=verwijderen punt
 undo.removephoto=verwijderen foto
 undo.removeaudio=verwijderen audiobestand
 undo.deleterange=verwijderen reeks
 undo.removephoto=verwijderen foto
 undo.removeaudio=verwijderen audiobestand
 undo.deleterange=verwijderen reeks
-undo.compress=comprimeren route
+undo.croptrack=bijknippen track
+undo.deletemarked=verwijderen punten
 undo.insert=punten invoegen
 undo.reverse=reeks omkeren
 undo.mergetracksegments=samenvoegen route segmenten
 undo.addtimeoffset=tijdsverschil toevoegen
 undo.addaltitudeoffset=hoogteverschil toevoegen
 undo.rearrangewaypoints=herschikken waypoint
 undo.insert=punten invoegen
 undo.reverse=reeks omkeren
 undo.mergetracksegments=samenvoegen route segmenten
 undo.addtimeoffset=tijdsverschil toevoegen
 undo.addaltitudeoffset=hoogteverschil toevoegen
 undo.rearrangewaypoints=herschikken waypoint
-undo.cutandmove=Verschuif sectie
+undo.cutandmove=verschuif sectie
 undo.connect=koppel
 undo.disconnect=loskoppelen
 undo.correlatephotos=correleer foto
 undo.connect=koppel
 undo.disconnect=loskoppelen
 undo.correlatephotos=correleer foto
@@ -705,7 +721,7 @@ error.undofailed.text=Kon actie niet terugdraaien
 error.function.noop.title=Functie had geen effect
 error.rearrange.noop=Herschikken van punten had geen effect
 error.function.notavailable.title=Functie niet beschikbaar
 error.function.noop.title=Functie had geen effect
 error.rearrange.noop=Herschikken van punten had geen effect
 error.function.notavailable.title=Functie niet beschikbaar
-error.function.nojava3d=Deze functie heeft Java3d nodig,verkrijgbaar bij sun.com.
+error.function.nojava3d=Deze functie heeft Java3d nodig,\nverkrijgbaar bij sun.com.
 error.3d=Er is een fout opgetreden bij de 3d afbeelding
 error.readme.notfound=Leesmij bestand niet gevonden
 error.osmimage.dialogtitle=Fout bij inlezen kaart afbeeldingen
 error.3d=Er is een fout opgetreden bij de 3d afbeelding
 error.readme.notfound=Leesmij bestand niet gevonden
 error.osmimage.dialogtitle=Fout bij inlezen kaart afbeeldingen
@@ -716,7 +732,9 @@ error.lookupsrtm.nonefound=Geen hoogtewaarden beschikbaar voor deze punten
 error.lookupsrtm.nonerequired=Alle punten hebben reeds hoogte, er hoeft niets te worden opgezocht.
 error.gpsies.uploadnotok=Gpsies server antwoordde met
 error.gpsies.uploadfailed=De upload is mislukt. Fout
 error.lookupsrtm.nonerequired=Alle punten hebben reeds hoogte, er hoeft niets te worden opgezocht.
 error.gpsies.uploadnotok=Gpsies server antwoordde met
 error.gpsies.uploadfailed=De upload is mislukt. Fout
+error.showphoto.failed=Foto laden mislukt
 error.playaudiofailed=Kon audiobestand niet afspelen
 error.cache.notthere=De tegelcache map niet gevonden
 error.cache.empty=De tegelcache map is leeg
 error.cache.cannotdelete=Er konden geen tegels verwijderd worden
 error.playaudiofailed=Kon audiobestand niet afspelen
 error.cache.notthere=De tegelcache map niet gevonden
 error.cache.empty=De tegelcache map is leeg
 error.cache.cannotdelete=Er konden geen tegels verwijderd worden
+error.interpolate.invalidparameter=Aantal punten moet tussen 1 en 1000 liggen
index f76d7af6164373b02400b82a4b2aa0159d451081..f58c8022a9b3722a5fdb71ae5ff55d43d4931a1c 100644 (file)
@@ -10,6 +10,7 @@ menu.file.exit=Zako\u0144cz
 menu.track=\u015acie\u017cka
 menu.track.undo=Cofnij
 menu.track.clearundo=Wyczy\u015b\u0107 list\u0119 zmian
 menu.track=\u015acie\u017cka
 menu.track.undo=Cofnij
 menu.track.clearundo=Wyczy\u015b\u0107 list\u0119 zmian
+menu.track.markrectangle=Zaznaczenie prostok\u0105tne
 menu.track.deletemarked=Usu\u0144 zaznaczone punkty
 menu.track.rearrange=Zmie\u0144 kolejno\u015b\u0107 punkt\u00f3w po\u015brednich
 menu.track.rearrange.start=Wszystkie na pocz\u0105tek \u015bcie\u017cki
 menu.track.deletemarked=Usu\u0144 zaznaczone punkty
 menu.track.rearrange=Zmie\u0144 kolejno\u015b\u0107 punkt\u00f3w po\u015brednich
 menu.track.rearrange.start=Wszystkie na pocz\u0105tek \u015bcie\u017cki
@@ -20,8 +21,6 @@ menu.range.all=Zaznacz wszystko
 menu.range.none=Usu\u0144 zaznaczenie
 menu.range.start=Zaznacz pocz\u0105tek zakresu
 menu.range.end=Zaznacz koniec zakresu
 menu.range.none=Usu\u0144 zaznaczenie
 menu.range.start=Zaznacz pocz\u0105tek zakresu
 menu.range.end=Zaznacz koniec zakresu
-menu.range.deleterange=Usu\u0144 zakres
-menu.range.interpolate=Wstaw pomi\u0119dzy
 menu.range.average=U\u015brednij zaznaczenie
 menu.range.reverse=Odwr\u00f3\u0107 zakres
 menu.range.mergetracksegments=Po\u0142\u0105cz fragmenty \u015bcie\u017cek
 menu.range.average=U\u015brednij zaznaczenie
 menu.range.reverse=Odwr\u00f3\u0107 zakres
 menu.range.mergetracksegments=Po\u0142\u0105cz fragmenty \u015bcie\u017cek
@@ -54,6 +53,7 @@ menu.map.connect=Po\u0142\u0105cz punkty \u015bcie\u017cki
 menu.map.autopan=Przesuwanie mapy
 menu.map.showmap=Poka\u017c map\u0119
 menu.map.showscalebar=Poka\u017c skal\u0119
 menu.map.autopan=Przesuwanie mapy
 menu.map.showmap=Poka\u017c map\u0119
 menu.map.showscalebar=Poka\u017c skal\u0119
+menu.map.editmode=Tryb edycji
 
 # Alt keys for menus
 altkey.menu.file=P
 
 # Alt keys for menus
 altkey.menu.file=P
@@ -86,6 +86,9 @@ function.exportpov=Eksportuj jako POV
 function.exportsvg=Eksportuj jako SVG
 function.editwaypointname=Zmie\u0144 nazw\u0119 punktu po\u015bredniego
 function.compress=Kompresuj \u015bcie\u017ck\u0119
 function.exportsvg=Eksportuj jako SVG
 function.editwaypointname=Zmie\u0144 nazw\u0119 punktu po\u015bredniego
 function.compress=Kompresuj \u015bcie\u017ck\u0119
+function.deleterange=Usu\u0144 zakres
+function.croptrack=Przytnij \u015bcie\u017ck\u0119
+function.interpolate=Wstaw pomi\u0119dzy punkty
 function.addtimeoffset=Dodaj przesuni\u0119cie czasu
 function.addaltitudeoffset=Dodaj przesuni\u0119cie wysoko\u015bci
 function.convertnamestotimes=Zamie\u0144 nazwy punkt\u00f3w na czas
 function.addtimeoffset=Dodaj przesuni\u0119cie czasu
 function.addaltitudeoffset=Dodaj przesuni\u0119cie wysoko\u015bci
 function.convertnamestotimes=Zamie\u0144 nazwy punkt\u00f3w na czas
@@ -140,6 +143,7 @@ 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.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.deleteaudio.deletepoint=Usun\u0105\u0107 punkt do\u0142\u0105czony do tego pliku audio?
 dialog.openoptions.title=Otw\u00f3rz opcje
 dialog.openoptions.filesnippet=Fragment z pliku
 dialog.load.table.field=Pole
 dialog.openoptions.title=Otw\u00f3rz opcje
 dialog.openoptions.filesnippet=Fragment z pliku
 dialog.load.table.field=Pole
@@ -219,8 +223,8 @@ 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.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.interpolate.parameter.text=Ilo\u015b\u0107 punkt\u00f3w do wstawienia pomi\u0119dzy wybrane punkty
+dialog.interpolate.betweenwaypoints=Wstawi\u0107 pomi\u0119dzy punkty po\u015brednie?
 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.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
@@ -237,7 +241,7 @@ dialog.pointedit.changevalue.title=Edytuj pole
 dialog.pointnameedit.name=Nazwa punktu po\u015bredniego
 dialog.pointnameedit.uppercase=WIELKIE litery
 dialog.pointnameedit.lowercase=ma\u0142e litery
 dialog.pointnameedit.name=Nazwa punktu po\u015bredniego
 dialog.pointnameedit.uppercase=WIELKIE litery
 dialog.pointnameedit.lowercase=ma\u0142e litery
-dialog.pointnameedit.sentencecase=Jak W Zdaniu
+dialog.pointnameedit.titlecase=Jak W Zdaniu
 dialog.addtimeoffset.add=Dodaj czas
 dialog.addtimeoffset.subtract=Odejmij czas
 dialog.addtimeoffset.days=Dni
 dialog.addtimeoffset.add=Dodaj czas
 dialog.addtimeoffset.subtract=Odejmij czas
 dialog.addtimeoffset.days=Dni
@@ -273,6 +277,8 @@ 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 mo\u017cna by\u0142o obliczy\u0107 odleg\u0142o\u015bci
 dialog.fullrangedetails.intro=Szczeg\u00f3\u0142y wybranego zakresu
 dialog.distances.currentpoint=Wybrany punkt
 dialog.distances.toofewpoints=Ta funkcja wymaga przynajmniej dw\u00f3ch punkt\u00f3w po\u015brednich, aby mo\u017cna by\u0142o obliczy\u0107 odleg\u0142o\u015bci
 dialog.fullrangedetails.intro=Szczeg\u00f3\u0142y wybranego zakresu
+dialog.fullrangedetails.coltotal=Z lukami
+dialog.fullrangedetails.colsegments=Bez luk
 dialog.setmapbg.intro=Wybierz dostawc\u0119 map t\u0142a lub dodaj nowego
 dialog.addmapsource.title=Dodaj dostawc\u0119 map
 dialog.addmapsource.sourcename=Nazwa dostawcy
 dialog.setmapbg.intro=Wybierz dostawc\u0119 map t\u0142a lub dodaj nowego
 dialog.addmapsource.title=Dodaj dostawc\u0119 map
 dialog.addmapsource.sourcename=Nazwa dostawcy
@@ -303,6 +309,7 @@ dialog.wikipedia.column.name=Tytu\u0142 artyku\u0142u
 dialog.wikipedia.column.distance=Odleg\u0142o\u015b\u0107
 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.wikipedia.column.distance=Odleg\u0142o\u015b\u0107
 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.nouncorrelatedaudios=Nie ma nie powi\u0105zanych plik\u00f3w audio.\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.select.photoname=Nazwa zdj\u0119cia
 dialog.correlate.select.timediff=R\u00f3\u017cnica czasowa
 dialog.correlate.photoselect.intro=Wybierz jedno z powi\u0105zanych zdj\u0119\u0107 i u\u017cyj go jako wzorca do przesuni\u0119cia czasu
 dialog.correlate.select.photoname=Nazwa zdj\u0119cia
 dialog.correlate.select.timediff=R\u00f3\u017cnica czasowa
@@ -340,7 +347,6 @@ dialog.rearrangephotos.toend=Przesu\u0144 na koniec
 dialog.rearrangephotos.nosort=Nie sortuj
 dialog.rearrangephotos.sortbyfilename=Sortuj po nazwie pliku
 dialog.rearrangephotos.sortbytime=Sortuj wed\u0142ug czasu
 dialog.rearrangephotos.nosort=Nie sortuj
 dialog.rearrangephotos.sortbyfilename=Sortuj po nazwie pliku
 dialog.rearrangephotos.sortbytime=Sortuj wed\u0142ug czasu
-dialog.compress.nonefound=Nie mo\u017cna usun\u0105\u0107 \u017cadnych punkt\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.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
@@ -351,6 +357,10 @@ dialog.compress.duplicates.title=Usuwanie duplikat\u00f3w
 dialog.compress.douglaspeucker.title=kompresja Douglasa-Peuckera
 dialog.compress.douglaspeucker.paramdesc=wsp\u00f3\u0142czynnik rozpi\u0119to\u015bci (szeroko\u015bci korytarza)
 dialog.compress.summarylabel=Punkty do usuni\u0119cia
 dialog.compress.douglaspeucker.title=kompresja Douglasa-Peuckera
 dialog.compress.douglaspeucker.paramdesc=wsp\u00f3\u0142czynnik rozpi\u0119to\u015bci (szeroko\u015bci korytarza)
 dialog.compress.summarylabel=Punkty do usuni\u0119cia
+dialog.compress.confirm1=
+dialog.compress.confirm2=punkt\u00f3w zosta\u0142o zaznaczonych\nU\u017cyj \u015acie\u017cka->Usu\u0144 zaznaczone punkty, by je usun\u0105\u0107
+dialog.compress.confirmnone=\u017cadne punkty nie zosta\u0142y zaznaczone
+dialog.deletemarked.nonefound=Nie mo\u017cna usun\u0105\u0107 \u017cadnych punkt\u00f3w
 dialog.pastecoordinates.desc=Wprowad\u017a lub wklej wsp\u00f3\u0142rz\u0119dne
 dialog.pastecoordinates.coords=Wsp\u00f3\u0142rz\u0119dne
 dialog.pastecoordinates.nothingfound=Sprawd\u017a wsp\u00f3\u0142rz\u0119dne i spr\u00f3buj jeszcze raz
 dialog.pastecoordinates.desc=Wprowad\u017a lub wklej wsp\u00f3\u0142rz\u0119dne
 dialog.pastecoordinates.coords=Wsp\u00f3\u0142rz\u0119dne
 dialog.pastecoordinates.nothingfound=Sprawd\u017a wsp\u00f3\u0142rz\u0119dne i spr\u00f3buj jeszcze raz
@@ -406,7 +416,6 @@ dialog.saveconfig.prune.languagefile=Plik t\u0142umaczenia
 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.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.gnuplotpath=\u015bcie\u017cka do gnuplot
 dialog.saveconfig.prune.gpsbabelpath=\u015bcie\u017cka do gpsbabel
 dialog.saveconfig.prune.exiftoolpath=\u015bcie\u017cka do exiftool
@@ -447,6 +456,7 @@ dialog.diskcache.save=Zapisz mapy na dysk
 dialog.diskcache.dir=katalog pami\u0119ci podr\u0119cznej
 dialog.diskcache.createdir=stw\u00f3rz katalog
 dialog.diskcache.nocreate=Nie utworzono katalogu pami\u0119ci podr\u0119cznej
 dialog.diskcache.dir=katalog pami\u0119ci podr\u0119cznej
 dialog.diskcache.createdir=stw\u00f3rz katalog
 dialog.diskcache.nocreate=Nie utworzono katalogu pami\u0119ci podr\u0119cznej
+dialog.diskcache.cannotwrite=W wybranym katalogu nie mo\u017cna zapisa\u0107 map
 dialog.diskcache.table.path=\u015acie\u017cka
 dialog.diskcache.table.usedby=u\u017cywane przez
 dialog.diskcache.table.zoom=Powi\u0119kszenie
 dialog.diskcache.table.path=\u015acie\u017cka
 dialog.diskcache.table.usedby=u\u017cywane przez
 dialog.diskcache.table.zoom=Powi\u0119kszenie
@@ -485,6 +495,7 @@ confirm.addaltitudeoffset=Dodano przesuni\u0119cie wysoko\u015bci
 confirm.rearrangewaypoints=Przestawiono punkty po\u015brednie
 confirm.rearrangephotos=Zmieniono kolejno\u015b\u0107 zdj\u0119\u0107
 confirm.cutandmove=Przesuni\u0119to zaznaczenie
 confirm.rearrangewaypoints=Przestawiono punkty po\u015brednie
 confirm.rearrangephotos=Zmieniono kolejno\u015b\u0107 zdj\u0119\u0107
 confirm.cutandmove=Przesuni\u0119to zaznaczenie
+confirm.interpolate=Dodano punkty
 confirm.convertnamestotimes=Zmieniono nazwy punkt\u00f3w po\u015brednich
 confirm.saveexif.ok1=Zapisano
 confirm.saveexif.ok2=plik(\u00f3w) zdj\u0119\u0107
 confirm.convertnamestotimes=Zmieniono nazwy punkt\u00f3w po\u015brednich
 confirm.saveexif.ok1=Zapisano
 confirm.saveexif.ok2=plik(\u00f3w) zdj\u0119\u0107
@@ -504,7 +515,7 @@ confirm.running=Przetwarzam dane ...
 confirm.lookupsrtm1=Znaleziono
 confirm.lookupsrtm2=warto\u015bci wysoko\u015bci
 confirm.deletefieldvalues=Warto\u015bci p\u00f3l usuni\u0119to
 confirm.lookupsrtm1=Znaleziono
 confirm.lookupsrtm2=warto\u015bci wysoko\u015bci
 confirm.deletefieldvalues=Warto\u015bci p\u00f3l usuni\u0119to
-confirm.audioload=dodano
+confirm.audioload=dodano pliki audio
 confirm.correlateaudios.single=audio zosta\u0142o po\u0142\u0105czone
 confirm.correlateaudios.multi=audio zosta\u0142y po\u0142\u0105czone
 
 confirm.correlateaudios.single=audio zosta\u0142o po\u0142\u0105czone
 confirm.correlateaudios.multi=audio zosta\u0142y po\u0142\u0105czone
 
@@ -580,7 +591,6 @@ display.range.time.mins=m
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=\u015arednia pr\u0119dko\u015b\u0107
 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.range.maxspeed=Pr\u0119dko\u015b\u0107 maksymalna
 details.range.numsegments=Liczba segment\u00f3w
 details.range.pace=Tempo
 details.range.maxspeed=Pr\u0119dko\u015b\u0107 maksymalna
 details.range.numsegments=Liczba segment\u00f3w
 details.range.pace=Tempo
@@ -593,6 +603,7 @@ details.nophoto=Brak zaznaczonego zdj\u0119cia
 details.photo.loading=Wczytywanie
 details.photo.bearing=Kierunek
 details.media.connected=Pod\u0142\u0105czony
 details.photo.loading=Wczytywanie
 details.photo.bearing=Kierunek
 details.media.connected=Pod\u0142\u0105czony
+details.media.fullpath=Pe\u0142na \u015bcie\u017cka
 details.audiodetails=Szczeg\u00f3\u0142y audio
 details.noaudio=Brak zaznaczonego audio
 details.audio.file=Plik audio
 details.audiodetails=Szczeg\u00f3\u0142y audio
 details.noaudio=Brak zaznaczonego audio
 details.audio.file=Plik audio
@@ -626,12 +637,15 @@ units.feet=Stopy
 units.feet.short=ft
 units.kilometres=Kilometry
 units.kilometres.short=km
 units.feet.short=ft
 units.kilometres=Kilometry
 units.kilometres.short=km
-units.kmh=km/h
+units.kilometresperhour.short=km/h
 units.miles=Mile
 units.miles.short=mi
 units.miles=Mile
 units.miles.short=mi
-units.mph=mi/h
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.milesperhour.short=mi/h
+units.nauticalmiles=Mile morskie
+units.nauticalmiles.short=Mm
+units.nauticalmilesperhour.short=w.
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=Godziny
 units.degminsec=Sto-min-sek
 units.degmin=Sto-min
 units.hours=Godziny
 units.degminsec=Sto-min-sek
 units.degmin=Sto-min
@@ -657,7 +671,8 @@ undo.deletepoint=usu\u0144 punkt
 undo.removephoto=usu\u0144 zdj\u0119cie (nie z dysku)
 undo.removeaudio=usu\u0144 audio
 undo.deleterange=usu\u0144 zakres
 undo.removephoto=usu\u0144 zdj\u0119cie (nie z dysku)
 undo.removeaudio=usu\u0144 audio
 undo.deleterange=usu\u0144 zakres
-undo.compress=skompresuj \u015bcie\u017ck\u0119
+undo.croptrack=przytnij \u015bcie\u017ck\u0119
+undo.deletemarked=usu\u0144 punkty
 undo.insert=wstaw punkty
 undo.reverse=odwr\u00f3\u0107 zakres
 undo.mergetracksegments=po\u0142\u0105cz fragmenty \u015bcie\u017cki
 undo.insert=wstaw punkty
 undo.reverse=odwr\u00f3\u0107 zakres
 undo.mergetracksegments=po\u0142\u0105cz fragmenty \u015bcie\u017cki
@@ -716,7 +731,9 @@ error.lookupsrtm.nonefound=Nie znaleziono danych o wysoko\u015bci.
 error.lookupsrtm.nonerequired=Wszystkie pola maj\u0105 informacj\u0119 o wysoko\u015bci, nie ma czego szuka\u0107
 error.gpsies.uploadnotok=Serwer Gpsies zwr\u00f3ci\u0142 informacj\u0119
 error.gpsies.uploadfailed=B\u0142\u0105d wysy\u0142ania
 error.lookupsrtm.nonerequired=Wszystkie pola maj\u0105 informacj\u0119 o wysoko\u015bci, nie ma czego szuka\u0107
 error.gpsies.uploadnotok=Serwer Gpsies zwr\u00f3ci\u0142 informacj\u0119
 error.gpsies.uploadfailed=B\u0142\u0105d wysy\u0142ania
+error.showphoto.failed=Nie powiod\u0142o si\u0119 za\u0142adowanie zdj\u0119cia
 error.playaudiofailed=Nie powiod\u0142o si\u0119 odtwarzanie pliku audio
 error.cache.notthere=Nie znaleziono katalogu kesza
 error.cache.empty=Katalog kesza jest pusty
 error.cache.cannotdelete=\u017badne p\u0142ytki nie mog\u0142y zosta\u0107 usuni\u0119te
 error.playaudiofailed=Nie powiod\u0142o si\u0119 odtwarzanie pliku audio
 error.cache.notthere=Nie znaleziono katalogu kesza
 error.cache.empty=Katalog kesza jest pusty
 error.cache.cannotdelete=\u017badne p\u0142ytki nie mog\u0142y zosta\u0107 usuni\u0119te
+error.interpolate.invalidparameter=Ilo\u015b\u0107 punkt\u00f3w musi zawiera\u0107 si\u0119 w zakresie od 1 do 1000
index 6266d43dc350e7915ea22959cc3bf5adbb9de86b..1220049fcfcdf17c7a8abe761f9e88c648ddac25 100644 (file)
@@ -20,8 +20,8 @@ menu.range.all=Selectionar tudo
 menu.range.none=N\u00e3o selecionar nenhuns
 menu.range.start=Definir in\u00edcio do intervalo
 menu.range.end=Definir fim do intervalo
 menu.range.none=N\u00e3o selecionar nenhuns
 menu.range.start=Definir in\u00edcio do intervalo
 menu.range.end=Definir fim do intervalo
-menu.range.deleterange=Remover intervalo
-menu.range.interpolate=Interpolar
+function.deleterange=Remover intervalo
+function.interpolate=Interpolar pontos
 menu.range.average=Sele\u00e7\u00e3o m\u00e9dia
 menu.range.reverse=Reverter intervalo
 menu.range.mergetracksegments=Mesclar trechos da rota
 menu.range.average=Sele\u00e7\u00e3o m\u00e9dia
 menu.range.reverse=Reverter intervalo
 menu.range.mergetracksegments=Mesclar trechos da rota
@@ -219,7 +219,6 @@ dialog.confirmreversetrack.title=Confirmar invers\u00e3o
 dialog.confirmreversetrack.text=Esta rota possui informa\u00e7\u00f5es de data-hora, as quais estar\u00e3o fora de sequ\u00eancia ap\u00f3s a revers\u00e3o.\n Voc\u00ea tem certeza que deseja reverter esta se\u00e7\u00e3o?
 dialog.confirmcutandmove.title=Confirmar cortar e mover
 dialog.confirmcutandmove.text=A rota cont\u00e9m informa\u00e7\u00f5es de data-hora, as quais estar\u00e3o fora de sequ\u00eancia ap\u00f3s o movimento.\n Voc\u00ea tem certeza que deseja mover esta se\u00e7\u00e3o?
 dialog.confirmreversetrack.text=Esta rota possui informa\u00e7\u00f5es de data-hora, as quais estar\u00e3o fora de sequ\u00eancia ap\u00f3s a revers\u00e3o.\n Voc\u00ea tem certeza que deseja reverter esta se\u00e7\u00e3o?
 dialog.confirmcutandmove.title=Confirmar cortar e mover
 dialog.confirmcutandmove.text=A rota cont\u00e9m informa\u00e7\u00f5es de data-hora, as quais estar\u00e3o fora de sequ\u00eancia ap\u00f3s o movimento.\n Voc\u00ea tem certeza que deseja mover esta se\u00e7\u00e3o?
-dialog.interpolate.title=Interpolar pontos
 dialog.interpolate.parameter.text=N\u00famero de pontos para inserir entre os pontos selecionados
 dialog.undo.title=A\u00e7\u00e3o(\u00f5es) de desfazer
 dialog.undo.pretext=Por favor, selecione a a\u00e7\u00e3o(\u00f5es) a desfazer
 dialog.interpolate.parameter.text=N\u00famero de pontos para inserir entre os pontos selecionados
 dialog.undo.title=A\u00e7\u00e3o(\u00f5es) de desfazer
 dialog.undo.pretext=Por favor, selecione a a\u00e7\u00e3o(\u00f5es) a desfazer
@@ -237,7 +236,7 @@ dialog.pointedit.changevalue.title=Editar campo
 dialog.pointnameedit.name=Nome do ponto
 dialog.pointnameedit.uppercase=MAI\u00daSCULAS
 dialog.pointnameedit.lowercase=min\u00fasculas
 dialog.pointnameedit.name=Nome do ponto
 dialog.pointnameedit.uppercase=MAI\u00daSCULAS
 dialog.pointnameedit.lowercase=min\u00fasculas
-dialog.pointnameedit.sentencecase=Frase
+dialog.pointnameedit.titlecase=Frase
 dialog.addtimeoffset.add=Adicionar tempo
 dialog.addtimeoffset.subtract=Subtrair tempo
 dialog.addtimeoffset.days=Dias
 dialog.addtimeoffset.add=Adicionar tempo
 dialog.addtimeoffset.subtract=Subtrair tempo
 dialog.addtimeoffset.days=Dias
@@ -340,7 +339,7 @@ dialog.rearrangephotos.toend=Mover para o fim
 dialog.rearrangephotos.nosort=N\u00e3o ordenar
 dialog.rearrangephotos.sortbyfilename=Ordenar pelo nome do arquivo
 dialog.rearrangephotos.sortbytime=Ordenar pela hora
 dialog.rearrangephotos.nosort=N\u00e3o ordenar
 dialog.rearrangephotos.sortbyfilename=Ordenar pelo nome do arquivo
 dialog.rearrangephotos.sortbytime=Ordenar pela hora
-dialog.compress.nonefound=Nenhum dado dos pontos pode ser removido
+dialog.deletemarked.nonefound=Nenhum dado dos pontos pode ser removido
 dialog.compress.closepoints.title=Remo\u00e7\u00e3o de ponto pr\u00f3ximo
 dialog.compress.closepoints.paramdesc=Fator de deslocamento
 dialog.compress.wackypoints.title=Remo\u00e7\u00e3o de ponto exc\u00eantrica
 dialog.compress.closepoints.title=Remo\u00e7\u00e3o de ponto pr\u00f3ximo
 dialog.compress.closepoints.paramdesc=Fator de deslocamento
 dialog.compress.wackypoints.title=Remo\u00e7\u00e3o de ponto exc\u00eantrica
@@ -406,7 +405,6 @@ dialog.saveconfig.prune.languagefile=Arquivo de idioma
 dialog.saveconfig.prune.gpsdevice=Dispositivo de GPS
 dialog.saveconfig.prune.gpsformat=Formato do GPS
 dialog.saveconfig.prune.povrayfont=Fonte Povray
 dialog.saveconfig.prune.gpsdevice=Dispositivo de GPS
 dialog.saveconfig.prune.gpsformat=Formato do GPS
 dialog.saveconfig.prune.povrayfont=Fonte Povray
-dialog.saveconfig.prune.metricunits=Usar unidades m\u00e9tricas?
 dialog.saveconfig.prune.gnuplotpath=Caminho para o gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Caminho para o gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Caminho para o exiftool
 dialog.saveconfig.prune.gnuplotpath=Caminho para o gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Caminho para o gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Caminho para o exiftool
@@ -580,7 +578,6 @@ display.range.time.mins=m
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=Velocidade m\u00e9dia
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=Velocidade m\u00e9dia
-details.range.avemovingspeed=Movimento m\u00e9dio
 details.range.maxspeed=Velocidade m\u00e1xima
 details.range.numsegments=N\u00famero de segmentos
 details.range.pace=Passo
 details.range.maxspeed=Velocidade m\u00e1xima
 details.range.numsegments=N\u00famero de segmentos
 details.range.pace=Passo
@@ -626,12 +623,12 @@ units.feet=P\u00e9s
 units.feet.short=ft
 units.kilometres=Quil\u00f4metros
 units.kilometres.short=km
 units.feet.short=ft
 units.kilometres=Quil\u00f4metros
 units.kilometres.short=km
-units.kmh=km/h
+units.kilometresperhour.short=km/h
 units.miles=Milhas
 units.miles.short=mi
 units.miles=Milhas
 units.miles.short=mi
-units.mph=mph
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.milesperhour.short=mph
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=horas
 units.degminsec=Graus-min-seg
 units.degmin=Graus-min
 units.hours=horas
 units.degminsec=Graus-min-seg
 units.degmin=Graus-min
@@ -657,7 +654,7 @@ undo.deletepoint=remover ponto
 undo.removephoto=remover foto
 undo.removeaudio=remover arquivo de \u00e1udio
 undo.deleterange=remover intervalo
 undo.removephoto=remover foto
 undo.removeaudio=remover arquivo de \u00e1udio
 undo.deleterange=remover intervalo
-undo.compress=comprimir rota
+undo.deletemarked=remover pontos
 undo.insert=inserir pontos
 undo.reverse=inverter intervalo
 undo.mergetracksegments=mesclar segmentos de rota
 undo.insert=inserir pontos
 undo.reverse=inverter intervalo
 undo.mergetracksegments=mesclar segmentos de rota
index 4df01434bf170e53c2eb207a18a41452c515bd69..b2950f20a5565a9745a413cfc30795188f6d9d65 100644 (file)
@@ -1,5 +1,5 @@
 # Text entries for the GpsPrune application
 # Text entries for the GpsPrune application
-# Romanian entries
+# Romanian entries as extra
 
 # Menu entries
 menu.file=Fi\u015fier
 
 # Menu entries
 menu.file=Fi\u015fier
@@ -9,36 +9,30 @@ menu.file.exit=Iesire
 menu.track=Traseu
 menu.track.undo=Anulare
 menu.track.clearundo=\u015etergere lista de anulari
 menu.track=Traseu
 menu.track.undo=Anulare
 menu.track.clearundo=\u015etergere lista de anulari
-menu.point.editpoint=Editare punct
-menu.point.deletepoint=\u015etergere punct
-menu.range.deleterange=\u015etergere gama
 menu.track.deletemarked=\u015etergere puncte marcate
 menu.track.deletemarked=\u015etergere puncte marcate
-menu.range.interpolate=Interpolare
-menu.range.average=Mediere selectie
-menu.range.reverse=Inversare selectie
-menu.range.mergetracksegments=Unire segmente traseu
 menu.track.rearrange=Rearanjare waypoint
 menu.track.rearrange.start=Toate la inceputul fisierului
 menu.track.rearrange.end=Toate la sfarsitul fisierului
 menu.track.rearrange.nearest=Fiecare la punctul cel mai apropiat al traseului
 menu.track.rearrange=Rearanjare waypoint
 menu.track.rearrange.start=Toate la inceputul fisierului
 menu.track.rearrange.end=Toate la sfarsitul fisierului
 menu.track.rearrange.nearest=Fiecare la punctul cel mai apropiat al traseului
-menu.range.cutandmove=Taiere si mutare selectie
-menu.point=Punct
 menu.range.all=Selectare toate
 menu.range.none=Nu selecta niciun punct
 menu.range.start=Seteaza inceputul selectiei
 menu.range.end=Seteaza sfarsitul selectiei
 menu.range.all=Selectare toate
 menu.range.none=Nu selecta niciun punct
 menu.range.start=Seteaza inceputul selectiei
 menu.range.end=Seteaza sfarsitul selectiei
+menu.range.average=Mediere selectie
+menu.range.reverse=Inversare selectie
+menu.range.mergetracksegments=Unire segmente traseu
+menu.range.cutandmove=Taiere si mutare selectie
+menu.point=Punct
+menu.point.editpoint=Editare punct
+menu.point.deletepoint=\u015etergere punct
 menu.photo=Foto
 menu.photo.saveexif=Salveaza la Exif
 menu.photo=Foto
 menu.photo.saveexif=Salveaza la Exif
-function.connecttopoint=Conecteaza la punct
-function.disconnectfrompoint=Deconecteaza de la punct
-function.removephoto=Elimina foto
 menu.view=Vizualizare
 menu.view.browser=Harta in browser
 menu.view.browser.google=Harti Google
 menu.view.browser.openstreetmap=Openstreetmap
 menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Harti Yahoo
 menu.view=Vizualizare
 menu.view.browser=Harta in browser
 menu.view.browser.google=Harti Google
 menu.view.browser.openstreetmap=Openstreetmap
 menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Harti Yahoo
-menu.view.browser.bing=Harti Bing
 menu.help=Ajutor
 # Popup menu for map
 menu.map.zoomin=Apropie
 menu.help=Ajutor
 # Popup menu for map
 menu.map.zoomin=Apropie
@@ -73,6 +67,9 @@ function.exportpov=Export\u0103 \u00eentr-un fi\u015fier POV
 function.exportsvg=Export\u0103 \u00eentr-un fi\u015fier SVG
 function.editwaypointname=Editare nume waypoint
 function.compress=Comprima traseu
 function.exportsvg=Export\u0103 \u00eentr-un fi\u015fier SVG
 function.editwaypointname=Editare nume waypoint
 function.compress=Comprima traseu
+function.deleterange=\u015etergere gama
+function.interpolate=Interpolare
+function.findwaypoint=Gasire waypoint
 function.charts=Grafice
 function.show3d=Vizualizare arborescenta
 function.distances=Distan\u0163e
 function.charts=Grafice
 function.show3d=Vizualizare arborescenta
 function.distances=Distan\u0163e
@@ -80,6 +77,9 @@ function.setmapbg=Fundal
 function.correlatephotos=Corelare fotografii
 function.setcolours=Selectare culorile
 function.setlanguage=Selectare limba
 function.correlatephotos=Corelare fotografii
 function.setcolours=Selectare culorile
 function.setlanguage=Selectare limba
+function.connecttopoint=Conecteaza la punct
+function.disconnectfrompoint=Deconecteaza de la punct
+function.removephoto=Elimina foto
 function.help=Ajutor
 function.showkeys=Arat\u0103 tastele scurt\u0103turi
 function.about=Despre GpsPrune
 function.help=Ajutor
 function.showkeys=Arat\u0103 tastele scurt\u0103turi
 function.about=Despre GpsPrune
index 14caca89482ccef314bb0ced5eaee9ec3b08a130..f14174d2052c13b4d8240a80e7552a16baf107d1 100644 (file)
@@ -20,8 +20,8 @@ menu.range.all=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435
 menu.range.none=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043a\u0443
 menu.range.start=\u041d\u0430\u0447\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430
 menu.range.end=\u041a\u043e\u043d\u0435\u0446 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430
 menu.range.none=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043a\u0443
 menu.range.start=\u041d\u0430\u0447\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430
 menu.range.end=\u041a\u043e\u043d\u0435\u0446 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430
-menu.range.deleterange=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b
-menu.range.interpolate=\u0422\u043e\u0447\u043a\u0430 \u043f\u043e \u0438\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u0438
+function.deleterange=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b
+function.interpolate=\u0418\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u044f \u0442\u043e\u0447\u0435\u043a
 menu.range.average=\u0422\u043e\u0447\u043a\u0430 \u043f\u043e \u0441\u0440\u0435\u0434\u043d\u0435\u043c\u0443
 menu.range.reverse=\u041f\u0435\u0440\u0435\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b
 menu.range.mergetracksegments=\u0421\u043b\u0438\u0442\u044c \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u044b \u0442\u0440\u0435\u043a\u0430
 menu.range.average=\u0422\u043e\u0447\u043a\u0430 \u043f\u043e \u0441\u0440\u0435\u0434\u043d\u0435\u043c\u0443
 menu.range.reverse=\u041f\u0435\u0440\u0435\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b
 menu.range.mergetracksegments=\u0421\u043b\u0438\u0442\u044c \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u044b \u0442\u0440\u0435\u043a\u0430
@@ -219,7 +219,6 @@ dialog.confirmreversetrack.title=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u043
 dialog.confirmreversetrack.text=\u042d\u0442\u043e\u0442 \u0442\u0440\u0435\u043a \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u043a\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0430 \u043f\u043e\u0441\u043b\u0435 \u0440\u0430\u0437\u0432\u043e\u0440\u043e\u0442\u0430.\n\u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435?
 dialog.confirmcutandmove.title=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 "\u0432\u044b\u0440\u0435\u0437\u0430\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438"
 dialog.confirmcutandmove.text=\u042d\u0442\u043e\u0442 \u0442\u0440\u0435\u043a \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u043a\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0430 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f.\n\u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435?
 dialog.confirmreversetrack.text=\u042d\u0442\u043e\u0442 \u0442\u0440\u0435\u043a \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u043a\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0430 \u043f\u043e\u0441\u043b\u0435 \u0440\u0430\u0437\u0432\u043e\u0440\u043e\u0442\u0430.\n\u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435?
 dialog.confirmcutandmove.title=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 "\u0432\u044b\u0440\u0435\u0437\u0430\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438"
 dialog.confirmcutandmove.text=\u042d\u0442\u043e\u0442 \u0442\u0440\u0435\u043a \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u043a\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0430 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u044f.\n\u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435?
-dialog.interpolate.title=\u0418\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u044f \u0442\u043e\u0447\u0435\u043a
 dialog.interpolate.parameter.text=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0442\u043e\u0447\u0435\u043a \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u043c\u0435\u0436\u0434\u0443 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c\u0438
 dialog.undo.title=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435(\u044f)
 dialog.undo.pretext=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435(\u044f)
 dialog.interpolate.parameter.text=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0442\u043e\u0447\u0435\u043a \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u043c\u0435\u0436\u0434\u0443 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c\u0438
 dialog.undo.title=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435(\u044f)
 dialog.undo.pretext=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u043c\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435(\u044f)
@@ -237,7 +236,7 @@ dialog.pointedit.changevalue.title=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0
 dialog.pointnameedit.name=\u0418\u043c\u044f \u043f\u0443\u0442\u0435\u0432\u043e\u0439 \u0442\u043e\u0447\u043a\u0438
 dialog.pointnameedit.uppercase=\u0412\u0435\u0440\u0445\u043d\u0438\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440
 dialog.pointnameedit.lowercase=\u043d\u0438\u0436\u043d\u0438\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440
 dialog.pointnameedit.name=\u0418\u043c\u044f \u043f\u0443\u0442\u0435\u0432\u043e\u0439 \u0442\u043e\u0447\u043a\u0438
 dialog.pointnameedit.uppercase=\u0412\u0435\u0440\u0445\u043d\u0438\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440
 dialog.pointnameedit.lowercase=\u043d\u0438\u0436\u043d\u0438\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440
-dialog.pointnameedit.sentencecase=\u041a\u0430\u0436\u0434\u043e\u0435 \u0421\u043b\u043e\u0432\u043e \u0441 \u0417\u0430\u0433\u043b\u0430\u0432\u043d\u043e\u0439
+dialog.pointnameedit.titlecase=\u041a\u0430\u0436\u0434\u043e\u0435 \u0421\u043b\u043e\u0432\u043e \u0441 \u0417\u0430\u0433\u043b\u0430\u0432\u043d\u043e\u0439
 dialog.addtimeoffset.add=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u043b\u0435
 dialog.addtimeoffset.subtract=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0434\u043e
 dialog.addtimeoffset.days=\u0414\u043d\u0438
 dialog.addtimeoffset.add=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u043b\u0435
 dialog.addtimeoffset.subtract=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0434\u043e
 dialog.addtimeoffset.days=\u0414\u043d\u0438
@@ -340,7 +339,7 @@ dialog.rearrangephotos.toend=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0
 dialog.rearrangephotos.nosort=\u041d\u0435 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c
 dialog.rearrangephotos.sortbyfilename=\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u0430
 dialog.rearrangephotos.sortbytime=\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438
 dialog.rearrangephotos.nosort=\u041d\u0435 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c
 dialog.rearrangephotos.sortbyfilename=\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u0430
 dialog.rearrangephotos.sortbytime=\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438
-dialog.compress.nonefound=\u041d\u0435\u0442 \u0442\u043e\u0447\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0431\u044b\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u044b
+dialog.deletemarked.nonefound=\u041d\u0435\u0442 \u0442\u043e\u0447\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0431\u044b\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u044b
 dialog.compress.closepoints.title=\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u0431\u043b\u0438\u0436\u0435\u043d\u043d\u044b\u0445 \u0442\u043e\u0447\u0435\u043a
 dialog.compress.closepoints.paramdesc=\u0420\u0430\u0437\u043c\u0430\u0445
 dialog.compress.wackypoints.title=\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 "\u0448\u0430\u043b\u044c\u043d\u044b\u0445"(\u043d\u0435\u043e\u0431\u044b\u0447\u043d\u044b\u0445) \u0442\u043e\u0447\u0435\u043a
 dialog.compress.closepoints.title=\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u0431\u043b\u0438\u0436\u0435\u043d\u043d\u044b\u0445 \u0442\u043e\u0447\u0435\u043a
 dialog.compress.closepoints.paramdesc=\u0420\u0430\u0437\u043c\u0430\u0445
 dialog.compress.wackypoints.title=\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 "\u0448\u0430\u043b\u044c\u043d\u044b\u0445"(\u043d\u0435\u043e\u0431\u044b\u0447\u043d\u044b\u0445) \u0442\u043e\u0447\u0435\u043a
@@ -406,7 +405,6 @@ dialog.saveconfig.prune.languagefile=\u042f\u0437\u044b\u043a\u043e\u0432\u043e\
 dialog.saveconfig.prune.gpsdevice=GPS \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e
 dialog.saveconfig.prune.gpsformat=GPS \u0444\u043e\u0440\u043c\u0430\u0442
 dialog.saveconfig.prune.povrayfont=Povray \u0448\u0440\u0438\u0444\u0442
 dialog.saveconfig.prune.gpsdevice=GPS \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e
 dialog.saveconfig.prune.gpsformat=GPS \u0444\u043e\u0440\u043c\u0430\u0442
 dialog.saveconfig.prune.povrayfont=Povray \u0448\u0440\u0438\u0444\u0442
-dialog.saveconfig.prune.metricunits=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0435\u0434\u0438\u043d\u0438\u0446\u044b?
 dialog.saveconfig.prune.gnuplotpath=\u041f\u0443\u0442\u044c \u043a GNUPLOT
 dialog.saveconfig.prune.gpsbabelpath=\u041f\u0443\u0442\u044c \u043a GPSBabel
 dialog.saveconfig.prune.exiftoolpath=\u041f\u0443\u0442\u044c \u043a ExifTool
 dialog.saveconfig.prune.gnuplotpath=\u041f\u0443\u0442\u044c \u043a GNUPLOT
 dialog.saveconfig.prune.gpsbabelpath=\u041f\u0443\u0442\u044c \u043a GPSBabel
 dialog.saveconfig.prune.exiftoolpath=\u041f\u0443\u0442\u044c \u043a ExifTool
@@ -438,7 +436,7 @@ dialog.colourchooser.red=\u041a\u0440\u0430\u0441\u043d\u044b\u0439
 dialog.colourchooser.green=\u0417\u0435\u043b\u0435\u043d\u044b\u0439
 dialog.colourchooser.blue=\u0421\u0438\u043d\u0438\u0439
 dialog.setlanguage.firstintro=\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u0437 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432, <p> \u0438\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u044f\u0437\u044b\u043a\u043e\u0432\u043e\u0439 \u0444\u0430\u0439\u043b.
 dialog.colourchooser.green=\u0417\u0435\u043b\u0435\u043d\u044b\u0439
 dialog.colourchooser.blue=\u0421\u0438\u043d\u0438\u0439
 dialog.setlanguage.firstintro=\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u0437 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u044f\u0437\u044b\u043a\u043e\u0432, <p> \u0438\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u044f\u0437\u044b\u043a\u043e\u0432\u043e\u0439 \u0444\u0430\u0439\u043b.
-dialog.setlanguage.secondintro=\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 <p> \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430 \u0432 GpsPrune.
+dialog.setlanguage.secondintro=\u0414\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u044f\u0437\u044b\u043a\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 <p>\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c GpsPrune .
 dialog.setlanguage.language=\u042f\u0437\u044b\u043a
 dialog.setlanguage.languagefile=\u042f\u0437\u044b\u043a\u043e\u0432\u043e\u0439 \u0444\u0430\u0439\u043b
 dialog.setlanguage.endmessage=\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 GpsPrune,\n\u0447\u0442\u043e\u0431\u044b \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u044f\u0437\u044b\u043a\u0430 \u0432\u0441\u0442\u0443\u043f\u0438\u043b\u043e \u0432 \u0441\u0438\u043b\u0443.
 dialog.setlanguage.language=\u042f\u0437\u044b\u043a
 dialog.setlanguage.languagefile=\u042f\u0437\u044b\u043a\u043e\u0432\u043e\u0439 \u0444\u0430\u0439\u043b
 dialog.setlanguage.endmessage=\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 GpsPrune,\n\u0447\u0442\u043e\u0431\u044b \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u044f\u0437\u044b\u043a\u0430 \u0432\u0441\u0442\u0443\u043f\u0438\u043b\u043e \u0432 \u0441\u0438\u043b\u0443.
@@ -466,9 +464,9 @@ dialog.searchwikipedianames.search=\u041f\u043e\u0438\u0441\u043a \u0434\u043b\u
 
 # 3d window
 dialog.3d.title=GpsPrune 3D-\u0432\u0438\u0434
 
 # 3d window
 dialog.3d.title=GpsPrune 3D-\u0432\u0438\u0434
-dialog.3d.altitudefactor=\u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u043f\u043e \u0432\u044b\u0441\u043e\u0442\u0435
-dialog.3dlines.title=\u0441\u0435\u0442\u043a\u0430 GpsPrune
-dialog.3dlines.empty=\u043d\u0435\u0442 \u0441\u0435\u0442\u043a\u0438 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f!
+dialog.3d.altitudefactor=\u041a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u043f\u043e \u0432\u044b\u0441\u043e\u0442\u0435
+dialog.3dlines.title=\u0421\u0435\u0442\u043a\u0430 GpsPrune
+dialog.3dlines.empty=\u041d\u0435\u0442 \u0441\u0435\u0442\u043a\u0438 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f!
 dialog.3dlines.intro=\u041a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0441\u0435\u0442\u043a\u0438 3D-\u0432\u0438\u0434\u0430
 
 # Confirm messages
 dialog.3dlines.intro=\u041a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0441\u0435\u0442\u043a\u0438 3D-\u0432\u0438\u0434\u0430
 
 # Confirm messages
@@ -528,15 +526,15 @@ button.yestoall=\u0414\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0445
 button.notoall=\u041d\u0435\u0442 \u0434\u043b\u044f \u0432\u0441\u0435\u0445
 button.select=\u0412\u044b\u0431\u0440\u0430\u0442\u044c
 button.selectall=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435
 button.notoall=\u041d\u0435\u0442 \u0434\u043b\u044f \u0432\u0441\u0435\u0445
 button.select=\u0412\u044b\u0431\u0440\u0430\u0442\u044c
 button.selectall=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435
-button.selectnone=\u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u0442\u0431\u0438\u0440\u0430\u0442\u044c
+button.selectnone=\u041e\u0442\u043c\u0435\u043d\u0442\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043a\u0443
 button.preview=\u041f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440
 button.load=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c
 button.upload=\u0412\u044b\u0433\u0440\u0443\u0437\u0438\u0442\u044c
 button.guessfields=\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f
 button.preview=\u041f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440
 button.load=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c
 button.upload=\u0412\u044b\u0433\u0440\u0443\u0437\u0438\u0442\u044c
 button.guessfields=\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u043c\u044b\u0435 \u043f\u043e\u043b\u044f
-button.showwebpage=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443
+button.showwebpage=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0435\u0431\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443
 button.check=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430
 button.resettodefaults=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435
 button.check=\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430
 button.resettodefaults=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0435
-button.browse=\u0423\u043a\u0430\u0437\u0430\u0442\u044c...
+button.browse=\u041e\u0431\u0437\u043e\u0440...
 button.addnew=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u043e\u0435
 button.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
 button.manage=\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c
 button.addnew=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u043e\u0435
 button.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
 button.manage=\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c
@@ -580,7 +578,6 @@ display.range.time.mins=m
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=\u0421\u0440\u0435\u0434\u043d\u044f\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=\u0421\u0440\u0435\u0434\u043d\u044f\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c
-details.range.avemovingspeed=\u0421\u0440\u0435\u0434\u043d\u044f\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0430
 details.range.maxspeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c
 details.range.numsegments=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u043e\u0432
 details.range.pace=\u0422\u0435\u043c\u043f
 details.range.maxspeed=\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c
 details.range.numsegments=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u043e\u0432
 details.range.pace=\u0422\u0435\u043c\u043f
@@ -626,14 +623,10 @@ units.feet=\u0444\u0443\u0442\u044b
 units.feet.short=ft
 units.kilometres=\u041a\u0438\u043b\u043e\u043c\u0435\u0442\u0440\u044b
 units.kilometres.short=km
 units.feet.short=ft
 units.kilometres=\u041a\u0438\u043b\u043e\u043c\u0435\u0442\u0440\u044b
 units.kilometres.short=km
-units.kmh=km/h
 units.kilometresperhour.short=km/h
 units.miles=\u041c\u0438\u043b\u0438
 units.miles.short=mi
 units.kilometresperhour.short=km/h
 units.miles=\u041c\u0438\u043b\u0438
 units.miles.short=mi
-units.mph=mph
 units.milesperhour.short=mph
 units.milesperhour.short=mph
-units.metrespersec=m/s
-units.feetpersec=ft/s
 units.hours=\u0427\u0430\u0441\u044b
 units.degminsec=\u0413\u0440\u0430\u0434-\u043c\u0438\u043d-\u0441\u0435\u043a
 units.degmin=\u0413\u0440\u0430\u0434-\u043c\u0438\u043d
 units.hours=\u0427\u0430\u0441\u044b
 units.degminsec=\u0413\u0440\u0430\u0434-\u043c\u0438\u043d-\u0441\u0435\u043a
 units.degmin=\u0413\u0440\u0430\u0434-\u043c\u0438\u043d
@@ -645,10 +638,10 @@ url.googlemaps=maps.google.ru
 wikipedia.lang=ru
 
 # Cardinals for 3d plots
 wikipedia.lang=ru
 
 # Cardinals for 3d plots
-cardinal.n=\u0421
-cardinal.s=\u042e
-cardinal.e=\u0412
-cardinal.w=\u0417
+cardinal.n=\u0421\u0435\u0432\u0435\u0440
+cardinal.s=\u042e\u0433
+cardinal.e=\u0412\u043e\u0441\u0442\u043e\u043a
+cardinal.w=\u0417\u0430\u043f\u0430\u0434
 
 # Undo operations
 undo.load=\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445
 
 # Undo operations
 undo.load=\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445
@@ -659,7 +652,7 @@ undo.deletepoint=\u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u043e\u0447\u
 undo.removephoto=\u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0444\u043e\u0442\u043e
 undo.removeaudio=\u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0437\u0432\u0443\u043a\u043e\u0437\u0430\u043f\u0438\u0441\u044c
 undo.deleterange=\u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b
 undo.removephoto=\u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0444\u043e\u0442\u043e
 undo.removeaudio=\u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0437\u0432\u0443\u043a\u043e\u0437\u0430\u043f\u0438\u0441\u044c
 undo.deleterange=\u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b
-undo.compress=\u0441\u0436\u0430\u0442\u044c \u0442\u0440\u0435\u043a
+undo.deletemarked=\u0441\u0436\u0430\u0442\u044c \u0442\u0440\u0435\u043a
 undo.insert=\u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0438
 undo.reverse=\u043f\u0435\u0440\u0435\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b
 undo.mergetracksegments=\u0441\u043b\u0438\u044f\u043d\u0438\u0435 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u043e\u0432 \u0442\u0440\u0435\u043a\u0430
 undo.insert=\u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0438
 undo.reverse=\u043f\u0435\u0440\u0435\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b
 undo.mergetracksegments=\u0441\u043b\u0438\u044f\u043d\u0438\u0435 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u043e\u0432 \u0442\u0440\u0435\u043a\u0430
index 81602655e35e29df63fe23bdd5be266c8ad4b0f9..d0983667dbcb4621f7a8bb4613fa1fd8a44f888a 100644 (file)
@@ -11,9 +11,9 @@ menu.track.undo=Geri al
 menu.track.clearundo=Geri alma listesi s\u0131f\u0131rla
 menu.point.editpoint=Nokta d\u00fczenle
 menu.point.deletepoint=Noktay\u0131 sil
 menu.track.clearundo=Geri alma listesi s\u0131f\u0131rla
 menu.point.editpoint=Nokta d\u00fczenle
 menu.point.deletepoint=Noktay\u0131 sil
-menu.range.deleterange=S\u0131ray\u0131 sil
+function.deleterange=S\u0131ray\u0131 sil
 menu.track.deletemarked=Se\u00e7ili noktalar\u0131 sil
 menu.track.deletemarked=Se\u00e7ili noktalar\u0131 sil
-menu.range.interpolate=\u0130nterpolasyon
+function.interpolate=\u0130nterpolasyon
 menu.range.average=Se\u00e7me ortala
 menu.range.reverse=S\u0131ra tersine \u00e7evir
 menu.range.mergetracksegments=\u0130z par\u00e7alar\u0131 birle\u015ftir
 menu.range.average=Se\u00e7me ortala
 menu.range.reverse=S\u0131ra tersine \u00e7evir
 menu.range.mergetracksegments=\u0130z par\u00e7alar\u0131 birle\u015ftir
@@ -183,7 +183,7 @@ dialog.pointedit.changevalue.title=Alan d\u00fczenle
 dialog.pointnameedit.name=Nokta ad\u0131
 dialog.pointnameedit.uppercase=B\u00dcY\u00dcK HARFLER
 dialog.pointnameedit.lowercase=k\u00fc\u00e7\u00fck harfler
 dialog.pointnameedit.name=Nokta ad\u0131
 dialog.pointnameedit.uppercase=B\u00dcY\u00dcK HARFLER
 dialog.pointnameedit.lowercase=k\u00fc\u00e7\u00fck harfler
-dialog.pointnameedit.sentencecase=\u0130lk Harfi B\u00fcy\u00fck
+dialog.pointnameedit.titlecase=\u0130lk Harfi B\u00fcy\u00fck
 dialog.addtimeoffset.add=Zaman ekle
 dialog.addtimeoffset.subtract=Zaman \u00e7\u0131kart
 dialog.addtimeoffset.days=G\u00fcn
 dialog.addtimeoffset.add=Zaman ekle
 dialog.addtimeoffset.subtract=Zaman \u00e7\u0131kart
 dialog.addtimeoffset.days=G\u00fcn
@@ -266,7 +266,6 @@ dialog.saveconfig.prune.languagecode=Dil kodu (TR)
 dialog.saveconfig.prune.gpsdevice=GPS ayg\u0131t
 dialog.saveconfig.prune.gpsformat=GPS bi\u00e7imi
 dialog.saveconfig.prune.povrayfont=Povray yaz\u0131tipi
 dialog.saveconfig.prune.gpsdevice=GPS ayg\u0131t
 dialog.saveconfig.prune.gpsformat=GPS bi\u00e7imi
 dialog.saveconfig.prune.povrayfont=Povray yaz\u0131tipi
-dialog.saveconfig.prune.metricunits=Metrik sistemi
 dialog.saveconfig.prune.gnuplotpath=gnuplot'un yeriyolu
 dialog.saveconfig.prune.gpsbabelpath=gpsbabel'in yeriyolu
 dialog.saveconfig.prune.exiftoolpath=exiftool'un yeriyolu
 dialog.saveconfig.prune.gnuplotpath=gnuplot'un yeriyolu
 dialog.saveconfig.prune.gpsbabelpath=gpsbabel'in yeriyolu
 dialog.saveconfig.prune.exiftoolpath=exiftool'un yeriyolu
@@ -359,7 +358,6 @@ display.range.time.mins=dak
 display.range.time.hours=saat
 display.range.time.days=g\u011fn
 details.range.avespeed=Ortalama h\u0131z\u0131
 display.range.time.hours=saat
 display.range.time.days=g\u011fn
 details.range.avespeed=Ortalama h\u0131z\u0131
-details.range.avemovingspeed=Ortalama hareketi
 details.lists.waypoints=Noktalar
 details.lists.photos=Fotolar
 details.photodetails=Foto ayr\u0131nt\u0131lar\u0131
 details.lists.waypoints=Noktalar
 details.lists.photos=Fotolar
 details.photodetails=Foto ayr\u0131nt\u0131lar\u0131
@@ -393,12 +391,12 @@ units.feet=Ayak
 units.feet.short=ft
 units.kilometres=Kilometre
 units.kilometres.short=km
 units.feet.short=ft
 units.kilometres=Kilometre
 units.kilometres.short=km
-units.kmh=km/h
+units.kilometresperhour.short=km/h
 units.miles=Mil
 units.miles.short=mi
 units.miles=Mil
 units.miles.short=mi
-units.mph=mph
-units.metrespersec=m/s
-units.feetpersec=ft/s
+units.milesperhour.short=mph
+units.metrespersec.short=m/s
+units.feetpersec.short=ft/s
 units.hours=saat
 units.degminsec=Derece/Dakika/Saniye
 units.degmin=Derece/Dakika
 units.hours=saat
 units.degminsec=Derece/Dakika/Saniye
 units.degmin=Derece/Dakika
@@ -421,7 +419,7 @@ undo.editpoint=noktay\u0131 d\u00fczenle
 undo.deletepoint=noktay\u0131 sil
 undo.removephoto=foto kald\u0131r
 undo.deleterange=s\u0131ra sil
 undo.deletepoint=noktay\u0131 sil
 undo.removephoto=foto kald\u0131r
 undo.deleterange=s\u0131ra sil
-undo.compress=izi s\u0131k\u0131\u015ft\u0131r
+undo.deletemarked=izi s\u0131k\u0131\u015ft\u0131r
 undo.insert=noktalar\u0131 ekle
 undo.reverse=s\u0131ra tersine d\u00f6nd\u00fcr
 undo.mergetracksegments=iz par\u00e7alar\u0131 birle\u015ftir
 undo.insert=noktalar\u0131 ekle
 undo.reverse=s\u0131ra tersine d\u00f6nd\u00fcr
 undo.mergetracksegments=iz par\u00e7alar\u0131 birle\u015ftir
index bce879697023babcbf6ad2e9f7e828bbcdb3b4b3..dc14d29e4448c6c496b8e18c46cbd8bb88e82857 100644 (file)
@@ -1,16 +1,17 @@
 # Text entries for the GpsPrune application
 # Text entries for the GpsPrune application
-# Chinese entries as extra
+# Chinese entries
 
 # Menu entries
 menu.file=\u6587\u4ef6
 
 # Menu entries
 menu.file=\u6587\u4ef6
-menu.file.addphotos=\u6dfb\u52a0\u76f8\u7247
+menu.file.addphotos=\u6dfb\u52a0\u7167\u7247
 menu.file.recentfiles=\u6700\u8fd1\u6253\u5f00\u8fc7\u6587\u4ef6
 menu.file.save=\u4fdd\u5b58
 menu.file.exit=\u9000\u51fa
 menu.track=\u8f68\u8ff9
 menu.track.undo=\u64a4\u9500
 menu.track.clearundo=\u6e05\u9664\u64a4\u9500\u6e05\u5355
 menu.file.recentfiles=\u6700\u8fd1\u6253\u5f00\u8fc7\u6587\u4ef6
 menu.file.save=\u4fdd\u5b58
 menu.file.exit=\u9000\u51fa
 menu.track=\u8f68\u8ff9
 menu.track.undo=\u64a4\u9500
 menu.track.clearundo=\u6e05\u9664\u64a4\u9500\u6e05\u5355
-menu.track.deletemarked=\u5220\u9664\u5df2\u6807\u793a\u8f68\u8ff9\u70b9
+menu.track.markrectangle=\u6807\u8bb0\u9009\u53d6\u533a\u57df\u5185\u7684\u70b9
+menu.track.deletemarked=\u5220\u9664\u5df2\u6807\u8bb0\u8f68\u8ff9\u70b9
 menu.track.rearrange=\u91cd\u65b0\u6392\u5217\u822a\u70b9
 menu.track.rearrange.start=\u81f3\u8d77\u59cb\u4f4d\u7f6e
 menu.track.rearrange.end=\u81f3\u672b\u4f4d\u7f6e
 menu.track.rearrange=\u91cd\u65b0\u6392\u5217\u822a\u70b9
 menu.track.rearrange.start=\u81f3\u8d77\u59cb\u4f4d\u7f6e
 menu.track.rearrange.end=\u81f3\u672b\u4f4d\u7f6e
@@ -20,16 +21,14 @@ menu.range.all=\u5168\u9009
 menu.range.none=\u64a4\u9500\u9009\u62e9
 menu.range.start=\u8bbe\u7f6e\u8d77\u70b9
 menu.range.end=\u8bbe\u7f6e\u7ec8\u70b9
 menu.range.none=\u64a4\u9500\u9009\u62e9
 menu.range.start=\u8bbe\u7f6e\u8d77\u70b9
 menu.range.end=\u8bbe\u7f6e\u7ec8\u70b9
-menu.range.deleterange=\u5220\u9664\u8f68\u8ff9\u70b9\u6bb5
-menu.range.interpolate=\u63d2\u5165\u8f68\u8ff9\u70b9
 menu.range.average=\u8bbe\u7f6e\u5e73\u5747\u8f68\u8ff9\u70b9
 menu.range.average=\u8bbe\u7f6e\u5e73\u5747\u8f68\u8ff9\u70b9
-menu.range.reverse=\u8f68\u8ff9\u70b9\u53cd\u5411
+menu.range.reverse=\u8f68\u8ff9\u70b9\u53cd\u8f6c
 menu.range.mergetracksegments=\u5408\u5e76\u8f68\u8ff9\u6bb5
 menu.range.cutandmove=\u79fb\u52a8
 menu.point=\u8f68\u8ff9\u70b9
 menu.point.editpoint=\u7f16\u8f91\u8f68\u8ff9\u70b9
 menu.point.deletepoint=\u5220\u9664\u8f68\u8ff9\u70b9
 menu.range.mergetracksegments=\u5408\u5e76\u8f68\u8ff9\u6bb5
 menu.range.cutandmove=\u79fb\u52a8
 menu.point=\u8f68\u8ff9\u70b9
 menu.point.editpoint=\u7f16\u8f91\u8f68\u8ff9\u70b9
 menu.point.deletepoint=\u5220\u9664\u8f68\u8ff9\u70b9
-menu.photo=\u76f8\u7247
+menu.photo=\u7167\u7247
 menu.photo.saveexif=\u5750\u6807\u4fdd\u5b58\u81f3Exif
 menu.audio=\u58f0\u97f3
 menu.view=\u67e5\u770b
 menu.photo.saveexif=\u5750\u6807\u4fdd\u5b58\u81f3Exif
 menu.audio=\u58f0\u97f3
 menu.view=\u67e5\u770b
@@ -39,7 +38,7 @@ 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.view.browser.openstreetmap=Openstreet\u5730\u56fe
 menu.view.browser.mapquest=Mapquest\u5730\u56fe
 menu.view.browser.yahoo=Yahoo\u5730\u56fe
-menu.view.browser.bing=Bing(\u5fc5\u5e94\uff09\u5730\u56fe
+menu.view.browser.bing=Bing(\u5fc5\u5e94)\u5730\u56fe
 menu.settings=\u8bbe\u7f6e
 menu.settings.onlinemode=\u4ece\u7f51\u4e0a\u5bfc\u5165\u5730\u56fe
 menu.settings.autosave=\u9000\u51fa\u65f6\u81ea\u52a8\u4fdd\u5b58\u8bbe\u7f6e
 menu.settings=\u8bbe\u7f6e
 menu.settings.onlinemode=\u4ece\u7f51\u4e0a\u5bfc\u5165\u5730\u56fe
 menu.settings.autosave=\u9000\u51fa\u65f6\u81ea\u52a8\u4fdd\u5b58\u8bbe\u7f6e
@@ -54,6 +53,7 @@ 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
 menu.map.autopan=\u81ea\u52a8\u7f29\u653e
 menu.map.showmap=\u663e\u793a\u5730\u56fe
 menu.map.showscalebar=\u663e\u793a\u6bd4\u4f8b\u5c3a
+menu.map.editmode=\u7f16\u8f91\u6a21\u5f0f
 
 # Alt keys for menus
 altkey.menu.file=F
 
 # Alt keys for menus
 altkey.menu.file=F
@@ -85,22 +85,25 @@ function.exportgpx=\u8f93\u51faGPX\u6587\u4ef6
 function.exportpov=\u8f93\u51faPOV\u6587\u4ef6
 function.exportsvg=\u8f93\u51faSVG\u6587\u4ef6
 function.editwaypointname=\u7f16\u8f91\u822a\u70b9\u540d
 function.exportpov=\u8f93\u51faPOV\u6587\u4ef6
 function.exportsvg=\u8f93\u51faSVG\u6587\u4ef6
 function.editwaypointname=\u7f16\u8f91\u822a\u70b9\u540d
-function.compress=\u538b\u7f29\u8f68\u8ff9(\u6807\u793a\u8981\u5220\u9664\u822a\u70b9\uff09
+function.compress=\u538b\u7f29\u8f68\u8ff9(\u6807\u8bb0\u8981\u5220\u9664\u822a\u70b9)
+function.deleterange=\u5220\u9664\u8f68\u8ff9\u70b9\u6bb5
+function.croptrack=\u4fee\u526a\u8f68\u8ff9
+function.interpolate=\u91cd\u53e0\u8f68\u8ff9\u70b9
 function.addtimeoffset=\u52a0\u5165\u65f6\u95f4\u5dee
 function.addaltitudeoffset=\u52a0\u5165\u9ad8\u5ea6\u504f\u79fb
 function.convertnamestotimes=\u822a\u70b9\u540d\u79f0\u8f6c\u4e3a\u65f6\u95f4
 function.deletefieldvalues=\u5220\u9664\u533a\u57df\u6570\u503c
 function.findwaypoint=\u67e5\u627e\u822a\u70b9
 function.pastecoordinates=\u8f93\u5165\u65b0\u5750\u6807
 function.addtimeoffset=\u52a0\u5165\u65f6\u95f4\u5dee
 function.addaltitudeoffset=\u52a0\u5165\u9ad8\u5ea6\u504f\u79fb
 function.convertnamestotimes=\u822a\u70b9\u540d\u79f0\u8f6c\u4e3a\u65f6\u95f4
 function.deletefieldvalues=\u5220\u9664\u533a\u57df\u6570\u503c
 function.findwaypoint=\u67e5\u627e\u822a\u70b9
 function.pastecoordinates=\u8f93\u5165\u65b0\u5750\u6807
-function.charts=\u9ad8\u5ea6\u901f\u5ea6\u56fe\u8868
+function.charts=\u56fe\u8868
 function.show3d=3D\u89c6\u56fe
 function.distances=\u8ddd\u79bb
 function.fullrangedetails=\u5168\u822a\u6bb5\u8be6\u7ec6\u4fe1\u606f
 function.setmapbg=\u80cc\u666f\u5730\u56fe
 function.setkmzimagesize=\u8bbe\u7f6eKMZ\u56fe\u50cf\u5c3a\u5bf8
 function.setpaths=\u8bbe\u7f6e\u7a0b\u5e8f\u8def\u5f84
 function.show3d=3D\u89c6\u56fe
 function.distances=\u8ddd\u79bb
 function.fullrangedetails=\u5168\u822a\u6bb5\u8be6\u7ec6\u4fe1\u606f
 function.setmapbg=\u80cc\u666f\u5730\u56fe
 function.setkmzimagesize=\u8bbe\u7f6eKMZ\u56fe\u50cf\u5c3a\u5bf8
 function.setpaths=\u8bbe\u7f6e\u7a0b\u5e8f\u8def\u5f84
-function.getgpsies=Gpsies\u8f68\u8ff9
-function.uploadgpsies=\u8f68\u8ff9\u4e0a\u4f20\u5230 Gpsies
+function.getgpsies=\u83b7\u53d6Gpsies\u8f68\u8ff9
+function.uploadgpsies=\u4e0a\u4f20\u8f68\u8ff9\u5230Gpsies
 function.lookupsrtm=\u4eceSRTM\u83b7\u5f97\u9ad8\u5ea6\u4fe1\u606f
 function.getwikipedia=\u7ef4\u57fa\u767e\u79d1\u6709\u5173\u672c\u5730\u6587\u7ae0
 function.searchwikipedianames=\u6309\u540d\u5b57\u4ece\u7ef4\u57fa\u767e\u79d1\u67e5\u627e
 function.lookupsrtm=\u4eceSRTM\u83b7\u5f97\u9ad8\u5ea6\u4fe1\u606f
 function.getwikipedia=\u7ef4\u57fa\u767e\u79d1\u6709\u5173\u672c\u5730\u6587\u7ae0
 function.searchwikipedianames=\u6309\u540d\u5b57\u4ece\u7ef4\u57fa\u767e\u79d1\u67e5\u627e
@@ -109,11 +112,11 @@ function.duplicatepoint=\u590d\u5236\u70b9
 function.setcolours=\u8bbe\u7f6e\u989c\u8272
 function.setlinewidth=\u8bbe\u7f6e\u7ebf\u4f53\u5bbd\u5ea6
 function.setlanguage=\u8bbe\u7f6e\u8bed\u8a00
 function.setcolours=\u8bbe\u7f6e\u989c\u8272
 function.setlinewidth=\u8bbe\u7f6e\u7ebf\u4f53\u5bbd\u5ea6
 function.setlanguage=\u8bbe\u7f6e\u8bed\u8a00
-function.connecttopoint=\u94fe\u63a5\u76f8\u7247
+function.connecttopoint=\u94fe\u63a5\u5230\u5f53\u524d\u70b9
 function.disconnectfrompoint=\u64a4\u9500\u94fe\u63a5
 function.removephoto=\u5220\u9664\u7167\u7247
 function.disconnectfrompoint=\u64a4\u9500\u94fe\u63a5
 function.removephoto=\u5220\u9664\u7167\u7247
-function.correlatephotos=\u94fe\u63a5\u76f8\u7247
-function.rearrangephotos=\u91cd\u6392\u76f8\u7247
+function.correlatephotos=\u94fe\u63a5\u7167\u7247\u7167
+function.rearrangephotos=\u91cd\u6392\u7167\u7247
 function.rotatephotoleft=\u5de6\u65cb\u8f6c
 function.rotatephotoright=\u53f3\u65cb\u8f6c
 function.photopopup=\u663e\u793a\u5f39\u51fa\u7167\u7247
 function.rotatephotoleft=\u5de6\u65cb\u8f6c
 function.rotatephotoright=\u53f3\u65cb\u8f6c
 function.photopopup=\u663e\u793a\u5f39\u51fa\u7167\u7247
@@ -137,9 +140,10 @@ dialog.exit.confirm.text=\u6570\u636e\u672a\u4fdd\u5b58\uff0c\u662f\u5426\u9000\
 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.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.deletepoint.deletephoto=\u5220\u9664\u94fe\u63a5\u5230\u8f68\u8ff9\u70b9\u7684\u7167\u7247\uff1f
+dialog.deletephoto.title=\u5220\u9664\u7167\u7247
+dialog.deletephoto.deletepoint=\u5220\u9664\u94fe\u63a5\u5230\u7167\u7247\u7684\u8f68\u8ff9\u70b9\uff1f
+dialog.deleteaudio.deletepoint=\u5220\u9664\u94fe\u63a5\u5230\u97f3\u9891\u7684\u8f68\u8ff9\u70b9\uff1f
 dialog.openoptions.title=\u6253\u5f00\u9009\u9879
 dialog.openoptions.filesnippet=\u63d0\u53d6\u6587\u4ef6\u7247\u6bb5
 dialog.load.table.field=\u6570\u636e\u6bb5
 dialog.openoptions.title=\u6253\u5f00\u9009\u9879
 dialog.openoptions.filesnippet=\u63d0\u53d6\u6587\u4ef6\u7247\u6bb5
 dialog.load.table.field=\u6570\u636e\u6bb5
@@ -159,10 +163,10 @@ dialog.open.contentsdoubled=\u6587\u4ef6\u542b\u6709\u4e24\u5957\u70b9\u4fe1\u60
 dialog.selecttracks.intro=\u9009\u62e9\u8981\u5bfc\u5165\u7684\u8f68\u8ff9
 dialog.selecttracks.noname=\u672a\u547d\u540d
 dialog.jpegload.subdirectories=\u542b\u6b21\u7ea7\u65b9\u4f4d
 dialog.selecttracks.intro=\u9009\u62e9\u8981\u5bfc\u5165\u7684\u8f68\u8ff9
 dialog.selecttracks.noname=\u672a\u547d\u540d
 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.jpegload.loadjpegswithoutcoords=\u542b\u65e0\u5750\u6807\u70b9\u7167\u7247
+dialog.jpegload.loadjpegsoutsidearea=\u542b\u533a\u57df\u5916\u7167\u7247
+dialog.jpegload.progress.title=\u5bfc\u5165\u7167\u7247
+dialog.jpegload.progress=\u8bf7\u7b49\u5f85\uff0c\u6b63\u641c\u7d22\u7167\u7247
 dialog.gpsload.nogpsbabel=\u627e\u4e0d\u5230Gpsbabel\uff0c\u7ee7\u7eed\uff1f
 dialog.gpsload.device=GPS\u8bbe\u5907\u540d\u79f0
 dialog.gpsload.format=GPS\u6587\u4ef6\u683c\u5f0f
 dialog.gpsload.nogpsbabel=\u627e\u4e0d\u5230Gpsbabel\uff0c\u7ee7\u7eed\uff1f
 dialog.gpsload.device=GPS\u8bbe\u5907\u540d\u79f0
 dialog.gpsload.format=GPS\u6587\u4ef6\u683c\u5f0f
@@ -185,9 +189,9 @@ dialog.save.overwrite.title=\u6587\u4ef6\u5df2\u5b58\u5728
 dialog.save.overwrite.text=\u6587\u4ef6\u5df2\u5b58\u5728\uff0c\u662f\u5426\u8986\u76d6\uff1f
 dialog.save.notypesselected=\u70b9\u7c7b\u578b\u672a\u9009\u5b9a
 dialog.exportkml.text=\u6570\u636e\u540d\u79f0
 dialog.save.overwrite.text=\u6587\u4ef6\u5df2\u5b58\u5728\uff0c\u662f\u5426\u8986\u76d6\uff1f
 dialog.save.notypesselected=\u70b9\u7c7b\u578b\u672a\u9009\u5b9a
 dialog.exportkml.text=\u6570\u636e\u540d\u79f0
-dialog.exportkml.altitude=\u7edd\u5bf9\u9ad8\u5ea6\uff08\u822a\u7a7a\u7528\uff09
+dialog.exportkml.altitude=\u7edd\u5bf9\u9ad8\u5ea6(\u822a\u7a7a\u7528)
 dialog.exportkml.kmz=\u538b\u7f29\u6210KMZ\u6587\u4ef6
 dialog.exportkml.kmz=\u538b\u7f29\u6210KMZ\u6587\u4ef6
-dialog.exportkml.exportimages=\u8f93\u51fa\u76f8\u7247\u7f29\u7565\u56fe\u81f3KMZ
+dialog.exportkml.exportimages=\u8f93\u51fa\u7f29\u7565\u56fe\u81f3KMZ
 dialog.exportkml.trackcolour=\u8f68\u8ff9\u989c\u8272
 dialog.exportgpx.name=\u540d\u79f0
 dialog.exportgpx.desc=\u63cf\u8ff0
 dialog.exportkml.trackcolour=\u8f68\u8ff9\u989c\u8272
 dialog.exportgpx.name=\u540d\u79f0
 dialog.exportgpx.desc=\u63cf\u8ff0
@@ -212,32 +216,32 @@ dialog.exportsvg.gradients=\u4f7f\u7528\u6e10\u53d8\u8272
 dialog.pointtype.desc=\u4fdd\u5b58\u4e0b\u5217\u70b9\uff1a
 dialog.pointtype.track=\u8f68\u8ff9\u70b9
 dialog.pointtype.waypoint=\u822a\u70b9
 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.pointtype.photo=\u7167\u7247\u70b9
 dialog.pointtype.audio=\u5e26\u58f0\u97f3\u7684\u822a\u70b9
 dialog.pointtype.selection=\u4ec5\u5df2\u9009\u62e9\u822a\u6bb5
 dialog.pointtype.audio=\u5e26\u58f0\u97f3\u7684\u822a\u70b9
 dialog.pointtype.selection=\u4ec5\u5df2\u9009\u62e9\u822a\u6bb5
-dialog.confirmreversetrack.title=\u786e\u8ba4\u53cd\u5411
-dialog.confirmreversetrack.text=\u8f68\u8ff9\u5305\u542b\u65f6\u95f4\u4fe1\u606f\uff0c\u53cd\u5411\u540e\u53ef\u80fd\u4e22\u5931\u3002\n\u662f\u5426\u7ee7\u7eed\uff1f
+dialog.confirmreversetrack.title=\u786e\u8ba4\u53cd\u8f6c
+dialog.confirmreversetrack.text=\u8f68\u8ff9\u5305\u542b\u65f6\u95f4\u4fe1\u606f\uff0c\u53cd\u8f6c\u540e\u53ef\u80fd\u4e22\u5931\u3002\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\u3002\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\u3002\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.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.interpolate.betweenwaypoints=\u521b\u5efa\u4e2d\u7ee7\u822a\u70b9\uff1f
+dialog.undo.title=\u64a4\u9500\u64cd\u4f5c
+dialog.undo.pretext=\u8bf7\u9009\u62e9\u8981\u64a4\u9500\u7684\u64cd\u4f5c
 dialog.undo.none.title=\u4e0d\u80fd\u64a4\u9500
 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\uff01
+dialog.undo.none.text=\u65e0\u64cd\u4f5c\u53ef\u64a4\u9500
+dialog.clearundo.title=\u6e05\u9664\u64a4\u9500\u64cd\u4f5c\u6e05\u5355
+dialog.clearundo.text=\u662f\u5426\u786e\u5b9e\u8981\u6e05\u9664\u64a4\u9500\u64cd\u4f5c\u6e05\u5355\uff1f\n\u64a4\u9500\u64cd\u4f5c\u4fe1\u606f\u4f1a\u4e22\u5931\uff01
 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.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.table.changed=\u5df2\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.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.pointnameedit.titlecase=\u6807\u9898\u952e
 dialog.addtimeoffset.add=\u5ef6\u540e\u65f6\u95f4
 dialog.addtimeoffset.subtract=\u63d0\u524d\u65f6\u95f4
 dialog.addtimeoffset.days=\u5929\u6570
 dialog.addtimeoffset.add=\u5ef6\u540e\u65f6\u95f4
 dialog.addtimeoffset.subtract=\u63d0\u524d\u65f6\u95f4
 dialog.addtimeoffset.days=\u5929\u6570
@@ -247,10 +251,10 @@ dialog.addtimeoffset.notimestamps=\u4e0d\u80fd\u6dfb\u52a0\u65f6\u95f4\u56e0\u4e
 dialog.findwaypoint.intro=\u8f93\u5165\u90e8\u5206\u822a\u70b9\u540d
 dialog.findwaypoint.search=\u641c\u7d22
 dialog.saveexif.title=\u4fdd\u5b58Exif
 dialog.findwaypoint.intro=\u8f93\u5165\u90e8\u5206\u822a\u70b9\u540d
 dialog.findwaypoint.search=\u641c\u7d22
 dialog.saveexif.title=\u4fdd\u5b58Exif
-dialog.saveexif.intro=\u9009\u62e9\u8981\u4fdd\u5b58\u7684\u76f8\u7247
+dialog.saveexif.intro=\u9009\u62e9\u8981\u4fdd\u5b58\u7684\u7167\u7247
 dialog.saveexif.nothingtosave=\u5750\u6807\u672a\u6539\u53d8\uff0c\u65e0\u4fdd\u5b58\u5185\u5bb9
 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.noexiftool=\u672a\u627e\u5230Exiftool\uff0c\u7ee7\u7eed\uff1f
+dialog.saveexif.table.photoname=\u7167\u7247\u540d
 dialog.saveexif.table.status=\u72b6\u6001
 dialog.saveexif.table.save=\u4fdd\u5b58
 dialog.saveexif.photostatus.connected=\u5df2\u94fe\u63a5
 dialog.saveexif.table.status=\u72b6\u6001
 dialog.saveexif.table.save=\u4fdd\u5b58
 dialog.saveexif.photostatus.connected=\u5df2\u94fe\u63a5
@@ -273,6 +277,8 @@ 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.fullrangedetails.intro=\u822a\u6bb5\u8be6\u60c5
 dialog.distances.currentpoint=\u5f53\u524d\u70b9
 dialog.distances.toofewpoints=\u9700\u8981\u822a\u70b9\u6765\u8ba1\u7b97\u8ddd\u79bb
 dialog.fullrangedetails.intro=\u822a\u6bb5\u8be6\u60c5
+dialog.fullrangedetails.coltotal=\u5305\u542b\u95f4\u65ad
+dialog.fullrangedetails.colsegments=\u4e0d\u5305\u542b\u95f4\u65ad
 dialog.setmapbg.intro=\u8bf7\u9009\u62e9\u5730\u56fe\uff0c\u6216\u6dfb\u52a0\u5730\u56fe
 dialog.addmapsource.title=\u6dfb\u52a0\u5730\u56fe
 dialog.addmapsource.sourcename=\u5730\u56fe\u6765\u6e90\u540d\u79f0
 dialog.setmapbg.intro=\u8bf7\u9009\u62e9\u5730\u56fe\uff0c\u6216\u6dfb\u52a0\u5730\u56fe
 dialog.addmapsource.title=\u6dfb\u52a0\u5730\u56fe
 dialog.addmapsource.sourcename=\u5730\u56fe\u6765\u6e90\u540d\u79f0
@@ -288,43 +294,44 @@ dialog.gpsies.nodescription=\u65e0\u63cf\u8ff0
 dialog.gpsies.nonefound=\u672a\u627e\u5230\u8f68\u8ff9
 dialog.gpsies.username=Gpsies\u7f51\u7ad9\u7528\u6237\u540d
 dialog.gpsies.password=Gpsies\u7f51\u7ad9\u5bc6\u7801
 dialog.gpsies.nonefound=\u672a\u627e\u5230\u8f68\u8ff9
 dialog.gpsies.username=Gpsies\u7f51\u7ad9\u7528\u6237\u540d
 dialog.gpsies.password=Gpsies\u7f51\u7ad9\u5bc6\u7801
-dialog.gpsies.keepprivate=\u8f68\u8ff9\u4fdd\u5bc6\uff08\u4e0d\u516c\u5f00\uff09
+dialog.gpsies.keepprivate=\u4e0d\u516c\u5f00\u8f68\u8ff9
 dialog.gpsies.confirmopenpage=\u6253\u5f00\u4e0a\u4f20\u8f68\u8ff9\u7684\u7f51\u7ad9\uff1f
 dialog.gpsies.activities=\u6d3b\u52a8\u7c7b\u578b
 dialog.gpsies.activity.trekking=\u5f92\u6b65
 dialog.gpsies.confirmopenpage=\u6253\u5f00\u4e0a\u4f20\u8f68\u8ff9\u7684\u7f51\u7ad9\uff1f
 dialog.gpsies.activities=\u6d3b\u52a8\u7c7b\u578b
 dialog.gpsies.activity.trekking=\u5f92\u6b65
-dialog.gpsies.activity.walking=\u7ade\u8d70
+dialog.gpsies.activity.walking=\u6b65\u884c
 dialog.gpsies.activity.jogging=\u8dd1\u6b65
 dialog.gpsies.activity.jogging=\u8dd1\u6b65
-dialog.gpsies.activity.biking=\u9a91\u81ea\u884c\u8f66
+dialog.gpsies.activity.biking=\u81ea\u884c\u8f66
 dialog.gpsies.activity.motorbiking=\u7535\u52a8\u81ea\u884c\u8f66
 dialog.gpsies.activity.snowshoe=\u96ea\u978b\u5065\u884c
 dialog.gpsies.activity.sailing=\u5e06\u8239
 dialog.gpsies.activity.skating=\u6ed1\u51b0
 dialog.wikipedia.column.name=\u6587\u7ae0\u9898\u76ee
 dialog.wikipedia.column.distance=\u8ddd\u79bb
 dialog.gpsies.activity.motorbiking=\u7535\u52a8\u81ea\u884c\u8f66
 dialog.gpsies.activity.snowshoe=\u96ea\u978b\u5065\u884c
 dialog.gpsies.activity.sailing=\u5e06\u8239
 dialog.gpsies.activity.skating=\u6ed1\u51b0
 dialog.wikipedia.column.name=\u6587\u7ae0\u9898\u76ee
 dialog.wikipedia.column.distance=\u8ddd\u79bb
-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\u3002\u7ee7\u7eed\uff1f
-dialog.correlate.photoselect.intro=\u9009\u62e9\u5df2\u94fe\u63a5\u76f8\u7247\u4f5c\u4e3a\u65f6\u95f4\u504f\u79fb
-dialog.correlate.select.photoname=\u76f8\u7247\u540d
+dialog.correlate.notimestamps=\u6570\u636e\u70b9\u4e2d\u65e0\u65f6\u95f4\u4fe1\u606f\uff0c\u7167\u7247\u65e0\u6cd5\u94fe\u63a5
+dialog.correlate.nouncorrelatedphotos=\u6240\u6709\u7167\u7247\u5df2\u94fe\u63a5\u3002\u7ee7\u7eed\uff1f
+dialog.correlate.nouncorrelatedaudios=\u6240\u6709\u97f3\u9891\u5df2\u94fe\u63a5\u3002\u7ee7\u7eed\uff1f
+dialog.correlate.photoselect.intro=\u9009\u62e9\u5df2\u94fe\u63a5\u7167\u7247\u4f5c\u4e3a\u65f6\u95f4\u504f\u79fb
+dialog.correlate.select.photoname=\u7167\u7247\u540d
 dialog.correlate.select.timediff=\u65f6\u95f4\u5dee
 dialog.correlate.select.timediff=\u65f6\u95f4\u5dee
-dialog.correlate.select.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.select.photolater=\u7167\u7247\u5ef6\u540e
+dialog.correlate.options.tip=\u63d0\u793a\uff1a\u624b\u52a8\u94fe\u63a5\u81f3\u5c11\u4e00\u5f20\u7167\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.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.minutes=\u5206
 dialog.correlate.options.offset.seconds=\u79d2
 dialog.correlate.options.offset.seconds=\u79d2
-dialog.correlate.options.photolater=\u76f8\u7247\u6ede\u540e\u4e8e\u8f68\u8ff9\u70b9
-dialog.correlate.options.pointlaterphoto=\u8f68\u8ff9\u70b9\u6ede\u540e\u4e8e\u76f8\u7247
-dialog.correlate.options.audiolater=\u58f0\u97f3\u6ede\u540e\u4e8e\u822a\u70b9
-dialog.correlate.options.pointlateraudio=\u822a\u70b9\u6ede\u540e\u4e8e\u58f0\u97f3
+dialog.correlate.options.photolater=\u7167\u7247\u6ede\u540e\u4e8e\u8f68\u8ff9\u70b9
+dialog.correlate.options.pointlaterphoto=\u8f68\u8ff9\u70b9\u6ede\u540e\u4e8e\u7167\u7247
+dialog.correlate.options.audiolater=\u97f3\u9891\u6ede\u540e\u4e8e\u822a\u70b9
+dialog.correlate.options.pointlateraudio=\u822a\u70b9\u6ede\u540e\u4e8e\u97f3\u9891
 dialog.correlate.options.limitspanel=\u5173\u8054\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=\u5173\u8054
 dialog.correlate.options.limitspanel=\u5173\u8054\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=\u5173\u8054
-dialog.correlate.alloutsiderange=\u65e0\u6cd5\u94fe\u63a5\uff0c\u6240\u6709\u76f8\u7247\u8d85\u51fa\u8f68\u8ff9\u65f6\u95f4\u8303\u56f4\u3002\n\u8bf7\u6539\u53d8\u65f6\u95f4\u504f\u79fb\u6216\u624b\u52a8\u94fe\u63a5\u81f3\u5c11\u4e00\u5f20\u76f8\u7247\u3002
+dialog.correlate.alloutsiderange=\u65e0\u6cd5\u94fe\u63a5\uff0c\u6240\u6709\u7167\u7247\u8d85\u51fa\u8f68\u8ff9\u65f6\u95f4\u8303\u56f4\u3002\n\u8bf7\u6539\u53d8\u65f6\u95f4\u504f\u79fb\u6216\u624b\u52a8\u94fe\u63a5\u81f3\u5c11\u4e00\u5f20\u5728\u7167\u7247\u3002
 dialog.correlate.filetimes=\u6587\u4ef6\u65f6\u95f4\u8868\u793a\u58f0\u97f3\u7684\uff1a
 dialog.correlate.filetimes2=\u90e8\u5206
 dialog.correlate.correltimes=\u5982\u8981\u5173\u8054\uff0c\u8bf7\u4f7f\u7528\uff1a
 dialog.correlate.filetimes=\u6587\u4ef6\u65f6\u95f4\u8868\u793a\u58f0\u97f3\u7684\uff1a
 dialog.correlate.filetimes2=\u90e8\u5206
 dialog.correlate.correltimes=\u5982\u8981\u5173\u8054\uff0c\u8bf7\u4f7f\u7528\uff1a
@@ -334,13 +341,12 @@ dialog.correlate.timestamp.end=\u7ed3\u675f
 dialog.correlate.audioselect.intro=\u9009\u62e9\u4ee5\u4e0b\u58f0\u97f3\u6587\u4ef6\u4f5c\u4e3a\u65f6\u95f4\u504f\u5dee
 dialog.correlate.select.audioname=\u58f0\u97f3\u6587\u4ef6\u540d\u5b57
 dialog.correlate.select.audiolater=\u58f0\u97f3\u5ef6\u8fdf
 dialog.correlate.audioselect.intro=\u9009\u62e9\u4ee5\u4e0b\u58f0\u97f3\u6587\u4ef6\u4f5c\u4e3a\u65f6\u95f4\u504f\u5dee
 dialog.correlate.select.audioname=\u58f0\u97f3\u6587\u4ef6\u540d\u5b57
 dialog.correlate.select.audiolater=\u58f0\u97f3\u5ef6\u8fdf
-dialog.rearrangephotos.desc=\u9009\u62e9\u76ee\u7684\u5730\u53ca\u6392\u76f8\u7247\u70b9
+dialog.rearrangephotos.desc=\u9009\u62e9\u76ee\u7684\u5730\u53ca\u7167\u7247\u70b9\u6392\u5217\u987a\u5e8f
 dialog.rearrangephotos.tostart=\u79fb\u5230\u5f00\u59cb
 dialog.rearrangephotos.toend=\u79fb\u5230\u672b\u5c3e
 dialog.rearrangephotos.nosort=\u4e0d\u6392\u5e8f
 dialog.rearrangephotos.sortbyfilename=\u6309\u540d\u79f0\u6392\u5e8f
 dialog.rearrangephotos.sortbytime=\u6309\u65f6\u95f4\u6392\u5e8f
 dialog.rearrangephotos.tostart=\u79fb\u5230\u5f00\u59cb
 dialog.rearrangephotos.toend=\u79fb\u5230\u672b\u5c3e
 dialog.rearrangephotos.nosort=\u4e0d\u6392\u5e8f
 dialog.rearrangephotos.sortbyfilename=\u6309\u540d\u79f0\u6392\u5e8f
 dialog.rearrangephotos.sortbytime=\u6309\u65f6\u95f4\u6392\u5e8f
-dialog.compress.nonefound=\u65e0\u6cd5\u5220\u9664\u6570\u636e\u70b9
 dialog.compress.closepoints.title=\u90bb\u8fd1\u70b9\u5220\u9664
 dialog.compress.closepoints.paramdesc=\u8303\u56f4\u7cfb\u6570
 dialog.compress.wackypoints.title=\u5f02\u5e38\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
@@ -351,6 +357,10 @@ dialog.compress.duplicates.title=\u91cd\u590d\u70b9\u5220\u9664
 dialog.compress.douglaspeucker.title=Douglas-Peucker \u538b\u7f29
 dialog.compress.douglaspeucker.paramdesc=\u95f4\u8ddd\u7cfb\u6570
 dialog.compress.summarylabel=\u8981\u5220\u9664\u7684\u70b9
 dialog.compress.douglaspeucker.title=Douglas-Peucker \u538b\u7f29
 dialog.compress.douglaspeucker.paramdesc=\u95f4\u8ddd\u7cfb\u6570
 dialog.compress.summarylabel=\u8981\u5220\u9664\u7684\u70b9
+dialog.compress.confirm1=\u5df2\u6807\u8bb0
+dialog.compress.confirm2=\u70b9\u3002\n\u70b9\u51fb \u8f68\u8ff9->\u5220\u9664 \u5220\u9664\u8fd9\u4e9b\u70b9
+dialog.compress.confirmnone=\u672a\u6807\u8bb0\u4efb\u4f55\u70b9
+dialog.deletemarked.nonefound=\u65e0\u6cd5\u5220\u9664\u6570\u636e\u70b9
 dialog.pastecoordinates.desc=\u5728\u6b64\u8f93\u5165\u6216\u7c98\u8d34\u5750\u6807\u70b9
 dialog.pastecoordinates.coords=\u5750\u6807\u70b9
 dialog.pastecoordinates.nothingfound=\u8bf7\u68c0\u67e5\u5750\u6807\u6570\u636e\u5e76\u91cd\u8bd5
 dialog.pastecoordinates.desc=\u5728\u6b64\u8f93\u5165\u6216\u7c98\u8d34\u5750\u6807\u70b9
 dialog.pastecoordinates.coords=\u5750\u6807\u70b9
 dialog.pastecoordinates.nothingfound=\u8bf7\u68c0\u67e5\u5750\u6807\u6570\u636e\u5e76\u91cd\u8bd5
@@ -372,24 +382,24 @@ dialog.about.systeminfo.gpsbabel=Gpsbabel \u662f\u5426\u5b89\u88c5
 dialog.about.systeminfo.gnuplot=Gnuplot \u662f\u5426\u5b89\u88c5
 dialog.about.systeminfo.exiflib=Exif \u5e93
 dialog.about.systeminfo.exiflib.internal=\u5185\u90e8
 dialog.about.systeminfo.gnuplot=Gnuplot \u662f\u5426\u5b89\u88c5
 dialog.about.systeminfo.exiflib=Exif \u5e93
 dialog.about.systeminfo.exiflib.internal=\u5185\u90e8
-dialog.about.systeminfo.exiflib.internal.failed=\u5185\u90e8\uff08\u672a\u627e\u5230\uff09
+dialog.about.systeminfo.exiflib.internal.failed=\u5185\u90e8(\u672a\u627e\u5230)
 dialog.about.systeminfo.exiflib.external=\u5916\u90e8
 dialog.about.systeminfo.exiflib.external=\u5916\u90e8
-dialog.about.systeminfo.exiflib.external.failed=\u5916\u90e8\uff08\u672a\u627e\u5230\uff09
+dialog.about.systeminfo.exiflib.external.failed=\u5916\u90e8(\u672a\u627e\u5230)
 dialog.about.yes=\u662f
 dialog.about.no=\u5426
 dialog.about.credits=\u81f4\u8c22
 dialog.about.credits.code=GpsPrune \u539f\u7801\u7f16\u5199
 dialog.about.credits.exifcode=Exif \u539f\u7801\u7f16\u5199
 dialog.about.yes=\u662f
 dialog.about.no=\u5426
 dialog.about.credits=\u81f4\u8c22
 dialog.about.credits.code=GpsPrune \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.icons=\u90e8\u5206\u56fe\u6807\u6765\u81ea\u4e8e
 dialog.about.credits.translators=\u8bd1\u8005
 dialog.about.credits.translators=\u8bd1\u8005
-dialog.about.credits.translations=\u7ffb\u8bd1\u52a9\u7406
+dialog.about.credits.translations=\u534f\u52a9\u7ffb\u8bd1
 dialog.about.credits.devtools=\u5f00\u53d1\u5de5\u5177
 dialog.about.credits.othertools=\u5176\u4ed6\u5de5\u5177
 dialog.about.credits.devtools=\u5f00\u53d1\u5de5\u5177
 dialog.about.credits.othertools=\u5176\u4ed6\u5de5\u5177
-dialog.about.credits.thanks=\u81f3\u8c22
+dialog.about.credits.thanks=\u81f4\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.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.newversion1=\u53d1\u73b0\u65b0\u7248\u672c\uff01\u6700\u65b0\u7248\u672c\u662f\uff1a
 dialog.checkversion.newversion2=
 dialog.checkversion.releasedate1=\u65b0\u7248\u672c\u53d1\u884c\u4e8e
 dialog.checkversion.releasedate2=
 dialog.checkversion.newversion2=
 dialog.checkversion.releasedate1=\u65b0\u7248\u672c\u53d1\u884c\u4e8e
 dialog.checkversion.releasedate2=
@@ -400,18 +410,17 @@ dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
 dialog.saveconfig.desc=\u4e0b\u5217\u8bbe\u7f6e\u5c06\u4fdd\u5b58\u5230\u8bbe\u7f6e\u6587\u4ef6
 dialog.saveconfig.prune.trackdirectory=\u8f68\u8ff9\u6587\u4ef6\u5939
 dialog.keys.macmodifier=Command
 dialog.saveconfig.desc=\u4e0b\u5217\u8bbe\u7f6e\u5c06\u4fdd\u5b58\u5230\u8bbe\u7f6e\u6587\u4ef6
 dialog.saveconfig.prune.trackdirectory=\u8f68\u8ff9\u6587\u4ef6\u5939
-dialog.saveconfig.prune.photodirectory=\u76f8\u7247\u6587\u4ef6\u5939
+dialog.saveconfig.prune.photodirectory=\u7167\u7247\u6587\u4ef6\u5939
 dialog.saveconfig.prune.languagecode=\u8bed\u8a00\u9009\u62e9(ZH)
 dialog.saveconfig.prune.languagefile=\u8bed\u8a00\u6587\u4ef6\u5305
 dialog.saveconfig.prune.gpsdevice=GPS\u7aef\u53e3\u540d\u79f0
 dialog.saveconfig.prune.gpsformat=GPS\u6587\u4ef6\u683c\u5f0f
 dialog.saveconfig.prune.povrayfont=Povray \u5b57\u4f53
 dialog.saveconfig.prune.languagecode=\u8bed\u8a00\u9009\u62e9(ZH)
 dialog.saveconfig.prune.languagefile=\u8bed\u8a00\u6587\u4ef6\u5305
 dialog.saveconfig.prune.gpsdevice=GPS\u7aef\u53e3\u540d\u79f0
 dialog.saveconfig.prune.gpsformat=GPS\u6587\u4ef6\u683c\u5f0f
 dialog.saveconfig.prune.povrayfont=Povray \u5b57\u4f53
-dialog.saveconfig.prune.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.gnuplotpath=gnuplot\u8def\u5f84
 dialog.saveconfig.prune.gpsbabelpath=gpsbabel\u8def\u5f84
 dialog.saveconfig.prune.exiftoolpath=exiftool\u8def\u5f84
-dialog.saveconfig.prune.mapsource=\u5df2\u9009\u62e9\u7684\u5730\u56fe\u6e90
-dialog.saveconfig.prune.mapsourcelist=\u5730\u56fe\u6e90
+dialog.saveconfig.prune.mapsource=\u5df2\u9009\u62e9\u7684\u5730\u56fe\u6570\u636e\u6e90
+dialog.saveconfig.prune.mapsourcelist=\u5730\u56fe\u6570\u636e\u6e90
 dialog.saveconfig.prune.diskcache=\u5b58\u50a8\u8def\u5f84
 dialog.saveconfig.prune.kmzimagewidth=KMZ\u56fe\u50cf\u5bbd\u5ea6
 dialog.saveconfig.prune.kmzimageheight=KMZ\u56fe\u50cf\u9ad8\u5ea6
 dialog.saveconfig.prune.diskcache=\u5b58\u50a8\u8def\u5f84
 dialog.saveconfig.prune.kmzimagewidth=KMZ\u56fe\u50cf\u5bbd\u5ea6
 dialog.saveconfig.prune.kmzimageheight=KMZ\u56fe\u50cf\u9ad8\u5ea6
@@ -419,7 +428,7 @@ dialog.saveconfig.prune.colourscheme=\u989c\u8272
 dialog.saveconfig.prune.linewidth=\u7ebf\u4f53\u5bbd\u5ea6
 dialog.saveconfig.prune.kmltrackcolour=KML\u8f68\u8ff9\u989c\u8272
 dialog.saveconfig.prune.autosavesettings=\u81ea\u52a8\u4fdd\u5b58\u8bbe\u7f6e
 dialog.saveconfig.prune.linewidth=\u7ebf\u4f53\u5bbd\u5ea6
 dialog.saveconfig.prune.kmltrackcolour=KML\u8f68\u8ff9\u989c\u8272
 dialog.saveconfig.prune.autosavesettings=\u81ea\u52a8\u4fdd\u5b58\u8bbe\u7f6e
-dialog.setpaths.intro=\u82e5\u9700\u8981\uff0c\u53ef\u8bbe\u5b9a\u5916\u6302\u7a0b\u5e8f\u8def\u5f84
+dialog.setpaths.intro=\u5982\u679c\u9700\u8981\uff0c\u53ef\u8bbe\u5b9a\u5916\u6302\u7a0b\u5e8f\u8def\u5f84
 dialog.setpaths.found=\u627e\u5230\u8def\u5f84\uff1f
 dialog.addaltitude.noaltitudes=\u8f68\u8ff9\u4e0d\u542b\u9ad8\u5ea6\u4fe1\u606f
 dialog.addaltitude.desc=\u9ad8\u5ea6\u504f\u79fb
 dialog.setpaths.found=\u627e\u5230\u8def\u5f84\uff1f
 dialog.addaltitude.noaltitudes=\u8f68\u8ff9\u4e0d\u542b\u9ad8\u5ea6\u4fe1\u606f
 dialog.addaltitude.desc=\u9ad8\u5ea6\u504f\u79fb
@@ -443,26 +452,27 @@ dialog.setlanguage.language=\u8bed\u8a00
 dialog.setlanguage.languagefile=\u8bed\u8a00\u5305
 dialog.setlanguage.endmessage=\u73b0\u5728\u8bf7\u4fdd\u5b58\u8bbe\u7f6e\u5e76\u91cd\u542fGpsPrune\n\u4f7f\u8bbe\u7f6e\u751f\u6548
 dialog.setlanguage.endmessagewithautosave=\u8981\u4f7f\u6240\u9009\u8bed\u8a00\u751f\u6548\uff0c\u8bf7\u91cd\u65b0\u542f\u52a8GosPrune
 dialog.setlanguage.languagefile=\u8bed\u8a00\u5305
 dialog.setlanguage.endmessage=\u73b0\u5728\u8bf7\u4fdd\u5b58\u8bbe\u7f6e\u5e76\u91cd\u542fGpsPrune\n\u4f7f\u8bbe\u7f6e\u751f\u6548
 dialog.setlanguage.endmessagewithautosave=\u8981\u4f7f\u6240\u9009\u8bed\u8a00\u751f\u6548\uff0c\u8bf7\u91cd\u65b0\u542f\u52a8GosPrune
-dialog.diskcache.save=\u5730\u56fe\u56fe\u7247\u4fdd\u5b58\u5230\u7535\u8111
-dialog.diskcache.dir=\u4fdd\u5b58\u8def\u5f84
-dialog.diskcache.createdir=\u65b0\u5efa\u8def\u5f84
-dialog.diskcache.nocreate=\u672a\u65b0\u5efa\u8def\u5f84
+dialog.diskcache.save=\u4fdd\u5b58\u5730\u56fe\u56fe\u7247
+dialog.diskcache.dir=\u4e34\u65f6\u6587\u4ef6\u5939
+dialog.diskcache.createdir=\u65b0\u5efa\u6587\u4ef6\u5939
+dialog.diskcache.nocreate=\u6587\u4ef6\u5939\u672a\u521b\u5efa
+dialog.diskcache.cannotwrite=\u65e0\u6cd5\u5728\u6307\u5b9a\u6587\u4ef6\u5939\u4e0b\u4fdd\u5b58\u5730\u56fe\u5757
 dialog.diskcache.table.path=\u8def\u5f84
 dialog.diskcache.table.usedby=\u4f7f\u7528\u8005
 dialog.diskcache.table.path=\u8def\u5f84
 dialog.diskcache.table.usedby=\u4f7f\u7528\u8005
-dialog.diskcache.table.zoom=\u653e\u5927\u7f29\u5c0f
-dialog.diskcache.table.tiles=\u627e\u5230\u7684\u5730\u56fe\u533a\u57df\u6570\u636e
+dialog.diskcache.table.zoom=\u7f29\u653e\u7ea7\u522b
+dialog.diskcache.table.tiles=\u5730\u56fe\u5757
 dialog.diskcache.table.megabytes=MB
 dialog.diskcache.table.megabytes=MB
-dialog.diskcache.tileset=\u5730\u56fe\u533a\u57df\u6570\u5b58\u653e\u8def\u5f84
+dialog.diskcache.tileset=\u5730\u56fe\u5757\u5b58\u653e\u8def\u5f84
 dialog.diskcache.tileset.multiple=\u6570\u76ee
 dialog.diskcache.tileset.multiple=\u6570\u76ee
-dialog.diskcache.deleteold=\u5220\u9664\u65e7\u533a\u57df\u6570\u636e
+dialog.diskcache.deleteold=\u5220\u9664\u65e7\u5730\u56fe\u5757
 dialog.diskcache.maximumage=\u6700\u957f\u65f6\u95f4(\u5929)
 dialog.diskcache.maximumage=\u6700\u957f\u65f6\u95f4(\u5929)
-dialog.diskcache.deleteall=\u5220\u9664\u6240\u6709\u533a\u57df\u6570\u636e
+dialog.diskcache.deleteall=\u5220\u9664\u6240\u6709\u5730\u56fe\u5757
 dialog.diskcache.deleted1=\u5df2\u5220\u9664
 dialog.diskcache.deleted2=\u7f13\u5b58\u5185\u6587\u4ef6
 dialog.deletefieldvalues.intro=\u9009\u62e9\u5f53\u524d\u8303\u56f4\u5185\u8981\u5220\u9664\u7684\u533a\u57df
 dialog.diskcache.deleted1=\u5df2\u5220\u9664
 dialog.diskcache.deleted2=\u7f13\u5b58\u5185\u6587\u4ef6
 dialog.deletefieldvalues.intro=\u9009\u62e9\u5f53\u524d\u8303\u56f4\u5185\u8981\u5220\u9664\u7684\u533a\u57df
-dialog.setlinewidth.text=\u8f93\u5165\u8f68\u8ff9\u7ebf\u5bbd\u50cf\u7d20\u503c\uff081-4\uff09
-dialog.downloadosm.desc=\u786e\u8ba4\u4eceOSM\u4e0b\u8f7d\u8be5\u5730\u533a\u539f\u59cb\u6570\u636e
-dialog.searchwikipedianames.search=\u67e5\u627e
+dialog.setlinewidth.text=\u8f93\u5165\u8f68\u8ff9\u7ebf\u5bbd\u50cf\u7d20\u503c(1-4)
+dialog.downloadosm.desc=\u786e\u8ba4\u4eceOSM\u4e0b\u8f7d\u8be5\u5730\u533a\u539f\u59cb\u6570\u636e:
+dialog.searchwikipedianames.search=\u67e5\u627e:
 
 # 3d window
 dialog.3d.title=GpsPrune 3D \u663e\u793a
 
 # 3d window
 dialog.3d.title=GpsPrune 3D \u663e\u793a
@@ -479,27 +489,28 @@ 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.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.reverserange=\u53cd\u8f6c\u7684\u8303\u56f4
 confirm.addtimeoffset=\u5df2\u52a0\u4e0a\u65f6\u95f4\u504f\u5dee
 confirm.addaltitudeoffset=\u5df2\u52a0\u4e0a\u9ad8\u5ea6\u504f\u5dee
 confirm.rearrangewaypoints=\u91cd\u65b0\u914d\u7f6e\u7684\u822a\u70b9
 confirm.addtimeoffset=\u5df2\u52a0\u4e0a\u65f6\u95f4\u504f\u5dee
 confirm.addaltitudeoffset=\u5df2\u52a0\u4e0a\u9ad8\u5ea6\u504f\u5dee
 confirm.rearrangewaypoints=\u91cd\u65b0\u914d\u7f6e\u7684\u822a\u70b9
-confirm.rearrangephotos=\u76f8\u7247\u5df2\u91cd\u6392
+confirm.rearrangephotos=\u7167\u7247\u5df2\u91cd\u6392
 confirm.cutandmove=\u5df2\u79fb\u52a8\u7684\u8f68\u8ff9\u6bb5
 confirm.cutandmove=\u5df2\u79fb\u52a8\u7684\u8f68\u8ff9\u6bb5
+confirm.interpolate=\u8f68\u8ff9\u70b9\u5df2\u6dfb\u52a0
 confirm.convertnamestotimes=\u822a\u70b9\u540d\u79f0\u5df2\u8f6c\u6362
 confirm.saveexif.ok1=\u5df2\u4fdd\u5b58
 confirm.convertnamestotimes=\u822a\u70b9\u540d\u79f0\u5df2\u8f6c\u6362
 confirm.saveexif.ok1=\u5df2\u4fdd\u5b58
-confirm.saveexif.ok2=\u76f8\u7247\u6587\u4ef6
+confirm.saveexif.ok2=\u7167\u7247\u6587\u4ef6
 confirm.undo.single=\u5df2\u64a4\u9500\u7684\u64cd\u4f5c
 confirm.undo.multi=\u5df2\u64a4\u9500\u7684\u64cd\u4f5c
 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.jpegload.single=\u5df2\u52a0\u5165\u7167\u7247
+confirm.jpegload.multi=\u5df2\u52a0\u5165\u7167\u7247
 confirm.media.connect=\u5a92\u4f53\u5df2\u5173\u8054
 confirm.media.connect=\u5a92\u4f53\u5df2\u5173\u8054
-confirm.photo.disconnect=\u76f8\u7247\u672a\u94fe\u63a5
+confirm.photo.disconnect=\u7167\u7247\u672a\u94fe\u63a5
 confirm.audio.disconnect=\u58f0\u97f3\u672a\u94fe\u63a5
 confirm.media.removed=\u5df2\u5220\u9664
 confirm.audio.disconnect=\u58f0\u97f3\u672a\u94fe\u63a5
 confirm.media.removed=\u5df2\u5220\u9664
-confirm.correlatephotos.single=\u76f8\u7247\u5df2\u94fe\u63a5
-confirm.correlatephotos.multi=\u76f8\u7247\u5df2\u94fe\u63a5
+confirm.correlatephotos.single=\u7167\u7247\u5df2\u94fe\u63a5
+confirm.correlatephotos.multi=\u7167\u7247\u5df2\u94fe\u63a5
 confirm.createpoint=\u5df2\u521b\u5efa\u70b9
 confirm.createpoint=\u5df2\u521b\u5efa\u70b9
-confirm.rotatephoto=\u76f8\u7247\u5df2\u65cb\u8f6c
+confirm.rotatephoto=\u7167\u7247\u5df2\u65cb\u8f6c
 confirm.running=\u8bf7\u7a0d\u7b49...
 confirm.lookupsrtm1=\u627e\u5230
 confirm.lookupsrtm2=\u9ad8\u5ea6\u503c
 confirm.running=\u8bf7\u7a0d\u7b49...
 confirm.lookupsrtm1=\u627e\u5230
 confirm.lookupsrtm2=\u9ad8\u5ea6\u503c
@@ -565,7 +576,7 @@ 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.index.selected=\u7b2c
 details.index.of=\u70b9\u53d6\u81ea
 details.nopointselection=\u6ca1\u6709\u9009\u62e9\u70b9
-details.photofile=\u76f8\u7247\u6587\u4ef6
+details.photofile=\u7167\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.norangeselection=\u6ca1\u6709\u9009\u62e9\u8f68\u8ff9/\u822a\u70b9\u6bb5
 details.rangedetails=\u8f68\u8ff9/\u822a\u70b9\u6bb5\u4fe1\u606f
 details.range.selected=\u9009\u4e2d
@@ -580,19 +591,19 @@ display.range.time.mins=\u5206
 display.range.time.hours=\u5c0f\u65f6
 display.range.time.days=\u5929
 details.range.avespeed=\u5e73\u5747\u901f\u5ea6
 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.maxspeed=\u6700\u5927\u901f\u5ea6
 details.range.numsegments=\u6bb5\u6570
 details.range.pace=\u6b65\u901f
 details.range.gradient=\u5761\u5ea6
 details.lists.waypoints=\u822a\u70b9
 details.range.maxspeed=\u6700\u5927\u901f\u5ea6
 details.range.numsegments=\u6bb5\u6570
 details.range.pace=\u6b65\u901f
 details.range.gradient=\u5761\u5ea6
 details.lists.waypoints=\u822a\u70b9
-details.lists.photos=\u76f8\u7247
+details.lists.photos=\u7167\u7247
 details.lists.audio=\u58f0\u97f3
 details.lists.audio=\u58f0\u97f3
-details.photodetails=\u76f8\u7247\u4fe1\u606f
-details.nophoto=\u65e0\u76f8\u7247\u88ab\u9009\u4e2d
-details.photo.loading=\u6b63\u5bfc\u5165
+details.photodetails=\u7167\u7247\u4fe1\u606f
+details.nophoto=\u6ca1\u6709\u9009\u4e2d\u7167\u7247
+details.photo.loading=\u5bfc\u5165\u4e2d
 details.photo.bearing=\u65b9\u5411
 details.media.connected=\u5df2\u94fe\u63a5
 details.photo.bearing=\u65b9\u5411
 details.media.connected=\u5df2\u94fe\u63a5
+details.media.fullpath=\u5b8c\u6574\u8def\u5f84
 details.audiodetails=\u8be6\u7ec6\u4fe1\u606f
 details.noaudio=\u672a\u9009\u62e9\u58f0\u97f3\u6587\u4ef6
 details.audio.file=\u58f0\u97f3\u6587\u4ef6
 details.audiodetails=\u8be6\u7ec6\u4fe1\u606f
 details.noaudio=\u672a\u9009\u62e9\u58f0\u97f3\u6587\u4ef6
 details.audio.file=\u58f0\u97f3\u6587\u4ef6
@@ -626,10 +637,15 @@ units.feet=\u82f1\u5c3a
 units.feet.short=\u82f1\u5c3a
 units.kilometres=\u5343\u7c73
 units.kilometres.short=\u5343\u7c73
 units.feet.short=\u82f1\u5c3a
 units.kilometres=\u5343\u7c73
 units.kilometres.short=\u5343\u7c73
-units.kmh=\u5343\u7c73/\u65f6
+units.kilometresperhour.short=\u5343\u7c73/\u65f6
 units.miles=\u82f1\u91cc
 units.miles.short=\u82f1\u91cc
 units.miles=\u82f1\u91cc
 units.miles.short=\u82f1\u91cc
-units.mph=\u82f1\u91cc/\u65f6
+units.milesperhour.short=\u82f1\u91cc/\u65f6
+units.nauticalmiles=\u6d77\u91cc
+units.nauticalmiles.short=\u6d77\u91cc
+units.nauticalmilesperhour.short=\u6d77\u91cc/\u65f6
+units.metrespersec.short=\u7c73/\u79d2
+units.feetpersec.short=\u82f1\u5c3a/\u79d2
 units.hours=\u5c0f\u65f6
 units.degminsec=\u5ea6-\u5206-\u79d2
 units.degmin=\u5ea6-\u5206
 units.hours=\u5c0f\u65f6
 units.degminsec=\u5ea6-\u5206-\u79d2
 units.degmin=\u5ea6-\u5206
@@ -648,16 +664,17 @@ cardinal.w=W
 
 # Undo operations
 undo.load=\u5bfc\u5165\u6570\u636e
 
 # Undo operations
 undo.load=\u5bfc\u5165\u6570\u636e
-undo.loadphotos=\u5bfc\u5165\u76f8\u7247
+undo.loadphotos=\u5bfc\u5165\u7167\u7247
 undo.loadaudios=\u8f7d\u5165\u58f0\u97f3\u6587\u4ef6
 undo.editpoint=\u7f16\u8f91\u8f68\u8ff9\u70b9
 undo.deletepoint=\u5220\u9664\u8f68\u8ff9\u70b9
 undo.loadaudios=\u8f7d\u5165\u58f0\u97f3\u6587\u4ef6
 undo.editpoint=\u7f16\u8f91\u8f68\u8ff9\u70b9
 undo.deletepoint=\u5220\u9664\u8f68\u8ff9\u70b9
-undo.removephoto=\u5220\u9664\u76f8\u7247
+undo.removephoto=\u5220\u9664\u7167\u7247
 undo.removeaudio=\u5220\u9664\u58f0\u97f3\u6587\u4ef6
 undo.deleterange=\u5220\u9664\u6bb5
 undo.removeaudio=\u5220\u9664\u58f0\u97f3\u6587\u4ef6
 undo.deleterange=\u5220\u9664\u6bb5
-undo.compress=\u538b\u7f29\u8f68\u8ff9
+undo.croptrack=\u4fee\u526a\u8f68\u8ff9
+undo.deletemarked=\u538b\u7f29\u8f68\u8ff9
 undo.insert=\u63d2\u5165\u822a\u70b9
 undo.insert=\u63d2\u5165\u822a\u70b9
-undo.reverse=\u53cd\u5411\u6bb5
+undo.reverse=\u53cd\u8f6c\u6bb5
 undo.mergetracksegments=\u5408\u5e76\u6bb5
 undo.addtimeoffset=\u6dfb\u52a0\u65f6\u95f4\u504f\u79fb
 undo.addaltitudeoffset=\u52a0\u5165\u9ad8\u5ea6\u504f\u79fb
 undo.mergetracksegments=\u5408\u5e76\u6bb5
 undo.addtimeoffset=\u6dfb\u52a0\u65f6\u95f4\u504f\u79fb
 undo.addaltitudeoffset=\u52a0\u5165\u9ad8\u5ea6\u504f\u79fb
@@ -665,33 +682,33 @@ undo.rearrangewaypoints=\u91cd\u65b0\u914d\u7f6e\u822a\u70b9
 undo.cutandmove=\u79fb\u52a8\u6bb5
 undo.connect=\u94fe\u63a5
 undo.disconnect=\u65ad\u5f00
 undo.cutandmove=\u79fb\u52a8\u6bb5
 undo.connect=\u94fe\u63a5
 undo.disconnect=\u65ad\u5f00
-undo.correlatephotos=\u94fe\u63a5\u76f8\u7247
-undo.rearrangephotos=\u91cd\u62cd\u76f8\u7247
+undo.correlatephotos=\u94fe\u63a5\u7167\u7247
+undo.rearrangephotos=\u91cd\u6392\u7167\u7247
 undo.createpoint=\u521b\u5efa\u8f68\u8ff9\u70b9
 undo.createpoint=\u521b\u5efa\u8f68\u8ff9\u70b9
-undo.rotatephoto=\u65cb\u8f6c\u76f8\u7247
-undo.convertnamestotimes=\u540d\u79f0\u8f6c\u4e3a\u65f6\u95f4
+undo.rotatephoto=\u65cb\u8f6c\u7167\u7247
+undo.convertnamestotimes=\u5c06\u540d\u79f0\u8f6c\u4e3a\u65f6\u95f4
 undo.lookupsrtm=\u4eceSRTM\u67e5\u627e\u9ad8\u5ea6
 undo.deletefieldvalues=\u5220\u9664\u533a\u57df\u6570\u636e
 undo.lookupsrtm=\u4eceSRTM\u67e5\u627e\u9ad8\u5ea6
 undo.deletefieldvalues=\u5220\u9664\u533a\u57df\u6570\u636e
-undo.correlateaudios=\u5173\u8054\u58f0\u97f3
+undo.correlateaudios=\u5173\u8054\u97f3\u9891
 
 # 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 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\u3002\u4fdd\u5b58\u526f\u672c\uff1f
-error.saveexif.failed1=\u56fe\u7247
-error.saveexif.failed2=\u4fdd\u5b58\u5931\u8d25
+error.saveexif.filenotfound=\u627e\u4e0d\u5230\u7167\u7247\u6587\u4ef6
+error.saveexif.cannotoverwrite1=\u7167\u7247
+error.saveexif.cannotoverwrite2=\u662f\u53ea\u8bfb\u6587\u4ef6\u3002\u4fdd\u5b58\u526f\u672c\uff1f
+error.saveexif.failed1=\u65e0\u6cd5\u4fdd\u5b58
+error.saveexif.failed2=\u5f20\u7167\u7247
 error.saveexif.forced1=
 error.saveexif.forced1=
-error.saveexif.forced2=\u4e2a\u56fe\u7247\u9700\u8981\u5f3a\u5236\u6267\u884c
+error.saveexif.forced2=\u5f20\u7167\u7247\u9700\u8981\u5f3a\u5236\u6267\u884c
 error.load.dialogtitle=\u5bfc\u5165\u6570\u636e\u9519\u8bef
 error.load.noread=\u65e0\u6cd5\u8bfb\u6587\u4ef6
 error.load.nopoints=\u6587\u4ef6\u4e2d\u65e0\u5750\u6807\u4fe1\u606f
 error.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.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.dialogtitle=\u5bfc\u5165\u7167\u7247\u9519\u8bef
 error.jpegload.nofilesfound=\u627e\u4e0d\u5230\u6587\u4ef6
 error.jpegload.nojpegsfound=\u627e\u4e0d\u5230Jpeg\u6587\u4ef6
 error.jpegload.nogpsfound=\u627e\u4e0d\u5230GPS\u4fe1\u606f
 error.jpegload.nofilesfound=\u627e\u4e0d\u5230\u6587\u4ef6
 error.jpegload.nojpegsfound=\u627e\u4e0d\u5230Jpeg\u6587\u4ef6
 error.jpegload.nogpsfound=\u627e\u4e0d\u5230GPS\u4fe1\u606f
@@ -714,7 +731,9 @@ error.lookupsrtm.nonefound=\u65e0\u9ad8\u5ea6\u4fe1\u606f
 error.lookupsrtm.nonerequired=\u6240\u6709\u70b9\u5747\u542b\u9ad8\u5ea6\u4fe1\u606f
 error.gpsies.uploadnotok=gpsies\u670d\u52a1\u5668\u8fd4\u56de\u4fe1\u606f\uff1a
 error.gpsies.uploadfailed=\u4e0a\u4f20\u5931\u8d25
 error.lookupsrtm.nonerequired=\u6240\u6709\u70b9\u5747\u542b\u9ad8\u5ea6\u4fe1\u606f
 error.gpsies.uploadnotok=gpsies\u670d\u52a1\u5668\u8fd4\u56de\u4fe1\u606f\uff1a
 error.gpsies.uploadfailed=\u4e0a\u4f20\u5931\u8d25
+error.showphoto.failed=\u52a0\u8f7d\u7167\u7247\u5931\u8d25
 error.playaudiofailed=\u65e0\u6cd5\u64ad\u653e\u58f0\u97f3\u6587\u4ef6
 error.cache.notthere=\u672a\u627e\u5230\u533a\u57df\u6570\u636e\u7f13\u5b58\u6587\u4ef6\u5939
 error.cache.empty=\u533a\u57df\u6570\u636e\u6587\u4ef6\u5939\u7a7a
 error.cache.cannotdelete=\u65e0\u53ef\u5220\u9664\u533a\u57df\u6570\u636e
 error.playaudiofailed=\u65e0\u6cd5\u64ad\u653e\u58f0\u97f3\u6587\u4ef6
 error.cache.notthere=\u672a\u627e\u5230\u533a\u57df\u6570\u636e\u7f13\u5b58\u6587\u4ef6\u5939
 error.cache.empty=\u533a\u57df\u6570\u636e\u6587\u4ef6\u5939\u7a7a
 error.cache.cannotdelete=\u65e0\u53ef\u5220\u9664\u533a\u57df\u6570\u636e
+error.interpolate.invalidparameter=\u8f93\u5165\u70b9\u6570\u91cf\u5fc5\u987b\u57281\u52301000\u4e4b\u95f4
index c55fc557ec6ee7bc5b58df0e19879b35935362ba..ab4f366d820967c67674e916c15985cddc5debb2 100644 (file)
@@ -88,7 +88,11 @@ public abstract class MediaHelper
                }
 
                // If we haven't got a result by now, try to load plain file
                }
 
                // If we haven't got a result by now, try to load plain file
-               File file = (inSourceFile == null ? new File(inPath) : new File(inSourceFile.getParent(), inPath));
+               File file = new File(inPath);
+               if (inSourceFile != null && !file.isAbsolute()) {
+                       file = new File(inSourceFile.getParent(), inPath);
+               }
+               // awkward construction because new File(startPath, absolutePath) doesn't work
                return createMediaObject(file);
        }
 
                return createMediaObject(file);
        }
 
index 76ed15785dc1fff93ec18661790e8c9955539711..2dd63dec16088fa4350b5b914c2c25a8d59ccdbc 100644 (file)
@@ -92,7 +92,8 @@ public class NmeaFileLoader
                if (messages.size() > 0)
                {
                        _app.informDataLoaded(getFieldArray(), makeDataArray(messages),
                if (messages.size() > 0)
                {
                        _app.informDataLoaded(getFieldArray(), makeDataArray(messages),
-                               Altitude.Format.METRES, new SourceInfo(inFile, SourceInfo.FILE_TYPE.NMEA));
+                               Altitude.Format.METRES, new SourceInfo(inFile, SourceInfo.FILE_TYPE.NMEA),
+                               null);
                }
        }
 
                }
        }
 
index 512b7e55fac5d9a72f58b8bd1aa1e0c870a8363c..1f88012807485d8010f387947bb00d9621375a03 100644 (file)
@@ -538,7 +538,7 @@ public class TextFileLoader
                // give data to App
                SourceInfo sourceInfo = new SourceInfo(_file, SourceInfo.FILE_TYPE.TEXT);
                _app.informDataLoaded(_fieldTableModel.getFieldArray(),
                // give data to App
                SourceInfo sourceInfo = new SourceInfo(_file, SourceInfo.FILE_TYPE.TEXT);
                _app.informDataLoaded(_fieldTableModel.getFieldArray(),
-                       _fileExtractTableModel.getData(), altitudeFormat, sourceInfo);
+                       _fileExtractTableModel.getData(), altitudeFormat, sourceInfo, null);
                // clear up file cacher
                _fileCacher.clear();
                // dispose of dialog
                // clear up file cacher
                _fileCacher.clear();
                // dispose of dialog
index a66883fa2fbd202203cfd10e0230968d94a6cf0d..a951cf75bf705009d720f4ffe642df8e1f28f3fb 100644 (file)
@@ -1,5 +1,5 @@
-GpsPrune version 13.4
-=====================
+GpsPrune version 14
+===================
 
 GpsPrune is an application for viewing, editing and managing coordinate data from GPS systems,
 including format conversion, charting and photo correlation.
 
 GpsPrune is an application for viewing, editing and managing coordinate data from GPS systems,
 including format conversion, charting and photo correlation.
@@ -17,7 +17,7 @@ Running
 =======
 
 To run GpsPrune from the jar file, simply call it from a command prompt or shell:
 =======
 
 To run GpsPrune from the jar file, simply call it from a command prompt or shell:
-   java -jar gpsprune_13.4.jar
+   java -jar gpsprune_14.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
 
 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,41 +25,18 @@ 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:
 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 gpsprune_13.4.jar --lang=DE
-
+   java -jar gpsprune_14.jar --lang=DE
 
 
-New with version 13.4
-=====================
-The following features were added since version 13.3:
-  - Fix for empty settings
-  - Fix for file suffixes of cached tiles
-  - Removed Osma source as tiles@home has been discontinued
 
 
-New with version 13.3
-=====================
-The following features were added since version 13.2:
-  - Completion of Italian translations
-  - Fix for exporting track names to version 1.1 gpx files
-  - Changed OpenCycleMap url
-  - Added diagnostics if unrecognised command-line parameter wasn't a valid file
-  - Improve error handling when tile downloading fails
-  - Fix for editing a cloudmade source
-
-New with version 13.2
-=====================
-The following features were added since version 13.1:
-  - Russian translation
-  - Fix for loading kml with placemarks with multiple coordinate lists
-  - Fix for exporting descriptions to version 1.1 gpx files
-
-New with version 13.1
+New with version 14
 =====================
 The following features were added since version 13:
 =====================
 The following features were added since version 13:
-  - Allow loading of photos and audio using relative paths from the gpx/kml file
-  - Cosmetic fixes to make the map controls more visible
-  - Allow osm-style map sources to use gifs or jpgs as well as pngs
-  - Allow edit of custom map sources
-  - Addition of a few more built-in map sources, such as hikebikemap and openseamap
+  - Dragging of existing points
+  - Creation of new points by dragging the halfway point between two points
+  - Nautical miles option including knots
+  - Full range details dialog
+  - Extension of interpolation function
+  - Selecting points within a rectangle to delete
 
 New with version 13
 ===================
 
 New with version 13
 ===================
@@ -76,6 +53,8 @@ The following features were added since version 12:
   - Importing of files through GPSBabel
   - List of recently used files in the menu
   - Display of bearing at which a photo was taken (display only)
   - Importing of files through GPSBabel
   - List of recently used files in the menu
   - Display of bearing at which a photo was taken (display only)
+  - Allow edit of custom map sources
+  - Russian translation
 
 New with version 12
 ===================
 
 New with version 12
 ===================
index debe0e799bb1134416b950ca29700c7c111d7143..6be44eb80bc3eb6beb828f0270db15c75255954e 100644 (file)
@@ -596,7 +596,7 @@ public class FileSaver
                        {
                                if (inTimestampFormat == Timestamp.FORMAT_ORIGINAL) {
                                        // output original string
                        {
                                if (inTimestampFormat == Timestamp.FORMAT_ORIGINAL) {
                                        // output original string
-                                       inBuffer.append(inPoint.getFieldValue(Field.TIMESTAMP));
+                                       inBuffer.append(inPoint.getTimestamp().getText(Timestamp.FORMAT_ORIGINAL));
                                }
                                else {
                                        // format value accordingly
                                }
                                else {
                                        // format value accordingly
index 76ec88f4de89db662f6761ae21e737c378fd2d1d..5c74a7a3894d22dd7c06d9e3e3bdb4b3fca7f1c3 100644 (file)
@@ -273,7 +273,7 @@ public class GpsSaver extends GenericFunction implements Runnable
                // Generate the GPX file and send to the GPS
                OutputStreamWriter writer = new OutputStreamWriter(process.getOutputStream());
                boolean[] saveFlags = {true, true, true, true, false, true}; // export everything
                // Generate the GPX file and send to the GPS
                OutputStreamWriter writer = new OutputStreamWriter(process.getOutputStream());
                boolean[] saveFlags = {true, true, true, true, false, true}; // export everything
-               GpxExporter.exportData(writer, _app.getTrackInfo(), trackName, null, saveFlags, false);
+               GpxExporter.exportData(writer, _app.getTrackInfo(), trackName, null, saveFlags, null);
                writer.close();
 
                // Read the error stream to see if there's a better error message there
                writer.close();
 
                // Read the error stream to see if there's a better error message there
index d35c35a8696be7e9863fca94fcb6c4c91dcf49ad..19007ac920dc33c45c2522def2adb648ea1368c7 100644 (file)
@@ -278,6 +278,11 @@ public class GpxExporter extends GenericFunction implements Runnable
         */
        public void run()
        {
         */
        public void run()
        {
+               // Instantiate source file cachers in case we want to copy output
+               GpxCacherList gpxCachers = null;
+               if (_copySourceCheckbox.isSelected()) {
+                       gpxCachers = new GpxCacherList(_trackInfo.getFileInfo());
+               }
                OutputStreamWriter writer = null;
                try
                {
                OutputStreamWriter writer = null;
                try
                {
@@ -291,7 +296,7 @@ public class GpxExporter extends GenericFunction implements Runnable
                                _pointTypeSelector.getJustSelection(), _timestampsCheckbox.isSelected()};
                        // write file
                        final int numPoints = exportData(writer, _trackInfo, _nameField.getText(),
                                _pointTypeSelector.getJustSelection(), _timestampsCheckbox.isSelected()};
                        // write file
                        final int numPoints = exportData(writer, _trackInfo, _nameField.getText(),
-                               _descriptionField.getText(), saveFlags, _copySourceCheckbox.isSelected());
+                               _descriptionField.getText(), saveFlags, gpxCachers);
 
                        // close file
                        writer.close();
 
                        // close file
                        writer.close();
@@ -331,19 +336,16 @@ public class GpxExporter extends GenericFunction implements Runnable
         * @param inName name of track (optional)
         * @param inDesc description of track (optional)
         * @param inSaveFlags array of booleans to export tracks, waypoints, photos, audios, selection, timestamps
         * @param inName name of track (optional)
         * @param inDesc description of track (optional)
         * @param inSaveFlags array of booleans to export tracks, waypoints, photos, audios, selection, timestamps
-        * @param inUseCopy true to copy source if available
+        * @param inGpxCachers list of Gpx cachers containing input data
         * @return number of points written
         * @throws IOException if io errors occur on write
         */
        public static int exportData(OutputStreamWriter inWriter, TrackInfo inInfo, String inName,
         * @return number of points written
         * @throws IOException if io errors occur on write
         */
        public static int exportData(OutputStreamWriter inWriter, TrackInfo inInfo, String inName,
-               String inDesc, boolean[] inSaveFlags, boolean inUseCopy) throws IOException
+               String inDesc, boolean[] inSaveFlags, GpxCacherList inGpxCachers) throws IOException
        {
        {
-               // Instantiate source file cachers in case we want to copy output
-               GpxCacherList gpxCachers = null;
-               if (inUseCopy) gpxCachers = new GpxCacherList(inInfo.getFileInfo());
                // Write or copy headers
                inWriter.write(getXmlHeaderString(inWriter));
                // Write or copy headers
                inWriter.write(getXmlHeaderString(inWriter));
-               final String gpxHeader = getGpxHeaderString(gpxCachers);
+               final String gpxHeader = getGpxHeaderString(inGpxCachers);
                final boolean isVersion1_1 = (gpxHeader.toUpperCase().indexOf("GPX/1/1") > 0);
                inWriter.write(gpxHeader);
                // Name field
                final boolean isVersion1_1 = (gpxHeader.toUpperCase().indexOf("GPX/1/1") > 0);
                inWriter.write(gpxHeader);
                // Name field
@@ -375,8 +377,13 @@ public class GpxExporter extends GenericFunction implements Runnable
                                // Make a wpt element for each waypoint
                                if (point.isWaypoint() && exportWaypoints)
                                {
                                // Make a wpt element for each waypoint
                                if (point.isWaypoint() && exportWaypoints)
                                {
-                                       String pointSource = (inUseCopy?getPointSource(gpxCachers, point):null);
-                                       if (pointSource != null) {
+                                       String pointSource = (inGpxCachers == null? null : getPointSource(inGpxCachers, point));
+                                       if (pointSource != null)
+                                       {
+                                               // If timestamp checkbox is off, strip time
+                                               if (!exportTimestamps) {
+                                                       pointSource = stripTime(pointSource);
+                                               }
                                                inWriter.write(pointSource);
                                                inWriter.write('\n');
                                        }
                                                inWriter.write(pointSource);
                                                inWriter.write('\n');
                                        }
@@ -392,12 +399,12 @@ public class GpxExporter extends GenericFunction implements Runnable
                {
                        // Output all route points (if any)
                        numSaved += writeTrackPoints(inWriter, inInfo, exportSelection, exportTrackpoints, exportPhotos,
                {
                        // Output all route points (if any)
                        numSaved += writeTrackPoints(inWriter, inInfo, exportSelection, exportTrackpoints, exportPhotos,
-                               exportAudios, exportTimestamps, true, gpxCachers, "<rtept", "\t<rte><number>1</number>\n",
+                               exportAudios, exportTimestamps, true, inGpxCachers, "<rtept", "\t<rte><number>1</number>\n",
                                null, "\t</rte>\n");
                        // Output all track points, if any
                        String trackStart = "\t<trk><name>" + trackName + "</name><number>1</number><trkseg>\n";
                        numSaved += writeTrackPoints(inWriter, inInfo, exportSelection, exportTrackpoints, exportPhotos,
                                null, "\t</rte>\n");
                        // Output all track points, if any
                        String trackStart = "\t<trk><name>" + trackName + "</name><number>1</number><trkseg>\n";
                        numSaved += writeTrackPoints(inWriter, inInfo, exportSelection, exportTrackpoints, exportPhotos,
-                               exportAudios, exportTimestamps, false, gpxCachers, "<trkpt", trackStart,
+                               exportAudios, exportTimestamps, false, inGpxCachers, "<trkpt", trackStart,
                                "\t</trkseg>\n\t<trkseg>\n", "\t</trkseg></trk>\n");
                }
 
                                "\t</trkseg>\n\t<trkseg>\n", "\t</trkseg></trk>\n");
                }
 
@@ -487,7 +494,12 @@ public class GpxExporter extends GenericFunction implements Runnable
                                                        inWriter.write(inSegmentTag);
                                                }
                                                if (numSaved == 0) {inWriter.write(inStartTag);}
                                                        inWriter.write(inSegmentTag);
                                                }
                                                if (numSaved == 0) {inWriter.write(inStartTag);}
-                                               if (pointSource != null) {
+                                               if (pointSource != null)
+                                               {
+                                                       // If timestamps checkbox is off, strip the time
+                                                       if (!exportTimestamps) {
+                                                               pointSource = stripTime(pointSource);
+                                                       }
                                                        inWriter.write(pointSource);
                                                        inWriter.write('\n');
                                                }
                                                        inWriter.write(pointSource);
                                                        inWriter.write('\n');
                                                }
@@ -630,10 +642,6 @@ public class GpxExporter extends GenericFunction implements Runnable
                        encoding =  Charset.forName(encoding).name();
                }
                catch (Exception e) {} // ignore failure to find encoding
                        encoding =  Charset.forName(encoding).name();
                }
                catch (Exception e) {} // ignore failure to find encoding
-               // Hack to fix bugs with Mac OSX (which reports MacRoman but is actually UTF-8)
-               if (encoding == null || encoding.toLowerCase().startsWith("macroman")) {
-                       encoding = "UTF-8";
-               }
                return encoding;
        }
 
                return encoding;
        }
 
@@ -849,4 +857,15 @@ public class GpxExporter extends GenericFunction implements Runnable
                // No link available, must have been loaded from zip file - no link possible
                return "";
        }
                // No link available, must have been loaded from zip file - no link possible
                return "";
        }
+
+
+       /**
+        * Strip the time from a GPX point source string
+        * @param inPointSource point source to copy
+        * @return point source with timestamp removed
+        */
+       private static String stripTime(String inPointSource)
+       {
+               return inPointSource.replaceAll("<time>.*?</time>", "");
+       }
 }
 }
index e360878006443a82da87f60e7bf38594ae7bcac5..ee30841d6d779f7790b95006a58a75eda7759433 100644 (file)
@@ -312,7 +312,7 @@ public class PovExporter extends Export3dFunction
        {
                FileWriter writer = null;
                // find out the line separator for this system
        {
                FileWriter writer = null;
                // find out the line separator for this system
-               String lineSeparator = System.getProperty("line.separator");
+               final String lineSeparator = System.getProperty("line.separator");
                try
                {
                        // create and scale model
                try
                {
                        // create and scale model
@@ -436,7 +436,7 @@ public class PovExporter extends Export3dFunction
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
-                 "      pigment {color rgb <0.2 1.0 0.2>}",
+                 "      pigment {color rgb <0.1 0.6 0.1>}", // dark green
                  "      finish { phong 1 }",
                  "   }",
                  " }",
                  "      finish { phong 1 }",
                  "   }",
                  " }",
@@ -444,7 +444,7 @@ public class PovExporter extends Export3dFunction
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
-                 "      pigment {color rgb <0.6 1.0 0.2>}",
+                 "      pigment {color rgb <0.4 0.9 0.2>}", // green
                  "      finish { phong 1 }",
                  "   }",
                  " }",
                  "      finish { phong 1 }",
                  "   }",
                  " }",
@@ -452,7 +452,7 @@ public class PovExporter extends Export3dFunction
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
-                 "      pigment {color rgb <1.0 1.0 0.1>}",
+                 "      pigment {color rgb <0.7 0.8 0.2>}", // yellow
                  "      finish { phong 1 }",
                  "   }",
                  " }",
                  "      finish { phong 1 }",
                  "   }",
                  " }",
@@ -460,7 +460,7 @@ public class PovExporter extends Export3dFunction
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
-                 "      pigment {color rgb <1.0 1.0 1.0>}",
+                 "      pigment {color rgb <0.5 0.8 0.6>}", // greeny
                  "      finish { phong 1 }",
                  "   }",
                  " }",
                  "      finish { phong 1 }",
                  "   }",
                  " }",
@@ -468,7 +468,15 @@ public class PovExporter extends Export3dFunction
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
                  "  sphere {",
                  "   <0, 0, 0>, 0.3", // size should depend on model size
                  "   texture {",
-                 "      pigment {color rgb <0.1 1.0 1.0>}",
+                 "      pigment {color rgb <0.2 0.9 0.9>}", // cyan
+                 "      finish { phong 1 }",
+                 "   }",
+                 " }",
+                 "#declare track_sphere5 =",
+                 "  sphere {",
+                 "   <0, 0, 0>, 0.3", // size should depend on model size
+                 "   texture {",
+                 "      pigment {color rgb <1.0 1.0 1.0>}", // white
                  "      finish { phong 1 }",
                  "   }",
                  " }",
                  "      finish { phong 1 }",
                  "   }",
                  " }",
@@ -533,7 +541,7 @@ public class PovExporter extends Export3dFunction
         * @param inLineSeparator line separator to use
         * @throws IOException on file writing error
         */
         * @param inLineSeparator line separator to use
         * @throws IOException on file writing error
         */
-       private void writeLatLongLines(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
+       private static void writeLatLongLines(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
        throws IOException
        {
                inWriter.write("// Latitude and longitude lines:");
        throws IOException
        {
                inWriter.write("// Latitude and longitude lines:");
@@ -563,7 +571,7 @@ public class PovExporter extends Export3dFunction
         * @param inLineSeparator line separator to use
         * @throws IOException on file writing error
         */
         * @param inLineSeparator line separator to use
         * @throws IOException on file writing error
         */
-       private void writeDataPointsBallsAndSticks(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
+       private static void writeDataPointsBallsAndSticks(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
        throws IOException
        {
                inWriter.write("// Data points:");
        throws IOException
        {
                inWriter.write("// Data points:");
@@ -605,7 +613,7 @@ public class PovExporter extends Export3dFunction
         * @param inLineSeparator line separator to use
         * @throws IOException on file writing error
         */
         * @param inLineSeparator line separator to use
         * @throws IOException on file writing error
         */
-       private void writeDataPointsTubesAndWalls(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
+       private static void writeDataPointsTubesAndWalls(FileWriter inWriter, ThreeDModel inModel, String inLineSeparator)
        throws IOException
        {
                inWriter.write("// Data points:");
        throws IOException
        {
                inWriter.write("// Data points:");
@@ -757,7 +765,7 @@ public class PovExporter extends Export3dFunction
         */
        private static byte checkHeightCode(byte inCode)
        {
         */
        private static byte checkHeightCode(byte inCode)
        {
-               final byte maxHeightCode = 4;
+               final byte maxHeightCode = 5;
                if (inCode < 0) return 0;
                if (inCode > maxHeightCode) return maxHeightCode;
                return inCode;
                if (inCode < 0) return 0;
                if (inCode > maxHeightCode) return maxHeightCode;
                return inCode;
index 4dffd90dcb03233031b603d2c255f57521a17e25..1671607d5e9c1a417b4b75e878aef5aa9465eec4 100644 (file)
@@ -127,9 +127,10 @@ public class Java3DWindow implements ThreeDWindow
                Object[] buttonTexts = {I18nManager.getText("button.continue"), I18nManager.getText("button.cancel")};
                if (_track.getNumPoints() > MAX_TRACK_SIZE && !TRACK_SIZE_WARNING_GIVEN)
                {
                Object[] buttonTexts = {I18nManager.getText("button.continue"), I18nManager.getText("button.cancel")};
                if (_track.getNumPoints() > MAX_TRACK_SIZE && !TRACK_SIZE_WARNING_GIVEN)
                {
-                       if (JOptionPane.showOptionDialog(_frame,
+                       // FIXME: Change text reference from exportpov to java3d
+                       if (JOptionPane.showOptionDialog(_parentFrame,
                                        I18nManager.getText("dialog.exportpov.warningtracksize"),
                                        I18nManager.getText("dialog.exportpov.warningtracksize"),
-                                       I18nManager.getText("function.exportpov"), JOptionPane.OK_CANCEL_OPTION,
+                                       I18nManager.getText("function.show3d"), JOptionPane.OK_CANCEL_OPTION,
                                        JOptionPane.WARNING_MESSAGE, null, buttonTexts, buttonTexts[1])
                                == JOptionPane.OK_OPTION)
                        {
                                        JOptionPane.WARNING_MESSAGE, null, buttonTexts, buttonTexts[1])
                                == JOptionPane.OK_OPTION)
                        {
index 7245633aa0667b936a0d5307fc8b0b84f2b38136..2c9ac97784e79f24e2c378766283720e354c8a15 100644 (file)
@@ -14,14 +14,13 @@ public class ThreeDModel
 {
        private Track _track = null;
        private PointScaler _scaler = null;
 {
        private Track _track = null;
        private PointScaler _scaler = null;
-       private double _modelSize;
        private double _scaleFactor = 1.0;
        private double _altFactor = 1.0;
        // MAYBE: How to store rods (lifts) in data?
        private byte[] _pointTypes = null;
        private byte[] _pointHeights = null;
 
        private double _scaleFactor = 1.0;
        private double _altFactor = 1.0;
        // MAYBE: How to store rods (lifts) in data?
        private byte[] _pointTypes = null;
        private byte[] _pointHeights = null;
 
-       private static final double DEFAULT_MODEL_SIZE = 10.0;
+       private static final double MODEL_SIZE = 10.0;
 
        // Constants for point types
        public static final byte POINT_TYPE_WAYPOINT      = 1;
 
        // Constants for point types
        public static final byte POINT_TYPE_WAYPOINT      = 1;
@@ -34,21 +33,8 @@ public class ThreeDModel
         * @param inTrack Track object
         */
        public ThreeDModel(Track inTrack)
         * @param inTrack Track object
         */
        public ThreeDModel(Track inTrack)
-       {
-               this(inTrack, DEFAULT_MODEL_SIZE);
-       }
-
-
-       /**
-        * Constructor
-        * @param inTrack Track object
-        * @param inSize model size
-        */
-       public ThreeDModel(Track inTrack, double inSize)
        {
                _track = inTrack;
        {
                _track = inTrack;
-               _modelSize = inSize;
-               if (_modelSize <= 0.0) _modelSize = DEFAULT_MODEL_SIZE;
        }
 
 
        }
 
 
@@ -86,19 +72,19 @@ public class ThreeDModel
                        if (_scaler.getMaximumHoriz() > _scaler.getMaximumVert())
                        {
                                // scale limited by longitude
                        if (_scaler.getMaximumHoriz() > _scaler.getMaximumVert())
                        {
                                // scale limited by longitude
-                               _scaleFactor = _modelSize / _scaler.getMaximumHoriz();
+                               _scaleFactor = MODEL_SIZE / _scaler.getMaximumHoriz();
                        }
                        else
                        {
                                // scale limited by latitude
                        }
                        else
                        {
                                // scale limited by latitude
-                               _scaleFactor = _modelSize / _scaler.getMaximumVert();
+                               _scaleFactor = MODEL_SIZE / _scaler.getMaximumVert();
                        }
                }
                // cap altitude scale factor if it's too big
                double maxScaledAlt = _scaler.getMaxScaledAlt() * _altFactor;
                        }
                }
                // cap altitude scale factor if it's too big
                double maxScaledAlt = _scaler.getMaxScaledAlt() * _altFactor;
-               if (maxScaledAlt > _modelSize) {
+               if (maxScaledAlt > MODEL_SIZE) {
                        // capped
                        // capped
-                       _altFactor = _altFactor * _modelSize / maxScaledAlt;
+                       _altFactor = _altFactor * MODEL_SIZE / maxScaledAlt;
                }
                // calculate lat/long lines
                _scaler.calculateLatLongLines();
                }
                // calculate lat/long lines
                _scaler.calculateLatLongLines();
@@ -219,6 +205,6 @@ public class ThreeDModel
         */
        public double getModelSize()
        {
         */
        public double getModelSize()
        {
-               return _modelSize;
+               return MODEL_SIZE;
        }
 }
        }
 }
index 10f71c23773be747c372c298151bf0abb90b4e82..9a9f7a428ce95be69b66a3741efe120b2afe6c81 100644 (file)
@@ -54,7 +54,8 @@ public class UndoAddAltitudeOffset implements UndoOperation
        {
                // Perform the inverse operation
                final int numPoints = _altitudes.length;
        {
                // Perform the inverse operation
                final int numPoints = _altitudes.length;
-               for (int i=0; i<numPoints; i++) {
+               for (int i=0; i<numPoints; i++)
+               {
                        DataPoint point = inTrackInfo.getTrack().getPoint(i+_startIndex);
                        point.getAltitude().reset(_altitudes[i]);
                        point.setModified(true);
                        DataPoint point = inTrackInfo.getTrack().getPoint(i+_startIndex);
                        point.getAltitude().reset(_altitudes[i]);
                        point.setModified(true);
similarity index 81%
rename from tim/prune/undo/UndoCompress.java
rename to tim/prune/undo/UndoDeleteMarked.java
index 50582215aaf82aeb265c52b3cddac6ca5cb7b7b7..63ef7493b6836e99042b8cc0fb28f65662ef905e 100644 (file)
@@ -6,9 +6,9 @@ import tim.prune.data.Track;
 import tim.prune.data.TrackInfo;\r
 \r
 /**\r
 import tim.prune.data.TrackInfo;\r
 \r
 /**\r
- * Operation to undo a track compression\r
+ * Operation to undo the deletion of marked points\r
  */\r
  */\r
-public class UndoCompress implements UndoOperation\r
+public class UndoDeleteMarked implements UndoOperation\r
 {\r
        private DataPoint[] _contents = null;\r
        protected int _numPointsDeleted = -1;\r
 {\r
        private DataPoint[] _contents = null;\r
        protected int _numPointsDeleted = -1;\r
@@ -19,7 +19,7 @@ public class UndoCompress implements UndoOperation
         * Constructor\r
         * @param inTrack track contents to copy\r
         */\r
         * Constructor\r
         * @param inTrack track contents to copy\r
         */\r
-       public UndoCompress(Track inTrack)\r
+       public UndoDeleteMarked(Track inTrack)\r
        {\r
                _contents = inTrack.cloneContents();\r
                // Copy boolean segment start flags\r
        {\r
                _contents = inTrack.cloneContents();\r
                // Copy boolean segment start flags\r
@@ -46,7 +46,7 @@ public class UndoCompress implements UndoOperation
         */\r
        public String getDescription()\r
        {\r
         */\r
        public String getDescription()\r
        {\r
-               String desc = I18nManager.getText("undo.compress");\r
+               String desc = I18nManager.getText("undo.deletemarked");\r
                if (_numPointsDeleted > 0)\r
                        desc = desc + " (" + _numPointsDeleted + ")";\r
                return desc;\r
                if (_numPointsDeleted > 0)\r
                        desc = desc + " (" + _numPointsDeleted + ")";\r
                return desc;\r
@@ -64,7 +64,7 @@ public class UndoCompress implements UndoOperation
                // Copy boolean segment start flags\r
                Track track = inTrackInfo.getTrack();\r
                if (_segmentStarts.length != track.getNumPoints())\r
                // Copy boolean segment start flags\r
                Track track = inTrackInfo.getTrack();\r
                if (_segmentStarts.length != track.getNumPoints())\r
-                       throw new UndoException("Cannot undo compress - track length no longer matches");\r
+                       throw new UndoException("Cannot undo delete - track length no longer matches");\r
                for (int i=0; i<_segmentStarts.length; i++) {\r
                        track.getPoint(i).setSegmentStart(_segmentStarts[i]);\r
                }\r
                for (int i=0; i<_segmentStarts.length; i++) {\r
                        track.getPoint(i).setSegmentStart(_segmentStarts[i]);\r
                }\r
index adb2ea397d0baffcb3d5f410c850c8d3cc3b3cd1..9919d0d3a7dd9cac197bc2059a15a38c996bb88e 100644 (file)
@@ -12,6 +12,7 @@ public class UndoDeletePoint implements UndoOperation
        private int _pointIndex = -1;\r
        private DataPoint _point = null;\r
        private int _photoIndex = -1;\r
        private int _pointIndex = -1;\r
        private DataPoint _point = null;\r
        private int _photoIndex = -1;\r
+       private int _audioIndex = -1;\r
        private boolean _segmentStart = false;\r
 \r
 \r
        private boolean _segmentStart = false;\r
 \r
 \r
@@ -20,13 +21,16 @@ public class UndoDeletePoint implements UndoOperation
         * @param inPointIndex index number of point within track\r
         * @param inPoint data point\r
         * @param inPhotoIndex index number of photo within photo list\r
         * @param inPointIndex index number of point within track\r
         * @param inPoint data point\r
         * @param inPhotoIndex index number of photo within photo list\r
+        * @param inAudioIndex index number of audio within audio list\r
         * @param inSegmentStart true if following track point starts new segment\r
         */\r
         * @param inSegmentStart true if following track point starts new segment\r
         */\r
-       public UndoDeletePoint(int inPointIndex, DataPoint inPoint, int inPhotoIndex, boolean inSegmentStart)\r
+       public UndoDeletePoint(int inPointIndex, DataPoint inPoint, int inPhotoIndex, int inAudioIndex,\r
+               boolean inSegmentStart)\r
        {\r
                _pointIndex = inPointIndex;\r
                _point = inPoint;\r
                _photoIndex = inPhotoIndex;\r
        {\r
                _pointIndex = inPointIndex;\r
                _point = inPoint;\r
                _photoIndex = inPhotoIndex;\r
+               _audioIndex = inAudioIndex;\r
                _segmentStart = inSegmentStart;\r
        }\r
 \r
                _segmentStart = inSegmentStart;\r
        }\r
 \r
@@ -69,6 +73,13 @@ public class UndoDeletePoint implements UndoOperation
                                _point.getPhoto().setDataPoint(_point);\r
                        }\r
                }\r
                                _point.getPhoto().setDataPoint(_point);\r
                        }\r
                }\r
+               // Re-add audio as well if necessary\r
+               if (_point.getAudio() != null && _audioIndex > -1)\r
+               {\r
+                       // add audio object to list\r
+                       inTrackInfo.getAudioList().addAudio(_point.getAudio(), _audioIndex);\r
+                       _point.getAudio().setDataPoint(_point);\r
+               }\r
                // Restore previous status of following track point if necessary\r
                if (!_segmentStart)\r
                {\r
                // Restore previous status of following track point if necessary\r
                if (!_segmentStart)\r
                {\r
index e2a76995ebb478ec868c9e4a8c68b8a9d4fcfed8..ba2b31ab5ef89540b8496be4e8908f0a9855ae7e 100644 (file)
@@ -1,6 +1,7 @@
 package tim.prune.undo;\r
 \r
 import tim.prune.I18nManager;\r
 package tim.prune.undo;\r
 \r
 import tim.prune.I18nManager;\r
+import tim.prune.data.AudioList;\r
 import tim.prune.data.DataPoint;\r
 import tim.prune.data.PhotoList;\r
 import tim.prune.data.TrackInfo;\r
 import tim.prune.data.DataPoint;\r
 import tim.prune.data.PhotoList;\r
 import tim.prune.data.TrackInfo;\r
@@ -10,37 +11,116 @@ import tim.prune.data.TrackInfo;
  */\r
 public class UndoDeleteRange implements UndoOperation\r
 {\r
  */\r
 public class UndoDeleteRange implements UndoOperation\r
 {\r
-       private int _startIndex = -1;\r
-       private DataPoint[] _points = null;\r
+       /**\r
+        * Inner class to hold a single range information set\r
+        */\r
+       class RangeInfo\r
+       {\r
+               public int _startIndex = -1;\r
+               public DataPoint[] _points = null;\r
+               public DataPoint _nextTrackPoint = null;\r
+               public boolean _segmentStart = false;\r
+\r
+               /**\r
+                * @param inPoint next track point after deleted section, or null\r
+                */\r
+               public void setNextTrackPoint(DataPoint inPoint)\r
+               {\r
+                       _nextTrackPoint = inPoint;\r
+                       if (inPoint != null) {\r
+                               _segmentStart = inPoint.getSegmentStart();\r
+                       }\r
+\r
+               }\r
+\r
+               /**\r
+                * @return true if the range is valid\r
+                */\r
+               public boolean isValid()\r
+               {\r
+                       return _startIndex >= 0 && _points != null && _points.length > 0;\r
+               }\r
+       }\r
+\r
+\r
+       // Instance variables for UndoDeleteRange\r
+       private RangeInfo _rangeInfo1 = null;\r
+       private RangeInfo _rangeInfo2 = null;\r
        private PhotoList _photoList = null;\r
        private PhotoList _photoList = null;\r
-       private DataPoint _nextTrackPoint = null;\r
-       private boolean _segmentStart = false;\r
+       private AudioList _audioList = null;\r
+       private String _nameKey = null;\r
+       private int _totalDeleted = 0;\r
 \r
 \r
        /**\r
         * Constructor\r
         * @param inTrackInfo track info object\r
 \r
 \r
        /**\r
         * Constructor\r
         * @param inTrackInfo track info object\r
+        * @param inNameKey key to use for undo text\r
+        * @param inStartIndex1 start index of first deleted segment\r
+        * @param inDeleteMedias1 flags to delete media for range1\r
+        * @param inStartIndex2 start index of second segment\r
+        * @param inDeleteMedias2 flags to delete media for range2\r
         */\r
         */\r
-       public UndoDeleteRange(TrackInfo inTrackInfo)\r
+       public UndoDeleteRange(TrackInfo inTrackInfo, String inNameKey,\r
+               int inStartIndex1, boolean[] inDeleteMedias1,\r
+               int inStartIndex2, boolean[] inDeleteMedias2)\r
        {\r
        {\r
-               _startIndex = inTrackInfo.getSelection().getStart();\r
-               _points = inTrackInfo.cloneSelectedRange();\r
-               _photoList = inTrackInfo.getPhotoList().cloneList();\r
-               // Save segment flag of following track point\r
-               _nextTrackPoint = inTrackInfo.getTrack().getNextTrackPoint(_startIndex + _points.length);\r
-               if (_nextTrackPoint != null) {\r
-                       _segmentStart = _nextTrackPoint.getSegmentStart();\r
+               _nameKey = inNameKey;\r
+               boolean mediaDeleted = false;\r
+               _totalDeleted = 0;\r
+               // Check if there's a valid first range\r
+               if (inStartIndex1 >= 0 && inDeleteMedias1 != null)\r
+               {\r
+                       final int numPoints = inDeleteMedias1.length;\r
+                       if (numPoints > 0)\r
+                       {\r
+                               _totalDeleted += numPoints;\r
+                               _rangeInfo1 = new RangeInfo();\r
+                               _rangeInfo1._startIndex = inStartIndex1;\r
+\r
+                               for (int i=0; i<numPoints && !mediaDeleted; i++) {\r
+                                       if (inDeleteMedias1[i]) mediaDeleted = true;\r
+                               }\r
+                               // Clone points\r
+                               _rangeInfo1._points = inTrackInfo.getTrack().cloneRange(inStartIndex1, inStartIndex1 + numPoints - 1);\r
+                               // Save segment flag of following track point\r
+                               _rangeInfo1.setNextTrackPoint(inTrackInfo.getTrack().getNextTrackPoint(inStartIndex1 + numPoints));\r
+                       }\r
+               }\r
+               // And the same for the second range, if any\r
+               if (inStartIndex2 >= 0 && inDeleteMedias2 != null)\r
+               {\r
+                       final int numPoints = inDeleteMedias2.length;\r
+                       if (numPoints > 0)\r
+                       {\r
+                               _totalDeleted += numPoints;\r
+                               _rangeInfo2 = new RangeInfo();\r
+                               _rangeInfo2._startIndex = inStartIndex2;\r
+                               for (int i=0; i<numPoints && !mediaDeleted; i++) {\r
+                                       if (inDeleteMedias2[i]) mediaDeleted = true;\r
+                               }\r
+\r
+                               // Clone points\r
+                               _rangeInfo2._points = inTrackInfo.getTrack().cloneRange(inStartIndex2, inStartIndex2 + numPoints - 1);\r
+                               // Save segment flag of following track point\r
+                               _rangeInfo2.setNextTrackPoint(inTrackInfo.getTrack().getNextTrackPoint(inStartIndex2 + numPoints));\r
+                       }\r
+               }\r
+               // If any media have been deleted, then the lists must be copied\r
+               if (mediaDeleted)\r
+               {\r
+                       _photoList = inTrackInfo.getPhotoList().cloneList();\r
+                       _audioList = inTrackInfo.getAudioList().cloneList();\r
                }\r
        }\r
 \r
 \r
        /**\r
                }\r
        }\r
 \r
 \r
        /**\r
-        * @return description of operation including range length\r
+        * @return description of operation including number of points deleted\r
         */\r
        public String getDescription()\r
        {\r
         */\r
        public String getDescription()\r
        {\r
-               return I18nManager.getText("undo.deleterange")\r
-                       + " (" + _points.length + ")";\r
+               return I18nManager.getText(_nameKey) + " (" + _totalDeleted + ")";\r
        }\r
 \r
 \r
        }\r
 \r
 \r
@@ -50,22 +130,48 @@ public class UndoDeleteRange implements UndoOperation
         */\r
        public void performUndo(TrackInfo inTrackInfo)\r
        {\r
         */\r
        public void performUndo(TrackInfo inTrackInfo)\r
        {\r
-               // restore photos to how they were before\r
-               inTrackInfo.getPhotoList().restore(_photoList);\r
-               // reconnect photos to points\r
-               for (int i=0; i<_points.length; i++)\r
+               // restore photos and audios to how they were before\r
+               if (_photoList != null) {\r
+                       inTrackInfo.getPhotoList().restore(_photoList);\r
+               }\r
+               if (_audioList != null) {\r
+                       inTrackInfo.getAudioList().restore(_audioList);\r
+               }\r
+\r
+               // Undo both the ranges\r
+               performUndo(inTrackInfo, _rangeInfo1);\r
+               performUndo(inTrackInfo, _rangeInfo2);\r
+       }\r
+\r
+       /**\r
+        * Perform the undo on a single deleted range\r
+        * @param inTrackInfo track info object\r
+        * @param inRangeInfo info object describing deleted range\r
+        */\r
+       private void performUndo(TrackInfo inTrackInfo, RangeInfo inRangeInfo)\r
+       {\r
+               if (inRangeInfo == null || !inRangeInfo.isValid()) return;\r
+\r
+               // reconnect photos and audios to points\r
+               final int numPoints = inRangeInfo._points.length;\r
+               for (int i=0; i<numPoints; i++)\r
                {\r
                {\r
-                       DataPoint point = _points[i];\r
-                       if (point != null && point.getPhoto() != null)\r
+                       DataPoint point = inRangeInfo._points[i];\r
+                       if (point != null && point.hasMedia())\r
                        {\r
                        {\r
-                               point.getPhoto().setDataPoint(point);\r
+                               if (point.getPhoto() != null) {\r
+                                       point.getPhoto().setDataPoint(point);\r
+                               }\r
+                               if (point.getAudio() != null) {\r
+                                       point.getAudio().setDataPoint(point);\r
+                               }\r
                        }\r
                }\r
                // restore point array into track\r
                        }\r
                }\r
                // restore point array into track\r
-               inTrackInfo.getTrack().insertRange(_points, _startIndex);\r
+               inTrackInfo.getTrack().insertRange(inRangeInfo._points, inRangeInfo._startIndex);\r
                // Restore segment flag of following track point\r
                // Restore segment flag of following track point\r
-               if (_nextTrackPoint != null) {\r
-                       _nextTrackPoint.setSegmentStart(_segmentStart);\r
+               if (inRangeInfo._nextTrackPoint != null) {\r
+                       inRangeInfo._nextTrackPoint.setSegmentStart(inRangeInfo._segmentStart);\r
                }\r
        }\r
                }\r
        }\r
-}
\ No newline at end of file
+}\r
index 228795b6d5d5d34e0b15d9bf7e955fc5f3544345..be41ea0d88f92c7ce15ef966a253a607b2fe853f 100644 (file)
@@ -2,6 +2,7 @@ package tim.prune.undo;
 \r
 import tim.prune.I18nManager;\r
 import tim.prune.data.DataPoint;\r
 \r
 import tim.prune.I18nManager;\r
 import tim.prune.data.DataPoint;\r
+import tim.prune.data.Field;\r
 import tim.prune.data.TrackInfo;\r
 import tim.prune.function.edit.FieldEditList;\r
 \r
 import tim.prune.data.TrackInfo;\r
 import tim.prune.function.edit.FieldEditList;\r
 \r
@@ -32,7 +33,9 @@ public class UndoEditPoint implements UndoOperation
        public String getDescription()\r
        {\r
                String desc = I18nManager.getText("undo.editpoint");\r
        public String getDescription()\r
        {\r
                String desc = I18nManager.getText("undo.editpoint");\r
-               String newName = _undoFieldList.getEdit(0).getValue();\r
+               String newName = null;\r
+               if (_undoFieldList.getEdit(0).getField() == Field.WAYPT_NAME)\r
+                       newName = _undoFieldList.getEdit(0).getValue();\r
                String pointName = _originalPoint.getWaypointName();\r
                if (newName != null && !newName.equals(""))\r
                        desc = desc + " " + newName;\r
                String pointName = _originalPoint.getWaypointName();\r
                if (newName != null && !newName.equals(""))\r
                        desc = desc + " " + newName;\r
index 39676af411d0eaa374aae01070bd2139cd01505a..f23892126824a01849c83be9fb4adf8ab40fa117 100644 (file)
@@ -5,7 +5,7 @@ import tim.prune.data.DataPoint;
 import tim.prune.data.TrackInfo;\r
 \r
 /**\r
 import tim.prune.data.TrackInfo;\r
 \r
 /**\r
- * Operation to undo an insertion (eg interpolate, average)\r
+ * Operation to undo an insertion (eg average)\r
  */\r
 public class UndoInsert implements UndoOperation\r
 {\r
  */\r
 public class UndoInsert implements UndoOperation\r
 {\r
diff --git a/tim/prune/undo/UndoInterpolate.java b/tim/prune/undo/UndoInterpolate.java
new file mode 100644 (file)
index 0000000..975a731
--- /dev/null
@@ -0,0 +1,60 @@
+package tim.prune.undo;\r
+\r
+import tim.prune.I18nManager;\r
+import tim.prune.data.DataPoint;\r
+import tim.prune.data.TrackInfo;\r
+\r
+/**\r
+ * Operation to undo an interpolation\r
+ */\r
+public class UndoInterpolate implements UndoOperation\r
+{\r
+       private int _startIndex = 0;\r
+       private int _totalInserted = 0;\r
+       private DataPoint[] _points = null;\r
+\r
+\r
+       /**\r
+        * Constructor\r
+        * @param inTrackInfo track info object\r
+        * @param inTotalInserted total number of points inserted\r
+        */\r
+       public UndoInterpolate(TrackInfo inTrackInfo, int inTotalInserted)\r
+       {\r
+               _startIndex = inTrackInfo.getSelection().getStart();\r
+               _points = inTrackInfo.cloneSelectedRange();\r
+               _totalInserted = inTotalInserted;\r
+       }\r
+\r
+\r
+       /**\r
+        * @return description of operation including parameters\r
+        */\r
+       public String getDescription()\r
+       {\r
+               return I18nManager.getText("undo.insert") + " (" + _totalInserted + ")";\r
+       }\r
+\r
+\r
+       /**\r
+        * Perform the undo operation on the given TrackInfo\r
+        * @param inTrackInfo TrackInfo object on which to perform the operation\r
+        */\r
+       public void performUndo(TrackInfo inTrackInfo) throws UndoException\r
+       {\r
+               // Work out how many points were in the track before the interpolation\r
+               final int newSize = inTrackInfo.getTrack().getNumPoints() - _totalInserted;\r
+               DataPoint[] oldPoints = inTrackInfo.getTrack().cloneContents();\r
+               DataPoint[] newPoints = new DataPoint[newSize];\r
+\r
+               // Restore track to previous values\r
+               System.arraycopy(oldPoints, 0, newPoints, 0, _startIndex);\r
+               System.arraycopy(_points, 0, newPoints, _startIndex, _points.length);\r
+               int endIndex = _startIndex + _points.length;\r
+               System.arraycopy(oldPoints, endIndex + _totalInserted, newPoints, endIndex, newSize - endIndex);\r
+\r
+               inTrackInfo.getTrack().replaceContents(newPoints);\r
+               // reset selection\r
+               inTrackInfo.getSelection().clearAll();\r
+       }\r
+}\r
index bb6a21176c48673f3a293115a97e6969fd98255e..b8c2b35970fbb05482ad8cfc4dd1bbe95aa0f08a 100644 (file)
@@ -1,6 +1,8 @@
 package tim.prune.undo;\r
 \r
 import tim.prune.I18nManager;\r
 package tim.prune.undo;\r
 \r
 import tim.prune.I18nManager;\r
+import tim.prune.data.DataPoint;\r
+import tim.prune.data.Photo;\r
 import tim.prune.data.TrackInfo;\r
 \r
 /**\r
 import tim.prune.data.TrackInfo;\r
 \r
 /**\r
@@ -50,6 +52,18 @@ public class UndoLoadPhotos implements UndoOperation
                        cropIndex = inTrackInfo.getTrack().getNumPoints() - _numPoints;\r
                        inTrackInfo.getTrack().cropTo(cropIndex);\r
                }\r
                        cropIndex = inTrackInfo.getTrack().getNumPoints() - _numPoints;\r
                        inTrackInfo.getTrack().cropTo(cropIndex);\r
                }\r
+               else\r
+               {\r
+                       // Loop through the points (if any) and detach them\r
+                       for (int i=0; i<_numPhotos; i++)\r
+                       {\r
+                               Photo photo = inTrackInfo.getPhotoList().getPhoto(inTrackInfo.getPhotoList().getNumPhotos() - 1 - i);\r
+                               if (photo.isConnected()) {\r
+                                       DataPoint point = photo.getDataPoint();\r
+                                       if (point != null) {point.setPhoto(null);}\r
+                               }\r
+                       }\r
+               }\r
                // crop photo list to previous size\r
                cropIndex = inTrackInfo.getPhotoList().getNumPhotos() - _numPhotos;\r
                inTrackInfo.getPhotoList().cropTo(cropIndex);\r
                // crop photo list to previous size\r
                cropIndex = inTrackInfo.getPhotoList().getNumPhotos() - _numPhotos;\r
                inTrackInfo.getPhotoList().cropTo(cropIndex);\r
index d82714ae1e6444ce18fda96d1d2cddbc1a0fcff9..d028b82a568a98da8c7b46ea8d7539f767c891c1 100644 (file)
@@ -29,9 +29,11 @@ public class UndoLookupSrtm implements UndoOperation
                // Make arrays of points and altitudes
                _points = new DataPoint[numPoints];
                _altitudes = new String[numPoints];
                // Make arrays of points and altitudes
                _points = new DataPoint[numPoints];
                _altitudes = new String[numPoints];
-               for (int i=0; i<numPoints; i++) {
+               for (int i=0; i<numPoints; i++)
+               {
                        DataPoint point = track.getPoint(i);
                        DataPoint point = track.getPoint(i);
-                       if (!point.hasAltitude() || point.getAltitude().getValue() == 0) {
+                       if (!point.hasAltitude() || point.getAltitude().getValue() == 0)
+                       {
                                _points[i] = point;
                                if (point.hasAltitude()) {
                                        _altitudes[i] = point.getFieldValue(Field.ALTITUDE);
                                _points[i] = point;
                                if (point.hasAltitude()) {
                                        _altitudes[i] = point.getFieldValue(Field.ALTITUDE);