]> gitweb.fperrin.net Git - GpsPrune.git/commitdiff
Version 20, March 2020 upstream/master
authoractivityworkshop <mail@activityworkshop.net>
Mon, 6 Apr 2020 19:38:26 +0000 (21:38 +0200)
committeractivityworkshop <mail@activityworkshop.net>
Mon, 6 Apr 2020 19:38:26 +0000 (21:38 +0200)
107 files changed:
.gitignore [new file with mode: 0644]
README.md
buildtools/build.sh
buildtools/pom.xml
buildtools/version.properties
src/tim/prune/App.java
src/tim/prune/FunctionLibrary.java
src/tim/prune/GpsPrune.java
src/tim/prune/I18nManager.java
src/tim/prune/config/Config.java
src/tim/prune/copyright.txt
src/tim/prune/data/Coordinate.java
src/tim/prune/data/FileInfo.java
src/tim/prune/data/RangeStats.java
src/tim/prune/data/RangeStatsWithGradients.java [new file with mode: 0644]
src/tim/prune/data/Selection.java
src/tim/prune/data/Timestamp.java
src/tim/prune/function/AboutScreen.java
src/tim/prune/function/AddAltitudeOffset.java
src/tim/prune/function/AddTimeOffset.java
src/tim/prune/function/ConnectToPointFunction.java
src/tim/prune/function/CreateMarkerWaypointsFunction.java
src/tim/prune/function/DistanceTimeLimitFunction.java
src/tim/prune/function/DuplicatePoint.java
src/tim/prune/function/FullRangeDetails.java [deleted file]
src/tim/prune/function/InterpolateFunction.java
src/tim/prune/function/PasteCoordinateList.java [new file with mode: 0644]
src/tim/prune/function/PasteCoordinates.java
src/tim/prune/function/PlayAudioFunction.java
src/tim/prune/function/PlusCodeFunction.java [new file with mode: 0644]
src/tim/prune/function/ProjectPoint.java [new file with mode: 0644]
src/tim/prune/function/RearrangeWaypointsFunction.java
src/tim/prune/function/SearchOpenCachingDeFunction.java
src/tim/prune/function/ShowFullDetails.java [new file with mode: 0644]
src/tim/prune/function/compress/CompressTrackFunction.java
src/tim/prune/function/compress/SingleParameterAlgorithm.java
src/tim/prune/function/distance/DistanceFunction.java
src/tim/prune/function/distance/DistanceTableModel.java
src/tim/prune/function/estimate/EstimateTime.java
src/tim/prune/function/estimate/EstimationParameters.java
src/tim/prune/function/estimate/LearnParameters.java
src/tim/prune/function/gpsies/FormPoster.java [deleted file]
src/tim/prune/function/gpsies/GetGpsiesFunction.java [deleted file]
src/tim/prune/function/gpsies/GpsiesXmlHandler.java [deleted file]
src/tim/prune/function/gpsies/UploadGpsiesFunction.java [deleted file]
src/tim/prune/function/olc/CoordPair.java [new file with mode: 0644]
src/tim/prune/function/olc/OlcArea.java [new file with mode: 0644]
src/tim/prune/function/olc/OlcDecoder.java [new file with mode: 0644]
src/tim/prune/function/search/GenericDownloaderFunction.java
src/tim/prune/function/search/SearchResult.java
src/tim/prune/function/search/TrackListModel.java [moved from src/tim/prune/function/gpsies/TrackListModel.java with 95% similarity]
src/tim/prune/function/search/wikimedia_galleries.txt
src/tim/prune/function/settings/SaveConfig.java
src/tim/prune/function/settings/SetDisplaySettings.java
src/tim/prune/function/settings/SetLanguage.java
src/tim/prune/function/settings/SetPathsFunction.java
src/tim/prune/function/sew/SplitSegmentsFunction.java
src/tim/prune/function/srtm/LookupSrtmFunction.java
src/tim/prune/function/srtm/TileFinder.java
src/tim/prune/gui/CoordDisplay.java [new file with mode: 0644]
src/tim/prune/gui/DetailsDisplay.java
src/tim/prune/gui/MenuManager.java
src/tim/prune/gui/StatusBar.java
src/tim/prune/gui/Viewport.java
src/tim/prune/gui/colour/ColourerFactory.java
src/tim/prune/gui/colour/FileColourer.java
src/tim/prune/gui/map/DiskTileCacher.java
src/tim/prune/gui/map/MapCanvas.java
src/tim/prune/gui/map/MapSourceLibrary.java
src/tim/prune/gui/map/MapTileManager.java
src/tim/prune/gui/map/TileDownloader.java
src/tim/prune/gui/profile/ProfileChart.java
src/tim/prune/jpeg/drew/ExifTiffHandler.java
src/tim/prune/lang/prune-texts_af.properties
src/tim/prune/lang/prune-texts_cy.properties [new file with mode: 0644]
src/tim/prune/lang/prune-texts_cz.properties
src/tim/prune/lang/prune-texts_da.properties
src/tim/prune/lang/prune-texts_de.properties
src/tim/prune/lang/prune-texts_de_CH.properties
src/tim/prune/lang/prune-texts_en.properties
src/tim/prune/lang/prune-texts_en_US.properties
src/tim/prune/lang/prune-texts_es.properties
src/tim/prune/lang/prune-texts_fi.properties
src/tim/prune/lang/prune-texts_fr.properties
src/tim/prune/lang/prune-texts_hu.properties
src/tim/prune/lang/prune-texts_it.properties
src/tim/prune/lang/prune-texts_ja.properties
src/tim/prune/lang/prune-texts_ko.properties
src/tim/prune/lang/prune-texts_nl.properties
src/tim/prune/lang/prune-texts_no.properties
src/tim/prune/lang/prune-texts_pl.properties
src/tim/prune/lang/prune-texts_pt.properties
src/tim/prune/lang/prune-texts_ro.properties
src/tim/prune/lang/prune-texts_ru.properties
src/tim/prune/lang/prune-texts_sv.properties
src/tim/prune/lang/prune-texts_tr.properties
src/tim/prune/lang/prune-texts_uk.properties
src/tim/prune/lang/prune-texts_zh.properties
src/tim/prune/load/ContentCacher.java [new file with mode: 0644]
src/tim/prune/load/FileCacher.java
src/tim/prune/load/FileSplitter.java
src/tim/prune/load/JpegLoader.java
src/tim/prune/load/TextCacher.java [new file with mode: 0644]
src/tim/prune/load/TextFileLoader.java
src/tim/prune/readme.txt
src/tim/prune/save/BaseImageConfigDialog.java
src/tim/prune/save/ImageExporter.java

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..8e9e794
--- /dev/null
@@ -0,0 +1,2 @@
+*.class
+*.jar
index 9e9c08b39e92118fefa1561f332b4add6f6b7d54..1a1aa06ddf261d3ce0d44b8610156ce1baca0b5a 100644 (file)
--- a/README.md
+++ b/README.md
@@ -3,5 +3,5 @@ GpsPrune is a map-based application for viewing, editing and converting coordina
 
 It's a cross-platform java application, and its home page is at https://gpsprune.activityworkshop.net .
 
-Here on github you'll find all the sources from version 1 to the current version 19.2, and in the wiki at https://github.com/activityworkshop/GpsPrune/wiki there's the beginning of a translation effort for anyone to contribute.
-Currently just the Spanish translations are online, to see whether it's a workable idea or not.  Please help with this if you can.
+Here on github you'll find all the sources from version 1 to the current version 20, and in the wiki at https://github.com/activityworkshop/GpsPrune/wiki there's the beginning of a translation effort for anyone to contribute.
+Currently just the Spanish translations and some missing French texts are online, to see whether it's a workable idea or not.  Please help with these if you can.
index b38e2ce60f042c9a31274ee4a6dfae683219843f..193244bb3319fa81e974dd1d9f09fbbb52c7f70c 100644 (file)
@@ -1,6 +1,7 @@
 # Build script
+set -e
 # Version number
-PRUNENAME=gpsprune_19.2
+PRUNENAME=gpsprune_20
 # remove compile directory
 rm -rf compile
 # remove dist directory
index 82b29ac8a8969475038b95377cacefb182b26d52..15b6562639083b2eba02a431e820e46a75c8e0e9 100644 (file)
@@ -7,7 +7,7 @@
 
        <groupId>tim.prune</groupId>
        <artifactId>gpsprune</artifactId>
-       <version>19.2</version>
+       <version>20</version>
        <packaging>jar</packaging>
 
        <name>tim.prune.gpsprune</name>
index af259261217d8ce2749853a802e4de6ec4f2547e..fe5699b021d0d7d613f4832110fdc957de74e9a9 100644 (file)
@@ -1 +1 @@
-version=19.2
+version=20
index 3a778588ab815a7f30c4b396e4de9d2c266836da..94e10e0e2ed873e6bbf7558419de14e393c20f08 100644 (file)
@@ -69,7 +69,7 @@ public class App
        private AppMode _appMode = AppMode.NORMAL;
 
        /** Enum for the app mode - currently only two options but may expand later */
-       public enum AppMode {NORMAL, DRAWRECT};
+       public enum AppMode {NORMAL, DRAWRECT}
 
 
        /**
@@ -649,7 +649,8 @@ public class App
                loadedTrack.load(inFieldArray, inDataArray, inOptions);
                if (loadedTrack.getNumPoints() <= 0)
                {
-                       showErrorMessage("error.load.dialogtitle", "error.load.nopoints");
+                       String msgKey = (inSourceInfo == null ? "error.load.nopointsintext" : "error.load.nopoints");
+                       showErrorMessage("error.load.dialogtitle", msgKey);
                        // load next file if there's a queue
                        loadNextFile();
                        return;
@@ -715,9 +716,12 @@ public class App
                                undo.setNumPhotosAudios(_trackInfo.getPhotoList().getNumPhotos(), _trackInfo.getAudioList().getNumAudios());
                                _undoStack.add(undo);
                                _track.combine(inLoadedTrack);
-                               // set source information
-                               inSourceInfo.populatePointObjects(_track, inLoadedTrack.getNumPoints());
-                               _trackInfo.getFileInfo().addSource(inSourceInfo);
+                               if (inSourceInfo != null)
+                               {
+                                       // set source information
+                                       inSourceInfo.populatePointObjects(_track, inLoadedTrack.getNumPoints());
+                                       _trackInfo.getFileInfo().addSource(inSourceInfo);
+                               }
                        }
                        else if (answer == JOptionPane.NO_OPTION)
                        {
@@ -732,8 +736,12 @@ public class App
                                _lastSavePosition = _undoStack.size();
                                _trackInfo.getSelection().clearAll();
                                _track.load(inLoadedTrack);
-                               inSourceInfo.populatePointObjects(_track, _track.getNumPoints());
-                               _trackInfo.getFileInfo().replaceSource(inSourceInfo);
+                               if (inSourceInfo != null)
+                               {
+                                       // set source information
+                                       inSourceInfo.populatePointObjects(_track, _track.getNumPoints());
+                                       _trackInfo.getFileInfo().replaceSource(inSourceInfo);
+                               }
                                _trackInfo.getPhotoList().removeCorrelatedPhotos();
                                _trackInfo.getAudioList().removeCorrelatedAudios();
                        }
@@ -747,16 +755,22 @@ public class App
                        _lastSavePosition = _undoStack.size();
                        _trackInfo.getSelection().clearAll();
                        _track.load(inLoadedTrack);
-                       inSourceInfo.populatePointObjects(_track, _track.getNumPoints());
-                       _trackInfo.getFileInfo().addSource(inSourceInfo);
+                       if (inSourceInfo != null)
+                       {
+                               inSourceInfo.populatePointObjects(_track, _track.getNumPoints());
+                               _trackInfo.getFileInfo().addSource(inSourceInfo);
+                       }
                }
                // Update config before subscribers are told
-               boolean isRegularLoad = (inSourceInfo.getFileType() != FILE_TYPE.GPSBABEL);
-               Config.getRecentFileList().addFile(new RecentFile(inSourceInfo.getFile(), isRegularLoad));
+               if (inSourceInfo != null)
+               {
+                       boolean isRegularLoad = (inSourceInfo.getFileType() != FILE_TYPE.GPSBABEL);
+                       Config.getRecentFileList().addFile(new RecentFile(inSourceInfo.getFile(), isRegularLoad));
+                       // Update status bar
+                       UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.loadfile")
+                               + " '" + inSourceInfo.getName() + "'");
+               }
                UpdateMessageBroker.informSubscribers();
-               // Update status bar
-               UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.loadfile")
-                       + " '" + inSourceInfo.getName() + "'");
                // update menu
                _menuManager.informFileLoaded();
                // Remove busy lock
index 0441826164d930de8b79acb7d45fd84a742d33ce..68303ed95946466daf23cf1adc5b15aa24f31786 100644 (file)
@@ -18,12 +18,12 @@ import tim.prune.function.DiskCacheConfig;
 import tim.prune.function.DownloadOsmFunction;
 import tim.prune.function.DuplicatePoint;
 import tim.prune.function.FindWaypoint;
-import tim.prune.function.FullRangeDetails;
+import tim.prune.function.ProjectPoint;
+import tim.prune.function.ShowFullDetails;
 import tim.prune.function.GetWikipediaFunction;
 import tim.prune.function.HelpScreen;
 import tim.prune.function.IgnoreExifThumb;
 import tim.prune.function.InterpolateFunction;
-import tim.prune.function.PasteCoordinates;
 import tim.prune.function.PhotoPopupFunction;
 import tim.prune.function.PlayAudioFunction;
 import tim.prune.function.RearrangePhotosFunction;
@@ -50,8 +50,6 @@ import tim.prune.function.distance.DistanceFunction;
 import tim.prune.function.edit.PointNameEditor;
 import tim.prune.function.estimate.EstimateTime;
 import tim.prune.function.estimate.LearnParameters;
-import tim.prune.function.gpsies.GetGpsiesFunction;
-import tim.prune.function.gpsies.UploadGpsiesFunction;
 import tim.prune.function.settings.SaveConfig;
 import tim.prune.function.settings.SetAltitudeTolerance;
 import tim.prune.function.settings.SetColours;
@@ -88,6 +86,7 @@ public abstract class FunctionLibrary
        public static GenericFunction FUNCTION_IMPORTBABEL = null;
        public static GenericFunction FUNCTION_SAVECONFIG  = null;
        public static GenericFunction FUNCTION_EDIT_WAYPOINT_NAME = null;
+       public static GenericFunction FUNCTION_PROJECT_POINT = null;
        public static GenericFunction FUNCTION_REARRANGE_WAYPOINTS = null;
        public static GenericFunction FUNCTION_SELECT_SEGMENT = null;
        public static GenericFunction FUNCTION_SPLIT_SEGMENTS = null;
@@ -112,7 +111,6 @@ public abstract class FunctionLibrary
        public static GenericFunction FUNCTION_ADD_ALTITUDE_OFFSET  = null;
        public static GenericFunction FUNCTION_CONVERT_NAMES_TO_TIMES  = null;
        public static GenericFunction FUNCTION_DELETE_FIELD_VALUES  = null;
-       public static GenericFunction FUNCTION_PASTE_COORDINATES = null;
        public static GenericFunction FUNCTION_FIND_WAYPOINT = null;
        public static GenericFunction FUNCTION_DUPLICATE_POINT = null;
        public static GenericFunction FUNCTION_CONNECT_TO_POINT = null;
@@ -127,12 +125,10 @@ public abstract class FunctionLibrary
        public static GenericFunction FUNCTION_CHARTS = null;
        public static GenericFunction FUNCTION_3D     = null;
        public static GenericFunction FUNCTION_DISTANCES  = null;
-       public static GenericFunction FUNCTION_FULL_RANGE_DETAILS = null;
+       public static GenericFunction FUNCTION_FULL_DETAILS = null;
        public static GenericFunction FUNCTION_AUTOPLAY_TRACK = null;
        public static GenericFunction FUNCTION_ESTIMATE_TIME = null;
        public static GenericFunction FUNCTION_LEARN_ESTIMATION_PARAMS = null;
-       public static GenericFunction FUNCTION_GET_GPSIES = null;
-       public static GenericFunction FUNCTION_UPLOAD_GPSIES = null;
        public static GenericFunction FUNCTION_GET_WEATHER_FORECAST = null;
        public static GenericFunction FUNCTION_LOAD_AUDIO = null;
        public static GenericFunction FUNCTION_REMOVE_AUDIO = null;
@@ -168,6 +164,7 @@ public abstract class FunctionLibrary
                FUNCTION_IMPORTBABEL = new BabelLoadFromFile(inApp);
                FUNCTION_SAVECONFIG = new SaveConfig(inApp);
                FUNCTION_EDIT_WAYPOINT_NAME = new PointNameEditor(inApp);
+               FUNCTION_PROJECT_POINT = new ProjectPoint(inApp);
                FUNCTION_REARRANGE_WAYPOINTS = new RearrangeWaypointsFunction(inApp);
                FUNCTION_SELECT_SEGMENT = new SelectSegmentFunction(inApp);
                FUNCTION_SPLIT_SEGMENTS = new SplitSegmentsFunction(inApp);
@@ -192,7 +189,6 @@ public abstract class FunctionLibrary
                FUNCTION_ADD_ALTITUDE_OFFSET = new AddAltitudeOffset(inApp);
                FUNCTION_CONVERT_NAMES_TO_TIMES = new ConvertNamesToTimes(inApp);
                FUNCTION_DELETE_FIELD_VALUES = new DeleteFieldValues(inApp);
-               FUNCTION_PASTE_COORDINATES = new PasteCoordinates(inApp);
                FUNCTION_FIND_WAYPOINT = new FindWaypoint(inApp);
                FUNCTION_DUPLICATE_POINT = new DuplicatePoint(inApp);
                FUNCTION_CONNECT_TO_POINT = new ConnectToPointFunction(inApp);
@@ -206,12 +202,10 @@ public abstract class FunctionLibrary
                FUNCTION_CHARTS = new Charter(inApp);
                FUNCTION_3D     = new ShowThreeDFunction(inApp);
                FUNCTION_DISTANCES = new DistanceFunction(inApp);
-               FUNCTION_FULL_RANGE_DETAILS = new FullRangeDetails(inApp);
+               FUNCTION_FULL_DETAILS = new ShowFullDetails(inApp);
                FUNCTION_AUTOPLAY_TRACK = new AutoplayFunction(inApp);
                FUNCTION_ESTIMATE_TIME = new EstimateTime(inApp);
                FUNCTION_LEARN_ESTIMATION_PARAMS = new LearnParameters(inApp);
-               FUNCTION_GET_GPSIES = new GetGpsiesFunction(inApp);
-               FUNCTION_UPLOAD_GPSIES = new UploadGpsiesFunction(inApp);
                FUNCTION_GET_WEATHER_FORECAST = new GetWeatherForecastFunction(inApp);
                FUNCTION_LOAD_AUDIO = new AudioLoader(inApp);
                FUNCTION_REMOVE_AUDIO = new RemoveAudioFunction(inApp);
index f396e9e4fdbc31a4c1ca2deb67cbe24eff7c6b76..874ece5a7b7dce6314c5179525b516cf88e31e56 100644 (file)
@@ -9,9 +9,11 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Locale;
+
 import javax.swing.JFrame;
 import javax.swing.JSplitPane;
 import javax.swing.JToolBar;
+import javax.swing.UIManager;
 import javax.swing.WindowConstants;
 
 import tim.prune.config.Config;
@@ -29,16 +31,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 https://activityworkshop.net
- * This software is copyright activityworkshop.net 2006-2018 and made available through the Gnu GPL version 2.
+ * This software is copyright activityworkshop.net 2006-2020 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 */
-       public static final String VERSION_NUMBER = "19.2";
+       public static final String VERSION_NUMBER = "20";
        /** Build number, just used for about screen */
-       public static final String BUILD_NUMBER = "363d";
+       public static final String BUILD_NUMBER = "378";
        /** Static reference to App object */
        private static App APP = null;
 
@@ -149,6 +151,14 @@ public class GpsPrune
                                Config.setConfigString(Config.KEY_LANGUAGE_FILE, "");
                        }
                }
+
+               // Set look-and-feel
+               try {
+                       String windowStyle = Config.getConfigString(Config.KEY_WINDOW_STYLE);
+                       UIManager.setLookAndFeel(windowStyle);
+               }
+               catch (Exception e) {}
+
                // Set up the window and go
                launch(dataFiles);
        }
index fbf781eb3fef3a79adbdc72548eb5b3c66c83f91..a271f81b9fc5a579ddcce33397a8cb3fbc110ab7 100644 (file)
@@ -18,10 +18,10 @@ import java.util.ResourceBundle;
 public abstract class I18nManager
 {
        /** Properties object into which all the texts are copied */
-       private static Properties LocalTexts = null;
+       private static Properties _localTexts = null;
 
        /** External properties file for developer testing */
-       private static Properties ExternalPropsFile = null;
+       private static Properties _externalPropsFile = null;
 
 
        /**
@@ -33,7 +33,7 @@ public abstract class I18nManager
                final String BUNDLE_NAME = "tim.prune.lang.prune-texts";
                final Locale BACKUP_LOCALE = new Locale("en", "GB");
 
-               LocalTexts = new Properties();
+               _localTexts = new Properties();
                // Load English texts first to use as defaults
                loadFromBundle(ResourceBundle.getBundle(BUNDLE_NAME, BACKUP_LOCALE));
 
@@ -65,7 +65,7 @@ public abstract class I18nManager
                while (e.hasMoreElements())
                {
                        String key = e.nextElement();
-                       LocalTexts.setProperty(key, inBundle.getString(key));
+                       _localTexts.setProperty(key, inBundle.getString(key));
                }
        }
 
@@ -81,9 +81,9 @@ public abstract class I18nManager
                try
                {
                        File file = new File(inFilename);
-                       ExternalPropsFile = new Properties();
+                       _externalPropsFile = new Properties();
                        fis = new FileInputStream(file);
-                       ExternalPropsFile.load(fis);
+                       _externalPropsFile.load(fis);
                        fileLoaded = true; // everything worked
                }
                catch (IOException ioe) {}
@@ -103,17 +103,17 @@ public abstract class I18nManager
        public static String getText(String inKey)
        {
                // look in external props file if available
-               if (ExternalPropsFile != null)
+               if (_externalPropsFile != null)
                {
-                       String extText = ExternalPropsFile.getProperty(inKey);
+                       String extText = _externalPropsFile.getProperty(inKey);
                        if (extText != null) return extText;
                }
                // look in texts if available
-               if (LocalTexts != null)
+               if (_localTexts != null)
                {
                        try
                        {
-                               String localText = LocalTexts.getProperty(inKey);
+                               String localText = _localTexts.getProperty(inKey);
                                if (localText != null) return localText;
                        }
                        catch (MissingResourceException mre) {}
index 84e5fd7dc6b4a248bb1d2bef51f18be225f90425..8c6eefec498706d0c789ad1ae3b4302a8e4022ac 100644 (file)
@@ -55,6 +55,8 @@ public abstract class Config
        public static final String KEY_POVRAY_FONT = "prune.povrayfont";
        /** Key for the selected unit set */
        public static final String KEY_UNITSET_KEY  = "prune.unitsetkey";
+       /** Key for the selected coordinate display format */
+       public static final String KEY_COORD_DISPLAY_FORMAT  = "prune.coorddisplay";
        /** Key for index of map source */
        public static final String KEY_MAPSOURCE_INDEX = "prune.mapsource";
        /** Key for number of fixed map sources */
@@ -87,6 +89,8 @@ public abstract class Config
        public static final String KEY_ANTIALIAS = "prune.antialias";
        /** Key for kml track colour */
        public static final String KEY_KML_TRACK_COLOUR = "prune.kmltrackcolour";
+       /** Key for window style (name of look-and-feel) */
+       public static final String KEY_WINDOW_STYLE = "prune.windowstyle";
        /** Key for autosaving settings */
        public static final String KEY_AUTOSAVE_SETTINGS = "prune.autosavesettings";
        /** Key for recently used files */
@@ -170,6 +174,8 @@ public abstract class Config
                _unitSet = UnitSetLibrary.getUnitSet(_configValues.getProperty(KEY_UNITSET_KEY));
                // Adjust map source index if necessary
                adjustSelectedMap();
+               // Reset coord display format
+               setConfigInt(KEY_COORD_DISPLAY_FORMAT, 0);
 
                if (loadFailed) {
                        throw new ConfigException();
@@ -197,6 +203,7 @@ public abstract class Config
                props.put(KEY_ANTIALIAS, "1"); // antialias on by default
                props.put(KEY_AUTOSAVE_SETTINGS, "0"); // autosave false by default
                props.put(KEY_UNITSET_KEY, "unitset.kilometres"); // metric by default
+               props.put(KEY_COORD_DISPLAY_FORMAT, "0"); // original
                props.put(KEY_HEIGHT_EXAGGERATION, "100"); // 100%, no exaggeration
                props.put(KEY_TERRAIN_GRID_SIZE, "50");
                props.put(KEY_ALTITUDE_TOLERANCE, "0"); // 0, all exact as before
@@ -246,6 +253,14 @@ public abstract class Config
                return _configFile;
        }
 
+       /**
+        * Set the file to which config was saved
+        */
+       public static void setConfigFile(File inFile)
+       {
+               _configFile = inFile;
+       }
+
        /**
         * @return config Properties object to allow all config values to be saved
         */
@@ -379,7 +394,7 @@ public abstract class Config
        public static void updatePointColourer(PointColourer inColourer)
        {
                _pointColourer = inColourer;
-               setConfigString(KEY_POINT_COLOURER, ColourerFactory.PointColourerToString(_pointColourer));
+               setConfigString(KEY_POINT_COLOURER, ColourerFactory.pointColourerToString(_pointColourer));
        }
 
        /**
index 3022774654f3f6b66501b143e2ca113bdc103eaa..db7f2dd61157be5b834af0d2cb491708e8d806f4 100644 (file)
@@ -1,4 +1,4 @@
-The source code of GpsPrune is copyright 2006-2018 activityworkshop.net
+The source code of GpsPrune is copyright 2006-2020 activityworkshop.net
 and is distributed under the terms of the Gnu GPL version 2.
 
 Portions of the package jpeg.drew were taken
@@ -6,4 +6,4 @@ from Drew Noakes' "Metadata extractor" v2.7.2 which is
 copyright Drew Noakes 2002-2015 and released under Apache 2.0.
 
 Translations are copyright various contributors, some of whom are named
-in the source code and some preferred to remain anonymous.
\ No newline at end of file
+in the source code and some preferred to remain anonymous.
index e30fa4ac357d89a68041fa07eee2f76bf5e8ee22..b668660236a5d164e710a4963a7b7c0ff64975fa 100644 (file)
@@ -475,4 +475,22 @@ public abstract class Coordinate
                return "Coord: " + _cardinal + " (" + _degrees + ") (" + _minutes + ") (" + _seconds + "."
                        + formatFraction(_fracs, _fracDenom) + ") = " + _asDouble;
        }
+
+       /**
+        * From a saved coordinate format display value, get the corresponding value to use
+        * @param inValue value from config
+        * @return coordinate format as int
+        */
+       public static int getCoordinateFormatForDisplay(int inValue)
+       {
+               switch(inValue)
+               {
+                       case FORMAT_DEG:
+                       case FORMAT_DEG_MIN:
+                       case FORMAT_DEG_MIN_SEC:
+                               return inValue;
+                       default:
+                               return FORMAT_NONE;
+               }
+       }
 }
index 41900cb8736df60d668238306079256bf2dca175..0c4ee5fd4606624b8de9ce00af8f57a3284ccee1 100644 (file)
@@ -51,7 +51,9 @@ public class FileInfo
         */
        public void removeSource()
        {
-               _sources.remove(_sources.size()-1);
+               if (!_sources.isEmpty()) {
+                       _sources.remove(_sources.size()-1);
+               }
        }
 
        /**
index 13ecaade10d4e6a8d0eccc87a383762ae399cc00..d8461c476b122a58561d215296b1fe7370aef74b 100644 (file)
 package tim.prune.data;
 
-import tim.prune.config.Config;
-
 /**
- * Class to do calculations of range statistics such as distances, durations,
- * speeds, gradients etc, and to hold the results of the calculations.
- * Used by FullRangeDetails as well as the EstimateTime functions.
+ * Class to do basic calculations of range statistics such as distances, durations,
+ * and altitude ranges, and to hold the results of the calculations.
  */
 public class RangeStats
 {
-       // MAYBE: Split into basic stats (quick to calculate, for detailsdisplay) and full stats (for other two)
-       private boolean _valid = false;
-       private int     _numPoints   = 0;
-       private int     _startIndex = 0, _endIndex = 0;
-       private int     _numSegments = 0;
-       private AltitudeRange _totalAltitudeRange = null, _movingAltitudeRange = null;
-       private AltitudeRange _gentleAltitudeRange = null, _steepAltitudeRange = null;
+       private int _numPoints   = 0;
+       private int _numSegments = 0;
+       private boolean _foundTrackPoint = false;
+       protected AltitudeRange _totalAltitudeRange = new AltitudeRange();
+       protected AltitudeRange _movingAltitudeRange = new AltitudeRange();
        private Timestamp _earliestTimestamp = null, _latestTimestamp = null;
        private long _movingMilliseconds = 0L;
        private boolean _timesIncomplete = false;
        private boolean _timesOutOfSequence = false;
-       private double _totalDistanceRads = 0.0, _movingDistanceRads = 0.0;
-       // Note, maximum speed is not calculated here, use the SpeedData class instead
+       protected double _totalDistanceRads = 0.0, _movingDistanceRads = 0.0;
+       protected DataPoint _prevPoint = null;
 
-       private static final double STEEP_ANGLE = 0.15; // gradient steeper than 15% counts as steep
 
+       /** Constructor */
+       public RangeStats()
+       {}
 
        /**
-        * Constructor
-        * @param inTrack track to compile data for
-        * @param inStartIndex start index of range to examine
-        * @param inEndIndex end index (inclusive) of range to examine
+        * Constructor giving Track
+        * @param inTrack track object to calculate with
         */
        public RangeStats(Track inTrack, int inStartIndex, int inEndIndex)
        {
-               if (inTrack != null && inStartIndex >= 0 && inEndIndex > inStartIndex
-                       && inEndIndex < inTrack.getNumPoints())
+               populateFromTrack(inTrack, inStartIndex, inEndIndex);
+       }
+
+       /**
+        * Add the specified points from the given track to the calculations
+        * @param inTrack track object
+        * @param inStartIndex start index (inclusive)
+        * @param inEndIndex end index (inclusive)
+        */
+       protected void populateFromTrack(Track inTrack, int inStartIndex, int inEndIndex)
+       {
+               for (int i=inStartIndex; i<=inEndIndex; i++)
                {
-                       _valid = calculateStats(inTrack, inStartIndex, inEndIndex);
+                       addPoint(inTrack.getPoint(i));
                }
        }
 
        /**
-        * Calculate the statistics and populate the member variables with the results
-        * @param inTrack track
-        * @param inStartIndex start index of range
-        * @param inEndIndex end index (inclusive) of range
-        * @return true on success
+        * @param inPoint point to add to the calculations
         */
-       private boolean calculateStats(Track inTrack, int inStartIndex, int inEndIndex)
+       public void addPoint(DataPoint inPoint)
        {
-               _startIndex = inStartIndex;
-               _endIndex = inEndIndex;
-               _numPoints = inEndIndex - inStartIndex + 1;
-               _totalAltitudeRange  = new AltitudeRange();
-               _movingAltitudeRange = new AltitudeRange();
-               _gentleAltitudeRange = new AltitudeRange();
-               _steepAltitudeRange  = new AltitudeRange();
-               DataPoint prevPoint = null;
-               Altitude prevAltitude = null;
-               _totalDistanceRads = _movingDistanceRads = 0.0;
-               double radsSinceLastAltitude = 0.0;
-               _movingMilliseconds = 0L;
-
-               // Loop over the points in the range
-               for (int i=inStartIndex; i<= inEndIndex; i++)
+               if (inPoint == null)
+               {
+                       return;
+               }
+               _numPoints++;
+               // ignore all waypoints
+               if (inPoint.isWaypoint()) {
+                       return;
+               }
+               if (inPoint.getSegmentStart() || !_foundTrackPoint) {
+                       _numSegments++;
+               }
+               _foundTrackPoint = true;
+               // Get the distance to the previous track point
+               if (_prevPoint != null)
                {
-                       DataPoint p = inTrack.getPoint(i);
-                       if (p == null) return false;
-                       // ignore all waypoints
-                       if (p.isWaypoint()) continue;
+                       double rads = DataPoint.calculateRadiansBetween(_prevPoint, inPoint);
+                       _totalDistanceRads += rads;
+                       if (!inPoint.getSegmentStart()) {
+                               _movingDistanceRads += rads;
+                       }
+               }
 
-                       if (p.getSegmentStart()) {
-                               _numSegments++;
+               // timestamps
+               if (inPoint.hasTimestamp())
+               {
+                       Timestamp currTstamp = inPoint.getTimestamp();
+                       if (_earliestTimestamp == null || currTstamp.isBefore(_earliestTimestamp)) {
+                               _earliestTimestamp = currTstamp;
                        }
-                       // Get the distance to the previous track point
-                       if (prevPoint != null)
-                       {
-                               double rads = DataPoint.calculateRadiansBetween(prevPoint, p);
-                               _totalDistanceRads += rads;
-                               if (!p.getSegmentStart()) {
-                                       _movingDistanceRads += rads;
-                               }
-                               // Keep track of rads since last point with an altitude
-                               radsSinceLastAltitude += rads;
+                       if (_latestTimestamp == null || currTstamp.isAfter(_latestTimestamp)) {
+                               _latestTimestamp = currTstamp;
                        }
-                       // Get the altitude difference to the previous track point
-                       if (p.hasAltitude())
+                       // Work out duration without segment gaps
+                       if (!inPoint.getSegmentStart() && _prevPoint != null && _prevPoint.hasTimestamp())
                        {
-                               Altitude altitude = p.getAltitude();
-                               _totalAltitudeRange.addValue(altitude);
-                               if (p.getSegmentStart()) {
-                                       _movingAltitudeRange.ignoreValue(altitude);
+                               long millisLater = currTstamp.getMillisecondsSince(_prevPoint.getTimestamp());
+                               if (millisLater < 0) {
+                                       _timesOutOfSequence = true;
                                }
-                               else
-                               {
-                                       _movingAltitudeRange.addValue(altitude);
-                                       if (prevAltitude != null)
-                                       {
-                                               // Work out gradient, see whether to ignore/add to gentle or steep
-                                               double heightDiff = altitude.getMetricValue() - prevAltitude.getMetricValue();
-                                               double metricDist = Distance.convertRadiansToDistance(radsSinceLastAltitude, UnitSetLibrary.UNITS_METRES);
-                                               final boolean isSteep = metricDist < 0.001 || (Math.abs(heightDiff / metricDist) > STEEP_ANGLE);
-                                               if (isSteep) {
-                                                       _steepAltitudeRange.ignoreValue(prevAltitude);
-                                                       _steepAltitudeRange.addValue(altitude);
-                                               }
-                                               else {
-                                                       _gentleAltitudeRange.ignoreValue(prevAltitude);
-                                                       _gentleAltitudeRange.addValue(altitude);
-                                               }
-                                       }
+                               else {
+                                       _movingMilliseconds += millisLater;
                                }
-                               prevAltitude = altitude;
-                               radsSinceLastAltitude = 0.0;
                        }
+               }
+               else {
+                       _timesIncomplete = true;
+               }
 
-                       if (p.hasTimestamp())
-                       {
-                               if (_earliestTimestamp == null || p.getTimestamp().isBefore(_earliestTimestamp)) {
-                                       _earliestTimestamp = p.getTimestamp();
-                               }
-                               if (_latestTimestamp == null || p.getTimestamp().isAfter(_latestTimestamp)) {
-                                       _latestTimestamp = p.getTimestamp();
-                               }
-                               // Work out duration without segment gaps
-                               if (!p.getSegmentStart() && prevPoint != null && prevPoint.hasTimestamp())
-                               {
-                                       long millisLater = p.getTimestamp().getMillisecondsSince(prevPoint.getTimestamp());
-                                       if (millisLater < 0) {_timesOutOfSequence = true;}
-                                       else {
-                                               _movingMilliseconds += millisLater;
-                                       }
-                               }
+               // altitudes
+               if (inPoint.hasAltitude())
+               {
+                       Altitude altitude = inPoint.getAltitude();
+                       _totalAltitudeRange.addValue(altitude);
+                       if (inPoint.getSegmentStart()) {
+                               _movingAltitudeRange.ignoreValue(altitude);
                        }
-                       else {
-                               _timesIncomplete = true;
+                       else
+                       {
+                               _movingAltitudeRange.addValue(altitude);
                        }
-
-                       prevPoint = p;
                }
-               return true;
-       }
 
+               // allow child classes to do additional calculations
+               doFurtherCalculations(inPoint);
 
-       /** @return true if results are valid */
-       public boolean isValid() {
-               return _valid;
+               _prevPoint = inPoint;
        }
 
-       /** @return start index of range */
-       public int getStartIndex() {
-               return _startIndex;
+       /**
+        * Hook for subclasses to do what they want in addition
+        * @param inPoint incoming point
+        */
+       protected void doFurtherCalculations(DataPoint inPoint)
+       {
        }
 
-       /** @return end index of range */
-       public int getEndIndex() {
-               return _endIndex;
-       }
 
        /** @return number of points in range */
        public int getNumPoints() {
@@ -179,16 +149,6 @@ public class RangeStats
                return _movingAltitudeRange;
        }
 
-       /** @return altitude range of range just considering low gradient bits */
-       public AltitudeRange getGentleAltitudeRange() {
-               return _gentleAltitudeRange;
-       }
-
-       /** @return altitude range of range just considering high gradient bits */
-       public AltitudeRange getSteepAltitudeRange() {
-               return _steepAltitudeRange;
-       }
-
        /** @return the earliest timestamp found */
        public Timestamp getEarliestTimestamp() {
                return _earliestTimestamp;
@@ -239,42 +199,26 @@ public class RangeStats
                return Distance.convertRadiansToDistance(_movingDistanceRads, UnitSetLibrary.UNITS_KILOMETRES);
        }
 
-       /** @return the total gradient in % (including segment gaps) */
-       public double getTotalGradient()
-       {
-               double dist = Distance.convertRadiansToDistance(_totalDistanceRads, UnitSetLibrary.UNITS_METRES);
-               if (dist > 0.0 && _totalAltitudeRange.hasRange()) {
-                       return _totalAltitudeRange.getMetricHeightDiff() / dist * 100.0;
-               }
-               return 0.0;
-       }
-
-       /** @return the moving gradient in % (ignoring segment gaps) */
-       public double getMovingGradient()
-       {
-               double dist = Distance.convertRadiansToDistance(_movingDistanceRads, UnitSetLibrary.UNITS_METRES);
-               if (dist > 0.0 && _movingAltitudeRange.hasRange()) {
-                       return _movingAltitudeRange.getMetricHeightDiff() / dist * 100.0;
-               }
-               return 0.0;
-       }
-
-       /** @return the total vertical speed (including segment gaps) in current vspeed units */
+       /**
+        * @return the total vertical speed (including segment gaps) in metric units
+        */
        public double getTotalVerticalSpeed()
        {
                long time = getTotalDurationInSeconds();
                if (time > 0 && _totalAltitudeRange.hasRange()) {
-                       return _totalAltitudeRange.getMetricHeightDiff() / time * Config.getUnitSet().getVerticalSpeedUnit().getMultFactorFromStd();
+                       return _totalAltitudeRange.getMetricHeightDiff() / time;
                }
                return 0.0;
        }
 
-       /** @return the moving vertical speed (ignoring segment gaps) in current vspeed units */
+       /**
+        * @return the moving vertical speed (ignoring segment gaps) in metric units
+        */
        public double getMovingVerticalSpeed()
        {
                long time = getMovingDurationInSeconds();
                if (time > 0 && _movingAltitudeRange.hasRange()) {
-                       return _movingAltitudeRange.getMetricHeightDiff() / time * Config.getUnitSet().getVerticalSpeedUnit().getMultFactorFromStd();
+                       return _movingAltitudeRange.getMetricHeightDiff() / time;
                }
                return 0.0;
        }
diff --git a/src/tim/prune/data/RangeStatsWithGradients.java b/src/tim/prune/data/RangeStatsWithGradients.java
new file mode 100644 (file)
index 0000000..c495c51
--- /dev/null
@@ -0,0 +1,106 @@
+package tim.prune.data;
+
+/**
+ * Class to do additional range calculations including gradients
+ * Used by full details display as well as the EstimateTime functions.
+ */
+public class RangeStatsWithGradients extends RangeStats
+{
+       private AltitudeRange _gentleAltitudeRange = new AltitudeRange();
+       private AltitudeRange _steepAltitudeRange = new AltitudeRange();
+       private Altitude _prevAltitude = null;
+       private double _radsSinceLastAltitude = 0.0;
+
+       private static final double STEEP_ANGLE = 0.15; // gradient steeper than 15% counts as steep
+
+
+       /**
+        * Default constructor
+        */
+       public RangeStatsWithGradients()
+       {
+               super();
+       }
+
+       /**
+        * Constructor
+        * @param inTrack track object
+        * @param inStartIndex start index
+        * @param inEndIndex end index
+        */
+       public RangeStatsWithGradients(Track inTrack, int inStartIndex, int inEndIndex)
+       {
+               super();
+               populateFromTrack(inTrack, inStartIndex, inEndIndex);
+       }
+
+       /**
+        * Add the given point to the calculations
+        * @param inPoint incoming point
+        */
+       protected void doFurtherCalculations(DataPoint inPoint)
+       {
+               if (_prevPoint != null)
+               {
+                       // Keep track of rads since last point with an altitude
+                       double rads = DataPoint.calculateRadiansBetween(_prevPoint, inPoint);
+                       _radsSinceLastAltitude += rads;
+               }
+
+               if (inPoint.hasAltitude())
+               {
+                       Altitude altitude = inPoint.getAltitude();
+
+                       if (!inPoint.getSegmentStart() && _prevAltitude != null)
+                       {
+                               // Work out gradient, see whether to ignore/add to gentle or steep
+                               double heightDiff = altitude.getMetricValue() - _prevAltitude.getMetricValue();
+                               double metricDist = Distance.convertRadiansToDistance(_radsSinceLastAltitude, UnitSetLibrary.UNITS_METRES);
+                               final boolean isSteep = metricDist < 0.001 || (Math.abs(heightDiff / metricDist) > STEEP_ANGLE);
+                               if (isSteep)
+                               {
+                                       _steepAltitudeRange.ignoreValue(_prevAltitude);
+                                       _steepAltitudeRange.addValue(altitude);
+                               }
+                               else
+                               {
+                                       _gentleAltitudeRange.ignoreValue(_prevAltitude);
+                                       _gentleAltitudeRange.addValue(altitude);
+                               }
+                       }
+                       _prevAltitude = altitude;
+                       _radsSinceLastAltitude = 0.0;
+               }
+
+       }
+
+       /** @return altitude range of range just considering low gradient bits */
+       public AltitudeRange getGentleAltitudeRange() {
+               return _gentleAltitudeRange;
+       }
+
+       /** @return altitude range of range just considering high gradient bits */
+       public AltitudeRange getSteepAltitudeRange() {
+               return _steepAltitudeRange;
+       }
+
+       /** @return the total gradient in % (including segment gaps) */
+       public double getTotalGradient()
+       {
+               double dist = Distance.convertRadiansToDistance(_totalDistanceRads, UnitSetLibrary.UNITS_METRES);
+               if (dist > 0.0 && _totalAltitudeRange.hasRange()) {
+                       return _totalAltitudeRange.getMetricHeightDiff() / dist * 100.0;
+               }
+               return 0.0;
+       }
+
+       /** @return the moving gradient in % (ignoring segment gaps) */
+       public double getMovingGradient()
+       {
+               double dist = Distance.convertRadiansToDistance(_movingDistanceRads, UnitSetLibrary.UNITS_METRES);
+               if (dist > 0.0 && _movingAltitudeRange.hasRange()) {
+                       return _movingAltitudeRange.getMetricHeightDiff() / dist * 100.0;
+               }
+               return 0.0;
+       }
+}
index 7b63d70838e660c9af142aa1b341f5c2bd40ccce..24fda5df99565270b898602ed75f6e5cca39802e 100644 (file)
@@ -11,14 +11,11 @@ public class Selection
 {
        private Track _track = null;
        private int _currentPoint = -1;
-       private boolean _valid = false;
        private int _prevNumPoints = 0;
        private int _startIndex = -1, _endIndex = -1;
        private int _currentPhotoIndex = -1;
        private int _currentAudioIndex = -1;
-       private AltitudeRange _altitudeRange = null;
-       private long _movingMilliseconds = 0L;
-       private double _angMovingDistance = -1.0;
+       private RangeStats _rangeStats = null;
 
 
        /**
@@ -36,7 +33,7 @@ public class Selection
         */
        public void markInvalid()
        {
-               _valid = false;
+               _rangeStats = null;
        }
 
 
@@ -63,6 +60,9 @@ public class Selection
         */
        private void recalculate()
        {
+               if (_rangeStats != null) {
+                       return;
+               }
                final int numPoints = _track.getNumPoints();
                // Recheck if the number of points has changed
                if (numPoints != _prevNumPoints)
@@ -72,52 +72,12 @@ public class Selection
                }
                if (numPoints > 0 && hasRangeSelected())
                {
-                       _altitudeRange = new AltitudeRange();
-                       Altitude altitude = null;
-                       Timestamp time = null, previousTime = null;
-                       DataPoint lastPoint = null, currPoint = null;
-                       _angMovingDistance = 0.0;
-                       _movingMilliseconds = 0L;
-                       // Loop over points in selection
-                       for (int i=_startIndex; i<=_endIndex; i++)
-                       {
-                               currPoint = _track.getPoint(i);
-                               altitude = currPoint.getAltitude();
-                               // Ignore waypoints in altitude calculations
-                               if (!currPoint.isWaypoint() && altitude.isValid())
-                               {
-                                       if (currPoint.getSegmentStart()) {
-                                               _altitudeRange.ignoreValue(altitude);
-                                       }
-                                       else {
-                                               _altitudeRange.addValue(altitude);
-                                       }
-                               }
-                               // Compare timestamps within the segments
-                               time = currPoint.getTimestamp();
-                               if (time.isValid())
-                               {
-                                       // add moving time
-                                       if (!currPoint.getSegmentStart() && previousTime != null && time.isAfter(previousTime)) {
-                                               _movingMilliseconds += time.getMillisecondsSince(previousTime);
-                                       }
-                                       previousTime = time;
-                               }
-                               // Calculate distances, again ignoring waypoints
-                               if (!currPoint.isWaypoint())
-                               {
-                                       if (lastPoint != null)
-                                       {
-                                               double radians = DataPoint.calculateRadiansBetween(lastPoint, currPoint);
-                                               if (!currPoint.getSegmentStart()) {
-                                                       _angMovingDistance += radians;
-                                               }
-                                       }
-                                       lastPoint = currPoint;
-                               }
-                       }
+                       _rangeStats = new RangeStats(_track, _startIndex, _endIndex);
+               }
+               else
+               {
+                       _rangeStats = new RangeStats();
                }
-               _valid = true;
        }
 
 
@@ -126,7 +86,7 @@ public class Selection
         */
        public int getStart()
        {
-               if (!_valid) recalculate();
+               recalculate();
                return _startIndex;
        }
 
@@ -136,7 +96,7 @@ public class Selection
         */
        public int getEnd()
        {
-               if (!_valid) recalculate();
+               recalculate();
                return _endIndex;
        }
 
@@ -145,8 +105,8 @@ public class Selection
         */
        public AltitudeRange getAltitudeRange()
        {
-               if (!_valid) recalculate();
-               return _altitudeRange;
+               recalculate();
+               return _rangeStats.getTotalAltitudeRange();
        }
 
 
@@ -155,8 +115,8 @@ public class Selection
         */
        public long getMovingSeconds()
        {
-               if (!_valid) recalculate();
-               return _movingMilliseconds / 1000L;
+               recalculate();
+               return _rangeStats.getMovingDurationInSeconds();
        }
 
        /**
@@ -164,7 +124,7 @@ public class Selection
         */
        public double getMovingDistance()
        {
-               return Distance.convertRadiansToDistance(_angMovingDistance);
+               return _rangeStats.getMovingDistance();
        }
 
        /**
@@ -176,6 +136,7 @@ public class Selection
                selectRange(-1, -1);
                _currentPhotoIndex = -1;
                _currentAudioIndex = -1;
+               markInvalid();
                check();
        }
 
@@ -276,6 +237,7 @@ public class Selection
                // Clear selected range
                _startIndex = _endIndex = -1;
                // Check for consistency and fire update
+               markInvalid();
                check();
        }
 
@@ -355,6 +317,7 @@ public class Selection
                {
                        // track is empty, clear selections
                        _currentPoint = _startIndex = _endIndex = -1;
+                       markInvalid();
                }
                UpdateMessageBroker.informSubscribers(DataSubscriber.SELECTION_CHANGED);
        }
index ac144bb8c59e8247deb67438a9f5c8504c258ca9..6083cf676bcc468f06178cd88f04e4f88547fa2e 100644 (file)
@@ -22,7 +22,7 @@ public abstract class Timestamp
        protected static final DateFormat ISO_8601_FORMAT_WITH_MILLIS
                = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
 
-       private static boolean MillisAddedToTimeFormat = false;
+       private static boolean _millisAddedToTimeFormat = false;
 
 
        /** Possible formats for parsing and displaying timestamps */
@@ -138,7 +138,7 @@ public abstract class Timestamp
        {
                if (!isValid()) return "";
                // Maybe we should add milliseconds to this format?
-               if (hasMilliseconds() && !MillisAddedToTimeFormat)
+               if (hasMilliseconds() && !_millisAddedToTimeFormat)
                {
                        try
                        {
@@ -147,7 +147,7 @@ public abstract class Timestamp
                                if (pattern.indexOf("ss") > 0 && pattern.indexOf("SS") < 0)
                                {
                                        sdf.applyPattern(pattern.replaceFirst("s+", "$0.SSS"));
-                                       MillisAddedToTimeFormat = true;
+                                       _millisAddedToTimeFormat = true;
                                }
                        }
                        catch (ClassCastException cce) {}
index 80a7983418149d97f3cf7fce1e9915cda968dae2..518b10e1568fbb29a2407f61cfee3682cf568b8f 100644 (file)
@@ -98,7 +98,7 @@ public class AboutScreen extends GenericFunction
                descBuffer.append("<p>").append(I18nManager.getText("dialog.about.languages")).append(" : ")
                        .append("afrikaans, \u010de\u0161tina, deutsch, english, espa\u00F1ol, fran\u00E7ais, italiano,<br>" +
                                " magyar, nederlands, polski, portugu\u00EAs, rom\u00E2n\u0103, suomi, \u0440\u0443\u0441\u0441\u043a\u0438\u0439 (russian),<br>" +
-                               " \u4e2d\u6587 (chinese), \u65E5\u672C\u8A9E (japanese), \uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean), schwiizerd\u00FC\u00FCtsch, ukrainian</p>");
+                               " \u4e2d\u6587 (chinese), \u65E5\u672C\u8A9E (japanese), \uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean), schwiizerd\u00FC\u00FCtsch</p>");
                descBuffer.append("<p>").append(I18nManager.getText("dialog.about.translatedby")).append("</p>");
                JEditorPane descPane = new JEditorPane("text/html", descBuffer.toString());
                descPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
index c98ab3e17843a27db638d74ffac802c5400bea36..26849de03711831a49e427b9e7fa7ae34c6d17a9 100644 (file)
@@ -101,7 +101,7 @@ public class AddAltitudeOffset extends GenericFunction
                MouseAdapter mouseListener = new MouseAdapter() {
                        public void mouseReleased(java.awt.event.MouseEvent arg0) {
                                _okButton.setEnabled(Math.abs(getOffset()) > 0.001);
-                       };
+                       }
                };
                _editField.addKeyListener(keyListener);
                _editField.addMouseListener(mouseListener);
index 2e259bb5f5895e94690355d2cbee039080a8434d..115bfa5997102edc0db005074c05fa5a97bb4754 100644 (file)
@@ -126,7 +126,7 @@ public class AddTimeOffset extends GenericFunction
                MouseAdapter mouseListener = new MouseAdapter() {
                        public void mouseReleased(java.awt.event.MouseEvent arg0) {
                                _okButton.setEnabled(getOffsetSecs() != 0L);
-                       };
+                       }
                };
                _dayField.addKeyListener(keyListener);
                _hourField.addKeyListener(keyListener);
index 0998020f2f2f871ed9d1d8522af91d13b72ef9b5..9921dc590aa8bfaed816f4e4456c241bc72c3e7b 100644 (file)
@@ -42,9 +42,9 @@ public class ConnectToPointFunction extends GenericFunction
                boolean connectPhoto = (point != null && photo != null && point.getPhoto() == null);
                boolean connectAudio = (point != null && audio != null && point.getAudio() == null);
 
-               if (connectPhoto && connectAudio) {
+               // if (connectPhoto && connectAudio) {
                        // TODO: Let user choose whether to connect photo/audio or both
-               }
+               // }
                // Make undo object
                UndoOperation undo = new UndoConnectMedia(point, connectPhoto?photo.getName():null,
                        connectAudio?audio.getName():null);
index f3dd1f1d9bca2eba8f78f42a3a136294363543e9..92b4ce56c497b6dbd33924d43f2984cea20ae3a7 100644 (file)
@@ -8,12 +8,14 @@ import tim.prune.UpdateMessageBroker;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Field;
 import tim.prune.data.FieldList;
+import tim.prune.data.RangeStats;
 import tim.prune.data.Track;
+import tim.prune.data.UnitSetLibrary;
 import tim.prune.undo.UndoAppendPoints;
 
 /**
- * Function to create waypoints marking either
- * at regular distance intervals or time intervals
+ * Function to create waypoints marking regular distance intervals,
+ * regular time intervals, or halfway points
  */
 public class CreateMarkerWaypointsFunction extends DistanceTimeLimitFunction
 {
@@ -22,12 +24,21 @@ public class CreateMarkerWaypointsFunction extends DistanceTimeLimitFunction
        /** Counter of previously used multiple */
        private int _previousMultiple = 0;
 
+       /*
+        * Type of halfway point
+        */
+       private enum HalfwayType
+       {
+               HALF_DISTANCE,
+               HALF_CLIMB,
+               HALF_DESCENT
+       }
 
        /**
         * Constructor
         */
        public CreateMarkerWaypointsFunction(App inApp) {
-               super(inApp);
+               super(inApp, true);
        }
 
        /**
@@ -51,55 +62,34 @@ public class CreateMarkerWaypointsFunction extends DistanceTimeLimitFunction
         */
        protected void performFunction()
        {
-               // Distribute either by distance or time
+               // Determine which kind of markers to create
                final int timeLimitSeconds = getTimeLimitInSeconds();
                final boolean createByTime = (timeLimitSeconds > 0);
-               final double distLimitRadians = getDistanceLimitRadians();
-               final boolean createByDistance = (distLimitRadians > 0.0);
-               if (!createByTime && !createByDistance) {
-                       return; // neither option selected
-               }
-
-               // Make undo object
-               final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
-               UndoAppendPoints undo = new UndoAppendPoints(numPoints);
+               final double distLimitKm = getDistanceLimitKilometres();
+               final boolean createByDistance = (distLimitKm > 0.0);
+               final boolean createHalves = isHalvesSelected();
 
                // set up the memory from scratch to collect the created points
                initMemory();
 
-               // Make new waypoints, looping through the points in the track
-               DataPoint currPoint = null, prevPoint = null;
-               double currValue = 0.0, prevValue = 0.0;
-               for (int i=0; i<numPoints; i++)
+               if (createByTime || createByDistance) {
+                       createWaypointsAtIntervals(timeLimitSeconds, distLimitKm);
+               }
+               else if (createHalves)
                {
-                       currPoint = _app.getTrackInfo().getTrack().getPoint(i);
-                       if (!currPoint.isWaypoint())
-                       {
-                               if (!currPoint.getSegmentStart() && prevPoint != null)
-                               {
-                                       // Calculate current value
-                                       if (createByTime)
-                                       {
-                                               if (currPoint.hasTimestamp() && prevPoint.hasTimestamp())
-                                               {
-                                                       currValue += (currPoint.getTimestamp().getMillisecondsSince(prevPoint.getTimestamp()) / 1000.0);
-                                                       processValue(prevPoint, prevValue, timeLimitSeconds, currPoint, currValue);
-                                               }
-                                       }
-                                       else if (createByDistance)
-                                       {
-                                               currValue += DataPoint.calculateRadiansBetween(prevPoint, currPoint);
-                                               processValue(prevPoint, prevValue, distLimitRadians, currPoint, currValue);
-                                       }
-                               }
-                               prevPoint = currPoint;
-                               prevValue = currValue;
-                       }
+                       createHalfwayWaypoints();
+               }
+               else
+               {
+                       return;
                }
 
-               // System.out.println(_pointsToAdd.size() + " markers to add...");
                if (!_pointsToAdd.isEmpty())
                {
+                       // Make undo object
+                       final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
+                       UndoAppendPoints undo = new UndoAppendPoints(numPoints);
+
                        // Append created points to Track
                        Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.ALTITUDE, Field.WAYPT_NAME};
                        final int numPointsToAdd = _pointsToAdd.size();
@@ -109,13 +99,53 @@ public class CreateMarkerWaypointsFunction extends DistanceTimeLimitFunction
                        _app.getTrackInfo().getTrack().combine(wpTrack);
 
                        undo.setNumPointsAppended(numPointsToAdd);
-                       _app.completeFunction(undo, I18nManager.getText("confirm.interpolate"));
-                       // TODO: Maybe add new token including number of points added/created
+                       final String confirmMessage = I18nManager.getTextWithNumber("confirm.pointsadded", _pointsToAdd.size());
+                       _app.completeFunction(undo, confirmMessage);
                        UpdateMessageBroker.informSubscribers();
                }
                _dialog.dispose();
        }
 
+       /**
+        * Create waypoints according to the given intervals
+        * @param inTimeLimitSeconds
+        * @param inDistLimitKm distance limit in kilometres
+        */
+       private void createWaypointsAtIntervals(int inTimeLimitSeconds, double inDistLimitKm)
+       {
+               final boolean createByTime = (inTimeLimitSeconds > 0);
+               final boolean createByDistance = (inDistLimitKm > 0.0);
+
+               // Make new waypoints, looping through the points in the track
+               DataPoint currPoint = null, prevPoint = null;
+               double currValue = 0.0, prevValue = 0.0;
+               RangeStats rangeStats = new RangeStats();
+               final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
+               for (int i=0; i<numPoints; i++)
+               {
+                       currPoint = _app.getTrackInfo().getTrack().getPoint(i);
+                       rangeStats.addPoint(currPoint);
+
+                       if (!currPoint.isWaypoint())
+                       {
+                               // Calculate current value
+                               if (createByTime)
+                               {
+                                       currValue = rangeStats.getMovingDurationInSeconds();
+                                       processValue(prevPoint, prevValue, inTimeLimitSeconds, currPoint, currValue);
+                               }
+                               else if (createByDistance)
+                               {
+                                       currValue = rangeStats.getMovingDistanceKilometres();
+                                       processValue(prevPoint, prevValue, inDistLimitKm, currPoint, currValue);
+                               }
+
+                               prevPoint = currPoint;
+                               prevValue = currValue;
+                       }
+               }
+       }
+
        /**
         * Consider a pair of points in the track to see if a new marker should be inserted between them
         * @param inPrevPoint previous point
@@ -138,8 +168,124 @@ public class CreateMarkerWaypointsFunction extends DistanceTimeLimitFunction
                        DataPoint marker = DataPoint.interpolate(inPrevPoint, inCurrPoint, fractionFromPrev);
                        marker.setFieldValue(Field.WAYPT_NAME, createLimitDescription(m), false);
                        _pointsToAdd.add(marker);
-                       // System.out.println("I would add a point here with values " + inPrevValue + " and " + inCurrValue);
                }
                _previousMultiple = currMultiple;
        }
+
+       /**
+        * Create waypoints for the halfway markers
+        */
+       private void createHalfwayWaypoints()
+       {
+               // Calculate the details of the whole track so we can see what to halve
+               final int numPoints = _app.getTrackInfo().getTrack().getNumPoints();
+               RangeStats totalStats = new RangeStats();
+               DataPoint currPoint = null;
+               for (int i=0; i<numPoints; i++)
+               {
+                       currPoint = _app.getTrackInfo().getTrack().getPoint(i);
+                       totalStats.addPoint(currPoint);
+               }
+               // Calculate total moving distance of track
+               final double totalDist = totalStats.getMovingDistanceKilometres();
+               // If the track has altitudes, also calculate total climb and total descent
+               final double totalClimb = totalStats.getMovingAltitudeRange().getClimb(UnitSetLibrary.UNITS_METRES);
+               final double totalDescent = totalStats.getMovingAltitudeRange().getDescent(UnitSetLibrary.UNITS_METRES);
+
+               final double halfDistance = totalDist / 2.0;
+               final double halfClimb = totalClimb / 2.0;
+               final double halfDescent = totalDescent / 2.0;
+
+               // Now loop through points again, looking for the halfway points
+               RangeStats partialStats = new RangeStats();
+               DataPoint prevPoint = null;
+               boolean createdDistance = false, createdClimb = false, createdDescent = false;
+               double prevDistance = 0.0, prevClimb = 0.0, prevDescent = 0.0;
+               for (int i=0; i<numPoints; i++)
+               {
+                       currPoint = _app.getTrackInfo().getTrack().getPoint(i);
+                       partialStats.addPoint(currPoint);
+                       if (!currPoint.isWaypoint())
+                       {
+                               // distance
+                               if (!createdDistance && totalDist > 0.0)
+                               {
+                                       final double currDist = partialStats.getMovingDistanceKilometres();
+                                       createdDistance = processHalfValue(prevPoint, prevDistance, halfDistance,
+                                               currPoint, currDist, HalfwayType.HALF_DISTANCE);
+                                       prevDistance = currDist;
+                               }
+                               // climb
+                               if (!createdClimb && totalClimb > 0.0)
+                               {
+                                       final double currClimb = partialStats.getMovingAltitudeRange().getClimb(UnitSetLibrary.UNITS_METRES);
+                                       createdClimb = processHalfValue(prevPoint, prevClimb, halfClimb,
+                                               currPoint, currClimb, HalfwayType.HALF_CLIMB);
+                                       prevClimb = currClimb;
+                               }
+                               // descent
+                               if (!createdDescent && totalDescent > 0.0)
+                               {
+                                       final double currDescent = partialStats.getMovingAltitudeRange().getDescent(UnitSetLibrary.UNITS_METRES);
+                                       createdDescent = processHalfValue(prevPoint, prevDescent, halfDescent,
+                                               currPoint, currDescent, HalfwayType.HALF_DESCENT);
+                                       prevDescent = currDescent;
+                               }
+
+                               prevPoint = currPoint;
+                       }
+               }
+       }
+
+       /**
+        * Consider a pair of points in the track to see if a new halfway marker should be inserted between them
+        * @param inPrevPoint previous point
+        * @param inPrevValue value of function at this previous point
+        * @param inTargetValue target halfway value
+        * @param inCurrPoint current point
+        * @param inCurrValue value of function at this current point
+        * @param inType type of halfway point
+        */
+       private boolean processHalfValue(DataPoint inPrevPoint, double inPrevValue, double inTargetValue,
+               DataPoint inCurrPoint, double inCurrValue, HalfwayType inType)
+       {
+               if (inPrevValue <= inTargetValue && inCurrValue >= inTargetValue)
+               {
+                       // Calculate position of limit between the two points
+                       final double valueBeforeBreak = inTargetValue - inPrevValue;
+                       final double valueAfterBreak = inCurrValue - inTargetValue;
+                       final double fractionFromPrev = valueBeforeBreak / (valueBeforeBreak + valueAfterBreak);
+                       DataPoint marker = DataPoint.interpolate(inPrevPoint, inCurrPoint, fractionFromPrev);
+                       marker.setFieldValue(Field.WAYPT_NAME, createHalfwayName(inType), false);
+                       _pointsToAdd.add(marker);
+                       return true;
+               }
+               return false;
+       }
+
+       /**
+        * Create the name of the halfway point according to type
+        * @param inType type of point
+        */
+       private String createHalfwayName(HalfwayType inType)
+       {
+               String typeString = null;
+               switch (inType)
+               {
+                       case HALF_DISTANCE:
+                               typeString = "distance";
+                               break;
+                       case HALF_CLIMB:
+                               typeString = "climb";
+                               break;
+                       case HALF_DESCENT:
+                               typeString = "descent";
+                               break;
+               }
+               if (typeString != null)
+               {
+                       return I18nManager.getText("dialog.markers.half." + typeString);
+               }
+               return "half";
+       }
 }
index eaa7b7d8a16ccd8fa42079a3421f6a4c8919ec96..48075e72efe9132ebedc0c640240776d842fd571 100644 (file)
@@ -10,8 +10,7 @@ import java.awt.event.ItemListener;
 import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
 
-import javax.swing.Box;
-import javax.swing.BoxLayout;
+import javax.swing.BorderFactory;
 import javax.swing.ButtonGroup;
 import javax.swing.JButton;
 import javax.swing.JComboBox;
@@ -28,6 +27,7 @@ import tim.prune.data.Field;
 import tim.prune.data.TimeDifference;
 import tim.prune.data.Unit;
 import tim.prune.data.UnitSetLibrary;
+import tim.prune.gui.GuiGridLayout;
 import tim.prune.gui.WholeNumberField;
 
 /**
@@ -40,6 +40,10 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
        protected JDialog _dialog = null;
        /** Radio buttons for splitting by distance and time */
        private JRadioButton _distLimitRadio = null, _timeLimitRadio = null;
+       /** Radio button for splitting by fraction (such as half-distance) */
+       private JRadioButton _halvesRadio = null;
+       /** Flag for whether to offer halves or not */
+       private boolean _showHalves = false;
        /** Dropdown for selecting distance units */
        private JComboBox<String> _distUnitsDropdown = null;
        /** Text field for entering distance */
@@ -52,29 +56,28 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
 
 
        /**
-        * React to item changes and key presses
+        * React to item changes and key presses by enabling / disabling ok button
         */
-       private abstract class ChangeListener extends KeyAdapter implements ItemListener
+       private class ChangeListener extends KeyAdapter implements ItemListener
        {
-               /** Method to be implemented */
-               public abstract void optionsChanged();
-
                /** Item changed in ItemListener */
                public void itemStateChanged(ItemEvent arg0) {
-                       optionsChanged();
+                       enableOkButton();
                }
 
                /** Key released in KeyListener */
                public void keyReleased(KeyEvent arg0) {
-                       optionsChanged();
+                       enableOkButton();
                }
        }
 
        /**
         * Constructor
         */
-       public DistanceTimeLimitFunction(App inApp) {
+       public DistanceTimeLimitFunction(App inApp, boolean inShowHalves)
+       {
                super(inApp);
+               _showHalves = inShowHalves;
        }
 
        /**
@@ -112,28 +115,31 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
                JPanel dialogPanel = new JPanel();
                dialogPanel.setLayout(new BorderLayout(5, 5));
 
-               // Make radio buttons for three different options
+               // Make radio buttons for the options
                _distLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.distancelimit") + ": ");
                _timeLimitRadio = new JRadioButton(I18nManager.getText("dialog.correlate.options.timelimit") + ": ");
+               if (_showHalves) {
+                       _halvesRadio = new JRadioButton(I18nManager.getText("dialog.markers.halves"));
+               }
                ButtonGroup radioGroup = new ButtonGroup();
                radioGroup.add(_distLimitRadio);
                radioGroup.add(_timeLimitRadio);
+               if (_showHalves) {
+                       radioGroup.add(_halvesRadio);
+               }
 
                // central panel for limits
                JPanel limitsPanel = new JPanel();
-               limitsPanel.setLayout(new BoxLayout(limitsPanel, BoxLayout.Y_AXIS));
-               limitsPanel.add(Box.createVerticalStrut(8));
-               ChangeListener optionsChangedListener = new ChangeListener() {
-                       public void optionsChanged() {
-                               enableOkButton();
-                       }
-               };
+               limitsPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
+               GuiGridLayout grid = new GuiGridLayout(limitsPanel, new double[] {0.5, 1.0},
+                       new boolean[] {false, false});
+               ChangeListener optionsChangedListener = new ChangeListener();
                // distance limits
-               JPanel distLimitPanel = new JPanel();
-               distLimitPanel.setLayout(new FlowLayout());
+               grid.add(_distLimitRadio);
                _distLimitRadio.setSelected(true);
                _distLimitRadio.addItemListener(optionsChangedListener);
-               distLimitPanel.add(_distLimitRadio);
+               JPanel distLimitPanel = new JPanel();
+               distLimitPanel.setLayout(new FlowLayout());
                _distanceField = new WholeNumberField(3);
                _distanceField.addKeyListener(optionsChangedListener);
                distLimitPanel.add(_distanceField);
@@ -143,13 +149,13 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
                _distUnitsDropdown.addItemListener(optionsChangedListener);
                distLimitPanel.add(_distUnitsDropdown);
                distLimitPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
-               limitsPanel.add(distLimitPanel);
+               grid.add(distLimitPanel);
 
                // time limit panel
+               grid.add(_timeLimitRadio);
+               _timeLimitRadio.addItemListener(optionsChangedListener);
                JPanel timeLimitPanel = new JPanel();
                timeLimitPanel.setLayout(new FlowLayout());
-               _timeLimitRadio.addItemListener(optionsChangedListener);
-               timeLimitPanel.add(_timeLimitRadio);
                _limitHourField = new WholeNumberField(2);
                _limitHourField.addKeyListener(optionsChangedListener);
                timeLimitPanel.add(_limitHourField);
@@ -159,7 +165,14 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
                timeLimitPanel.add(_limitMinField);
                timeLimitPanel.add(new JLabel(I18nManager.getText("units.minutes")));
                timeLimitPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
-               limitsPanel.add(timeLimitPanel);
+               grid.add(timeLimitPanel);
+
+               // halves
+               if (_showHalves)
+               {
+                       grid.add(_halvesRadio);
+                       _halvesRadio.addItemListener(optionsChangedListener);
+               }
 
                dialogPanel.add(limitsPanel, BorderLayout.NORTH);
 
@@ -203,6 +216,9 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
                else if (_timeLimitRadio.isSelected()) {
                        enabled = _limitHourField.getValue() > 0 || _limitMinField.getValue() > 0;
                }
+               else if (_halvesRadio != null && _halvesRadio.isSelected()) {
+                       enabled = true;
+               }
                _okButton.setEnabled(enabled);
 
                // Also enable/disable the other fields
@@ -245,6 +261,21 @@ public abstract class DistanceTimeLimitFunction extends GenericFunction
                return 0.0;
        }
 
+       /**
+        * @return selected distance limit in km, or 0.0
+        */
+       protected double getDistanceLimitKilometres()
+       {
+               return Distance.convertRadiansToDistance(getDistanceLimitRadians(), UnitSetLibrary.UNITS_KILOMETRES);
+       }
+
+       /**
+        * @return true if "halves" option was selected
+        */
+       protected boolean isHalvesSelected() {
+               return _halvesRadio != null && _halvesRadio.isSelected();
+       }
+
        /**
         * The dialog has been completed and OK pressed, so do the corresponding function
         */
index 341066a68422160a84a2877155a8c64a1ead516d..7739092831816f238bdc3db92b68eb5b6e24c3e7 100644 (file)
@@ -30,7 +30,8 @@ public class DuplicatePoint extends GenericFunction
        public void begin()
        {
                DataPoint point = _app.getTrackInfo().getCurrentPoint();
-               if (point != null) {
+               if (point != null)
+               {
                        // Pass information back to App to complete function
                        _app.createPoint(point.clonePoint());
                }
diff --git a/src/tim/prune/function/FullRangeDetails.java b/src/tim/prune/function/FullRangeDetails.java
deleted file mode 100644 (file)
index 07ef39e..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-package tim.prune.function;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.FlowLayout;
-import java.awt.GridLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-
-import javax.swing.BorderFactory;
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-
-import tim.prune.App;
-import tim.prune.GenericFunction;
-import tim.prune.I18nManager;
-import tim.prune.config.Config;
-import tim.prune.data.RangeStats;
-import tim.prune.data.Selection;
-import tim.prune.data.Unit;
-import tim.prune.gui.DisplayUtils;
-import tim.prune.gui.profile.SpeedData;
-
-/**
- * Class to show the full range details in a separate popup
- */
-public class FullRangeDetails extends GenericFunction
-{
-       /** 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 the maximum speed */
-       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;
-
-
-       /**
-        * Constructor
-        * @param inApp App object
-        */
-       public FullRangeDetails(App inApp)
-       {
-               super(inApp);
-       }
-
-       /** Get the name key */
-       public String getNameKey() {
-               return "function.fullrangedetails";
-       }
-
-       /**
-        * Begin the function
-        */
-       public void begin()
-       {
-               if (_dialog == null)
-               {
-                       _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
-                       _dialog.setLocationRelativeTo(_parentFrame);
-                       _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
-                       _dialog.getContentPane().add(makeDialogComponents());
-                       _dialog.pack();
-               }
-               updateDetails();
-               _dialog.setVisible(true);
-       }
-
-       /**
-        * Create dialog components
-        * @return Panel containing all gui elements in dialog
-        */
-       private Component makeDialogComponents()
-       {
-               JPanel dialogPanel = new JPanel();
-               dialogPanel.setLayout(new BorderLayout(5, 5));
-               // Label at top
-               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();
-               midPanel.setLayout(new GridLayout(0, 3, 6, 2));
-               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);
-               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);
-               _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);
-               _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
-               JPanel buttonPanel = new JPanel();
-               buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
-               JButton closeButton = new JButton(I18nManager.getText("button.close"));
-               closeButton.addActionListener(new ActionListener() {
-                       public void actionPerformed(ActionEvent e)
-                       {
-                               _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;
-       }
-
-
-       /**
-        * Update the labels with the current details
-        */
-       private void updateDetails()
-       {
-               Selection selection = _app.getTrackInfo().getSelection();
-               // Do the calculations with a separate class
-               RangeStats stats = new RangeStats(_app.getTrackInfo().getTrack(), selection.getStart(), selection.getEnd());
-
-               // Number of points
-               _numPointsLabel.setText("" + stats.getNumPoints());
-               // Number of segments
-               _numSegsLabel.setText("" + stats.getNumSegments());
-               final boolean isMultiSegments = (stats.getNumSegments() > 1);
-               // Set visibility of third column accordingly
-               _movingDistanceLabel.setVisible(isMultiSegments);
-               _movingDurationLabel.setVisible(isMultiSegments || stats.getTimestampsOutOfSequence());
-               // FIXME: What to show if timestamps are out of sequence? Warning message?
-               _movingClimbLabel.setVisible(isMultiSegments);
-               _movingDescentLabel.setVisible(isMultiSegments);
-               _movingSpeedLabel.setVisible(isMultiSegments);
-               _movingPaceLabel.setVisible(isMultiSegments);
-               _movingGradientLabel.setVisible(isMultiSegments);
-               _movingVertSpeedLabel.setVisible(isMultiSegments);
-
-               // Total and moving distance in current units
-               final Unit distUnit = Config.getUnitSet().getDistanceUnit();
-               final String distUnitsStr = I18nManager.getText(distUnit.getShortnameKey());
-               _totalDistanceLabel.setText(DisplayUtils.roundedNumber(stats.getTotalDistance()) + " " + distUnitsStr);
-               _movingDistanceLabel.setText(DisplayUtils.roundedNumber(stats.getMovingDistance()) + " " + distUnitsStr);
-
-               // Duration
-               _totalDurationLabel.setText(DisplayUtils.buildDurationString(stats.getTotalDurationInSeconds()));
-               _movingDurationLabel.setText(DisplayUtils.buildDurationString(stats.getMovingDurationInSeconds()));
-
-               // Climb and descent
-               final Unit altUnit = Config.getUnitSet().getAltitudeUnit();
-               final String altUnitsStr = " " + I18nManager.getText(altUnit.getShortnameKey());
-               if (stats.getTotalAltitudeRange().hasRange()) {
-                       _totalClimbLabel.setText(stats.getTotalAltitudeRange().getClimb(altUnit) + altUnitsStr);
-                       _totalDescentLabel.setText(stats.getTotalAltitudeRange().getDescent(altUnit) + altUnitsStr);
-               }
-               else {
-                       _totalClimbLabel.setText("");
-                       _totalDescentLabel.setText("");
-               }
-               if (stats.getMovingAltitudeRange().hasRange()) {
-                       _movingClimbLabel.setText(stats.getMovingAltitudeRange().getClimb(altUnit) + altUnitsStr);
-                       _movingDescentLabel.setText(stats.getMovingAltitudeRange().getDescent(altUnit) + altUnitsStr);
-               }
-               else {
-                       _movingClimbLabel.setText("");
-                       _movingDescentLabel.setText("");
-               }
-
-               // Overall pace and speed
-               final String speedUnitsStr = I18nManager.getText(Config.getUnitSet().getSpeedUnit().getShortnameKey());
-               long numSecs = stats.getTotalDurationInSeconds();
-               double dist = stats.getTotalDistance();
-               if (numSecs > 0 && dist > 0)
-               {
-                       _totalSpeedLabel.setText(DisplayUtils.roundedNumber(dist/numSecs*3600.0) + " " + speedUnitsStr);
-                       _totalPaceLabel.setText(DisplayUtils.buildDurationString((long) (numSecs/dist))
-                               + " / " + distUnitsStr);
-               }
-               else {
-                       _totalSpeedLabel.setText("");
-                       _totalPaceLabel.setText("");
-               }
-               // and same for within the segments
-               numSecs = stats.getMovingDurationInSeconds();
-               dist = stats.getMovingDistance();
-               if (numSecs > 0 && dist > 0)
-               {
-                       _movingSpeedLabel.setText(DisplayUtils.roundedNumber(dist/numSecs*3600.0) + " " + speedUnitsStr);
-                       _movingPaceLabel.setText(DisplayUtils.buildDurationString((long) (numSecs/dist))
-                               + " / " + distUnitsStr);
-               }
-               else {
-                       _movingSpeedLabel.setText("");
-                       _movingPaceLabel.setText("");
-               }
-
-               // Gradient
-               if (stats.getTotalAltitudeRange().hasRange()) {
-                       _totalGradientLabel.setText(DisplayUtils.formatOneDp(stats.getTotalGradient()) + " %");
-               }
-               else {
-                       _totalGradientLabel.setText("");
-               }
-               if (stats.getMovingAltitudeRange().hasRange()) {
-                       _movingGradientLabel.setText(DisplayUtils.formatOneDp(stats.getMovingGradient()) + " %");
-               }
-               else {
-                       _movingGradientLabel.setText("");
-               }
-
-               // Maximum speed
-               SpeedData speeds = new SpeedData(_app.getTrackInfo().getTrack());
-               speeds.init(Config.getUnitSet());
-               double maxSpeed = 0.0;
-               for (int i=selection.getStart(); i<=selection.getEnd(); i++)
-               {
-                       if (speeds.hasData(i) && (speeds.getData(i) > maxSpeed)) {
-                               maxSpeed = speeds.getData(i);
-                       }
-               }
-               if (maxSpeed > 0.0) {
-                       _maxSpeedLabel.setText(DisplayUtils.roundedNumber(maxSpeed) + " " + speedUnitsStr);
-               }
-               else {
-                       _maxSpeedLabel.setText("");
-               }
-
-               // vertical speed
-               final String vertSpeedUnitsStr = I18nManager.getText(Config.getUnitSet().getVerticalSpeedUnit().getShortnameKey());
-               if (stats.getMovingAltitudeRange().hasRange() && stats.getTotalDurationInSeconds() > 0)
-               {
-                       // got an altitude and time - do totals
-                       _totalVertSpeedLabel.setText(DisplayUtils.roundedNumber(stats.getTotalVerticalSpeed()) + " " + vertSpeedUnitsStr);
-                       _movingVertSpeedLabel.setText(DisplayUtils.roundedNumber(stats.getMovingVerticalSpeed()) + " " + vertSpeedUnitsStr);
-               }
-               else
-               {
-                       // no vertical speed available
-                       _totalVertSpeedLabel.setText("");
-                       _movingVertSpeedLabel.setText("");
-               }
-       }
-}
index 221fdaf989c6c62141d0dfbe7ac29cfb66b069f0..ce0dad59faa1603d2831c8cbe2f6579dfb120dfe 100644 (file)
@@ -122,7 +122,8 @@ public class InterpolateFunction extends SingleNumericParameterFunction
                // Replace track with new points array
                if (track.replaceContents(newPoints))
                {
-                       _app.completeFunction(undo, I18nManager.getText("confirm.interpolate"));
+                       final String confirmMessage = I18nManager.getTextWithNumber("confirm.pointsadded", totalInserted);
+                       _app.completeFunction(undo, confirmMessage);
                        // Alter selection
                        _app.getTrackInfo().getSelection().selectRange(startIndex, endIndex + totalInserted);
                }
diff --git a/src/tim/prune/function/PasteCoordinateList.java b/src/tim/prune/function/PasteCoordinateList.java
new file mode 100644 (file)
index 0000000..9fc259e
--- /dev/null
@@ -0,0 +1,147 @@
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.load.TextFileLoader;
+
+/**
+ * Class to provide the function to paste a list of coordinates
+ * and create points for them as if they were loaded from a text file
+ */
+public class PasteCoordinateList extends GenericFunction
+{
+       private JDialog _dialog = null;
+       private JTextArea _coordArea = null;
+       private JButton _okButton = null;
+
+
+       /**
+        * Constructor
+        * @param inApp application object for callback
+        */
+       public PasteCoordinateList(App inApp)
+       {
+               super(inApp);
+       }
+
+       /** Get the name key */
+       public String getNameKey() {
+               return "function.pastecoordinatelist";
+       }
+
+       /**
+        * Begin the function
+        */
+       public void begin()
+       {
+               // Make dialog window
+               if (_dialog == null)
+               {
+                       _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+                       _dialog.setLocationRelativeTo(_parentFrame);
+                       _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+                       _dialog.getContentPane().add(makeDialogComponents());
+                       _dialog.pack();
+               }
+               // MAYBE: Paste clipboard into the edit area
+               _coordArea.setText("");
+               enableOK();
+               _dialog.setVisible(true);
+       }
+
+
+       /**
+        * Create dialog components
+        * @return Panel containing all gui elements in dialog
+        */
+       private Component makeDialogComponents()
+       {
+               JPanel dialogPanel = new JPanel();
+               dialogPanel.setLayout(new BorderLayout(0, 10));
+               dialogPanel.add(new JLabel(I18nManager.getText("dialog.pastecoordinatelist.desc")), BorderLayout.NORTH);
+               _coordArea = new JTextArea(8, 35);
+               _coordArea.setLineWrap(true);
+               _coordArea.setWrapStyleWord(true);
+               JScrollPane coordsPane = new JScrollPane(_coordArea);
+               // Listeners to enable/disable ok button
+               KeyAdapter keyListener = new KeyAdapter() {
+                       /** Key released */
+                       public void keyReleased(KeyEvent inE) {
+                               enableOK();
+                               if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                                       _dialog.dispose();
+                               }
+                       }
+               };
+               MouseAdapter mouseListener = new MouseAdapter() {
+                       public void mouseReleased(MouseEvent inE) {
+                               enableOK();
+                       }
+               };
+               _coordArea.addKeyListener(keyListener);
+               _coordArea.addMouseListener(mouseListener);
+               dialogPanel.add(coordsPane, BorderLayout.CENTER);
+               // button panel at bottom
+               JPanel buttonPanel = new JPanel();
+               buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+               _okButton = new JButton(I18nManager.getText("button.ok"));
+               ActionListener okListener = new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               if (_okButton.isEnabled()) {finish();}
+                       }
+               };
+               _okButton.addActionListener(okListener);
+               _okButton.setEnabled(false);
+               buttonPanel.add(_okButton);
+               JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+               cancelButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               _dialog.dispose();
+                       }
+               });
+               buttonPanel.add(cancelButton);
+               dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+               dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+               return dialogPanel;
+       }
+
+       /**
+        * Enable or disable the OK button based on the contents of the text field
+        */
+       private void enableOK()
+       {
+               String text = _coordArea.getText();
+               _okButton.setEnabled(text != null && text.length() > 6
+                       && (text.indexOf(' ') >= 0 || text.indexOf(',') >= 0));
+       }
+
+       /**
+        * Finish the dialog when OK pressed
+        */
+       private void finish()
+       {
+               new TextFileLoader(_app, _parentFrame).loadText(_coordArea.getText());
+               _dialog.dispose();
+       }
+}
index c9b2ad1c7ff3f74da6e8162fbb84d8fa886c1e42..c60bb854afe03cabd19189495b38399ba2f0c06d 100644 (file)
@@ -183,7 +183,8 @@ public class PasteCoordinates extends GenericFunction
                else if (items.length == 3) {
                        point = parseValues(items[0].trim(), items[1].trim(), items[2].trim());
                }
-               else {
+               else
+               {
                        // Splitting with commas didn't work, so try spaces
                        items = _coordField.getText().split(" ");
                        if (items.length == 2) {
@@ -211,7 +212,8 @@ public class PasteCoordinates extends GenericFunction
                                I18nManager.getText("dialog.pastecoordinates.nothingfound"),
                                I18nManager.getText(getNameKey()), JOptionPane.ERROR_MESSAGE);
                }
-               else {
+               else
+               {
                        // See if name was entered
                        String name = _nameField.getText();
                        if (name != null && name.length() > 0) {
index 2ac71e93b6e38bbbaab727aa1a6d7d421c4a117a..44b77d9bc3ca7827081ff48f86a53c3143f9e27e 100644 (file)
@@ -1,11 +1,11 @@
 package tim.prune.function;
 
+import java.awt.Desktop;
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
 
 import javax.sound.sampled.AudioInputStream;
 import javax.sound.sampled.AudioSystem;
@@ -146,17 +146,10 @@ public class PlayAudioFunction extends GenericFunction implements Runnable
                {
                        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);
+                               Desktop.getDesktop().open(inFile);
                                played = true;
                        }
-                       catch (InvocationTargetException e) {
-                               System.err.println("ITE: " + e.getCause().getClass().getName() + " - " + e.getCause().getMessage());
-                               played = false;
-                       }
-                       catch (Exception ignore) {
+                       catch (IOException ignore) {
                                System.err.println(ignore.getClass().getName() + " - " + ignore.getMessage());
                                played = false;
                        }
diff --git a/src/tim/prune/function/PlusCodeFunction.java b/src/tim/prune/function/PlusCodeFunction.java
new file mode 100644 (file)
index 0000000..b208b7f
--- /dev/null
@@ -0,0 +1,209 @@
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.data.Field;
+import tim.prune.function.olc.OlcArea;
+import tim.prune.function.olc.OlcDecoder;
+import tim.prune.gui.GuiGridLayout;
+
+/**
+ * Class to provide the function to parse
+ * OpenLocationCodes, or PlusCodes
+ */
+public class PlusCodeFunction extends GenericFunction
+{
+       private JDialog _dialog = null;
+       private JTextField _codeField = null;
+       private JButton _okButton = null;
+
+
+       /**
+        * Constructor
+        * @param inApp application object for callback
+        */
+       public PlusCodeFunction(App inApp)
+       {
+               super(inApp);
+       }
+
+       /** Get the name key */
+       public String getNameKey() {
+               return "function.enterpluscode";
+       }
+
+       /**
+        * Begin the function
+        */
+       public void begin()
+       {
+               // Make dialog window
+               if (_dialog == null)
+               {
+                       _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+                       _dialog.setLocationRelativeTo(_parentFrame);
+                       _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+                       _dialog.getContentPane().add(makeDialogComponents());
+                       _dialog.pack();
+               }
+               // MAYBE: Paste clipboard into the edit field
+               _codeField.setText("");
+               enableOK();
+               _dialog.setVisible(true);
+       }
+
+
+       /**
+        * Create dialog components
+        * @return Panel containing all gui elements in dialog
+        */
+       private Component makeDialogComponents()
+       {
+               JPanel dialogPanel = new JPanel();
+               dialogPanel.setLayout(new BorderLayout(0, 10));
+               dialogPanel.add(new JLabel(I18nManager.getText("dialog.pluscode.desc")), BorderLayout.NORTH);
+               JPanel mainPanel = new JPanel();
+               GuiGridLayout grid = new GuiGridLayout(mainPanel);
+               _codeField = new JTextField("", 12);
+               // Listeners to enable/disable ok button
+               KeyAdapter keyListener = new KeyAdapter() {
+                       /** Key released */
+                       public void keyReleased(KeyEvent inE) {
+                               enableOK();
+                               if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                                       _dialog.dispose();
+                               }
+                       }
+               };
+               MouseAdapter mouseListener = new MouseAdapter() {
+                       public void mouseReleased(MouseEvent inE) {
+                               enableOK();
+                       }
+               };
+               _codeField.addKeyListener(keyListener);
+               _codeField.addMouseListener(mouseListener);
+               JLabel codeLabel = new JLabel(I18nManager.getText("dialog.pluscode.code"));
+               codeLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+               grid.add(codeLabel);
+               grid.add(_codeField);
+               dialogPanel.add(mainPanel, BorderLayout.CENTER);
+               // button panel at bottom
+               JPanel buttonPanel = new JPanel();
+               buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+               _okButton = new JButton(I18nManager.getText("button.ok"));
+               ActionListener okListener = new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               if (_okButton.isEnabled()) {finish();}
+                       }
+               };
+               _okButton.addActionListener(okListener);
+               _okButton.setEnabled(false);
+               _codeField.addActionListener(okListener);
+               buttonPanel.add(_okButton);
+               JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+               cancelButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               _dialog.dispose();
+                       }
+               });
+               buttonPanel.add(cancelButton);
+               dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+               dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+               return dialogPanel;
+       }
+
+       /**
+        * Enable or disable the OK button based on the contents of the text field
+        */
+       private void enableOK()
+       {
+               String text = _codeField.getText();
+               _okButton.setEnabled(text != null && text.length() > 7
+                       && text.indexOf(' ') < 0 && text.indexOf(',') < 0);
+       }
+
+       /**
+        * Finish the dialog when OK pressed
+        */
+       private void finish()
+       {
+               OlcArea area = OlcDecoder.decode(_codeField.getText());
+
+               if (area == null)
+               {
+                       JOptionPane.showMessageDialog(_parentFrame,
+                               I18nManager.getText("dialog.pluscode.nothingfound"),
+                               I18nManager.getText(getNameKey()), JOptionPane.ERROR_MESSAGE);
+               }
+               else if (loadTrack(area))
+               {
+                       _dialog.dispose();
+               }
+       }
+
+       /**
+        * Load the generated points from the given area
+        * @param inArea rectangular area
+        * @return true on success
+        */
+       private boolean loadTrack(OlcArea inArea)
+       {
+               if (inArea == null)
+               {
+                       return false;
+               }
+
+               final Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.WAYPT_NAME};
+               _app.autoAppendNextFile();
+
+               if (inArea.minLat == inArea.maxLat && inArea.minLon == inArea.maxLon)
+               {
+                       String[][] pointData = new String[1][];
+                       pointData[0] = new String[3]; // lat, long, name
+                       pointData[0][0] = "" + inArea.minLat;
+                       pointData[0][1] = "" + inArea.minLon;
+                       pointData[0][2] = _codeField.getText();
+                       _app.informDataLoaded(fields, pointData, null, null);
+               }
+               else
+               {
+                       String[][] pointData = new String[6][];
+                       for (int i=0; i<5; i++)
+                       {
+                               pointData[i] = new String[3]; // lat, long, name
+                               pointData[i][0] = "" + ((i%4==0 || i==3) ? inArea.minLat : inArea.maxLat);
+                               pointData[i][1] = "" + ((i%4==0 || i==1) ? inArea.minLon : inArea.maxLon);
+                               pointData[i][2] = null;
+                       }
+                       // Middle point with name
+                       pointData[5] = new String[3]; // lat, long, name
+                       pointData[5][0] = "" + ((inArea.minLat + inArea.maxLat) / 2.0);
+                       pointData[5][1] = "" + ((inArea.minLon + inArea.maxLon) / 2.0);
+                       pointData[5][2] = _codeField.getText();
+                       _app.informDataLoaded(fields, pointData, null, null);
+               }
+               return true;
+       }
+}
diff --git a/src/tim/prune/function/ProjectPoint.java b/src/tim/prune/function/ProjectPoint.java
new file mode 100644 (file)
index 0000000..10c0675
--- /dev/null
@@ -0,0 +1,225 @@
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.config.Config;
+import tim.prune.data.Coordinate;
+import tim.prune.data.DataPoint;
+import tim.prune.data.Distance;
+import tim.prune.data.Field;
+import tim.prune.data.Latitude;
+import tim.prune.data.Longitude;
+import tim.prune.data.Unit;
+import tim.prune.data.UnitSetLibrary;
+import tim.prune.gui.DecimalNumberField;
+import tim.prune.gui.GuiGridLayout;
+import tim.prune.gui.WholeNumberField;
+
+
+/**
+ * Class to provide the function to project the current point
+ * with a given bearing and distance
+ */
+public class ProjectPoint extends GenericFunction
+{
+       private JDialog _dialog = null;
+       private WholeNumberField _bearingField = null;
+       private JLabel _distanceDescLabel = null;
+       private DecimalNumberField _distanceField = null;
+       private boolean _distanceIsMetric = true;
+       private JTextField _nameField = null;
+       private JButton _okButton = null;
+
+
+       /**
+        * Constructor
+        * @param inApp application object for callback
+        */
+       public ProjectPoint(App inApp)
+       {
+               super(inApp);
+       }
+
+       /** Get the name key */
+       public String getNameKey() {
+               return "function.projectpoint";
+       }
+
+       /**
+        * Begin the function
+        */
+       public void begin()
+       {
+               // Make dialog window
+               if (_dialog == null)
+               {
+                       _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+                       _dialog.setLocationRelativeTo(_parentFrame);
+                       _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+                       _dialog.getContentPane().add(makeDialogComponents());
+                       _dialog.pack();
+               }
+
+               // Clear fields
+               _bearingField.setText("");
+               _distanceField.setText("");
+               _nameField.setText("");
+               // Set the units of the distance label
+               setLabelText();
+               enableOK();
+               _dialog.setVisible(true);
+       }
+
+
+       /**
+        * Create dialog components
+        * @return Panel containing all gui elements in dialog
+        */
+       private Component makeDialogComponents()
+       {
+               JPanel dialogPanel = new JPanel();
+               dialogPanel.setLayout(new BorderLayout(0, 10));
+               dialogPanel.add(new JLabel(I18nManager.getText("dialog.projectpoint.desc")), BorderLayout.NORTH);
+               JPanel mainPanel = new JPanel();
+               GuiGridLayout grid = new GuiGridLayout(mainPanel);
+               _bearingField = new WholeNumberField(3);
+               _distanceField = new DecimalNumberField(false);
+               // Listeners to enable/disable ok button
+               KeyAdapter keyListener = new KeyAdapter() {
+                       /** Key released */
+                       public void keyReleased(KeyEvent inE) {
+                               enableOK();
+                               if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                                       _dialog.dispose();
+                               }
+                       }
+               };
+               MouseAdapter mouseListener = new MouseAdapter() {
+                       public void mouseReleased(MouseEvent inE) {
+                               enableOK();
+                       }
+               };
+               _bearingField.addKeyListener(keyListener);
+               _bearingField.addMouseListener(mouseListener);
+               _distanceField.addKeyListener(keyListener);
+               _distanceField.addMouseListener(mouseListener);
+
+               JLabel bearingLabel = new JLabel(I18nManager.getText("dialog.projectpoint.bearing"));
+               bearingLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+               grid.add(bearingLabel);
+               grid.add(_bearingField);
+
+               // Distance including units
+               _distanceDescLabel = new JLabel(I18nManager.getText("fieldname.distance") + " (ft)");
+               // Note, this label will be reset at each run
+               _distanceDescLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+               grid.add(_distanceDescLabel);
+               grid.add(_distanceField);
+
+               // Waypoint name
+               JLabel nameLabel = new JLabel(I18nManager.getText("dialog.pointnameedit.name"));
+               nameLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+               grid.add(nameLabel);
+               _nameField = new JTextField("", 12);
+               grid.add(_nameField);
+               dialogPanel.add(mainPanel, BorderLayout.CENTER);
+               // button panel at bottom
+               JPanel buttonPanel = new JPanel();
+               buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+               _okButton = new JButton(I18nManager.getText("button.ok"));
+               ActionListener okListener = new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               if (_okButton.isEnabled()) {finish();}
+                       }
+               };
+               _okButton.addActionListener(okListener);
+               _okButton.setEnabled(false);
+
+               buttonPanel.add(_okButton);
+               JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+               cancelButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               _dialog.dispose();
+                       }
+               });
+               buttonPanel.add(cancelButton);
+               dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+               dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
+               return dialogPanel;
+       }
+
+       /**
+        * Set the label text according to the current units
+        */
+       private void setLabelText()
+       {
+               Unit distUnit = Config.getUnitSet().getDistanceUnit();
+               _distanceIsMetric = (distUnit == UnitSetLibrary.UNITS_METRES || distUnit == UnitSetLibrary.UNITS_KILOMETRES);
+               distUnit = _distanceIsMetric ? UnitSetLibrary.UNITS_METRES : UnitSetLibrary.UNITS_FEET;
+               final String unitKey = distUnit.getShortnameKey();
+               _distanceDescLabel.setText(I18nManager.getText("fieldname.distance") + " (" + I18nManager.getText(unitKey) + ")");
+       }
+
+       /**
+        * Enable or disable the OK button based on the contents of the input fields
+        */
+       private void enableOK()
+       {
+               final boolean bearingOk = !_bearingField.getText().isEmpty()
+                       && _bearingField.getValue() < 360;
+               final boolean distanceOk = _distanceField.getValue() > 0.0;
+               _okButton.setEnabled(bearingOk && distanceOk);
+       }
+
+       /**
+        * Finish the dialog when OK pressed
+        */
+       private void finish()
+       {
+               DataPoint currPoint = _app.getTrackInfo().getCurrentPoint();
+               Unit distUnit = _distanceIsMetric ? UnitSetLibrary.UNITS_METRES : UnitSetLibrary.UNITS_FEET;
+               final double projectRads = Distance.convertDistanceToRadians(_distanceField.getValue(), distUnit);
+               final double origLatRads = Math.toRadians(currPoint.getLatitude().getDouble());
+               final double origLonRads = Math.toRadians(currPoint.getLongitude().getDouble());
+               System.out.println("Project from: " + origLatRads + ", " + origLonRads);
+               final double bearingRads = Math.toRadians(_bearingField.getValue());
+
+               double lat2 = Math.asin(Math.sin(origLatRads) * Math.cos(projectRads)
+                       + Math.cos(origLatRads) * Math.sin(projectRads) * Math.cos(bearingRads));
+               double lon2 = origLonRads + Math.atan2(Math.sin(bearingRads) * Math.sin(projectRads) * Math.cos(origLatRads),
+                       Math.cos(projectRads) - Math.sin(origLatRads) * Math.sin(lat2));
+
+               double finalLatDeg = Math.toDegrees(lat2);
+               double finalLonDeg = Math.toDegrees(lon2);
+               System.out.println("Result is: lat=" + finalLatDeg + ", lon=" + finalLonDeg);
+
+               // Create point and append to track
+               DataPoint point = new DataPoint(new Latitude(finalLatDeg, Coordinate.FORMAT_DEG),
+                       new Longitude(finalLonDeg, Coordinate.FORMAT_DEG), null);
+               point.setFieldValue(Field.WAYPT_NAME, _nameField.getText(), false);
+               _app.createPoint(point);
+
+               _dialog.dispose();
+       }
+}
index 17e937027c2d021593979e7c54fefcdf4851f940..c62b13097875c1485209feb243fa623b69b767d0 100644 (file)
@@ -119,7 +119,7 @@ public class RearrangeWaypointsFunction extends RearrangeFunction
                // Exit if the data is already in the specified order
                final boolean wpsToStart = (inRearrangeOption == Rearrange.TO_START);
                final boolean doSort = (inSortOption != SortMode.DONT_SORT);
-               if (numWaypoints == 0 || numNonWaypoints == 0
+               if (numWaypoints == 0
                        || (wpsToStart && !wayAfterNon && nonAfterWay && !doSort)
                        || (!wpsToStart && wayAfterNon && !nonAfterWay && !doSort)
                        || inRearrangeOption == Rearrange.TO_NEAREST)
index 20e2fc81d4de00698f7265c4651212bf71ff740d..39df30a6657050ee8b50f9485f6e19679eaf38af 100644 (file)
@@ -84,7 +84,7 @@ public class SearchOpenCachingDeFunction extends GenericDownloaderFunction
        private void submitSearch(double inLat, double inLon)
        {
                // The only parameters are lat and long from the current point
-               String urlString = "http://opencaching.de/search.php?searchto=searchbydistance&showresult=1"
+               String urlString = "https://opencaching.de/search.php?searchto=searchbydistance&showresult=1"
                        + "&output=XML&sort=bydistance&lat=" + inLat
                        + "&lon=" + inLon + "&distance=" + MAX_DISTANCE + "&unit=km";
                // Parse the returned XML with a special handler
diff --git a/src/tim/prune/function/ShowFullDetails.java b/src/tim/prune/function/ShowFullDetails.java
new file mode 100644 (file)
index 0000000..8f8289e
--- /dev/null
@@ -0,0 +1,417 @@
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.util.TimeZone;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextArea;
+
+import tim.prune.App;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.config.Config;
+import tim.prune.config.TimezoneHelper;
+import tim.prune.data.AltitudeRange;
+import tim.prune.data.AudioClip;
+import tim.prune.data.Coordinate;
+import tim.prune.data.DataPoint;
+import tim.prune.data.Field;
+import tim.prune.data.Photo;
+import tim.prune.data.RangeStatsWithGradients;
+import tim.prune.data.Selection;
+import tim.prune.data.SpeedCalculator;
+import tim.prune.data.SpeedValue;
+import tim.prune.data.Track;
+import tim.prune.data.Unit;
+import tim.prune.data.UnitSet;
+import tim.prune.gui.CoordDisplay;
+import tim.prune.gui.DisplayUtils;
+
+
+/**
+ * Class to show the full point/range details in a separate popup
+ */
+public class ShowFullDetails extends GenericFunction
+{
+       private JDialog _dialog = null;
+       private JTabbedPane _tabs = null;
+       private JButton _okButton = null;
+
+       private JTextArea _pointTextArea = null;
+       private JTextArea _rangeTextArea = null;
+
+
+       /**
+        * Constructor
+        * @param inApp App object
+        */
+       public ShowFullDetails(App inApp)
+       {
+               super(inApp);
+       }
+
+       /** Get the name key */
+       public String getNameKey() {
+               return "function.viewfulldetails";
+       }
+
+       /**
+        * Begin the function
+        */
+       public void begin()
+       {
+               if (_dialog == null)
+               {
+                       _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
+                       _dialog.setLocationRelativeTo(_parentFrame);
+                       _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+                       _dialog.getContentPane().add(makeDialogComponents());
+                       _dialog.pack();
+               }
+               updateDetails();
+               _dialog.setVisible(true);
+               _okButton.requestFocus();
+       }
+
+       /**
+        * Create dialog components
+        * @return Panel containing all gui elements in dialog
+        */
+       private Component makeDialogComponents()
+       {
+               JPanel mainPanel = new JPanel();
+               mainPanel.setLayout(new BorderLayout());
+
+               _tabs = new JTabbedPane();
+               mainPanel.add(_tabs, BorderLayout.CENTER);
+
+               JPanel pointPanel = new JPanel();
+               pointPanel.setLayout(new BorderLayout());
+               _pointTextArea = new JTextArea(I18nManager.getText("details.nopointselection"));
+               _pointTextArea.setEditable(false);
+               _pointTextArea.setLineWrap(true);
+               JScrollPane scrollPane = new JScrollPane(_pointTextArea);
+               scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+               scrollPane.setPreferredSize(new Dimension(500, 230));
+               pointPanel.add(scrollPane, BorderLayout.CENTER);
+               _tabs.add(I18nManager.getText("details.pointdetails"), pointPanel);
+
+               JPanel rangePanel = new JPanel();
+               rangePanel.setLayout(new BorderLayout());
+               _rangeTextArea = new JTextArea(I18nManager.getText("details.norangeselection"));
+               _rangeTextArea.setEditable(false);
+               _rangeTextArea.setLineWrap(true);
+               JScrollPane scrollPane2 = new JScrollPane(_rangeTextArea);
+               scrollPane2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+               scrollPane2.setPreferredSize(new Dimension(500, 230));
+               rangePanel.add(scrollPane2, BorderLayout.CENTER);
+               _tabs.add(I18nManager.getText("details.rangedetails"), rangePanel);
+
+               // OK button at the bottom
+               JPanel okPanel = new JPanel();
+               okPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
+               _okButton = new JButton(I18nManager.getText("button.ok"));
+               _okButton.addActionListener(new ActionListener()
+               {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               _dialog.dispose();
+                       }
+               });
+               _okButton.addKeyListener(new KeyListener() {
+                       public void keyPressed(KeyEvent e)
+                       {
+                               if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {_dialog.dispose();}
+                       }
+                       public void keyTyped(KeyEvent e) {}
+                       public void keyReleased(KeyEvent e) {}
+               });
+               okPanel.add(_okButton);
+               mainPanel.add(okPanel, BorderLayout.SOUTH);
+               return mainPanel;
+       }
+
+
+       /**
+        * Update the labels with the current details
+        */
+       private void updateDetails()
+       {
+               if (_app.getTrackInfo().getCurrentPoint() != null)
+               {
+                       final String pointString = makePointDescription(_app.getTrackInfo().getTrack(),
+                               _app.getTrackInfo().getSelection().getCurrentPointIndex());
+                       _pointTextArea.setText(pointString);
+                       // Select point tab
+                       _tabs.setSelectedIndex(0);
+               }
+               else
+               {
+                       _pointTextArea.setText(I18nManager.getText("details.nopointselection"));
+                       // Select range tab
+                       _tabs.setSelectedIndex(1);
+               }
+
+               Selection selection = _app.getTrackInfo().getSelection();
+               if (selection.hasRangeSelected())
+               {
+                       RangeStatsWithGradients stats = new RangeStatsWithGradients(_app.getTrackInfo().getTrack(),
+                               selection.getStart(), selection.getEnd());
+                       SpeedValue maxSpeed = calculateMaxSpeed(_app.getTrackInfo().getTrack(),
+                               selection.getStart(), selection.getEnd());
+                       _rangeTextArea.setText(makeRangeDescription(stats, maxSpeed));
+               }
+               else
+               {
+                       _rangeTextArea.setText(I18nManager.getText("details.norangeselection"));
+               }
+       }
+
+       /**
+        * Calculate the maximum horizontal speed value in the given selection
+        * @param inTrack track object
+        * @param inStartIndex start of selection
+        * @param inEndIndex end of selection
+        * @return max speed, if any
+        */
+       private static SpeedValue calculateMaxSpeed(Track inTrack, int inStartIndex, int inEndIndex)
+       {
+               SpeedValue maxSpeed = new SpeedValue();
+               SpeedValue currSpeed = new SpeedValue();
+               for (int i=inStartIndex; i<=inEndIndex; i++)
+               {
+                       SpeedCalculator.calculateSpeed(inTrack, i, currSpeed);
+                       if (currSpeed.isValid() && (!maxSpeed.isValid() || currSpeed.getValue() > maxSpeed.getValue()))
+                       {
+                               maxSpeed.setValue(currSpeed.getValue());
+                       }
+               }
+               return maxSpeed;
+       }
+
+       /**
+        * @param inTrack current track
+        * @param inPointIndex current point index
+        * @return string describing point details
+        */
+       private static String makePointDescription(Track inTrack, int inPointIndex)
+       {
+               DataPoint point = inTrack.getPoint(inPointIndex);
+               if (point == null)
+               {
+                       return "";
+               }
+
+               final int coordDisplayFormat = Coordinate.getCoordinateFormatForDisplay(
+                       Config.getConfigInt(Config.KEY_COORD_DISPLAY_FORMAT));
+               StringBuffer result = new StringBuffer();
+               final String latStr = CoordDisplay.makeCoordinateLabel(point.getLatitude(), coordDisplayFormat);
+               final String lonStr = CoordDisplay.makeCoordinateLabel(point.getLongitude(), coordDisplayFormat);
+               addTextPair(result, "fieldname.latitude", latStr);
+               addTextPair(result, "fieldname.longitude", lonStr);
+               addTextPair(result, "fieldname.coordinates", latStr + ", " + lonStr);
+
+               if (point.hasAltitude())
+               {
+                       final Unit altUnit = Config.getUnitSet().getAltitudeUnit();
+                       addTextPair(result, "fieldname.altitude", "" + point.getAltitude().getValue(altUnit),
+                               I18nManager.getText(altUnit.getShortnameKey()));
+               }
+               if (point.hasTimestamp())
+               {
+                       TimeZone timezone = TimezoneHelper.getSelectedTimezone();
+                       addTextPair(result, "fieldname.date", point.getTimestamp().getDateText(timezone));
+                       addTextPair(result, "fieldname.timestamp", point.getTimestamp().getTimeText(timezone));
+               }
+
+               addTextPair(result, "fieldname.waypointname", point.getWaypointName());
+
+               addTextPair(result, "fieldname.description", point.getFieldValue(Field.DESCRIPTION));
+
+               addTextPair(result, "fieldname.waypointtype", point.getFieldValue(Field.WAYPT_TYPE));
+
+               // Speed can come from either timestamps and distances, or speed values in data
+               SpeedValue speedValue = new SpeedValue();
+               SpeedCalculator.calculateSpeed(inTrack, inPointIndex, speedValue);
+               UnitSet unitSet = Config.getUnitSet();
+               if (speedValue.isValid())
+               {
+                       final String speedUnitsStr = I18nManager.getText(unitSet.getSpeedUnit().getShortnameKey());
+                       String speed = DisplayUtils.roundedNumber(speedValue.getValue());
+                       addTextPair(result, "fieldname.speed", speed, speedUnitsStr);
+               }
+
+               // Now do the vertical speed in the same way
+               SpeedCalculator.calculateVerticalSpeed(inTrack, inPointIndex, speedValue);
+               if (speedValue.isValid())
+               {
+                       final String vSpeedUnitsStr = I18nManager.getText(unitSet.getVerticalSpeedUnit().getShortnameKey());
+                       String speed = DisplayUtils.roundedNumber(speedValue.getValue());
+                       addTextPair(result, "fieldname.verticalspeed", speed, vSpeedUnitsStr);
+               }
+
+               Photo currentPhoto = point.getPhoto();
+               if (currentPhoto != null)
+               {
+                       addTextPair(result, "details.photofile", currentPhoto.getName());
+                       addTextPair(result, "details.media.fullpath", currentPhoto.getFullPath());
+               }
+
+               AudioClip currentAudio = point.getAudio();
+               if (currentAudio != null)
+               {
+                       addTextPair(result, "details.audio.file", currentAudio.getName());
+                       addTextPair(result, "details.media.fullpath", currentAudio.getFullPath());
+               }
+
+               return result.toString();
+       }
+
+       /**
+        * Make the range description text
+        * @param inStats stats object
+        * @param inMaxSpeed maximum speed info
+        * @return string describing range
+        */
+       private static String makeRangeDescription(RangeStatsWithGradients inStats, SpeedValue inMaxSpeed)
+       {
+               StringBuffer result = new StringBuffer();
+               addTextPair(result, "details.track.points", "" + inStats.getNumPoints());
+               addTextPair(result, "details.range.numsegments", "" + inStats.getNumSegments());
+               final boolean hasMultipleSegments = (inStats.getNumSegments() > 1);
+
+               UnitSet unitSet = Config.getUnitSet();
+               final String speedUnitsStr = I18nManager.getText(unitSet.getSpeedUnit().getShortnameKey());
+               if (inMaxSpeed.isValid())
+               {
+                       final String maxSpeedStr = DisplayUtils.roundedNumber(inMaxSpeed.getValue()) + " " + speedUnitsStr;
+                       addTextPair(result, "details.range.maxspeed", maxSpeedStr);
+               }
+
+               addHeading(result, "dialog.fullrangedetails.colsegments");
+               final Unit distUnit = Config.getUnitSet().getDistanceUnit();
+               final String distUnitsStr = I18nManager.getText(distUnit.getShortnameKey());
+               final double movingDist = inStats.getMovingDistance();
+               addTextPair(result, "fieldname.distance", DisplayUtils.roundedNumber(movingDist),
+                       distUnitsStr);
+               long numSecs = inStats.getMovingDurationInSeconds();
+               addTextPair(result, "fieldname.duration", DisplayUtils.buildDurationString(numSecs));
+
+               if (numSecs > 0 && movingDist > 0.0)
+               {
+                       addTextPair(result, "details.range.avespeed", DisplayUtils.roundedNumber(movingDist/numSecs*3600.0),
+                               speedUnitsStr);
+                       addTextPair(result, "details.range.pace", DisplayUtils.buildDurationString((long) (numSecs/movingDist)),
+                               "/ " + distUnitsStr);
+               }
+               final Unit altUnit = unitSet.getAltitudeUnit();
+               final String altUnitsStr = I18nManager.getText(altUnit.getShortnameKey());
+               if (inStats.getMovingAltitudeRange().hasRange())
+               {
+                       AltitudeRange altRange = inStats.getMovingAltitudeRange();
+                       addTextPair(result, "fieldname.altitude", "" + altRange.getMinimum(altUnit) + altUnitsStr + " "
+                               + I18nManager.getText("details.altitude.to") + " "
+                               + altRange.getMaximum(altUnit) + altUnitsStr);
+                       addTextPair(result, "details.range.climb", "" + altRange.getClimb(altUnit), altUnitsStr);
+                       addTextPair(result, "details.range.descent", "" + altRange.getDescent(altUnit), altUnitsStr);
+                       addTextPair(result, "details.range.gradient", DisplayUtils.formatOneDp(inStats.getMovingGradient()), "%");
+                       if (numSecs > 0)
+                       {
+                               final String vertSpeedUnitsStr = I18nManager.getText(unitSet.getVerticalSpeedUnit().getShortnameKey());
+                               final String vertSpeedStr = DisplayUtils.roundedNumber(inStats.getMovingVerticalSpeed());
+                               addTextPair(result, "fieldname.verticalspeed", vertSpeedStr, vertSpeedUnitsStr);
+                       }
+               }
+
+               if (hasMultipleSegments)
+               {
+                       addHeading(result, "dialog.fullrangedetails.coltotal");
+                       final double totalDist = inStats.getTotalDistance();
+                       addTextPair(result, "fieldname.distance", DisplayUtils.roundedNumber(totalDist), distUnitsStr);
+                       long totalSecs = inStats.getTotalDurationInSeconds();
+                       addTextPair(result, "fieldname.duration", DisplayUtils.buildDurationString(totalSecs));
+                       if (totalSecs > 0 && totalDist > 0.0)
+                       {
+                               addTextPair(result, "details.range.avespeed", DisplayUtils.roundedNumber(totalDist/totalSecs*3600.0),
+                                       speedUnitsStr);
+                               addTextPair(result, "details.range.pace", DisplayUtils.buildDurationString((long) (totalSecs/totalDist)),
+                                       "/ " + distUnitsStr);
+                       }
+                       if (inStats.getTotalAltitudeRange().hasRange())
+                       {
+                               AltitudeRange altRange = inStats.getTotalAltitudeRange();
+                               addTextPair(result, "details.range.climb", "" + altRange.getClimb(altUnit), altUnitsStr);
+                               addTextPair(result, "details.range.descent", "" + altRange.getDescent(altUnit), altUnitsStr);
+                               addTextPair(result, "details.range.gradient", DisplayUtils.formatOneDp(inStats.getTotalGradient()), "%");
+                               if (totalSecs > 0)
+                               {
+                                       final String vertSpeedUnitsStr = I18nManager.getText(unitSet.getVerticalSpeedUnit().getShortnameKey());
+                                       final String vertSpeedStr = DisplayUtils.roundedNumber(inStats.getTotalVerticalSpeed());
+                                       addTextPair(result, "fieldname.verticalspeed", vertSpeedStr, vertSpeedUnitsStr);
+                               }
+                       }
+               }
+               return result.toString();
+       }
+
+       /**
+        * Add the label and value to the buffer
+        * @param inBuffer buffer to append to
+        * @param inLabelKey label key
+        * @param inValue value text
+        */
+       private static void addTextPair(StringBuffer inBuffer, String inLabelKey, String inValue)
+       {
+               addTextPair(inBuffer, inLabelKey, inValue, null);
+       }
+
+       /**
+        * Add the label and value to the buffer
+        * @param inBuffer buffer to append to
+        * @param inLabelKey label key
+        * @param inValue value text
+        * @param inUnits optional units string
+        */
+       private static void addTextPair(StringBuffer inBuffer, String inLabelKey, String inValue, String inUnits)
+       {
+               if (inValue != null && !inValue.equals(""))
+               {
+                       inBuffer.append(I18nManager.getText(inLabelKey));
+                       inBuffer.append(": ");
+                       inBuffer.append(inValue);
+                       if (inUnits != null && !inUnits.equals(""))
+                       {
+                               inBuffer.append(' ');
+                               inBuffer.append(inUnits);
+                       }
+                       inBuffer.append("\n");
+               }
+       }
+
+       /**
+        * Add a heading to the buffer
+        * @param inBuffer buffer to append to
+        * @param inLabelKey key for heading
+        */
+       private static void addHeading(StringBuffer inBuffer, String inLabelKey)
+       {
+               final String heading = I18nManager.getText(inLabelKey);
+               inBuffer.append('\n').append(heading).append('\n');
+               for (int i=0; i<heading.length(); i++)
+               {
+                       inBuffer.append('=');
+               }
+               inBuffer.append('\n');
+       }
+}
index 8e89360d7f79ba820f2743a001e319a42dd99a6c..1c127b3e109dd090a8f3bbff585766a20df8e17d 100644 (file)
@@ -147,7 +147,7 @@ public class CompressTrackFunction extends MarkAndDeleteFunction
                        public void actionPerformed(ActionEvent arg0)
                        {
                                preview();
-                       };
+                       }
                };
                // construct track details to be used by all algorithms
                TrackDetails details = new TrackDetails(_track);
index fbf0ccff49c550b79969cda539ec4b4bde008513..a949c1c16b8792c0a3e09890fdfe3c45561b66cb 100644 (file)
@@ -37,9 +37,9 @@ public abstract class SingleParameterAlgorithm extends CompressionAlgorithm
                _parameterField = new JTextField();
                // Add listener to parameter field to re-run preview (and en/disable ok) when param changed
                _parameterField.addKeyListener(new KeyListener() {
-                       public void keyTyped(java.awt.event.KeyEvent arg0) {};
-                       public void keyPressed(java.awt.event.KeyEvent arg0) {};
-                       public void keyReleased(java.awt.event.KeyEvent arg0) {if (isActivated()) _listener.actionPerformed(null);};
+                       public void keyTyped(java.awt.event.KeyEvent arg0) {}
+                       public void keyPressed(java.awt.event.KeyEvent arg0) {}
+                       public void keyReleased(java.awt.event.KeyEvent arg0) {if (isActivated()) _listener.actionPerformed(null);}
                });
        }
 
index 5fe6e7e7d9e307d901ad25c23b2a4ea021acc3d3..e0b7aed7354938616982ba8d933f6e531f37d651 100644 (file)
@@ -114,12 +114,7 @@ public class DistanceFunction extends GenericFunction
                // second table for distances
                _distModel = new DistanceTableModel();
                JTable distTable = new JTable(_distModel);
-               // Use reflection to call distTable.setAutoCreateRowSorter(true) which is new with Java 1.6
-               try {
-                       Class<?> d = Class.forName("javax.swing.JTable");
-                       d.getDeclaredMethod("setAutoCreateRowSorter", new Class[]{Boolean.TYPE}).invoke(distTable, Boolean.TRUE);
-               }
-               catch (Exception e) {}
+               distTable.setAutoCreateRowSorter(true);
                scrollPane = new JScrollPane(distTable);
                scrollPane.setPreferredSize(new Dimension(200, 250));
                mainPanel.add(scrollPane);
index 2c1d83d1337b56af1a8ab1fbad0a3cc938b3d5a2..b0340b9e5948f6735a2684488fc2ccea7dfb77c3 100644 (file)
@@ -37,7 +37,7 @@ public class DistanceTableModel extends GenericTableModel
        {
                if (inColumnIndex == 0) {return getPointName(inRowIndex);}
                if (_distances == null) {return 0.0;}
-               return new Double(_distances[inRowIndex]);
+               return Double.valueOf(_distances[inRowIndex]);
        }
 
        /**
index ef6979358edaefb64828469f18a2c41e6daf8846..8caad11892eb83dc219cd2a92bc0198dedb9456b 100644 (file)
@@ -23,7 +23,7 @@ import tim.prune.App;
 import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
 import tim.prune.config.Config;
-import tim.prune.data.RangeStats;
+import tim.prune.data.RangeStatsWithGradients;
 import tim.prune.data.Selection;
 import tim.prune.data.Unit;
 import tim.prune.gui.DecimalNumberField;
@@ -54,7 +54,7 @@ public class EstimateTime extends GenericFunction
        private JLabel _descentParamLabel = null;
        private DecimalNumberField _gentleDescentField = null, _steepDescentField = null;
        /** Range stats */
-       private RangeStats _stats = null;
+       private RangeStatsWithGradients _stats = null;
 
 
        /**
@@ -78,7 +78,8 @@ public class EstimateTime extends GenericFunction
        {
                // Get the stats on the selection before launching the dialog
                Selection selection = _app.getTrackInfo().getSelection();
-               _stats = new RangeStats(_app.getTrackInfo().getTrack(), selection.getStart(), selection.getEnd());
+               _stats = new RangeStatsWithGradients(_app.getTrackInfo().getTrack(),
+                       selection.getStart(), selection.getEnd());
 
                if (_stats.getMovingDistance() < 0.01)
                {
@@ -297,7 +298,11 @@ public class EstimateTime extends GenericFunction
                EstimationParameters estParams = new EstimationParameters(Config.getConfigString(Config.KEY_ESTIMATION_PARAMS));
 
                String[] paramValues = estParams.getStrings();
-               if (paramValues == null || paramValues.length != 5) {return;} // TODO: What to do in case of error?
+               if (paramValues == null || paramValues.length != 5)
+               {
+                       // TODO: What to do in case of error?
+                       return;
+               }
                // Flat time is either for 5 km, 3 miles or 3 nm
                _flatSpeedLabel.setText(I18nManager.getText("dialog.estimatetime.parameters.timefor") +
                        " " + EstimationParameters.getStandardDistance() + ": ");
index 1b8046740b767b21bc8e55cdda4134831d092efa..afe59383da9c6d21962dcdfc0ae0b47748f83753 100644 (file)
@@ -6,7 +6,7 @@ import java.util.Locale;
 
 import tim.prune.I18nManager;
 import tim.prune.config.Config;
-import tim.prune.data.RangeStats;
+import tim.prune.data.RangeStatsWithGradients;
 import tim.prune.data.Unit;
 import tim.prune.data.UnitSetLibrary;
 
@@ -254,9 +254,11 @@ public class EstimationParameters
         * @param inStats stats of current range
         * @return estimated number of minutes required
         */
-       public double applyToStats(RangeStats inStats)
+       public double applyToStats(RangeStatsWithGradients inStats)
        {
-               if (inStats == null || !inStats.isValid()) return 0.0;
+               if (inStats == null) {
+                       return 0.0;
+               }
                final Unit METRES = UnitSetLibrary.UNITS_METRES;
                final double STANDARD_CLIMB = 100.0; // metres
                final double STANDARD_DISTANCE = 5.0; // kilometres
index 74021dd3b2ba46fd03e6fddbd9054b50ba6ae65a..3efaa2f33161808ac9bab161d4a9cb024dd9a8fa 100644 (file)
@@ -26,7 +26,7 @@ import tim.prune.I18nManager;
 import tim.prune.config.Config;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Distance;
-import tim.prune.data.RangeStats;
+import tim.prune.data.RangeStatsWithGradients;
 import tim.prune.data.Track;
 import tim.prune.data.Unit;
 import tim.prune.data.UnitSetLibrary;
@@ -100,7 +100,7 @@ public class LearnParameters extends GenericFunction implements Runnable
        {
                _progress.setMaximum(100);
                // Go through the track and collect the range stats for each sample
-               ArrayList<RangeStats> statsList = new ArrayList<RangeStats>(20);
+               ArrayList<RangeStatsWithGradients> statsList = new ArrayList<RangeStatsWithGradients>(20);
                Track track = _app.getTrackInfo().getTrack();
                final int numPoints = track.getNumPoints();
                final int sampleSize = numPoints / 30;
@@ -108,15 +108,15 @@ public class LearnParameters extends GenericFunction implements Runnable
                for (int i=0; i<30; i++)
                {
                        int startIndex = i * sampleSize;
-                       RangeStats stats = getRangeStats(track, startIndex, startIndex + sampleSize, prevStartIndex);
+                       RangeStatsWithGradients stats = getRangeStats(track, startIndex, startIndex + sampleSize, prevStartIndex);
                        if (stats != null && stats.getMovingDistanceKilometres() > 1.0
                                && !stats.getTimestampsIncomplete() && !stats.getTimestampsOutOfSequence()
                                && stats.getTotalDurationInSeconds() > 100
-                               && stats.getStartIndex() > prevStartIndex)
+                               && startIndex > prevStartIndex)
                        {
                                // System.out.println("Got stats for " + stats.getStartIndex() + " to " + stats.getEndIndex());
                                statsList.add(stats);
-                               prevStartIndex = stats.getStartIndex();
+                               prevStartIndex = startIndex;
                        }
                        _progress.setValue(i);
                }
@@ -246,7 +246,8 @@ public class LearnParameters extends GenericFunction implements Runnable
         * @param inPreviousStartIndex the previously used start index, or -1
         * @return range stats object or null if required information missing from this bit of the track
         */
-       private RangeStats getRangeStats(Track inTrack, int inStartIndex, int inEndIndex, int inPreviousStartIndex)
+       private RangeStatsWithGradients getRangeStats(Track inTrack, int inStartIndex,
+               int inEndIndex, int inPreviousStartIndex)
        {
                // Check parameters
                if (inTrack == null || inStartIndex < 0 || inEndIndex <= inStartIndex || inStartIndex > inTrack.getNumPoints()) {
@@ -297,7 +298,7 @@ public class LearnParameters extends GenericFunction implements Runnable
 
                // Check moving distance
                if (movingRads >= minimumRads) {
-                       return new RangeStats(inTrack, start, endIndex);
+                       return new RangeStatsWithGradients(inTrack, start, endIndex);
                }
                return null;
        }
@@ -307,12 +308,12 @@ public class LearnParameters extends GenericFunction implements Runnable
         * @param inStatsList list of (non-null) RangeStats objects
         * @return A matrix with n rows and 5 columns
         */
-       private static Matrix buildAMatrix(ArrayList<RangeStats> inStatsList)
+       private static Matrix buildAMatrix(ArrayList<RangeStatsWithGradients> inStatsList)
        {
                final Unit METRES = UnitSetLibrary.UNITS_METRES;
                Matrix result = new Matrix(inStatsList.size(), 5);
                int row = 0;
-               for (RangeStats stats : inStatsList)
+               for (RangeStatsWithGradients stats : inStatsList)
                {
                        result.setValue(row, 0, stats.getMovingDistanceKilometres());
                        result.setValue(row, 1, stats.getGentleAltitudeRange().getClimb(METRES));
@@ -329,11 +330,11 @@ public class LearnParameters extends GenericFunction implements Runnable
         * @param inStatsList list of (non-null) RangeStats objects
         * @return B matrix with single column of n rows
         */
-       private static Matrix buildBMatrix(ArrayList<RangeStats> inStatsList)
+       private static Matrix buildBMatrix(ArrayList<RangeStatsWithGradients> inStatsList)
        {
                Matrix result = new Matrix(inStatsList.size(), 1);
                int row = 0;
-               for (RangeStats stats : inStatsList)
+               for (RangeStatsWithGradients stats : inStatsList)
                {
                        result.setValue(row, 0, stats.getMovingDurationInSeconds() / 60.0); // convert seconds to minutes
                        row++;
@@ -372,12 +373,13 @@ public class LearnParameters extends GenericFunction implements Runnable
         * @param inRowToIgnore row index to ignore, or -1 to use them all
         * @return true if the samples look ok
         */
-       private static boolean isRangeSetSufficient(ArrayList<RangeStats> inRangeSet, int inRowToIgnore)
+       private static boolean isRangeSetSufficient(ArrayList<RangeStatsWithGradients> inRangeSet, int inRowToIgnore)
        {
-               int numGC = 0, numSC = 0, numGD = 0, numSD = 0; // number of samples with gentle/steep climb/descent values > 0
+               // number of samples with gentle/steep climb/descent values > 0
+               int numGC = 0, numSC = 0, numGD = 0, numSD = 0;
                final Unit METRES = UnitSetLibrary.UNITS_METRES;
                int i = 0;
-               for (RangeStats stats : inRangeSet)
+               for (RangeStatsWithGradients stats : inRangeSet)
                {
                        if (i != inRowToIgnore)
                        {
@@ -396,7 +398,7 @@ public class LearnParameters extends GenericFunction implements Runnable
         * @param inStatsList list of stats
         * @return results in an object
         */
-       private MatrixResults reduceSamples(ArrayList<RangeStats> inStatsList)
+       private MatrixResults reduceSamples(ArrayList<RangeStatsWithGradients> inStatsList)
        {
                int statsIndexToRemove = -1;
                Matrix answer = null;
diff --git a/src/tim/prune/function/gpsies/FormPoster.java b/src/tim/prune/function/gpsies/FormPoster.java
deleted file mode 100644 (file)
index 5939e63..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-package tim.prune.function.gpsies;\r
-\r
-import java.net.HttpURLConnection;\r
-import java.net.URLConnection;\r
-import java.net.URL;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.util.Random;\r
-import java.io.OutputStream;\r
-\r
-/**\r
- * Taken from the Client HTTP Request class at com.myjavatools.web\r
- * and subsequently simplified and modified\r
- * @author Vlad Patryshev\r
- */\r
-public class FormPoster\r
-{\r
-       private URLConnection _connection = null;\r
-       private OutputStream _os = null;\r
-       private static final Random RANDOM_GEN = new Random();\r
-       private static final String BOUNDARY = "---------------------------"\r
-               + randomString() + randomString() + randomString();\r
-\r
-\r
-       /** Connect (if not already connected) */\r
-       protected void connect() throws IOException {\r
-               if (_os == null) _os = _connection.getOutputStream();\r
-       }\r
-\r
-       /** Write a single character */\r
-       protected void write(char c) throws IOException {\r
-               connect();\r
-               _os.write(c);\r
-       }\r
-\r
-       /** Write a string */\r
-       protected void write(String s) throws IOException {\r
-               connect();\r
-               _os.write(s.getBytes());\r
-       }\r
-\r
-       /** Write a -r-n newline sequence */\r
-       protected void newline() throws IOException {\r
-               write("\r\n");\r
-       }\r
-\r
-       /** Write a string followed by a newline */\r
-       protected void writeln(String s) throws IOException {\r
-               write(s);\r
-               newline();\r
-       }\r
-\r
-       /** Generate a random alphanumeric string */\r
-       private static String randomString() {\r
-               return Long.toString(RANDOM_GEN.nextLong(), 36);\r
-       }\r
-\r
-       /** Write a boundary marker */\r
-       private void boundary() throws IOException {\r
-               write("--");\r
-               write(BOUNDARY);\r
-       }\r
-\r
-\r
-       /**\r
-        * Creates a new multipart POST HTTP request for a specified URL\r
-        * @param url the URL to send request to\r
-        * @throws IOException\r
-        */\r
-       public FormPoster(URL inUrl) throws IOException\r
-       {\r
-               _connection = inUrl.openConnection();\r
-               _connection.setDoOutput(true);\r
-               _connection.setRequestProperty("Content-Type",\r
-                       "multipart/form-data; boundary=" + BOUNDARY);\r
-       }\r
-\r
-       /** Write a header with the given name */\r
-       private void writeName(String inName) throws IOException\r
-       {\r
-               newline();\r
-               write("Content-Disposition: form-data; name=\"");\r
-               write(inName);\r
-               write('"');\r
-       }\r
-\r
-       /**\r
-        * adds a string parameter to the request\r
-        * @param name parameter name\r
-        * @param value parameter value\r
-        * @throws IOException\r
-        */\r
-       public void setParameter(String inName, String inValue) throws IOException\r
-       {\r
-               boundary();\r
-               writeName(inName);\r
-               newline(); newline();\r
-               writeln(inValue);\r
-       }\r
-\r
-       /** Pipe the contents of the input stream to the output stream */\r
-       private static void pipe(InputStream in, OutputStream out) throws IOException\r
-       {\r
-               byte[] buf = new byte[500000];\r
-               int nread;\r
-               synchronized (in) {\r
-                       while((nread = in.read(buf, 0, buf.length)) >= 0) {\r
-                               out.write(buf, 0, nread);\r
-                       }\r
-               }\r
-               out.flush();\r
-               buf = null;\r
-       }\r
-\r
-       /**\r
-        * adds a file parameter to the request\r
-        * @param inName parameter name\r
-        * @param inFilename the name of the file\r
-        * @param inStream input stream to read the contents of the file from\r
-        * @throws IOException\r
-        */\r
-       public void setParameter(String inName, String inFilename, InputStream inStream) throws IOException\r
-       {\r
-               boundary();\r
-               writeName(inName);\r
-               write("; filename=\"");\r
-               write(inFilename);\r
-               write('"');\r
-               newline();\r
-               write("Content-Type: ");\r
-               String type = URLConnection.guessContentTypeFromName(inFilename);\r
-               if (type == null) {type = "application/octet-stream";}\r
-               writeln(type);\r
-               newline();\r
-               pipe(inStream, _os);\r
-               newline();\r
-       }\r
-\r
-       /**\r
-        * posts the requests to the server\r
-        * @return input stream with the server response\r
-        * @throws IOException\r
-        */\r
-       public InputStream post() throws IOException\r
-       {\r
-               boundary();\r
-               writeln("--");\r
-               _os.close();\r
-               return _connection.getInputStream();\r
-       }\r
-\r
-       /**\r
-        * @return the HTTP response code, 200 for success or -1 if not available\r
-        */\r
-       public int getResponseCode() throws IOException\r
-       {\r
-               if (_connection != null && _connection instanceof HttpURLConnection) {\r
-                       return ((HttpURLConnection) _connection).getResponseCode();\r
-               }\r
-               return -1;\r
-       }\r
-}\r
diff --git a/src/tim/prune/function/gpsies/GetGpsiesFunction.java b/src/tim/prune/function/gpsies/GetGpsiesFunction.java
deleted file mode 100644 (file)
index cdcc9a9..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-package tim.prune.function.gpsies;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.ArrayList;
-
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import tim.prune.App;
-import tim.prune.GpsPrune;
-import tim.prune.I18nManager;
-import tim.prune.function.search.GenericDownloaderFunction;
-import tim.prune.function.search.SearchResult;
-import tim.prune.load.xml.XmlFileLoader;
-import tim.prune.load.xml.ZipFileLoader;
-
-/**
- * Function to load track information from Gpsies.com
- * according to the currently viewed area
- */
-public class GetGpsiesFunction extends GenericDownloaderFunction
-{
-       /** Number of results per page */
-       private static final int RESULTS_PER_PAGE = 20;
-       /** Maximum number of results to get */
-       private static final int MAX_RESULTS = 60;
-       /** New API key (specific to this program) */
-       private static final String GPSIES_API_KEY = "oumgvvbckiwpvsnb";
-
-
-       /**
-        * Constructor
-        * @param inApp App object
-        */
-       public GetGpsiesFunction(App inApp) {
-               super(inApp);
-       }
-
-       /**
-        * @return name key
-        */
-       public String getNameKey() {
-               return "function.getgpsies";
-       }
-
-       /**
-        * @param inColNum index of column, 0 or 1
-        * @return key for this column
-        */
-       protected String getColumnKey(int inColNum)
-       {
-               if (inColNum == 0) return "dialog.gpsies.column.name";
-               return "dialog.gpsies.column.length";
-       }
-
-
-       /**
-        * Run method to call gpsies.com in separate thread
-        */
-       public void run()
-       {
-               _statusLabel.setText(I18nManager.getText("confirm.running"));
-               // Act on callback to update list and send another request if necessary
-               double[] coords = _app.getViewport().getBounds();
-               int currPage = 1;
-
-               ArrayList<SearchResult> trackList = null;
-               URL url = null;
-               String descMessage = "";
-               InputStream inStream = null;
-               // 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 +
-                               "&key=" + GPSIES_API_KEY;
-                       // Parse the returned XML with a special handler
-                       GpsiesXmlHandler xmlHandler = new GpsiesXmlHandler();
-                       try
-                       {
-                               url = new URL(urlString);
-                               SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
-                               URLConnection conn = url.openConnection();
-                               conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER);
-                               inStream = conn.getInputStream();
-                               saxParser.parse(inStream, xmlHandler);
-                       }
-                       catch (Exception e) {
-                               descMessage = e.getClass().getName() + " - " + e.getMessage();
-                       }
-                       // Close stream and ignore errors
-                       try {
-                               inStream.close();
-                       } catch (Exception e) {}
-                       // Add track list to model
-                       trackList = xmlHandler.getTrackList();
-                       _trackListModel.addTracks(trackList);
-
-                       // Compare number of results with results per page and call again if necessary
-                       currPage++;
-               }
-               while (trackList != null && trackList.size() == RESULTS_PER_PAGE
-                       && _trackListModel.getRowCount() < MAX_RESULTS && !_cancelled);
-               // Set status label according to error or "none found", leave blank if ok
-               if (descMessage.equals("") && (trackList == null || trackList.size() == 0)) {
-                       descMessage = I18nManager.getText("dialog.gpsies.nonefound");
-               }
-               _statusLabel.setText(descMessage);
-       }
-
-       /**
-        * Load the selected track(s)
-        */
-       protected void loadSelected()
-       {
-               // 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++)
-               {
-                       int rowNum = rowNums[i];
-                       if (rowNum >= 0 && rowNum < _trackListModel.getRowCount())
-                       {
-                               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
-               _cancelled = true;
-               _dialog.dispose();
-       }
-}
diff --git a/src/tim/prune/function/gpsies/GpsiesXmlHandler.java b/src/tim/prune/function/gpsies/GpsiesXmlHandler.java
deleted file mode 100644 (file)
index c549c59..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-package tim.prune.function.gpsies;
-
-import java.util.ArrayList;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import tim.prune.function.search.SearchResult;
-
-/**
- * XML handler for dealing with XML returned from gpsies.com
- */
-public class GpsiesXmlHandler extends DefaultHandler
-{
-       private String _value = null;
-       private ArrayList<SearchResult> _trackList = null;
-       private SearchResult _track = null;
-
-
-       /**
-        * React to the start of an XML tag
-        */
-       public void startElement(String inUri, String inLocalName, String inTagName,
-               Attributes inAttributes) throws SAXException
-       {
-               if (inTagName.equals("tracks")) {
-                       _trackList = new ArrayList<SearchResult>();
-               }
-               else if (inTagName.equals("track")) {
-                       _track = new SearchResult();
-               }
-               _value = null;
-               super.startElement(inUri, inLocalName, inTagName, inAttributes);
-       }
-
-       /**
-        * React to the end of an XML tag
-        */
-       public void endElement(String inUri, String inLocalName, String inTagName)
-       throws SAXException
-       {
-               if (inTagName.equals("track")) {
-                       _trackList.add(_track);
-               }
-               else if (inTagName.equals("title")) {
-                       _track.setTrackName(_value);
-               }
-               else if (inTagName.equals("description")) {
-                       _track.setDescription(_value);
-               }
-               else if (inTagName.equals("fileId")) {
-                       _track.setWebUrl("https://gpsies.com/map.do?fileId=" + _value);
-               }
-               else if (inTagName.equals("trackLengthM")) {
-                       try {
-                               _track.setLength(Double.parseDouble(_value));
-                       }
-                       catch (NumberFormatException nfe) {}
-               }
-               else if (inTagName.equals("downloadLink")) {
-                       _track.setDownloadLink(_value);
-               }
-               super.endElement(inUri, inLocalName, inTagName);
-       }
-
-       /**
-        * React to characters received inside tags
-        */
-       public void characters(char[] inCh, int inStart, int inLength)
-       throws SAXException
-       {
-               String value = new String(inCh, inStart, inLength);
-               _value = (_value==null?value:_value+value);
-               super.characters(inCh, inStart, inLength);
-       }
-
-       /**
-        * @return the list of tracks
-        */
-       public ArrayList<SearchResult> getTrackList()
-       {
-               return _trackList;
-       }
-}
diff --git a/src/tim/prune/function/gpsies/UploadGpsiesFunction.java b/src/tim/prune/function/gpsies/UploadGpsiesFunction.java
deleted file mode 100644 (file)
index 3cef9db..0000000
+++ /dev/null
@@ -1,332 +0,0 @@
-package tim.prune.function.gpsies;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.FlowLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import javax.swing.BorderFactory;
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JPasswordField;
-import javax.swing.JScrollPane;
-import javax.swing.JTextArea;
-import javax.swing.JTextField;
-import javax.swing.border.EtchedBorder;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-
-import tim.prune.App;
-import tim.prune.GenericFunction;
-import tim.prune.I18nManager;
-import tim.prune.function.browser.BrowserLauncher;
-import tim.prune.gui.GuiGridLayout;
-import tim.prune.save.GpxExporter;
-import tim.prune.save.SettingsForExport;
-
-/**
- * Function to upload track information up to Gpsies.com
- */
-public class UploadGpsiesFunction extends GenericFunction
-{
-       /** Dialog object */
-       private JDialog _dialog = null;
-       /** Edit box for user name */
-       private JTextField _usernameField = null;
-       /** Edit box for password */
-       private JPasswordField _passwordField = null;
-       /** Name of track */
-       private JTextField _nameField = null;
-       /** Description */
-       private JTextArea _descField = null;
-       /** Private checkbox */
-       private JCheckBox _privateCheckbox = null;
-       /** Activity checkboxes */
-       private JCheckBox[] _activityCheckboxes = null;
-       /** Writer object for GPX export */
-       private OutputStreamWriter _writer = null;
-       /** upload button */
-       private JButton _uploadButton = null;
-
-       /** URL to post form to */
-       private static final String GPSIES_URL = "http://www.gpsies.com/upload.do";
-       /** Keys for describing activities */
-       private static final String[] ACTIVITY_KEYS = {"trekking", "walking", "jogging",
-               "biking", "motorbiking", "snowshoe", "sailing", "skating"};
-
-       /**
-        * Constructor
-        * @param inApp App object
-        */
-       public UploadGpsiesFunction(App inApp) {
-               super(inApp);
-       }
-
-       /**
-        * @return name key
-        */
-       public String getNameKey() {
-               return "function.uploadgpsies";
-       }
-
-       /**
-        * Begin the function
-        */
-       public void begin()
-       {
-               // Initialise dialog, show empty list
-               if (_dialog == null)
-               {
-                       _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
-                       _dialog.setLocationRelativeTo(_parentFrame);
-                       _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
-                       _dialog.getContentPane().add(makeDialogComponents());
-                       _dialog.pack();
-               }
-               // Show dialog
-               _dialog.setVisible(true);
-       }
-
-
-       /**
-        * Create dialog components
-        * @return Panel containing all gui elements in dialog
-        */
-       private Component makeDialogComponents()
-       {
-               JPanel dialogPanel = new JPanel();
-               dialogPanel.setLayout(new BorderLayout());
-
-               JPanel gridPanel = new JPanel();
-               GuiGridLayout grid = new GuiGridLayout(gridPanel);
-               grid.add(new JLabel(I18nManager.getText("dialog.gpsies.username")));
-               _usernameField = new JTextField(15);
-               grid.add(_usernameField);
-               grid.add(new JLabel(I18nManager.getText("dialog.gpsies.password")));
-               _passwordField = new JPasswordField(15);
-               grid.add(_passwordField);
-               // Track name and description
-               grid.add(new JLabel(I18nManager.getText("dialog.gpsies.column.name")));
-               _nameField = new JTextField(15);
-               grid.add(_nameField);
-               grid.add(new JLabel(I18nManager.getText("dialog.gpsies.description")));
-               _descField = new JTextArea(5, 15);
-               _descField.setLineWrap(true);
-               _descField.setWrapStyleWord(true);
-               grid.add(new JScrollPane(_descField));
-               // Listener on all these text fields to enable/disable the ok button
-               KeyAdapter keyListener = new KeyAdapter() {
-                       /** Key released */
-                       public void keyReleased(KeyEvent inE) {
-                               enableOK();
-                               if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
-                                       _dialog.dispose();
-                               }
-                       }
-               };
-               _usernameField.addKeyListener(keyListener);
-               _passwordField.addKeyListener(keyListener);
-               _nameField.addKeyListener(keyListener);
-               // Listen for tabs on description field, to change focus not enter tabs
-               _descField.addKeyListener(new KeyAdapter() {
-                       /** Key pressed */
-                       public void keyPressed(KeyEvent inE) {
-                               if (inE.getKeyCode() == KeyEvent.VK_TAB) {
-                                       inE.consume();
-                                       if (inE.isShiftDown()) {
-                                               _nameField.requestFocusInWindow();
-                                       }
-                                       else {
-                                               _privateCheckbox.requestFocusInWindow();
-                                       }
-                               }
-                       }
-               });
-               // Listen for Ctrl-backspace on password field (delete contents)
-               _passwordField.addKeyListener(new KeyAdapter() {
-                       /** Key released */
-                       public void keyReleased(KeyEvent inE) {
-                               if (inE.isControlDown() && (inE.getKeyCode() == KeyEvent.VK_BACK_SPACE
-                                       || inE.getKeyCode() == KeyEvent.VK_DELETE)) {
-                                       _passwordField.setText("");
-                               }
-                       }
-               });
-               // Checkbox for private / public
-               grid.add(new JLabel(I18nManager.getText("dialog.gpsies.keepprivate")));
-               _privateCheckbox = new JCheckBox();
-               _privateCheckbox.setSelected(true);
-               grid.add(_privateCheckbox);
-
-               // panel for activity type checkboxes
-               JPanel activityPanel = new JPanel();
-               activityPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
-               ChangeListener checkListener = new ChangeListener() {
-                       public void stateChanged(ChangeEvent arg0) {
-                               enableOK();
-                       }
-               };
-               // Why not a simple grid layout here?
-               GuiGridLayout actGrid = new GuiGridLayout(activityPanel, new double[] {1.0, 1.0}, new boolean[] {false, false});
-               final int numActivities = ACTIVITY_KEYS.length;
-               _activityCheckboxes = new JCheckBox[numActivities];
-               for (int i=0; i<numActivities; i++)
-               {
-                       _activityCheckboxes[i] = new JCheckBox(I18nManager.getText("dialog.gpsies.activity." + ACTIVITY_KEYS[i]));
-                       _activityCheckboxes[i].addChangeListener(checkListener);
-                       actGrid.add(_activityCheckboxes[i]);
-               }
-               grid.add(new JLabel(I18nManager.getText("dialog.gpsies.activities")));
-               grid.add(activityPanel);
-               JPanel midPanel = new JPanel();
-               midPanel.setLayout(new BoxLayout(midPanel, BoxLayout.Y_AXIS));
-               midPanel.add(gridPanel);
-               dialogPanel.add(midPanel, BorderLayout.CENTER);
-
-               // button panel at bottom
-               JPanel buttonPanel = new JPanel();
-               buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
-               _uploadButton = new JButton(I18nManager.getText("button.upload"));
-               _uploadButton.setEnabled(false);
-               _uploadButton.addActionListener(new ActionListener() {
-                       public void actionPerformed(ActionEvent e) {
-                               startUpload();
-                       }
-               });
-               buttonPanel.add(_uploadButton);
-               JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
-               cancelButton.addActionListener(new ActionListener() {
-                       public void actionPerformed(ActionEvent e) {
-                               _dialog.dispose();
-                       }
-               });
-               buttonPanel.add(cancelButton);
-               dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
-               dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
-               return dialogPanel;
-       }
-
-
-       /**
-        * Check the inputs and enable or disable the upload button
-        */
-       private void enableOK()
-       {
-               // Check for lengths of input fields - only username, password and filename are required
-               boolean ok = (_usernameField.getText().length() > 0 && _nameField.getText().length() > 0);
-               if (ok) {
-                       // also check password field
-                       char[] pass = _passwordField.getPassword();
-                       ok = pass.length > 0;
-                       for (int i=0; i<pass.length; i++) {pass[i] = '0';} // recommended by javadoc
-                       if (ok) {
-                               ok = false;
-                               for (int i=0; i<_activityCheckboxes.length; i++) {
-                                       ok = ok || _activityCheckboxes[i].isSelected();
-                               }
-                       }
-               }
-               _uploadButton.setEnabled(ok);
-       }
-
-
-       /**
-        * Start the upload process (require separate thread?)
-        */
-       private void startUpload()
-       {
-               BufferedReader reader = null;
-               try
-               {
-                       FormPoster poster = new FormPoster(new URL(GPSIES_URL));
-                       poster.setParameter("device", "Prune");
-                       poster.setParameter("username", _usernameField.getText());
-                       poster.setParameter("password", new String(_passwordField.getPassword()));
-                       boolean hasActivity = false;
-                       for (int i=0; i<ACTIVITY_KEYS.length; i++)
-                       {
-                               if (_activityCheckboxes[i].isSelected()) {
-                                       hasActivity = true;
-                                       poster.setParameter("trackTypes", ACTIVITY_KEYS[i]);
-                               }
-                       }
-                       if (!hasActivity) {poster.setParameter("trackTypes", "walking");} // default if none given
-                       poster.setParameter("filename", _nameField.getText());
-                       poster.setParameter("fileDescription", _descField.getText());
-                       poster.setParameter("startpointCountry", "DE");
-                       poster.setParameter("endpointCountry", "DE"); // both those will be corrected by gpsies
-                       poster.setParameter("status", (_privateCheckbox.isSelected()?"3":"1"));
-                       poster.setParameter("submit", "speichern"); // required
-                       // Use Pipes to connect the GpxExporter's output with the FormPoster's input
-                       PipedInputStream iStream = new PipedInputStream();
-                       PipedOutputStream oStream = new PipedOutputStream(iStream);
-                       _writer = new OutputStreamWriter(oStream);
-                       new Thread(new Runnable() {
-                               public void run() {
-                                       try {
-                                               GpxExporter.exportData(_writer, _app.getTrackInfo(), _nameField.getText(),
-                                                       null, new SettingsForExport(), null);
-                                       } catch (IOException e) {}
-                                       finally {
-                                               try {_writer.close();} catch (IOException e) {}
-                                       }
-                               }
-                       }).start();
-                       poster.setParameter("formFile", "filename.gpx", iStream);
-
-                       BufferedInputStream answer = new BufferedInputStream(poster.post());
-                       int response = poster.getResponseCode();
-                       reader = new BufferedReader(new InputStreamReader(answer));
-                       String line = reader.readLine();
-                       // Try to extract gpsies page url from the returned message
-                       String pageUrl = null;
-                       if (response == 200 && line.substring(0, 2).toUpperCase().equals("OK"))
-                       {
-                               final int bracketPos = line.indexOf('[');
-                               if (bracketPos > 0 && line.endsWith("]")) {
-                                       pageUrl = line.substring(bracketPos + 1, line.length()-1);
-                               }
-                       }
-                       if (pageUrl != null)
-                       {
-                               // OK received and managed to extract a Url from the return message.
-                               int userChoice = JOptionPane.showConfirmDialog(_app.getFrame(),
-                                       I18nManager.getText("dialog.gpsies.confirmopenpage"),
-                                       I18nManager.getText(getNameKey()), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
-                               if (userChoice == JOptionPane.OK_OPTION) {
-                                       BrowserLauncher.launchBrowser(pageUrl);
-                               }
-                       }
-                       else {
-                               _app.showErrorMessageNoLookup(getNameKey(), I18nManager.getText("error.gpsies.uploadnotok")
-                                       + ": " + line);
-                       }
-               }
-               catch (MalformedURLException e) {}
-               catch (IOException ioe) {
-                       _app.showErrorMessageNoLookup(getNameKey(), I18nManager.getText("error.gpsies.uploadfailed") + ": "
-                               + ioe.getClass().getName() + " : " + ioe.getMessage());
-               }
-               finally {
-                       try {if (reader != null) reader.close();} catch (IOException e) {}
-               }
-               _dialog.dispose();
-       }
-}
diff --git a/src/tim/prune/function/olc/CoordPair.java b/src/tim/prune/function/olc/CoordPair.java
new file mode 100644 (file)
index 0000000..778b46d
--- /dev/null
@@ -0,0 +1,75 @@
+package tim.prune.function.olc;
+
+class ParseException extends Exception {}
+
+/**
+ * Pair of coordinates
+ */
+class CoordPair
+{
+       /** Alphabet of allowed characters */
+       private static final String ALPHABET = "23456789CFGHJMPQRVWX";
+
+       public double lat = 0.0;
+       public double lon = 0.0;
+
+       /** Constructor */
+       public CoordPair(double inLat, double inLon)
+       {
+               lat = inLat;
+               lon = inLon;
+       }
+
+       /** Constant pair to represent padding */
+       public static CoordPair PADDING = new CoordPair(-1.0, -1.0);
+
+       /**
+        * Try to parse the given pair of characters into a CoordPair
+        * @param inFirst first character of pair
+        * @param inSecond second character of pair
+        * @return CoordPair from (0, 0) to (19/20, 19/20)
+        * @throws ParseException
+        */
+       public static CoordPair decode(char inFirst, char inSecond) throws ParseException
+       {
+               final boolean isFirstPadding = (inFirst == '0');
+               final boolean isSecondPadding = (inSecond == '0');
+               if (isFirstPadding && isSecondPadding) {return CoordPair.PADDING;}
+               if (isFirstPadding || isSecondPadding) {throw new ParseException();}
+               // Try to turn these characters into numbers
+               final double lat = decodeChar(inFirst);
+               final double lon = decodeChar(inSecond);
+               return new CoordPair(lat / 20.0, lon / 20.0);
+       }
+
+       /**
+        * Try to parse the given single character into a CoordPair
+        * @param inChar single character from level 11
+        * @return CoordPair from (0, 0) to (19/20, 19/20)
+        * @throws ParseException
+        */
+       public static CoordPair decode(char inChar) throws ParseException
+       {
+               // Try to turn this character into a number
+               final int charIndex = decodeChar(inChar);
+               final int lat = charIndex / 4;
+               final int lon = charIndex % 4;
+               return new CoordPair(lat / 5.0, lon / 4.0);
+       }
+
+       /**
+        * Get the index from the given character
+        * @param inChar character from OLC
+        * @return index from 0 to 19
+        * @throws ParseException if character not found
+        */
+       private static int decodeChar(char inChar) throws ParseException
+       {
+               final int index = ALPHABET.indexOf(inChar);
+               if (index < 0)
+               {
+                       throw new ParseException();
+               }
+               return index;
+       }
+}
diff --git a/src/tim/prune/function/olc/OlcArea.java b/src/tim/prune/function/olc/OlcArea.java
new file mode 100644 (file)
index 0000000..bc7a3e8
--- /dev/null
@@ -0,0 +1,21 @@
+package tim.prune.function.olc;
+
+/**
+ * Class to represent the result of an OLC decoding
+ */
+public class OlcArea
+{
+       public double minLat = 0.0;
+       public double maxLat = 0.0;
+       public double minLon = 0.0;
+       public double maxLon = 0.0;
+
+       /** Constructor */
+       public OlcArea(double inMinLat, double inMinLon, double inMaxLat, double inMaxLon)
+       {
+               minLat = inMinLat;
+               minLon = inMinLon;
+               maxLat = inMaxLat;
+               maxLon = inMaxLon;
+       }
+}
diff --git a/src/tim/prune/function/olc/OlcDecoder.java b/src/tim/prune/function/olc/OlcDecoder.java
new file mode 100644 (file)
index 0000000..122f6fe
--- /dev/null
@@ -0,0 +1,101 @@
+package tim.prune.function.olc;
+
+
+/**
+ * Decoder of OLC (Open Location Code) strings
+ */
+public class OlcDecoder
+{
+       /**
+        * Decode the given String into an OlcArea object
+        * @param inCode code representing an OLC
+        * @return an OlcArea object, or null if parsing failed
+        */
+       public static OlcArea decode(String inCode)
+       {
+               if (inCode == null || inCode.length() < 8) {
+                       return null;
+               }
+               String code = inCode.trim().toUpperCase();
+               if (code.length() < 8 || code.length() > 12) {
+                       return null;
+               }
+               double lat = 0.0, lon = 0.0;
+               double resolution = 400.0;
+               int charPos = 0;
+               int numSteps = 0;
+               boolean amPadding = false;
+               try
+               {
+                       while (charPos < inCode.length())
+                       {
+                               if (charPos == 0 || charPos == 2 || charPos == 4 || charPos == 6 || charPos == 9)
+                               {
+                                       // take next two characters, make pair, position += 2
+                                       CoordPair pair = CoordPair.decode(code.charAt(charPos), code.charAt(charPos+1));
+                                       if (pair == CoordPair.PADDING) {
+                                               amPadding = true;
+                                       }
+                                       else if (amPadding)
+                                       {
+                                               return null;
+                                       }
+                                       else
+                                       {
+                                               // Add to current lat, lon
+                                               lat += (pair.lat * resolution);
+                                               lon += (pair.lon * resolution);
+                                               numSteps++;
+                                               resolution /= 20.0;
+                                       }
+                                       charPos += 2;
+                               }
+                               else if (charPos == 8)
+                               {
+                                       if (code.charAt(charPos) != '+')
+                                       {
+                                               return null;
+                                       }
+                                       charPos += 1;
+                               }
+                               else if (charPos == 11)
+                               {
+                                       // take next character, make pair
+                                       CoordPair pair = CoordPair.decode(code.charAt(charPos));
+                                       // Add to current lat, lon
+                                       lat += (pair.lat * resolution);
+                                       lon += (pair.lon * resolution);
+                                       charPos += 1;
+                                       numSteps++;
+                                       resolution /= 20.0;
+                               }
+                               else
+                               {
+                                       return null;
+                               }
+                       }
+
+                       // Make OlcArea object and return it
+                       if (numSteps < 1)
+                       {
+                               return null;
+                       }
+                       else if (numSteps < 6)
+                       {
+                               // make four points
+                               lat -= 90.0;
+                               lon -= 180.0;
+                               return new OlcArea(lat, lon, lat+resolution, lon+resolution);
+                       }
+                       else
+                       {
+                               // make single point:
+                               lat -= 90.0;
+                               lon -= 180.0;
+                               return new OlcArea(lat, lon, lat+resolution*2.5, lon+resolution*2.0);
+                       }
+               }
+               catch (ParseException e) {}
+               return null;
+       }
+}
\ No newline at end of file
index fa8d4c33d90bf43838f19f039d9b510226fccf51..079bf9d11e0ce70852fd21131aa5f4ced0dcd72a 100644 (file)
@@ -25,11 +25,10 @@ import tim.prune.App;
 import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
 import tim.prune.function.browser.BrowserLauncher;
-import tim.prune.function.gpsies.TrackListModel;
 
 /**
  * Function to load track information from any source,
- * subclassed for special cases like gpsies, wikipedia or OSM
+ * subclassed for special cases like wikipedia or OSM
  */
 public abstract class GenericDownloaderFunction extends GenericFunction implements Runnable
 {
index d757b017a2d6456e9e43475418116c84e6144ec3..52b902f85e08f04b7d02f74ff239514427c34aaf 100644 (file)
@@ -1,7 +1,7 @@
 package tim.prune.function.search;
 
 /**
- * Class to hold a search result from wikipedia / gpsies etc
+ * Class to hold a search result from wikipedia or other online service
  */
 public class SearchResult implements Comparable<SearchResult>
 {
similarity index 95%
rename from src/tim/prune/function/gpsies/TrackListModel.java
rename to src/tim/prune/function/search/TrackListModel.java
index 850921303801d33878c6b429ec2709087ed7fd6a..d9163be25cb894c27ea7feadf47cad7909bbc223 100644 (file)
@@ -1,4 +1,4 @@
-package tim.prune.function.gpsies;
+package tim.prune.function.search;
 
 import java.text.NumberFormat;
 import java.util.ArrayList;
@@ -9,10 +9,9 @@ import javax.swing.table.AbstractTableModel;
 import tim.prune.I18nManager;
 import tim.prune.config.Config;
 import tim.prune.data.Unit;
-import tim.prune.function.search.SearchResult;
 
 /**
- * Model for list of tracks from a search result (eg gpsies.com, geonames, overpass)
+ * Model for list of tracks from a search result (eg geonames, overpass)
  */
 public class TrackListModel extends AbstractTableModel
 {
index 364723712a0c785fabb6de8d9c6643d55fabef40..6b1ba55192f6dbb68666bab73c72a3fc20121539 100644 (file)
+116/122/A-180 Z light pillbox          49 57 30.7 N    14 05 23.85 E
+A-4/51/A-200 Y light pillbox   Back to 1938 state restored Pillbox Type 37 built in a unique modification into road embankment between Dolní Bezděkov and Bratronice, Kladno District, Czech Republic.       50 04 47.94 N   14 02 01.85 E
 A Arnoia               42 14 54.95 N   8 08 04.88 W
 A Barciela, Oroso              42 57 57.49 N   8 26 31.07 W
-A Cañiza      A Cañiza is a municipality in Galicia, in the province of Pontevedra.  42 12 45.46 N   8 16 29.77 W
-A Coruña      A Coruña is a Galician city, in north-western Spain.   43 21 58.95 N   8 24 28.71 W
-A Estrada              41 32 35.1 N    2 12 59.63 E
-A Guarda               41 54 09.12 N   8 52 27.15 W
-A Gudiña      A Gudiña is a municipality in Galicia, in the province of Ourense.     42 03 40.13 N   7 08 34.19 W
-A Illa de Arousa       A Illa de Arousa is a municipality in Galicia, in the province of Pontevedra.   42 33 08.36 N   8 52 06.13 W
-A Merca        A Merca is a municipality in Galicia, in the province of Ourense.       42 13 22.53 N   7 54 15.55 W
-A Mezquita             42 00 42.5 N    7 02 43.17 W
-A Pobra de Trives              42 20 19.96 N   7 15 15.88 W
-A Pobra do Brollón            42 33 29.3 N    7 23 40.15 W
-A Pobra do Caramiñal  A Pobra do Caramiñal is a municipality in the province of A Coruña, Galicia, Spain.   42 36 12.2 N    8 56 14.25 W
-A Rúa A Rúa is a municipality in Galicia, in the province of Ourense.        42 23 34.93 N   7 06 59.02 W
-A Veiga        A Veiga is a municipality in Galicia, in the province of Ourense.       42 15 01.36 N   7 01 30.25 W
-A Walk on Main Street, Ferndale, California    Ferndale is a small town in Humboldt County, California. Its Main Street is listed by the National Register of Historic Places as a historic district.  40 34 32.16 N   124 15 54 W
-A Walk up Main Street, Adamstown, Pennsylvania Adamstown is a small, historic town in Lancaster County, Pennsylvania.  40 14 36.96 N   76 03 16.2 W
 Abbaye d'Acey          47 15 42 N      5 39 25 E
 Abbaye de Bourgueil            47 16 46.2 N    0 10 18.12 E
 Abbaye de Cluny        The Abbey of Cluny (or Cluni, or Clugny) was founded on 2 September 909 and is located in the modern-day department of Saône-et-Loire in the region of Bourgogne, in east-central France, near Mâcon. 46 26 03 N      4 39 33 E
-Abbaye de Fontenay             47 38 27 N      4 23 23 E
 Abbaye de Fontevraud   Fontevraud Abbey is located near Saumur in Anjou, France        47 10 53 N      0 03 06 E
 Abbaye de La Sauve-Majeure             44 46 07.24 N   0 18 42.41 W
-Abbaye de Montmajour           43 42 20 N      4 39 50 E
+Abbaye de Montmajour           43 42 20.16 N   4 39 50.04 E
 Abbaye de Saint-Germain-des-Prés              48 51 14 N      2 20 04 E
 Abbaye de Saint-Savin-sur-Gartempe             46 33 51 N      0 51 58 E
 Abbaye de Sénanque            43 55 42 N      5 11 13 E
 Abbaye de Valmagne             43 29 12.97 N   3 33 44.19 E
 Abbaye du Relec                48 26 56 N      3 43 00 W
-Abbaye Saint Wandrille Monastery Saint Wandrille in France     49 31 46.42 N   0 45 59.58 E
 Abbaye Saint-Corneille         49 25 02.6 N    2 49 28.57 E
-Abbaye Saint-Florentin, Bonneval               48 10 40.41 N   1 23 04.87 E
-Abeilhan               43 27 02 N      3 17 43 E
+Abbaye Saint Wandrille Monastery Saint Wandrille in France     49 31 46.42 N   0 45 59.58 E
+Abeilhan       Abeilhan is a commune of the Hérault département in the Region of Occitanie - France. 43 27 02 N      3 17 43 E
 Abri-caverne de l'ouvrage du Haut-Bois         47 35 24.07 N   6 48 34.23 E
 Abtei Saint-André (Lavaudieu)         45 15 49 N      3 27 17 E
+A Cañiza      A Cañiza is a municipality in Galicia, in the province of Pontevedra.  42 12 45.46 N   8 16 29.77 W
 Aceldama       Aceldama or Akeldama is the Aramaic name for a place in Jerusalem associated with Judas Iscariot, one of the followers of Jesus.        31 46 05.1 N    35 13 59.51 E
-Adissan                43 32 09.96 N   3 25 45.12 E
-Agadir         30 25 00 N      9 35 00 W
-Agel           43 20 18.96 N   2 51 13.68 E
+Adissan        Adissan is a commune of the Hérault département in the Region of Occitanie - France.  43 32 09.96 N   3 25 45.12 E
+Aérodrome de Besançon-Thise          47 16 25.68 N   6 04 59.09 E
+A Estrada      A Estrada is a municipality in Galicia, Spain in the province of Pontevedra.    41 32 35.1 N    2 12 59.63 E
+Agel   Agel is a commune of the Hérault département - France.        43 20 18.96 N   2 51 13.68 E
 Agrón, Ames           42 54 20.32 N   8 41 43.21 W
+A Guarda       A Guarda is a municipality in Galicia, in the province of Pontevedra.   41 54 09.12 N   8 52 27.15 W
+A Gudiña      A Gudiña is a municipality in Galicia, in the province of Ourense.     42 03 40.13 N   7 08 34.19 W
 Aguiño, Ribeira               42 31 24.99 N   9 00 57.6 W
-Aichi prefecture               35 04 59 N      136 58 59 E
 Aiguafreda     Montseny        41 46 05.2 N    2 15 05.39 E
+A Illa de Arousa       A Illa de Arousa is a municipality in Galicia, in the province of Pontevedra.   42 33 08.36 N   8 52 06.13 W
 Alagna Valsesia        Alagna Valsesia is a village in Piemonte in Italy.      45 51 05.16 N   7 56 16.98 E
 Albrechtsburg  The Albrechtsburg is the castle that dominates the city centre of Meißen, Germany.     51 09 59.65 N   13 28 17.83 E
 Aletsch        Aletsch region, UNESCO World Heritage Site since 2001, in Bernese Alps, Switzerland     46 27 50.9 N    8 04 20.89 E
 Allariz        Allariz is a municipality in Galicia, in the province of Ourense.       42 11 20.76 N   7 48 09.71 W
+Alte Kanzlei, Stuttgart                48 46 39.1 N    9 10 42.97 E
 Alt Katholische Christuskirche Offenbach               50 06 01.91 N   8 45 52.28 E
+A Merca        A Merca is a municipality in Galicia, in the province of Ourense.       42 13 22.53 N   7 54 15.55 W
 Ames           42 51 35.95 N   8 38 58.21 W
+A Mezquita             42 00 42.5 N    7 02 43.17 W
 Amoeiro                42 24 37.45 N   7 57 15.38 W
 Ansemil, Silleda               42 44 21.56 N   8 16 12.47 W
 Anta de Casaínhos             38 52 50.16 N   9 10 09.91 W
 Antwerp Central Station                51 13 02 N      4 25 15.6 E
-Aquis Querquennis      Aquis Querquennis was a Roman castra at Os Baños, Bande (Ourense, Galiza).     41 58 27.2 N    7 58 52.1 W
+A Pobra de Trives              42 20 19.96 N   7 15 15.88 W
+A Pobra do Brollón            42 33 29.3 N    7 23 40.15 W
+A Pobra do Caramiñal  A Pobra do Caramiñal is a municipality in the province of A Coruña, Galicia, Spain.   42 36 12.2 N    8 56 14.25 W
+Aquis Querquennis              41 58 12 N      7 58 48 W
 Arbo           42 06 39.45 N   8 18 57.47 W
-Arc de Triomf de Barcelona     The Arc de Triomf (Triumphal Arch) is an archway structure in Barcelona, Spain. 41 23 27 N      2 10 50 E
+Arc de Triomf de Barcelona             41 23 28 N      2 10 50.02 E
 Arc de Triomphe du Carrousel   The Arc de Triomphe du Carrousel is a triumphal arch in Paris, located in the Place du Carrousel on the site of the former Tuileries Palace.    48 51 43 N      2 19 58 E
-Arch of Constantine            41 53 23 N      12 29 27 E
+Arch of Constantine            41 53 22.92 N   12 29 26.88 E
 Arch of Septimius Severus (Rome)       The Arch of Septimius Severus is situated in the Forum Romanum in Rome. 41 53 34 N      12 29 05 E
 Arch of Titus  The Arch of Titus is a triumphal arch with a single arched opening, located on the Summa Sacra Via to the west of the Roman Forum in Rome.      41 53 26 N      12 29 19 E
-Arnhem         51 59 00 N      5 55 00 E
-Arenys de Munt Arenys de Munt is a village in the comarca of Maresme, Catalonia.       41 36 46 N      2 32 25 E
+A Rúa A Rúa is a municipality in Galicia, in the province of Ourense.        42 23 34.93 N   7 06 59.02 W
+Askersund      Askersund is a town in Sweden.  58 53 00 N      14 54 00 E
 As Neves       As Neves is a municipality in Galicia, in the province of Pontevedra.   42 05 10.49 N   8 24 53.43 W
 As Pontes de García Rodríguez                43 26 47.63 N   7 51 09.54 W
-Askersund              58 53 00 N      14 54 00 E
 Assumption Cathedral in Odessa Assumption Cathedral in Odessa, Ukraine 46 28 49.43 N   30 44 21.24 E
+Äußerer Plauenscher Friedhof Cemetery „Äußerer Plauenscher Friedhof“ in Dresden-Plauen 51 01 11.89 N   13 42 26.03 E
 Australian Synchrotron The Australian Synchrotron, a synchrotron facility in the suburb of Clayton, in Melbourne, Victoria, Australia. 37 54 51 S      145 08 33 E
+A Veiga        A Veiga is a municipality in Galicia, in the province of Ourense.       42 15 01.36 N   7 01 30.25 W
 Avión Avión is a municipality in Galicia, in the province of Ourense.        42 22 23.73 N   8 15 02.64 W
+A Walk on Main Street, Ferndale, California    Ferndale is a small town in Humboldt County, California.        40 34 32.16 N   124 15 54 W
+A Walk up Main Street, Adamstown, Pennsylvania Adamstown is a small, historic town in Lancaster County, Pennsylvania.  40 14 36.96 N   76 03 16.2 W
 Ayasofya       The Church of the Holy Wisdom, commonly known as Hagia Sophia in English, is the former Greek Orthodox patriarchal cathedral, converted in 1453 to a mosque, now a museum, in Istanbul. 41 00 30.5 N    28 58 47.7 E
-Aérodrome de Besançon-Thise          47 16 25.68 N   6 04 59.09 E
-Aşgabat               37 57 00 N      58 23 00 E
+B-6/61/A-220 Z light pillbox   B-6/61/A-220Z light pillbox, Beroun     49 57 25.96 N   14 05 35.6 E
+B-7/5/A-200 Z light pillbox            49 56 28.3 N    14 07 53.68 E
+B-7/6/A-200 Z light pillbox            49 56 19.34 N   14 07 56.34 E
 Bahnhof Dresden-Neustadt       Dresden-Neustadt railway station and the four inner city bridges        51 03 56 N      13 44 27 E
 Baiona Baiona is a municipality in Galicia, Spain in the province of Pontevedra.       42 07 03.29 N   8 51 01.86 W
+Baker Glacier  Chugach National Forest, Alaska 61 04 53 N      148 21 52 W
 Baltar Baltar is a municipality in Galicia, in the province of Ourense.        41 57 04.75 N   7 42 56.7 W
 Barbadás              42 17 56.03 N   7 53 13.14 W
-Basilique Notre-Dame de la Daurade             43 36 03 N      1 26 23 E
+Basilique Notre-Dame de la Daurade             36 02.88 N      1 26 22.92 E
 Basilique Notre-Dame de Thierenbach            47 52 54.12 N   7 11 21.16 E
-Basilique Saint-Sauveur de Rennes              48 06 42 N      1 40 55 W
+Basilique Saint-Sauveur de Rennes              48 06 42 N      1 40 54 W
 Beade  Beade is a municipality in Galicia, in the province of Ourense. 42 20 06.72 N   8 08 45.05 W
+Bear Lake (Alaska)     Kenai Peninsula, Alaska 60 12 03 N      149 21 11 W
 Bergfriedhof (Stuttgart)       The Bergfriedhof is a cemetery in the Stadtbezirk Stuttgart-Ost in Stuttgart.   48 47 19.16 N   9 12 23.35 E
 Bergondo               43 19 15.36 N   8 13 54.04 W
 Berlin Anhalter Bahnhof        The Anhalter Bahnhof was a large main-line railway station in Berlin. Today it is just a stop on the Berlin S-Bahn.     52 30 11 N      13 22 55 E
 Betanzos               43 16 44.24 N   8 12 55.95 W
 Bibliothèque Sainte-Geneviève                48 50 49.5 N    2 20 45 E
-Bibracte               46 55 23 N      4 02 15 E
+Bibracte       Bibracte est le nom de la cité gauloise, capitale des Eduens, qui était située au sommet du mont Beuvray (France)    46 55 23 N      4 02 15 E
 Biella         45 34 05.07 N   8 03 02.61 E
 Bienertparks in Dresden        Als Bienertpark werden verschiedene Parkanlagen in Dresden bezeichnet, deren Entstehung auf die Familie Gottlieb Traugott Bienert zurückgeht.  51 01 48.29 N   13 42 54.9 E
-Bishkek                42 52 00 N      74 34 00 E
+Billings Glacier       Chugach National Forest, Alaska 60 52 55 N      148 34 28 W
+Bishkek                42 52 00.12 N   74 34 00.12 E
 Boccadasse     Boccadasse è un antico borgo marinaro situato nel levante di Genova.   44 23 23.85 N   8 58 22.71 E
 Boettcherstrasse               53 04 30 N      8 48 21 E
 Boiro          42 38 13.16 N   8 52 12.31 W
 Boke   Boke is a small village in the German district Paderborn; it belongs to the city of Delbrück.  51 43 48 N      8 33 43.56 E
 Bolongaropalast        The Bolongaro Palace is a baroque building in Frankfurt-Höchst.        50 06 04 N      8 33 08 E
 Borne des Trois Puissances     Dreiländerstein        47 30 10.58 N   7 07 48.76 E
-Borovsk        Эта страница на русском: Боровск     55 12 27.19 N   36 29 05.05 E
+Borovsk        Borovsk, a town established in 1358, stands between Moscow and Kaluga.  55 12 27.19 N   36 29 05.05 E
 Bosco delle Querce     The Regional Natural Park Bosco delle Querce (Oaks' Wood), built after the Seveso Disaster on the "A" zone.     45 38 55 N      9 09 10 E
 Botanischer Garten Heidelberg          49 25 00 N      8 40 10 E
-Brancion               46 32 51 N      4 47 48.12 E
-Brudermühlbrücke     The Brudermühlbrücke is a bridge in Munich across the Isar.   48 06 45.3 N    11 33 36.07 E
-Brudermühlstraße     The Brudermühlstraße is a street in Munich, part of the Mittlerer Ring around the city centre.        48 06 44.2 N    11 33 01.37 E
+Brancion       Brancion is a small fortified medieval city in Burgundy, Central France.        46 32 51 N      4 47 48.12 E
+Broad Pass     George Parks Highway, Alaska    63 19 22 N      149 10 10 W
+Brudermühlbrücke     The Brudermühlbrücke is a bridge in Munich across the Isar.   48 06 45.36 N   11 33 36 E
+Brudermühlstraße     The Brudermühlstraße is a street in Munich, part of the Mittlerer Ring around the city centre.        48 06 43.92 N   11 32 58.56 E
 Buenos Aires           34 36 13 S      58 22 54 W
 Bueu   Bueu is a municipality in Galicia, Spain in the province of Pontevedra. 42 19 24.69 N   8 47 23.1 W
-Buffalo Central Terminal       The New York Central Terminal in Buffalo, USA, was a key railroad station from 1929 to 1979.    42 53 22.44 N   78 49 51.08 W
+Bürgerhospital (Stuttgart)            48 47 34.6 N    9 10 45.95 E
 Burg Stahleck  Stahleck Castle in Bacharach is a 12th century castle occupying a commanding view of the Rhine in the Loreley valley. Nowadays it's a youth hostel.     50 03 29.49 N   7 45 56.46 E
 Burj Khalifa   The Burj Khalifa ("Khalifa Tower") is a skyscraper in Dubai, United Arab Emirates.      25 11 49.7 N    55 16 26.8 E
-Bürgerhospital (Stuttgart)            48 47 34.6 N    9 10 45.95 E
 Cabanas                43 24 50.49 N   8 10 04.15 W
-Cabo Fisterra  Cape Finisterre is a rock-bound peninsula on the west coast of Galicia, in Fisterra (Spain).    42 52 50.96 N   9 16 18.27 W
+Cabo Fisterra          42 52 57 N      9 16 19.92 W
 Cabrils                41 31 42 N      2 22 09 E
-Cadaqués      Cadaqués is a touristic village in Costa Brava, Alt Empordà, Catalonia, Spain.        42 17 19.46 N   3 16 40.96 E
+Cáceres       Cáceres is the capital of Cáceres Province, in Extremadura, Spain.    39 28 23 N      6 22 16 W
+Cadaqués              42 17 18.96 N   3 16 40.08 E
 Calgary                51 02 42 N      114 03 26 W
 Cambados               42 30 52.2 N    8 48 24.89 W
 Cambre Cambre is a municipality in the province A Coruña, Galicia, Spain.     43 17 37.32 N   8 20 34.49 W
@@ -117,7 +120,8 @@ Candelabro de Paracas       The Paracas Candelabra is a well-known prehistoric geoglyp
 Cangas         42 15 47.1 N    8 47 09.5 W
 Cape Arkona    There are two bunkers at Cape Arkona.   54 40 47 N      13 25 57 E
 Cape Horn      Cape Horn is often said to be the southernmost point of South America.  55 58 47 S      67 16 18 W
-Capela de São Nicolau Capela de São Nicolau ou Passos da Via Sacra. Em Portugal, Porto.      41 08 27.14 N   8 36 55.49 W
+Capela de São Nicolau         32 41 08 27.15 N        8 36 55.57 W
+Cap Glacier    Chugach National Forest, Alaska 60 56 57 N      147 54 57 W
 Capriata d'Orba        Capriata d'Orba è un comune in provincia di Alessandria, Piemonte, Italia.     44 43 43.93 N   8 41 25.29 E
 Carballeda de Avia     Carballeda de Avia is a municipality in Galicia, in the province of Ourense.    42 19 12.81 N   8 09 53.03 W
 Cariño        Cariño is a municipality in the province A Coruña, Galicia, Spain.    43 43 58 N      7 52 39.76 W
@@ -126,8 +130,7 @@ Cartelle    Cartelle is a municipality in Galicia, in the province of Ourense.      42 1
 Casa Buonarroti (Florence)     Casa Buonarroti è un museo di Firenze  43 46 11.64 N   11 15 49 E
 Casa de las Carnicerías, León        The Casa de las Carnicerías (butcher's shops), a monument declared as a Bien de Interés Cultural in 1992, is located at San Martín square, León (Spain).    42 35 48.84 N   5 34 04.4 W
 Casa del esquileo, Cabanillas del Monte        The casa del esquileo (shearing shed) is a monument placed at Cabanillas del Monte, Torrecaballeros, Segovia (Spain).   40 58 36 N      4 01 54 W
-Casa Milà     Casa Milà, also known as La Pedrera (the open quarry), is a modernist building in Barcelona, Catalonia, Spain  41 23 42.66 N   2 09 42.37 E
-Cassine                44 45 03 N      8 31 44 E
+Casa Milà             41 23 43.08 N   2 09 42.12 E
 Castel del Monte       Castel del Monte is a castle in Apulia, in Italy.       41 05 05.28 N   16 16 15.57 E
 Castellazzo Bormida    Castellazzo Bormida is a comune (municipality) in the Province of Alessandria in the Italian region Piedmont    44 50 46 N      8 34 42 E
 Castello di Duino      Il castello di Duino è un castello situato nel comune di Duino-Aurisina, in provincia di Trieste, Italia.      45 46 18.39 N   13 36 14.3 E
@@ -138,7 +141,7 @@ Castelo da Rocha Forte              42 51 42.29 N   8 34 29.38 W
 Castelo de Castro Marim                37 13 07.43 N   7 26 29.69 W
 Castelo de Maceda              42 16 13.92 N   7 39 32.36 W
 Castelo de Monforte de Lemos           42 31 26.71 N   7 30 38.86 W
-Castelo de Monterreal          42 07 29.82 N   8 50 59.18 W
+Castelo de Monterreal          42 07 32.16 N   8 51 00 W
 Castelo de Pambre              42 51 34.87 N   7 56 53.7 W
 Castelo de Ribadavia           42 17 12.3 N    8 08 37.49 W
 Castelo de San Felipe  Castillo de San Felipe is a castle in the county of Ferrol, Galicia     43 27 53 N      8 16 54 W
@@ -146,27 +149,28 @@ Castelo de Santa Cruz             43 20 54.08 N   8 21 00.64 W
 Castelo de Santo Antón                43 21 56.6 N    8 23 16.12 W
 Castelo de Sobroso     The Sobroso Castle is a castle located in Vilasobroso- Mondariz, Provincia of Pontevedra, Galicia (Spain).      42 12 17.31 N   8 27 20.51 W
 Castelo de Soutomaior          42 19 46.77 N   8 34 05.54 W
-Castelo de Vilalba             43 17 52.79 N   7 40 56.44 W
+Castelo de Vilalba             43 17 52.8 N    7 40 56.42 W
 Castelo de Vilamarín          42 27 02.87 N   7 54 02.26 W
 Castiñeiras, Ribeira          42 31 57.33 N   8 59 44.67 W
 Castrelo de Miño      Castrelo de Miño is a municipality in Galicia, in the province of Ourense.     42 17 49.63 N   8 04 02.63 W
 Castrelo do Val        Castrelo do Val is a municipality in Galicia, in the province of Ourense.       41 59 26.73 N   7 25 25.2 W
 Castro Caldelas        Castro Caldelas is a municipality in Galicia, in the province of Ourense.       42 22 32.62 N   7 24 54 W
-Castro de Baroña      O Castro de Baroña está situado na parroquia de Baroña no concello de Porto do Son.  42 41 40.91 N   9 01 54.91 W
+Castro de Baroña              42 41 41.8 N    9 01 55.99 W
 Castro de Rei          43 12 32.14 N   7 23 58.38 W
 Catacaos               5 16 00 S       80 41 00 W
+Cataract Glacier       Chugach National Forest, Alaska 61 01 39 N      148 25 23 W
 Catedral de Santiago de Compostela             42 52 51.27 N   8 32 42.17 W
-Cathedral of Justo     The Cathedral of Justo is being built by Justo Gallego in Mejorada del Campo (Community of Madrid, Spain).      40 23 38.88 N   3 29 17.99 W
 Cathédrale Notre-Dame d'Amiens        The cathedral of Our Lady of Amiens (fr: Cathédrale Notre-Dame d'Amiens), or just Amiens Cathedral, is the tallest complete cathedral in France.       49 53 42 N      2 18 08 E
-Cathédrale Notre-Dame de Chartres             48 26 50 N      1 29 16 E
+Cathédrale Notre-Dame de Chartres             48 26 52 N      1 29 16 E
 Cathédrale Notre-Dame de Paris                48 51 10.8 N    2 20 59.28 E
 Cathédrale Notre-Dame de Reims        Cathedral "Notre-Dame de Reims", located in Reims, France       49 15 13.9 N    4 02 02.5 E
 Cathédrale Notre-Dame de Strasbourg           48 34 55 N      7 45 03 E
 Cathédrale Notre-Dame du Havre                49 29 13 N      0 06 30 E
 Cathédrale Saint-André de Bordeaux           44 50 16 N      0 34 39 W
 Cathédrale Saint-Bénigne de Dijon            47 19 17 N      5 02 04 E
-Cathédrale Saint-Julien du Mans       Interior        48 00 33 N      0 11 56 E
 Cathédrale Sainte-Cécile d'Albi              43 55 42.57 N   2 08 34.6 E
+Cathédrale Saint-Julien du Mans       Interior        48 00 33 N      0 11 56 E
+Cathedral of Justo     The Cathedral of Justo is being built by Justo Gallego in Mejorada del Campo (Community of Madrid, Spain).      40 23 38.88 N   3 29 17.99 W
 Catoira        Catoira is a municipality in Galicia, Spain in the province of Pontevedra.      42 39 54.98 N   8 43 57.93 W
 Cedeira        Cedeira is a municipality in the province A Coruña, Galicia, Spain.    43 39 39.53 N   8 03 10.41 W
 Celanova       Celanova is a municipality in Galicia, in the province of Ourense.      42 09 07.02 N   7 57 24.65 W
@@ -176,56 +180,45 @@ Cesantes, Redondela               42 18 33.05 N   8 36 44.72 W
 Champ-de-Mars (Paris)          48 51 22 N      2 17 54 E
 Chantada               42 36 27.15 N   7 46 09.2 W
 Chapela, Redondela             42 15 53.95 N   8 40 22.71 W
-Chapelle de Languidou  Chapel in Plovan / Bretagne     47 54 49.13 N   4 21 09.72 W
+Chapelle de Languidou          47 54 49.13 N   4 21 09.72 W
 Chapelle Notre-Dame de Molsheim                48 32 26.16 N   7 29 40.13 E
-Chapelle Notre-Dame du Schaefertal (Soultzmatt)                47 57 06.84 N   7 12 59.4 E
-Chapelle Notre-Dame du Verger  Chapelle Notre-Dame du Verger dans l'anse du Verger à Cancale (Ille-et-Vilaine)        48 41 37 N      1 52 51 W
 Chapelle Notre-Dame-du-Chêne de Plobsheim             48 27 35.28 N   7 42 49.32 E
 Chapelle Notre-Dame-du-Grasweg de Huttenheim           48 21 31.32 N   7 34 33.85 E
+Chapelle Notre-Dame du Schaefertal (Soultzmatt)                47 57 06.84 N   7 12 59.4 E
+Chapelle Notre-Dame du Verger  Chapelle Notre-Dame du Verger dans l'anse du Verger à Cancale (Ille-et-Vilaine)        48 41 37 N      1 52 51 W
 Chapelle royale Saint-Louis, Dreux             48 44 18 N      1 21 48 E
+Chapelle Sainte-Marguerite d'Epfig             48 21 15.84 N   7 28 40.12 E
+Chapelle Sainte-Marie de l'Assomption d'Obersteigen            48 38 32.28 N   7 18 22.32 E
 Chapelle Saint-Gonéry         48 50 29.4 N    3 13 42.38 W
 Chapelle Saint-Sébastien de Dambach-la-Ville          48 19 37.56 N   7 25 11.75 E
 Chapelle Saint-Théodore de Vienne             45 31 28.56 N   4 52 24.13 E
 Chapelle Saint-Ulrich d'Avolsheim              48 33 43.56 N   7 30 01.51 E
-Chapelle Sainte-Marguerite d'Epfig             48 21 15.84 N   7 28 40.12 E
-Chapelle Sainte-Marie de l'Assomption d'Obersteigen            48 38 32.28 N   7 18 22.32 E
 Chapelles du Kochersberg               48 38 42 N      7 31 14.88 E
-Château d'Angers              47 28 11.67 N   0 33 33.61 W
-Château de Bugarach           42 52 36.16 N   2 21 05.15 E
-Château de Couiza             42 56 42.68 N   2 15 14.11 E
-Château de Condé             49 00 20 N      3 33 34 E
-Chiesa di Sant'Antonio in Caggiano     Church of Saint Anthony in Caggiano.    40 34 04.13 N   15 29 39.47 E
-Chioggia       Chioggia is a town in Veneto in Italy.  45 13 04.23 N   12 16 36.76 E
-Chroniques de Jérusalem       Jerusalem Mount of Olives Santa Marta Passionists church.       31 46 15.83 N   35 15 08.48 E
-Church of Adelboden    The gothic village church of Adelboden was built in the 15th century    46 29 34.1 N    7 33 32.4 E
-Church of Saints Apostles Peter and Paul in Vilnius            54 41 38.82 N   25 18 22.69 E
-Church of St. Johns in Vilnius Organ   54 40 57.5 N    25 17 19.22 E
-Church of São Vítor (Braga)  Igreja de São Victor em Braga  41 33 09.95 N   8 24 47.49 W
 Château d'Anet                48 51 29 N      1 26 19 E
+Château d'Angers              47 28 11.67 N   0 33 33.61 W
 Château d'Arlay               46 45 32.4 N    5 32 16.44 E
-Château d'Azay-le-Rideau      The Château de Azay-le-Rideau is one of the most famous castles in t
-he French Loire Valley.        47 15 33 N      0 27 58 E
-Château d'Effiat      The château d'Effiat in Puy de Dôme, Auvergne, France.        46 02 37 N      3 15 06 E
-Château d'If          43 16 47.5 N    5 19 30.5 E
-Château d'Ussé       The Château d'Ussé is a château of the Loire Valley in Rigny-Ussé.  47 14 59 N      0 17 28 E
+Château d'Azay-le-Rideau      The Château de Azay-le-Rideau is one of the most famous castles in the French Loire Valley.    47 15 33 N      0 27 58 E
 Château de Blois      The Château de Blois is one of the most renowned châteaux of the Loire Valley.        47 35 07.8 N    1 19 51.42 E
 Château de Bressieux          45 19 21 N      5 16 45.01 E
 Château de Brest              48 22 52.52 N   4 29 40.95 W
 Château de Chambord           47 36 58.22 N   1 31 03.25 E
 Château de Chamerolles                48 03 37.08 N   2 09 51.01 E
 Château de Chantilly          49 11 38 N      2 29 09 E
+Château de Châteaudun                48 04 14 N      1 19 25 E
 Château de Chenonceau         47 19 30 N      1 04 14.16 E
 Château de Cheverny           47 30 01 N      1 27 29 E
 Château de Chinon             47 10 05 N      0 14 10 E
-Château de Châteaudun                48 04 14 N      1 19 25 E
 Château de Cléron            47 05 16 N      6 03 27 E
+Château de Condé             49 00 20 N      3 33 34 E
+Château de Crussol    The Château de Crussol is a castle in the Ardèche départment of France.      44 56 18 N      4 51 09 E
 Château de Domfront           48 35 39 N      0 39 09 W
+Château d'Effiat      The château d'Effiat in Puy de Dôme, Auvergne, France.        46 02 37 N      3 15 06 E
 Château de Fontainebleau      The Château of Fontainebleau is the largest of the French royal châteaux.     48 24 08 N      2 42 02 E
 Château de Frontenay          46 47 08.88 N   5 37 05.88 E
 Château de Gevrey-Chambertin          47 13 46 N      4 57 56 E
-Château de l'Arthaudière     The Château de l'Arthaudière is a castle in the Isère départment of the Rhône-Alpes région of France.     45 07 09 N      5 13 59 E
 Château de Lagarde            43 03 02 N      1 56 08.5 E
 Château de Langeais   The Château de Langeais in the Loire Valley    47 19 29.28 N   0 24 21.96 E
+Château de l'Arthaudière     The Château de l'Arthaudière is a castle in the Isère départment of the Rhône-Alpes région of France.     45 07 09 N      5 13 59 E
 Château de Loches     The Château de Loches in Loches is a château of the Loire Valley. The castle area, consisting of three buildings, among them one the oldest keeps in France, is one of the best preserved European architecture ensembles of the Middle Ages. 47 07 37 N      0 59 54 E
 Château de Maintenon          48 35 08 N      1 34 41 E
 Château de Malmaison  Château de Malmaison was the place of residence of Joséphine de Beauharnais and Napoleon Bonaparte    48 52 15 N      2 10 01 E
@@ -233,34 +226,49 @@ Château de Montfaucon            47 14 46.32 N   6 04 42.24 E
 Château de Murol              45 34 42 N      2 56 43 E
 Château de Pagax              44 36 29.88 N   2 15 06.98 E
 Château de Puivert            42 55 16.21 N   2 03 17.82 E
+Château des Adhémar          44 33 33.02 N   4 45 15.35 E
 Château de Saint-Germain-en-Laye      The Château de Saint-Germain-en-Laye is a former royal residence in Saint-Germain-en-Laye, located ca. 19 km to the west of Paris. Nowadays it serves as Musée des Antiquités Nationales.    48 53 53 N      2 05 47 E
 Château de Saint-Izaire       The Château de Saint-Izaire is a castle in the Saint-Izaire commune of the Aveyron département of France      43 58 31 N      2 43 10 E
+Château de Saissac    The Château de Saissac is a Cathar castle in the Saissac commune, Aude département of France. 43 21 25 N      2 10 04.7 E
 Château de Suscinio           47 30 46 N      2 43 46 W
 Château de Suze-la-Rousse             44 17 14.64 N   4 50 11.62 E
 Château de Thorens    The Château de Thorens is a castle in the commune of Thorens-Glières in the Haute-Savoie département of France.      45 59 37 N      6 15 20 E
 Château de Valençay  The Château de Valençay is one of the châteaux of the Loire Valley in the french region Centre.      47 09 27 N      1 33 48 E
+Château de Varillettes        The Château de Varillettes is a château in the Cantal.        45 01 26.76 N   3 08 53.16 E
 Château de Vaux-le-Vicomte            48 33 53.46 N   2 42 50.4 E
 Château de Wangenbourg        The castle of Wangenbourg is a mediaeval castle in Wangenbourg-Engental, Bas-Rhin, France.      48 37 15 N      7 18 51 E
-Château des Adhémar          44 33 33.02 N   4 45 15.35 E
+Château d'Harcourt    The Château d'Harcourt is a castle located in the commune of Harcourt in the Eure département of France       49 10 26 N      0 47 11 E
+Château d'If          43 16 47.5 N    5 19 30.5 E
 Château du Haut-Kœnigsbourg  The castle of Haut-Kœnigsbourg is a mediaeval castle located in Orschwiller, France.   48 14 58 N      7 20 39 E
-Château-Gaillard              49 14 17.26 N   1 24 09.91 E
+Château d'Ussé       The Château d'Ussé is a château of the Loire Valley in Rigny-Ussé.  47 14 59 N      0 17 28 E
+Château-Gaillard      Château-Gaillard is a castle in Les Andelys (Normandie, France).       49 14 17.26 N   1 24 09.91 E
+Chena Hot Springs, Alaska              65 03 10 N      146 03 19 W
+Chiesa di Sant'Antonio in Caggiano     Church of Saint Anthony in Caggiano.    40 34 04.13 N   15 29 39.47 E
+Chioggia       Chioggia is a town in Veneto in Italy.  45 13 04.23 N   12 16 36.76 E
+Chroniques de Jérusalem       Jerusalem Mount of Olives Santa Marta Passionists church.       31 46 15.83 N   35 15 08.48 E
+Church of Adelboden    The gothic village church of Adelboden was built in the 15th century    46 29 34.1 N    7 33 32.4 E
+Church of Saints Apostles Peter and Paul in Vilnius            54 41 38.82 N   25 18 22.69 E
+Church of São Vítor (Braga)  Igreja de São Victor em Braga  41 33 09.95 N   8 24 47.49 W
+Church of St. Johns in Vilnius         54 40 57.5 N    25 17 19.22 E
 Cimetière du Montparnasse     The Montparnasse cemetery (Fr: Cimetière du Montparnasse) is a famous cemetery in the Montparnasse quarter of Paris, France.   48 50 17 N      2 19 37 E
-Cimetière du Père-Lachaise   Père Lachaise Cemetery (French: Cimetière du Père-Lachaise) (officially, cimetière de l'Est “eastern cemetery”) is the largest cemetery in the city of Paris at 118 acres (48 ha), though there are larger cemeteries in Paris suburbs. 48 51 43 N      2 23 39 E
+Cimetière du Père-Lachaise   Père Lachaise Cemetery (French: Cimetière du Père-Lachaise) (officially, cimetière de l'Est “eastern cemetery”) is the largest cemetery in the city of Paris at 118 acres (48 ha), though there are larger cemeteries in Paris suburbs. 48 51 42.84 N   2 23 39.12 E
 Cinque Terre   The Cinque Terre are five coastal villages in the province of La Spezia, Italy. 44 06 37.74 N   9 44 31.35 E
-Ciudad Real            38 59 00 N      3 55 00 W
-Clermont-Ferrand               45 46 47 N      3 05 13 E
-Clos Vougeot           47 10 29.72 N   4 57 19.74 E
-Collingwood Monument   A monument to Admiral Collingwood (1748-1810) was erected in Tynemouth, North East England, in 1845.    55 00 52.96 N   1 25 12.14 W
+City Palace (Udaipur)  The City Palace in Udaipur was the royal palace of the Maharana of Mewar. The palace is located on the east bank of Lake Pichola in Udaipur, Rajasthan, India.  24 34 37.2 N    73 41 00.96 E
+Ciudad Real            38 58 59.88 N   3 55 00.12 W
+Clos Vougeot   Clos Vougeot is a famous vineyard in Burgundy, France.  47 10 29.72 N   4 57 19.74 E
+Cochrane Bay   Chugach National Forest, Alaska 60 44 18 N      148 20 06 W
 Collégiale Notre-Dame de Melun                48 32 08 N      2 39 37 E
 Collégiale Saint-Florent de Niederhaslach             48 32 35 N      7 20 29 E
 Collégiale Saint-Martin de Colmar             48 04 38.5 N    7 21 29 E
-Collégiale Saint-Thiébaut de Thann           47 48 40 N      7 06 06 E
 Collégiale Saints-Michel-et-Gangolphe de Lautenbach           47 56 27.96 N   7 09 32.94 E
+Collégiale Saint-Thiébaut de Thann           47 48 40 N      7 06 06 E
+Collingwood Monument   A monument to Admiral Collingwood (1748-1810) was erected in Tynemouth, North East England, in 1845.    55 00 52.96 N   1 25 12.14 W
 Colonia-Haus   The Colonia-Haus is a 45-storey, 147 m skyscraper completed in 1973 in the Riehl district of Cologne, Germany.  50 57 38 N      6 58 55 E
 Colonne Vendôme               48 52 02.89 N   2 19 45.89 E
 Comacchio      Comacchio is a town in Emilia Romagna in Italy. 44 41 31.74 N   12 10 55.95 E
 Concatedral de Santa María de Guadalajara             40 38 04.72 N   3 09 45.15 W
 Conciergerie   The Conciergerie in the Palais de Justice, Paris, France        48 51 23 N      2 20 44 E
+Córdoba (Argentina)   Intendancy square       31 24 00 S      64 11 00 W
 Corrubedo, Ribeira             42 34 21.64 N   9 04 22.76 W
 Cortegada      Cortegada is a municipality in Galicia, in the province of Ourense.     42 12 24.86 N   8 10 01.06 W
 Coulée verte René-Dumont     The Promenade plantée is an elevated park in the 12th arrondissement of Paris, France. 48 50 32 N      2 23 15 E
@@ -269,41 +277,165 @@ Couvent de la Divine Providence de Saint-Jean-de-Bassel          48 48 12.12 N   6 59 32.0
 Couvent de Reinacker           48 40 51.96 N   7 24 27.5 E
 Crecente       Crecente is a municipality in Galicia, in the province of Pontevedra.   42 09 07.02 N   8 13 22.52 W
 Credit Lyonnais Head Office            48 52 14.95 N   2 20 11.45 E
-Château de Crussol    The Château de Crussol is a castle in the Ardèche départment of France.      44 56 18 N      4 51 09 E
 Cualedro               41 59 18.46 N   7 35 40.71 W
 Culleredo      Culleredo is a municipality in the province A Coruña, Galicia, Spain.  43 17 31.02 N   8 23 08.99 W
 Curtis Hall Arboretum          40 04 42 N      75 07 44 W
-Cáceres       Cáceres is the capital of Cáceres Province, in Extremadura, Spain.    39 28 23 N      6 22 16 W
-Córdoba (Argentina)   Intendancy square       31 24 00 S      64 11 00 W
+Cygnus olor from Carolasee     The swans and pond are there since 1882.        51 01 59.16 N   13 45 52.69 E
 Dakar          14 43 55 N      17 27 26 W
 Dalhems kyrka  Die Kirche von Dalhem zählt zu den berühmtesten auf Gotland. Ihr Turm, der im 14. Jahrhundert angefügt wurde, gehört zu den höchsten der Landkirchen Gotlands.     57 33 08.7 N    18 32 03.2 E
 Dazaifu Tenman-gū             33 31 17.49 N   130 32 05.45 E
+Delaney Park, Anchorage, Alaska                61 12 47 N      149 54 04 W
 Dent du Géant         45 51 43 N      6 57 06 E
 Detroit Institute of Arts      The Detroit Institute of Arts is a large art museum in Detroit, Michigan in the United States.  42 21 33.5 N    83 03 53.3 W
-Deutsches Museum Verkehrszentrum       München        48 07 57.85 N   11 32 40.69 E
+Deutsches Museum Verkehrszentrum       Ganghoferstraße 29, 80339 München     48 07 57.85 N   11 32 40.69 E
 Deyrulzaferan          37 17 57.6 N    40 47 33.9 E
+Đình Bảng  Bảng Communal House (Đình Bảng in Vietnamese) is one of largest and finest village communal houses in Việt Nam. 21 06 29.99 N   105 57 06.31 E
+Doran Strait   Chugach National Forest, Alaska 61 04 34 N      148 11 20 W
+Dorfkirche Dabergotz           52 54 10.44 N   12 43 30.42 E
+Dorfkirche Golzow (Barnim)             52 54 41.37 N   13 48 32.69 E
+Dorfkirche Hohenfinow          52 48 38.1 N    13 55 29.08 E
+Dorfkirche Kirchlotheim                51 10 07.83 N   8 53 46.05 E
 Dorfkirche Klein Haßlow       Church in Klein Haßlow, Wittstock municipality, Ostprignitz-Ruppin district, Brandenburg state, Germany        53 10 29.84 N   12 31 28.6 E
 Dorfkirche Priort      Church in Priort, Wustermark municipality, Havelland district, Brandenburg state, Germany.      52 30 44.61 N   12 57 49.36 E
+Dorfkirche Zechow              53 03 18.01 N   12 54 44.88 E
 Dozón         42 34 09.35 N   8 03 08.25 W
 Drexel University              39 57 14.68 N   75 11 12.76 W
 Duchesse Anne (voilier)                51 02 15.37 N   2 22 20.21 E
 Duino-Aurisina         45 45 02.29 N   13 40 29.6 E
 Durban         29 53 00 S      31 03 00 E
 Dürrenstein (Südtirol)       The Dürrenstein is a mountain in the Dolomites in South Tyrol. 46 40 24 N      12 11 04 E
-Effnerplatz    The Effnerplatz is a square in the north of Munich, in the Borough Bogenhausen. 48 09 11.79 N   11 36 54.73 E
-Église Saint-Jean-Baptiste de Laure-Minervois         43 16 20.78 N   2 31 12.11 E
-Église Saint-Louis-en-l'Île  The Saint-Louis-en-l'Île Church (lit. "St. Louis on the Island"), is a Catholic church located on Île Saint-Louis in the IVe arrondissement of Paris  48 51 4.38 N 2 21 27.47 E
+École centrale de Lille       École Centrale de Lille is a graduate engineering school located in campus Lille I within Université Lille Nord de France.    50 36 21.62 N   3 08 13.63 E
+École Jules Ferry de Royan            45 37 38.16 N   1 01 33.66 W
+Effnerplatz    The Effnerplatz is a square in the north of Munich in the Borough Bogenhausen.  48 09 09 N      11 36 51.12 E
+Église de la Sainte-Trinité (Lauterbourg)            48 58 30.1 N    8 10 40.77 E
+Église de l'Assomption simultanée (La Petite-Pierre)         48 51 25.2 N    7 18 55.84 E
+Église de Saint-Lothain               46 49 27.84 N   5 38 30.12 E
+Église de Saint-Paul de Frontignan    L'Église de Saint-Paul de Frontignan est une église catholique de l'ancien diocèse de Maguelone en Languedoc, France.        43 26 50.47 N   3 45 18.66 E
+Église des Augustins (Ribeauvillé)           48 11 43.44 N   7 19 08.87 E
+Église des Jésuites (Molsheim)               48 32 25.3 N    7 29 45 E
+Église des Saints-Innocents (Blienschwiller)          48 20 25.8 N    7 25 06.17 E
+Église Notre-Dame de la Dalbade               43 35 51.36 N   1 26 32.89 E
+Église Notre-Dame-de-la-Nativité (Saverne)           48 44 28.32 N   7 21 50.36 E
+Église Notre-Dame-de-l'Assomption (Bergheim)          48 12 18 N      7 21 53.28 E
+Église Notre-Dame-de-l'Assomption (Bernardswiller)            48 27 10.08 N   7 27 49.57 E
+Église Notre-Dame-de-l'Assomption (Monswiller)                48 45 17.61 N   7 22 39.66 E
+Église Notre-Dame-de-l'Assomption (Rosenwiller)               48 30 21.96 N   7 26 25.48 E
+Église Notre-Dame-de-l'Assomption (Rouffach)          47 57 24 N      7 18 02 E
+Église Notre-Dame (Guebwiller)                47 54 20.75 N   7 12 52.56 E
+Église protestante (Balbronn)         48 35 05.28 N   7 26 15.97 E
+Église protestante (Baldenheim)               48 14 15 N      7 32 14.35 E
+Église protestante (Berg)             48 53 52.08 N   7 09 24.01 E
+Église protestante (Bischheim)                48 36 55.08 N   7 45 21.89 E
+Église protestante du Temple Neuf (Strasbourg)                48 35 00 N      7 44 54 E
+Église protestante (Fouday)           48 25 17.76 N   7 11 12.95 E
+Église protestante (Harskirchen)              48 56 02.04 N   7 02 20.15 E
+Église protestante (Scharrachbergheim)                48 35 35.52 N   7 29 55.9 E
+Église protestante (Schiltigheim)             48 36 21.96 N   7 45 05.04 E
+Église protestante (Sélestat)                48 15 36.36 N   7 27 11.56 E
+Église protestante (Weiterswiller)            48 51 10.44 N   7 24 50.9 E
+Église Sainte-Marie-Madeleine de Rennes-le-Château           42 55 41.05 N   2 15 45.69 E
+Église Saint-Eustache de Paris                48 51 48 N      2 20 42 E
+Église Saint-Gervais-Saint-Protais            48 51 19.8 N    2 21 16.6 E
+Église Saint-Laurent (Paris)          48 52 29.45 N   2 21 29.92 E
+Église Saint-Louis-en-l'Île  The Saint-Louis-en-l'Île Church (lit. "St. Louis on the Island"), is a Catholic church located on Île Saint-Louis in the IVe arrondissement of Paris  48 51 4.38 N    2 21 27.47 E
 Église Saint-Martin de Chambonas              44 25 02.45 N   4 07 43.97 E
-Eglise Saint-Pierre des Cuisines               43 36 15.49 N   1 26 08.26 E
+Église Saint-Michel d'Ernolsheim-lès-Saverne Bells   48 47 27.85 N   7 22 47.57 E
+Église Saint-Nicolas-du-Chardonnet    St. Nicolas du Chardonnet is a church in the centre of Paris, France located in the 5th arrondissement. 48 50 57 N      2 21 01 E
+Église Saint-Pierre de Montmartre     Saint-Pierre de Montmartre is a church in Paris 48 53 12 N      2 20 31 E
+Église Saint-Pierre-de-Rhèdes                43 35 16.22 N   3 04 43.64 E
+Eglise Saint-Pierre des Cuisines       L'Église Saint-Pierre des Cuisines, située rue de la Boule, à côté de la place Saint-Pierre à Toulouse, est la plus vieille église du sud-ouest de la France. Elle est construite sur une ancienne nécropole gallo-romaine du IVe siècle.      43 36 15.49 N   1 26 08.26 E
+Église Saint-Pierre-Saint-Paul de Rueil-Malmaison             48 52 35.4 N    2 10 53.15 E
+Église Saints-Pierre-et-Paul (Andlau)         48 23 16.3 N    7 24 54.3 E
+Église Saints-Pierre-et-Paul (Eguisheim)              48 02 32.28 N   7 18 21.2 E
+Église Saints-Pierre-et-Paul (Hohatzenheim)           48 42 44.64 N   7 36 59.11 E
+Église Saints-Pierre-et-Paul (Neuwiller-lès-Saverne)         48 49 25 N      7 24 20 E
+Église Saints-Pierre-et-Paul (Obernai)                48 27 47.88 N   7 28 54.48 E
+Église Saints-Pierre-et-Paul (Ottmarsheim)            47 47 13.2 N    7 30 25.2 E
+Église Saints-Pierre-et-Paul (Rosheim)                48 29 48 N      7 28 14 E
+Église Saints-Pierre-et-Paul (Sigolsheim)             48 08 04.2 N    7 18 03.1 E
+Église Saints-Pierre-et-Paul (Wissembourg)            49 02 14 N      7 56 30 E
+Église Saint-Sulpice          48 51 04 N      2 20 05 E
 Église Saint-Vincent-de-Paul (Paris)  Saint-Vincent-de-Paul is a church in Paris near the Gare du Nord        48 52 43.7 N    2 21 06.6 E
-El Padul               37 01 27 N      3 37 36 W
+Églises St Pierre le Vieux (Strasbourg)       protestant church       48 34 58 N      7 44 24 E
+Église St Antoine de Padoue (Saverne)         48 44 29.4 N    7 21 40.82 E
+Église St Arbogast (Offenheim)                48 37 53.76 N   7 36 59.54 E
+Église St Barthélemy (Sarrewerden)           48 55 22.8 N    7 04 56.93 E
+Église St Benoît (Bergholtzzell)             47 55 51.34 N   7 13 54.48 E
+Église St Blaise (Valff)              48 25 12.36 N   7 31 06.96 E
+Église St Cyriaque (Altorf)           48 31 22.7 N    7 31 50 E
+Église Ste Anne (Turckheim)           48 05 15.72 N   7 16 41.12 E
+Église Ste Aurélie protestante (Strasbourg)          48 34 53 N      7 44 00 E
+Église Ste Colombe (Hattstatt)                48 00 44.28 N   7 18 06.01 E
+Église Ste Croix (Kaysersberg)        Lamentation of Christ   48 08 20.04 N   7 15 48.56 E
+Église Ste Croix (Rountzenheim)               48 49 08.76 N   8 00 26.39 E
+Église Ste Foy (Sélestat)            48 15 33.67 N   7 27 21.81 E
+Église Ste Lucie (Niederhergheim)             47 59 10.32 N   7 23 48.41 E
+Église Ste Madeleine (Strasbourg)             48 34 48 N      7 45 17 E
+Église Ste Marguerite (Geispolsheim)          48 30 50.4 N    7 38 36.06 E
+Église Ste Odile (Lapoutroie)         48 09 08.64 N   7 10 03.97 E
+Église Ste Odile (Wintzfelden)                47 58 32.88 N   7 11 49.92 E
+Église St Étienne (Rosheim)          48 29 43.8 N    7 27 59.72 E
+Église St Étienne (Seltz)            48 53 37.32 N   8 06 28.44 E
+Église St Étienne simultanée (Wangen)               48 37 01.56 N   7 27 53.68 E
+Église Ste Walburge (Walbourg)                48 53 05.51 N   7 47 21.97 E
+Église St Gall (Niedermorschwihr)             48 05 57.84 N   7 16 26.47 E
+Église St Gall protestante (Domfessel)                48 57 06.48 N   7 09 07.56 E
+Église St Georges (Châtenois)                48 16 09.12 N   7 23 51 E
+Église St Georges (Sélestat)         48 15 36 N      7 27 24.12 E
+Église St Grégoire (Ribeauvillé)            48 11 49.2 N    7 19 00.41 E
+Église St Guillaume protestante (Strasbourg)          48 34 55.5 N    7 45 28 E
+Église St Hippolyte (Saint-Hippolyte)         48 14 01.68 N   7 22 04.01 E
+Église St Jacques-le-Majeur (Kuttolsheim)             48 38 37.32 N   7 31 41.34 E
+Église St Jacques-le-Majeur simultanée (Dettwiller)          48 45 12.6 N    7 27 56.77 E
+Église St Jacques-le-Majeur simultanée (Hunawihr)            48 10 42.24 N   7 18 38.02 E
+Église St Jean-Baptiste (Saint-Jean-Saverne)          48 46 18.7 N    7 21 48.5 E
+Église St Jean-Baptiste simultanée (Hohwiller)               48 45 12.78 N   7 27 56.77 E
+Église St Jean-Baptiste (Surbourg)            48 54 34.2 N    7 50 50.28 E
+Église St Jean-Baptiste (Wattwiller)          47 50 07.72 N   7 10 37.27 E
+Église St Jean protestante (Wissembourg)              49 02 18.96 N   7 56 33.36 E
+Église St Jean (Strasbourg)           48 35 04 N      7 44 25 E
+Église St Laurent (Dieffenbach-au-Val)                48 18 44.64 N   7 19 41.34 E
+Église St Laurent protestante (Dorlisheim)            48 31 30 N      7 29 13.99 E
+Église St Léger (Guebwiller)         47 54 42.1 N    7 12 33.75 E
+Église St Léger (Murbach)            47 55 24 N      7 09 29 E
+Église St Martin (Ammerschwihr)               48 07 37.92 N   7 16 54.01 E
+Église St Martin (Ebersheim)          48 18 14.04 N   7 30 14.08 E
+Église St Martin (Pfaffenheim)                47 59 05.28 N   7 17 08.59 E
+Église St Martin protestante (Barr)           48 24 33.84 N   7 26 51.47 E
+Église St Martin protestante (Westhoffen)             48 36 01.8 N    7 26 30.3 E
+Église St Maurice (Ebersmunster)              48 18 39.5 N    7 31 37 E
+Église St Maurice (Fegersheim)                48 29 23.64 N   7 40 50.27 E
+Église St Maurice (Orschwiller)               48 14 27.24 N   7 22 44.62 E
+Église St Maurice (Soultz-Haut-Rhin)          47 53 13.2 N    7 13 48.29 E
+Église St Maurice (Soultz-les-Bains)          48 34 17.4 N    7 29 09.35 E
+Église St Maurice (Willgottheim)              48 40 14.52 N   7 30 33.23 E
+Église St Médard (Bœrsch)           48 28 40.44 N   7 26 24.4 E
+Église St Michel (Reichshoffen)               48 55 54.84 N   7 39 52.02 E
+Église St Michel (Weyersheim)         48 43 06.24 N   7 48 07.96 E
+Église St Nicolas (Haguenau)          48 49 13 N      7 47 32 E
+Église St Nicolas (Neuve-Église)             48 19 50.88 N   7 18 48.24 E
+Église St Nicolas (Wingersheim)               48 43 18.84 N   7 38 08.02 E
+Église St Pantaléon (Gueberschwihr)          48 00 16.92 N   7 16 29.78 E
+Église St Paul protestante (Strasbourg)               48 35 11 N      7 45 35 E
+Église St Pierre "Dompeter" (Molsheim, Avolsheim)             48 33 24.12 N   7 30 19.59 E
+Église St Pierre le Jeune catholique (Strasbourg)             48 35 18.35 N   7 44 55.75 E
+Église St Pierre le Jeune protestante (Strasbourg)            48 35 08 N      7 44 47 E
+Église St Rémi (Itterswiller)                48 21 51.48 N   7 25 37.42 E
+Église St Sébastien (Soultzmatt)             47 57 37.08 N   7 14 15.36 E
+Église St Thomas protestante (Strasbourg)             48 34 47 N      7 44 44 E
+Église St Trophime (Eschau)           48 29 25.08 N   7 42 57.96 E
+Église St Ulrich (Altenstadt)         49 01 49.8 N    7 58 05.88 E
+Église St Ulrich (Wittersheim)                48 46 53.04 N   7 39 27.47 E
+Eklutna Village Cemetery       Anchorage, Alaska       61 27 38 N      149 21 42 W
 El Vendrell            41 13 11.72 N   1 32 04.08 E
 Empúries      Empúries is a town on the Mediterranean coast of the Catalan comarca of Alt Empordà in Catalonia, Spain.      42 08 20.29 N   3 07 11.19 E
 Enclos paroissial de Saint-Thégonnec          48 31 13.4 N    3 56 47.44 W
-Erica, Victoria         37 59 00 S     146 22 00 E
+Erica, Victoria                37 59 00 S      146 22 00 E
 Erlöserkirche (Bad Homburg)   The Church of the Redeemer is a protestant church in Bad Homburg, Germany.      50 13 35.5 N    8 36 42 E
 Esgos          42 19 29.71 N   7 41 45.94 W
+Esther Passage Chugach National Forest, Alaska 60 53 20 N      147 56 27 W
 European Parliament    The European Parliament is the parliament of the European Union.        48 35 51.82 N   7 46 09.82 E
+Explorer Glacier       Chugach National Forest, Alaska 60 46 34 N      148 55 03 W
 Familistère           49 54 15 N      3 37 31 E
 Fangelsbachfriedhof    The Fangelsbachfriedhof is one of the most important historical cemeteries in Stuttgart.        48 45 56 N      9 10 28 E
 Feldkommandostelle Hegewald (East Prussia)             54 08 05.54 N   21 58 36.02 E
@@ -312,115 +444,129 @@ Ferrol          43 29 21.47 N   8 13 29.94 W
 Ferrytoll Park & Ride  Ferrytoll Park & Ride is a bus/car interchange in Fife, Scotland, at the northern end of the Forth road crossing.       56 01 21.47 N   3 24 22.97 W
 Fieschergletscher              46 30 07.88 N   8 08 30.59 E
 Fiesole (area archeologica)            43 48 29.04 N   11 17 39.19 E
+Filialkirche hl. Gotthart in Lansach, Weißenstein             46 41 12.84 N   13 42 16.56 E
 Fish Creek, Victoria           38 41 00 S      146 05 00 E
 Flaucher       Flaucher is an area in the south of Munich on the left and right hand side of the Isar (district: Sendling and Thalkirchen).    48 06 27 N      11 33 27 E
 Fontaine des Neuf-Canons               43 31 36.12 N   5 26 55.25 E
 Fontaine du Palmier            48 51 26.99 N   2 20 50.17 E
+Forêt domaniale de Sète      The National Forest of Sète in the commune of Sète, Hérault, France. 43 24 18.74 N   3 40 13.74 E
+Forge d'Étueffont             47 43 20.9 N    6 55 15.19 E
+Fortaleza da Nogueirosa                43 23 29.12 N   8 08 09.12 W
+Fortaleza de San Paio de Narla         43 00 25.83 N   7 49 14 W
 Fort Boyard    Fort Boyard is a fort located between the île d'Aix and the île d'Oléron in the Pertuis d'Antioche straits, on the west coast of France.     45 59 58.71 N   1 12 50.16 W
 Fort de Bessoncourt            47 38 58.41 N   6 55 37.74 E
 Fort de la Miotte              47 38 53.29 N   6 52 30.33 E
-Fort de Vézelois              47 36 01.67 N   6 54 29.41 E
 Fort des Basses Perches                47 37 34.05 N   6 52 06.81 E
+Fort de Vézelois              47 36 01.67 N   6 54 29.41 E
 Fort du Bois d'Oye             47 34 27.7 N    6 50 36.55 E
-Fort Ross      Fort Ross, a former Russian fur trade outpost, located on the coast of Northern California (United States).     38 30 51.35 N   123 14 36.88 W
-Fortaleza da Nogueirosa                43 23 29.12 N   8 08 09.12 W
-Fortaleza de San Paio de Narla         43 00 25.83 N   7 49 14 W
 Forte di Gavi  Il Forte di Gavi è una fortezza storica costruita su un preesistente castello di origine medioevale.   44 41 27.95 N   8 48 15.55 E
 Fortezza del Priamar   La fortezza del Priamar è un antico insediamento storico presente nella città ligure di Savona, Italia.       44 18 16.29 N   8 29 03.44 E
-Forêt domaniale de Sète      The National Forest of Sète in the commune of Sète, Hérault, France. 43 24 18.74 N   3 40 13.74 E
+Fort Ross      Fort Ross, a former Russian fur trade outpost, located on the coast of Northern California.     38 30 51.35 N   123 14 36.88 W
 Fosse De Sessevalle            50 22 11.03 N   3 15 41.09 E
 Four solaire d'Odeillo The "Centre du Four Solaire Félix Trombe" is located in Odeillo, France.       42 29 37 N      2 01 45 E
+Fox Island (Alaska)    Kenai Peninsula, Alaska 59 54 46 N      149 20 52 W
 Francelos, Ribadavia           42 16 35.51 N   8 09 34.88 W
 Franciscan Monastery in Katowice Panewniki     Neo-Romanesque monastery of the Franciscans in Katowice Panewniki in Poland from the early XX century.  50 13 37 N      18 57 45 E
-Pfarrkirche St. Bartholomäus in Friesach              46 57 04.28 N   14 24 18.19 E
 Fubine Fubine è un comune in provincia di Alessandria, Piemonte, Italia.      44 57 55.35 N   8 25 32.75 E
 Funkturm Leipzig               51 18 49.02 N   12 23 34.93 E
-Fuzhou Fuzhou, also known as Foochow, is a city in China.      26 04 16 N      119 18 13 E
+Fuzhou         26 04 16 N      119 18 13 E
+Galata Bridge  Galata Bridge crosses the Golden Horn in Istanbul, Turkey       41 01 13.1 N    28 58 24.4 E
 Gandino                45 48 42 N      9 54 11 E
-Gardens of Nymphenburg Palace  Der Nymphenburger Schlosspark ist eines der größten und bedeutendsten Gartenkunstwerke Deutschlands.  48 09 29 N      11 30 13 E
+Gardens of Nymphenburg Palace  Der Nymphenburger Schlosspark ist eines der größten und bedeutendsten Gartenkunstwerke Deutschlands.  48 09 28 N      11 29 34 E
 Gare de Metz-Ville             49 06 35.28 N   6 10 39 E
-Gare de Paris-Est      Literally East Station, Paris, but usually called Gare de l'Est in Paris, France.       48 52 37 N      2 21 33 E
-Gare de Paris-Nord     Literally North Station, Paris, but usually called Gare du Nord in Paris, France.       48 52 58 N      2 21 24 E
+Gare de Paris-Est              48 52 36.84 N   2 21 33.12 E
+Gare de Paris-Nord             48 52 58 N      2 21 24 E
 Gare de Paris-Saint-Lazare     Gare Paris Saint-Lazare is one of the six large terminus railway stations of Paris.     48 52 37 N      2 19 28 E
-Garmischer Straße     The Garmischer Straße is a street in Munich, part of the Mittlerer Ring around the city centre.        48 07 28.03 N   11 31 14.51 E
+Garmischer Straße     The Garmischer Straße is a street in Munich, part of the Mittlerer Ring around the city centre.        48 07 28.2 N    11 31 14.52 E
 Garten des Himmlischen Friedens        The Garten des Himmlischen Friedens (lit. Garden of Heavenly Peace) is a small walled Chinese garden in the Bethmannpark in Frankfurt-Nordend   50 07 07.57 N   8 41 26.52 E
 Gavi   Gavi is a town in Piemonte in Italy.    44 41 19.35 N   8 48 10.64 E
 Gedankengang Offenbach This is part of a series of tunnels in Offenbach that have been redesigned.     50 05 58.64 N   8 45 49.92 E
-Georg-Brauchle-Ring    The Georg-Brauchle-Ring is a street in Munich.  48 10 34.46 N   11 32 35.48 E
 Gernikako Arbola       The Gernika oak where the lords of Biscay (including several kings of Castile and Spain) came to take the oath of respect to the basques Fueros (Rules and Rights).     43 18 53.43 N   2 40 47.92 W
 Giardino dei Semplici di Firenze       The Orto Botanico di Firenze (2.3 hectares), also known as the Giardino dei Semplici, is a botanical garden maintained by the University of Florence.   43 46 45 N      11 15 39 E
 Giurtelecu Șimleului  Giurtelecu Șimleului is a settlement in Romania.       47 18 N 22 48 E
 Glanum         43 46 26 N      4 49 57 E
+Godwin Glacier Chugach National Forest, Alaska 60 07 45 N      149 12 52 W
 Goethedenkmal (Wien)   The Goethe monument at the Opernring in Vienna by Edmund Hellmer        48 12 12.07 N   16 21 57.73 E
 Gogar Tram Depot               55 56 22.27 N   3 19 36.44 W
+Göltzschtalbrücke            50 37 21.29 N   12 14 37.46 E
+Goose Lake Park, Anchorage, Alaska             61 11 49 N      149 49 13 W
 Gorle          45 42 14 N      9 43 08 E
+Görzig (Rietz-Neuendorf)      Train station   52 14 20.25 N   14 11 48.91 E
 Government House, Jersey               49 11 41.44 N   2 05 39.78 W
 Gradara        Gradara is a town in Marche, Italy.     43 56 15.75 N   12 45 59.25 E
+Gråmanstorps kyrka            56 08 59.33 N   13 06 00.4 E
 Grand Hôtel de Cabourg                49 17 37.32 N   0 06 59.08 W
 Grand Palais   The Grand Palais in Paris, France       48 51 58 N      2 18 45 E
-Granollers     Granollers is a city near Barcelona, in Catalonia, Spain.       41 32 35.1 N    2 12 59.63 E
-Gromo  Gromo is a town in Lombardia in Italy.  45 58 09.91 N   9 55 25.72 E
-Gråmanstorps kyrka            56 08 59.33 N   13 06 00.4 E
+Gromo  Gromo is a town in Lombardia in Italy.  45 57 51.84 N   9 55 39 E
+Grouse Lake    Kenai Peninsula, Alaska 60 12 05 N      149 22 29 W
+Gulkana Glacier        Eastern Alaska Range, Alaska    63 14 26 N      145 28 03 W
 Gut Böckel    Böckel Castle in Rödinghausen, District of Herford, North Rhine-Westphalia, Germany.  52 13 29.1 N    8 31 02.98 E
 Gymnasium Koblenzer Straße    The Gymnasium Koblenzer Straße, also known as Kobi, is a German grammar school in Urdenbach, an urban borough of Düsseldorf.  51 08 58.67 N   6 53 08.95 E
-Göltzschtalbrücke            50 37 21.29 N   12 14 37.46 E
-Hamburg        Hamburg is a City-State in the North of Germany and one of the biggest seaports in Europe.      53 34 07 N      10 02 19 E
+Haage  Train station   52 40 37.61 N   12 35 48.46 E
 Hamburger Rathaus              53 33 01 N      9 59 32 E
+Hamburg        Hamburg is a City-State in the North of Germany and one of the biggest seaports in Europe.      53 34 07 N      10 02 19 E
+Hamburg-Moorburg Sprengung Kraftwerk   Bursting of the 256 meters high chimney of the deactivated HEW power plant in Hamburg-Moorburg, Germany. The chimney was Hamburg's highest massiv building. The HEW power plant Hamburg-Moorburg was in operation from 1974 untill 2001. It was one of the biggest conventional power plant in Germany and was fired on both with natural gas and fuel oil.     53 29 24 N      9 57 06 E
 Hameau de la Reine             48 49 07 N      2 06 46 E
-Hampigny               48 27 21 N      4 35 24 E
-Hansestaden Visby      The Hanseatic town Visby was founded in the 10th century, on the then independent Baltic Sea island of Gotland. 57 38 20 N      18 17 40 E
-Château d'Harcourt    The Château d'Harcourt is a castle located in the commune of Harcourt in the Eure département of France       49 10 26 N      0 47 11 E
+Hammer (Liebenwalde)   Former town hall        52 52 54.39 N   13 26 32.69 E
+Hansestaden Visby      The Hanseatic town Visby is the description of Visby, Sweden, from the UNESCO World Heritage Committee. 57 38 20 N      18 17 40 E
+Hans Paasche   Hans Paasche (3 April 1881 – 21 May 1920) was a German politician and pacifist.       52 59 48.32 N   15 58 47.1 E
+Harriman Fjord Chugach National Forest, Alaska 61 02 20 N      148 19 17 W
 Haus Werburg   Haus Werburg is a small water castle in Spenge, Kreis Herford.  52 08 30.78 N   8 28 33.66 E
 Hazmburk       Hazmburk is a hill with castle in České středohoří in Czech Republic.      50 26 03 N      14 00 52 E
-Heckenstallerstraße   The Heckenstallerstraße is a street in Munich, part of the Mittlerer Ring around the city centre.      48 06 35.77 N   11 31 42 E
+Heckenstallerstraße   The Heckenstallerstraße is a street in Munich, part of the Mittlerer Ring around the city centre.      48 06 35.64 N   11 31 41.88 E
 Hellig Kors Kirke      Hellig Kors Kirke is a church on Nørrebro in Copenhagen, Denmark.      55 41 15.72 N   12 33 05.04 E
 Henninger-Turm The 120-m-high Henninger Turm is located in Frankfurt-Sachsenhausen in Germany. 50 05 50.16 N   8 41 36.77 E
 Herford        Herford is a city in North Rhine-Westphalia, Germany.   52 06 57.81 N   8 40 12.11 E
 HMS Otus       The HMS Otus is a british Oberon class submarine. It serves today as a museum Sassnitz harbour. 54 30 43.13 N   13 38 29.79 E
-Holy Trinity Cathedral in Odessa               46 28 34.36 N   30 44 18.43 E
+Holgate Arm    Kenai Fjords National Park, Alaska      59 49 56 N      149 47 56 W
+Holy Trinity Cathedral in Odessa       Holy Trinity Cathedral in Odessa        46 28 33.96 N   30 44 17.16 E
+Hope Highway, Alaska   Kenai Peninsula, Alaska 60 46 50 N      149 25 50 W
 Hoppenlaufriedhof      The Hoppenlaufriedhof is a cemetery in Stuttgart.       48 46 54 N      9 10 05 E
 Horyuji        Hōryū-ji (法隆寺, "Temple of the Flourishing Law") is a Buddhist temple in Ikaruga, Nara Prefecture, Japan.        34 36 53.06 N   135 44 03.02 E
 Hospitalkirche (Stuttgart)             48 46 40 N      9 10 22 E
-Humprecht      Humprecht is a castle on top of a hill near Sobotka in the Hradec Králové region in the Czech Republic.       50 28 13 N      15 10 11 E
 Hôtel Biron           48 51 19 N      2 18 57 E
-Hôtel d'Ulmo          43 35 51 N      1 26 59.28 E
 Hôtel de Bourgtheroulde               49 26 31.2 N    1 05 17.77 E
 Hôtel de Sens         48 51 12 N      2 21 33 E
 Hôtel de Soubise              48 51 38 N      2 21 30 E
+Hôtel d'Ulmo          43 35 51 N      1 26 59.28 E
 Hôtel Lutetia         48 51 04 N      2 19 39 E
 Hôtel Négresco               43 41 40 N      7 15 27 E
-Igreja de São Martinho de Aldoar              41 10 14.58 N   8 40 13.83 W
+Hübners Mühle in Werder (Havel)      The fire ruin of the windmill of miller and baker named Hübner in Werder (Havel)       52 22 28.38 N   12 55 15.28 E
+Humprecht      Humprecht is a castle on top of a hill near Sobotka in the Hradec Králové region in the Czech Republic.       50 28 13.08 N   15 10 10.92 E
+Igreja de São Martinho de Aldoar              41 10 14.59 N   8 40 13.84 W
 Igrexa de San Pedro de Vilanova de Dozón      The romanic parochial Church of San Pedro of Dozón     42 35 06.77 N   8 01 27.02 W
-Igrexa de Santa María de Cambre               43 17 32.03 N   8 20 34.4 W
+Igrexa de Santa María de Cambre               43 17 31.92 N   8 20 34.08 W
 Igrexa de Santo Antolín de Toques             42 58 41.36 N   7 58 59.23 W
 Illa de Cortegada              42 37 05.87 N   8 47 02.7 W
 Iloilo City    The City of Iloilo is the capital city of the Provinces of the Philippines of Iloilo.   10 41 24 N      122 33 00 E
 Innerer Plauenscher Friedhof   Cemetery „Innerer Plauenscher Friedhof“ near church „Auferstehungskirche“ in Dresden-Plauen     51 01 42.38 N   13 42 15.91 E
 Institut de théologie orthodoxe Saint-Serge           48 52 59.98 N   2 23 01.23 E
-Isarring       The Isarring is a street in Munich, part of the Mittlerer Ring around the city centre.  48 09 36.65 N   11 36 03.89 E
-Isfahan اصفهان           32 39 05 N      51 40 45 E
+Isabel Pass    Richardson Highway, Alaska      63 11 15 N      145 33 28 W
+Isarring       The Isarring is a street in Munich, part of the Mittlerer Ring around the city centre.  48 09 36.72 N   11 36 03.96 E
 Isla San Carlos        Isla San Carlos or peninsula of San Carlos, is part of Venezuela and is located north of the island of Toas.    10 59 42.73 N   71 36 43.16 W
 Ivrea  Ivrea is a town in Piemonte in Italy.   45 27 50.4 N    7 52 42.96 E
 Jagdschloss Wermsdorf          51 16 59.52 N   12 56 21.85 E
 Jardin de l'État      The Jardin de l'État is a botanical garden on Réunion island. 20 53 12 S      55 27 04 E
 Jardin des Tuileries           48 51 50 N      2 19 34 E
-Jaroměř      Pond    50 21 22.45 N   15 55 17.21 E
+Jaroměř      Pond    50 21 21.6 N    15 55 15.6 E
 Jesuitenkirche (Wien)  The Jesuitenkirche (Jesuit church) is a prominent church in Vienna, Austria.    48 12 32.95 N   16 22 39.48 E
 Jin Mao Tower  Jin Mao Building        31 14 14 N      121 30 05 E
 Johannesburg   Johannesburg is the largest city in South Africa.       26 12 16 S      28 02 44 E
+José María Acuña López     José María Acuña López, born in Pontevedra (Spain) on April 4, 1903 and died on 4 June 1991 in Vigo (Spain), was a spanish sculptor.        42 19 46.38 N   8 34 04.43 W
 Jubiläumssäule               48 46 42.85 N   9 10 47.53 E
-Jumkils kyrka  Jumkils kyrka tillhör Bälingebygdens församling, Upplands västra kontrakt, Uppsala stift / Diocese of Uppsala.      59 56 33.2 N    17 25 23.7 E
 Jüdischer Friedhof Haunetal           50 45 12.6 N    9 41 00.6 E
+Jumkils kyrka  Jumkils kyrka tillhör Bälingebygdens församling, Upplands västra kontrakt, Uppsala stift / Diocese of Uppsala.      59 56 33.2 N    17 25 23.7 E
 Kaaba          21 25 21.11 N   39 49 34.41 E
 Kagawa prefecture      Kagawa Prefecture (香川県, Kagawa-ken?) is a prefecture of Japan located on Shikoku island. The capital is Takamatsu.        34 20 24.4 N    134 02 35.8 E
-Kansai International Airport   Kansai International Airport, is an international airport located on an artificial island in the middle of Osaka Bay, off the shore of Sennan district of Osaka, Japan. 34 26 03 N      135 13 58 E
+Kansai International Airport   Kansai International Airport is an international airport located on an artificial island in the middle of Osaka Bay, off the shore of Sennan district of Osaka, Japan.  34 26 03 N      135 13 58 E
 Karlsfried     Karlsfried Castle is situated nearby the town of Zittau in Sachsen, Germany.    50 50 05.05 N   14 47 32.29 E
 Katharinenhospital Stuttgart           48 48 01.87 N   9 12 21.6 E
-Kathmandu              27 43 00 N      85 22 00 E
+Kathmandu              27 43 12 N      85 22 12 E
 Kiel   Kiel is the capital city and most populous city of the northern German state Schleswig-Holstein.        54 19 31 N      10 08 26 E
 Kleinmarkthalle Frankfurt      Vegetable stall 50 06 45 N      8 41 01 E
 Klimkówka - stary dwór               49 35 18.78 N   21 49 50.14 E
 Kloster Ettal  The monastery of Ettal is a Benedictine monastery in Bavaria/Germany near Oberammergau. 47 34 09.33 N   11 05 40.42 E
+Korsberga kyrka, Småland              57 18 25.2 N    15 07 25.6 E
 Kotohira Gu    Kotohira Gu in Kotohira, Kagawa prefecture, Japan.      34 11 02.2 N    133 48 34 E
 Kreis Herford          52 06 57.54 N   8 39 40.42 E
 Kreis Minden-Lübbecke Der Kreis Minden-Lübbecke ist ein Landkreis im Osten des Landes Nordrhein-Westfalen mit Sitz in Minden.        52 16 53.48 N   8 54 41.71 E
@@ -429,32 +575,31 @@ Kriegerdenkmal in Arnsdorf (Ruhland)              51 25 48.02 N   13 51 05.5 E
 Kronprinzenpalais (Stuttgart)          48 46 41.56 N   9 10 39.88 E
 Krumbach (Schwaben)    Krumbach (Schwaben) ist eine Stadt im Landkreis Günzburg, Regierungsbezirk Schwaben, Bayern.   48 14 35 N      10 21 48 E
 Krummesse      Krummesse is a village in Schleswig-Holstein, Germany, which partly belongs to Kreis Herzogtum Lauenburg and partly to Lübeck. 53 46 45 N      10 38 30 E
-Kuala Lumpur           3 09 35 N       101 42 00 E
+Kuala Lumpur           3 08 52.08 N    101 41 43.08 E
 Kunsthalle Bremen              53 04 22 N      8 48 49 E
 Kuressaare             58 09 00 N      22 16 48 E
 Kusterdingen           48 31 20.28 N   9 07 15.24 E
 Lac Blanc (Orbey)      Dans le massif des Vosges, près d'Orbey.       48 07 31.32 N   7 05 34.95 E
-Lac Chambon            45 34 13 N      2 55 18 E
 Lac de Serre-Ponçon   Le Lac de Serre-Ponçon, vallé de l'Ubaye, Hautes-Alpes, France        44 30 33.26 N   6 22 10.8 E
-Lac des Dix            46 03 25.74 N   7 23 51.17 E
+Lake Louise, Alaska    Borough di Matanuska-Susitna, Alaska    62 19 26 N      146 32 56 W
 Lalín Lalín is a municipality in Galicia, Spain in the province of Pontevedra.       42 39 36.8 N    8 06 43.31 W
 Langes Tannen          53 41 32.67 N   9 40 28.6 E
-Large Hadron Collider  CERN collider near Geneva, Switzerland  46 16 17 N      6 03 48.5 E
+Large Hadron Collider          46 16 17 N      6 03 48.5 E
 Larouco        Larouco is a municipality in Galicia, in the province of Ourense.       42 20 48.74 N   7 09 37.22 W
 Lavoir de Gex          46 20 02.04 N   6 03 30.02 E
 Laza   Laza is a municipality in Galicia, in the province of Ourense.  42 03 36.68 N   7 27 37.14 W
+Learnard Glacier       Chugach National Forest, Alaska 60 48 44 N      148 42 55 W
+Leiro  Leiro is a municipality in Galicia, in the province of Ourense. 42 22 11.51 N   8 07 27.42 W
 Le Louxor              48 52 00 N      2 20 59 E
 Le Sauze-du-Lac        Le Sauze-du-Lac est un petit village de les Hautes-Alpes, prés du lac de Serre-Ponçon.        44 28 42.94 N   6 18 52.35 E
-Le Train Bleu          48 50 42 N      2 22 24 E
-Legnano        Legnano is a town in the north-west of Lombardy, situated on the flat lands of the Po Valley between Milan and Lake Maggiore.   45 35 48.84 N   8 54 32 E
-Leiro  Leiro is a municipality in Galicia, in the province of Ourense. 42 22 11.51 N   8 07 27.42 W
 Les Invalides          48 51 18 N      2 18 45 E
+Le Train Bleu          48 50 42 N      2 22 24 E
 Levanto        Levanto is a village in Liguria in Italy.       44 10 15.82 N   9 36 41.68 E
 Lighthouses at Cape Arkona     There are two lighthouses and one bearing tower at Cape Arkona. 54 40 47 N      13 25 57 E
-Ligne Aubagne - Fuveau         43 23 41.38 N   5 33 59.44 E
-Lima           12 05 36 S      77 02 48 W
-Loro Parque    Puerto de la Cruz, Tenerife, Canarias, España  28 24 30.18 N   16 33 51.25 W
-Loschwitzer Friedhof   Cemetery "Loschwitzer Friedhof" in Dresden-Loschwitz    51 02 46 N      13 49 18.98 E
+Lima   Lima    12 03 00 S      77 02 00 W
+Loro Parque            28 24 29.88 N   16 33 52.74 W
+Loschwitzer Friedhof   Cemetery „Loschwitzer Friedhof“ in Dresden-Loschwitz        51 02 46 N      13 49 18.98 E
+Lowell Point, Alaska   Kenai Peninsula, Alaska 60 04 18 N      149 26 37 W
 Luise-Kiesselbach-Platz        The Luise-Kiesselbach-Platz is a square in the southwest of Munich.     48 06 44.17 N   11 31 03.27 E
 Lunds domkyrka Lunds domkyrka or Lund Cathedral is the cathedral of Lund in Skåne in southern Sweden. 55 42 14.59 N   13 11 36.91 E
 LWL-Freilichtmuseum Detmold    The LWL-Freilichtmuseum Detmold (earlier name: Westfälisches Freilichtmuseum Detmold) is a museum for folklife studies in the town of Detmold, Germany.        51 55 25 N      8 52 12 E
@@ -468,7 +613,10 @@ Maisons de la rue Jeanne-Mance             45 30 31.9 N    73 34 11.02 W
 Manneken Pis van Brussel       Manneken Pis in Brussels        50 50 42 N      4 21 00 E
 Manufacture nationale de Sèvres               48 49 43 N      2 13 21 E
 Manzaneda      Manzaneda is a municipality in Galicia, in the province of Ourense.     42 18 35.33 N   7 13 58.01 W
+Margaret Eagan Sullivan Park, Anchorage, Alaska                61 12 31 N      149 55 16 W
+Marienkirche Witzwort          54 23 58.86 N   8 59 06.17 E
 Marín         42 23 31.28 N   8 42 16.58 W
+Mary's Tomb            31 46 48.5 N    35 14 21.41 E
 Maside Maside is a municipality in Galicia, in the province of Ourense.        42 24 44.75 N   8 01 31.85 W
 Matitone (Genova)      Il Matitone è un grattacielo di Genova dalla struttura a forma di lapis. È situato nella zona portuale di San Benigno, a breve distanza dalla torre della Lanterna.   44 24 40.59 N   8 54 25.07 E
 Matteus kyrka, Stockholm               59 20 43.08 N   18 02 32.94 E
@@ -476,110 +624,112 @@ Maximiliansbrücke in München          48 08 12.42 N   11 35 31.45 E
 Meaño Meaño is a municipality in Galicia, Spain in the province of Pontevedra.       42 26 31.95 N   8 46 46.02 W
 Meis   Meis is a municipality in Galicia, Spain in the province of Pontevedra. 42 30 49.01 N   8 41 27.14 W
 Melón Melón is a municipality in Galicia, in the province of Ourense.        42 15 26.97 N   8 13 01.51 W
+Mérida (Spain)                38 54 56.88 N   6 19 59.88 W
 Mii-dera       Mii-dera 三井寺, formally Onjōji 園城寺, is a Tendai Buddhist temple in the city of Otsu, Shiga Prefecture, Japan.       35 00 48.09 N   135 51 10.26 E
 Millennium Town Park   The Millennium Town Park is a public park in Saint Helier, Jersey.      49 11 15.01 N   2 06 06.95 W
-Minden Minden is a German city in North Rhine-Westphalia.      52 17 20.18 N   8 55 04.19 E
 Mindener Dom   Cathedral in Minden, District of Minden-Lübbecke, North Rhine-Westphalia, Germany.     52 17 19.85 N   8 55 09.94 E
 Mindener Kreisbahnen   Kreisbahnen Minden, ein Unternehmen aus dem 19. Jahrhundert, das in Abwandlungen noch heute besteht.    52 18 01.14 N   8 54 50.98 E
+Minden Minden is a German city in North Rhine-Westphalia.      52 17 20.18 N   8 55 04.19 E
 Mittagskogel   Mittagskogel is a peak in the Karawanken mountain chain in Carinthia / Austria / EU.    46 30 26.54 N   13 57 08.1 E
 Moaña Moaña is a municipality in Galicia, Spain in the province of Pontevedra.       42 17 05.52 N   8 44 57.56 W
 Moe, Victoria          38 10 20 S      146 16 04 E
+Möja kyrka            59 24 18.8 N    18 52 53 E
 Molino Stucky  Il Molino Stucky è uno storico edificio di Venezia. È un esempio di architettura industriale neogotica.       45 25 41.55 N   12 19 11.95 E
 Monastery of San Paio de Diomondi              42 36 13.6 N    7 42 34.1 W
 Monforte de Lemos              42 31 19.98 N   7 30 46.56 W
-Monte Amiata   Il Monte Amiata è un monte situato nella Toscana.      42 54 00 N      11 38 00 E
-Monte Musinè  el Monte Musinè es una cima de los Alpes Grayos, en Italia.    45 06 50 N      7 27 16 E
+Mońki Railway station 53 24 00 N      22 47 00 E
+Monte Amiata   Il Monte Amiata è un monte situato nella Toscana.      42 53 15.9 N    11 37 27.73 E
 Monterrei      Monterrei is a municipality in Galicia, in the province of Ourense.     41 56 51.19 N   7 26 58.52 W
-Montevideo             34 52 01 S      56 10 00 W
-Montmartre Cemetery    Montmartre Cemetery (Fr: Cimetière de Montmartre) is a famous cemetery located at 37 Avenue Samson, in the 18th arrondissement of Paris, France.       48 53 16 N      2 19 49 E
+Montevideo     Montevideo is the capital and largest city of Uruguay.  34 52 01 S      56 10 00 W
+Montmartre Cemetery    Montmartre Cemetery (Fr: Cimetière de Montmartre) is a famous cemetery located at 37 Avenue Samson, in the 18th arrondissement of Paris, France.       48 53 16.08 N   2 19 49.08 E
 Monument de Joseph Sec Monument Joseph Sec, 8 avenue Pasteur, Aix-en-Provence, France. 43 31 59.44 N   5 26 46.71 E
 Monument international de la Réformation              46 12 00.78 N   6 08 45.19 E
 Mos    Mos is a municipality in Galicia, Spain in the province of Pontevedra.  42 11 39.08 N   8 39 11.19 W
+Mössingen             48 24 23 N      9 03 27 E
 Mosteiro de San Clodio de Leiro                42 22 02.61 N   8 06 54.12 W
 Mosteiro de San Salvador de Celanova           42 09 06.55 N   7 57 24.85 W
 Mosteiro de Santa María de Aciveiro           42 37 03 N      8 18 06 W
-Mońki Railway station 53 24 00 N      22 47 00 E
+Mount Muir, Alaska     Chugach Mountains, Alaska       61 06 29 N      148 22 42 W
 Mugardos       Mugardos is a municipality in the province A Coruña, Galicia, Spain.   43 27 43.7 N    8 15 12.52 W
-Muntic Muntic is a village in Istria, Croatia. 44 55 00 N      13 56 00 E
-Murol          45 34 23 N      2 56 35 E
+Mühlen am Löbauer Wasser             51 12 02.21 N   14 39 21.09 E
 Muros          42 46 28.69 N   9 03 23.75 W
 Murray House           22 13 05.15 N   114 12 34.96 E
 Murviel-lès-Béziers          43 26 29 N      3 08 42 E
+Museo Archeologico Regionale Paolo Orsi        Archaeological Museum Paolo Orsi in Syracuse    37 04 34.36 N   15 17 10.89 E
 Museo Civico d'Arte Antica di Torino   Il Museo Civico d'Arte Antica è un polo museale situato a Torino presso Palazzo Madama.        45 04 15.95 N   7 41 07.72 E
 Museo della Storia del Genoa           44 24 37.8 N    8 56 11.39 E
 Museo Regionale della Fauna Alpina - Alpenfaunamuseum "Beck-Peccoz"    Un museo sulla fauna alpina situato a Gressoney-Saint-Jean, in Valle d'Aosta, Italia.   45 46 35.57 N   7 49 36.84 E
 Museum für Moderne Kunst      The Museum für Moderne Kunst (MMK) is an art museum in Frankfurt am Main.      50 06 42.56 N   8 41 03.86 E
-Mérida (Spain)                38 54 57 N      6 20 00 W
-Möja kyrka            59 24 18.8 N    18 52 53 E
-Mössingen             48 24 23 N      9 03 27 E
-Mühlen am Löbauer Wasser             51 12 02.21 N   14 39 21.09 E
 Narón Narón is a municipality in the province A Coruña, Galicia, Spain.     43 32 14.91 N   8 10 53.28 W
+Naturschutzgebiet „Königsbrücker Heide“          51 20 07.58 N   13 52 06.67 E
 Necrópole Megalítica da Lameira de Cima      Necrópole Megalítica da Lameira de Cima, freguesia de Antas, Penedono, Portugal.      40 56 09.92 N   7 20 57.52 W
 Neda   Neda is a municipality in the province A Coruña, Galicia, Spain.       43 29 58.68 N   8 09 21.51 W
-Nedroma                35 00 47.01 N   1 44 51.12 W
 Neues Rathaus München         48 08 16.07 N   11 34 33.35 E
 Neues Schloss, Stuttgart               48 46 41 N      9 10 55 E
 New Mosque in Istanbul New Mosque (Yeni Cami) in Istanbul      41 01 01.05 N   28 58 19.2 E
 Niujie Mosque  The Niujie Mosque (Chinese: 牛街清真寺; pinyin: niújiē qīngzhēnsì) is the oldest mosque in Beijing, China. It was built in 996 and completely rebuilt under the Kangxi Emperor (1622-1722).   39 53 04 N      116 21 29 E
 Nizza-Ufer     The Nizza bank is a park with mild microclimate at the Main river bank in Frankfurt am Main. The Park was constructed in 1860.  50 06 15.68 N   8 40 14.37 E
 Noorderplantsoen       The Noorderplantsoen is a park in the Dutch city of Groningen.  53 13 25 N      6 33 20 E
+Nordwestbahnhof, Vienna        Emergency quarters from Northwest Railway Wagon 13 46.81 N      16 22 58.91 E
+Nulbay Park, Anchorage, Alaska         61 12 57 N      149 54 36 W
 Nullamunjie Olive Grove, Victoria      Nullamunjie olive groves are situated in the mountains of eastern Victoria, Australia on the slopes of Mount Stawell and near the banks of the Tambo River.     37 11 05 S      147 43 58 E
 O Barco de Valdeorras          42 24 38.82 N   6 58 33.51 W
-O Bolo O Bolo is a municipality in Galicia, in the province of Ourense.        42 18 27.11 N   7 05 52.28 W
-O Carballiño          42 25 53.18 N   8 04 38.47 W
-O Grove                42 29 34.29 N   8 52 04.9 W
-O Pereiro de Aguiar    O Pereiro de Aguiar is a municipality in Galicia, in the province of Ourense.   42 20 47.83 N   7 48 06.62 W
-O Porriño     O Porriño is a municipality in Galicia, Spain in the province of Pontevedra.   42 09 41.84 N   8 37 15 W
-O Rosal        O Rosal is a municipality in Galicia, Spain in the province of Pontevedra.      41 56 07.3 N    8 50 05.63 W
-O Ézaro, Dumbría             42 54 38.2 N    9 07 54.12 W
 Obermillstatt          46 48 36.91 N   13 35 29.41 E
 Obervellach            46 55 55.76 N   13 12 06.68 E
+O Bolo O Bolo is a municipality in Galicia, in the province of Ourense.        42 18 27.11 N   7 05 52.28 W
+O Carballiño          42 25 53.18 N   8 04 38.47 W
 Ocean Park, Hong Kong          22 14 45.1 N    114 10 33.3 E
+O Ézaro, Dumbría             42 54 38.2 N    9 07 54.12 W
+O Grove                42 29 34.29 N   8 52 04.9 W
 Ohr Somayach Synagogue Ohr Somayach Synagogue, the main synagogue in Odessa, Ukraine   46 28 40.55 N   30 44 22.13 E
 Oia    Oia is a municipality in Galicia, Spain in the province of Pontevedra.  42 00 06.45 N   8 52 30.54 W
+Oímbra                41 53 07.94 N   7 28 19.78 W
 Oleiros        Oleiros is a municipality in the province A Coruña, Galicia, Spain.    43 19 57.16 N   8 18 54.38 W
 Oleiros, Ribeira               42 36 11.29 N   9 00 20.52 W
 Olgastraße (Stuttgart)                48 46 04.17 N   9 10 44.23 E
+O Pereiro de Aguiar    O Pereiro de Aguiar is a municipality in Galicia, in the province of Ourense.   42 20 47.83 N   7 48 06.62 W
+O Porriño     O Porriño is a municipality in Galicia, Spain in the province of Pontevedra.   42 09 41.84 N   8 37 15 W
 Oradour-sur-Glane      Oradour-sur-Glane was a village in the Limousin region of Vichy France that came under direct German control in 1942.   45 55 55 N      1 01 54 E
-Oran           35 41 49 N      0 37 59 W
 Orangerie (Neustrelitz)        Die Orangerie in Neustrelitz wurde bereits 1755 erbaut und erfuhr 1840 bis 1842 einen grundlegenden Umbau durch Friedrich Wilhelm Buttel.       53 21 40 N      13 03 27 E
 Organización Médica Colegial de España      Spanish Medical Colleges Organization   40 24 57.24 N   3 41 49.49 W
+O Rosal        O Rosal is a municipality in Galicia, Spain in the province of Pontevedra.      41 56 07.3 N    8 50 05.63 W
 Ortigueira     Ortigueira is a municipality in the province A Coruña, Galicia, Spain. 43 41 12.94 N   7 51 10.47 W
 Os Blancos     Os Blancos is a municipality in Galicia, in the province of Ourense.    41 59 50.61 N   7 45 12.34 W
 Ouaisné               49 10 45.75 N   2 11 10.77 W
 Oza-Cesuras    Oza-Cesuras, municipality in the province of A Coruña, in Galicia (Spain).     43 16 44.24 N   8 12 55.95 W
 Ozurgeti       Ozurgeti is a town and the regional administrative centre of Western Georgian province of Guria, former Macharadze or Makharadze.       41 55 26.26 N   42 00 33.84 E
-Oímbra                41 53 07.94 N   7 28 19.78 W
 Palace and park of Versailles          48 48 15.85 N   2 07 23.38 E
+Palácio de Estói             37 05 47.79 N   7 53 44.05 W
+Palácio Nacional da Pena              38 47 15.24 N   9 23 25.75 W
+Palácio Nacional de Mafra     O Palácio Nacional de Mafra é um palácio e mosteiro monumental de estilo neoclássico localizado em Mafra (Portugal) a poucos mais de 50 quilómetros de Lisboa.     38 56 12 N      9 19 35 W
 Palais Brongniart      The Palais Brongniart was the site of the Paris Stock Exchange until 1987.      48 52 09.01 N   2 20 26.98 E
 Palais de justice de Paris     Palais de Justice is a building complex on the Île-de-la-Cité in Paris. It was built on the site of the Palais de la Cité, the residence of the Kings of France until the 14th century.      48 51 20.6 N    2 20 42.18 E
 Palais de l'Élysée           48 52 13 N      2 18 59 E
-Palais des Papes       The Palais des Papes in Avignon, France was the residency of popes during the 14th and 15th century.       43 57 02 N 4 48 25 E   43.95068 N 4.80704 E  43.95068 4.80704
+Palais des Papes       The Palais des Papes in Avignon, France was the residency of popes during the 14th and 15th century.    43 57 02 N      4 48 25 E
+Palais ducal de Nevers The Palais Ducal in Nevers, France      46 59 18 N      3 09 30 E
 Palais du parlement de Bretagne                48 06 46.08 N   1 40 40.01 W
 Palais du parlement du Dauphiné               45 11 35.97 N   5 43 42.86 E
 Palais du Tau          49 15 11 N      4 02 04 E
-Palais ducal de Nevers The Palais Ducal in Nevers, France      46 59 18 N      3 09 30 E
 Palais Garnier The Palais Garnier, also known as Opéra Garnier or Opéra national de Paris is an opera house situated at the northern end of the avenue de l'Opera, in Paris. 48 52 19 N      2 19 54 E
-Palais Granvelle (Besançon)           47 14 08.52 N   6 01 35.76 E
 Palais Idéal          45 15 22.85 N   5 01 42.74 E
 Palais Longchamp               43 18 15.48 N   5 23 40.2 E
 Palais Royal           48 51 52.5 N    2 20 15.1 E
 Palmenhaus, Vienna     Vienna's Palmenhaus ('palm house', a Jugendstil greenhouse built in 1901) is a building in Vienna's 1st district, beneath 'Burggarten' and Hofburg.     48 12 18 N      16 22 01 E
-Palácio de Estói             37 05 47.79 N   7 53 44.05 W
-Palácio Nacional da Pena              38 47 15.24 N   9 23 25.75 W
-Palácio Nacional de Mafra     O Palácio Nacional de Mafra é um palácio e mosteiro monumental de estilo neoclássico localizado em Mafra (Portugal) a poucos mais de 50 quilómetros de Lisboa.     38 56 12 N      9 19 35 W
 Pamukkale      Pamukkale is a natural site and attraction and a UNESCO World Heritage Site in south-western Turkey.    37 55 25 N      29 07 24 E
 Panthéon de Paris             48 50 46 N      2 20 45 E
-Parc Astérix          48 27 21 N      4 35 24 E
+Parc Astérix          49 08 07.08 N   2 34 18.12 E
 Parc du Thabor         48 06 51 N      1 40 12 W
-Parc Monceau           48 52 45.84 N   2 18 33.23 E
+Parc Monceau   Parc Monceau is a public park situated in the 8th and 17th Arrondissements of Paris at the junction of Boulevard de Courcelles, Rue de Prony and Rue Georges Berger.    48 52 45.84 N   2 18 33.23 E
 Parc Natural del Delta de l'Ebre       Village 40 42 09 N      0 48 32 E
 Paris-Gare de Lyon             48 50 41 N      2 22 25 E
-Emin Pasha     Emin Pasha (born Eduard Schnitzer, 1840-1892) was a German explorer of Central Africa.  42 12 40.68 N   20 44 28.26 E
+Passage Canal, Alaska  Chugach National Forest, Alaska 60 48 53 N      148 31 28 W
+Penniman Glaciers      Chugach National Forest, Alaska 61 05 42 N      148 20 24 W
 Petit Palais   The Petit Palais is a palace in Paris, France built for the Universal Exhibition in 1900. It now houses the Musée des Beaux-Arts de la Ville de Paris (Paris Museum of Fine Arts).     48 51 57.72 N   2 18 52.39 E
 Petuelpark             48 10 39.64 N   11 34 45.32 E
 Petuelring     The Petuelring is a street in Munich, part of the Mittlerer Ring around the city centre.        48 10 40.25 N   11 34 19 E
 Petueltunnel   The Petueltunnel is a tunnel that runs beneath the Petuelring between the Boroughs Milbertshofen-Am Hart and Schwabing-West in Munich.  48 10 39.9 N    11 34 37.48 E
+Pfaffendorf (Rietz-Neuendorf)          52 15 57.79 N   14 09 46.25 E
+Pfarrkirche St. Bartholomäus in Friesach              46 57 04.28 N   14 24 18.19 E
 Phare de Chassiron             46 02 48.12 N   1 24 37.01 W
 Philadelphia City Hall Philadelphia City Hall is the seat of government for the city of Philadelphia, Pennsylvania.    39 57 08.28 N   75 09 48.96 W
 Piazza Corvetto (Genova)       Piazza Corvetto è una delle principali piazze di Genova        44 24 36.1 N    8 56 18.2 E
@@ -588,158 +738,182 @@ Piazza delle Erbe (Verona)              45 26 36.74 N   10 59 48.53 E
 Piazza Navona  Piazza Navona is a square in Parione, the VI. Rione (district) from Rome, Italy.        41 53 56.21 N   12 28 23.15 E
 Piazza Venezia Piazza Venezia is Located in Rome.      41 53 47 N      12 28 57 E
 Pieve di San Giorgio di Valpolicella   The Pieve di San Giorgio di Valpolicella is a particularly large and elaborate Pieve (ancient church) of the city of Sant'Ambrogio di Valpolicella, Italy.      45 32 07 N      10 51 00 E
-Piode  Piode è un comune della Valsesia, in provincia di Vercelli, Piemonte, Italia.  45 46 09.98 N   8 02 57.28 E
+Pigot Glacier  Chugach National Forest, Alaska 60 54 12 N      148 28 44 W
 Piñor Piñor is a municipality in Galicia, in the province of Ourense.        42 29 50.69 N   8 00 21.39 W
-Place de la Concorde   The Place de la Concorde is one of the major public squares in Paris, France.   48 51 56 N      2 19 16 E
+Piode  Piode è un comune della Valsesia, in provincia di Vercelli, Piemonte, Italia.  45 46 09.98 N   8 02 57.28 E
+Plaça Catalunya       Plaça Catalunya (or Plaza de Cataluña in spanish) is a large square in central Barcelona.     41 23 13.21 N   2 10 12.09 E
+Place de la Concorde   The Place de la Concorde is one of the major public squares in Paris, France.   48 51 56.16 N   2 19 15.96 E
 Place des Vosges       Place des Vosges in Paris, France       48 51 20 N      2 21 56 E
+Placer River Valley    Kenai Peninsula, Alaska 60 49 25 N      148 59 47 W
 Plaridel Airport               14 53 27.91 N   120 51 09.9 E
-Plaça Catalunya       Plaça Catalunya (or Plaza de Cataluña in spanish) is a large square in central Barcelona.     41 23 13.21 N   2 10 12.09 E
 Pont Ambroix   The Pont Ambroix was a Roman bridge across the Vidourle in Gallargues-le-Montueux, Gard department, and Villetelle, Hérault department, both Languedoc-Roussillon, France.     43 43 02 N      4 09 07 E
 Pont Camille-de-Hogues         46 48 49.12 N   0 32 15.32 E
 Pont de la Concorde            48 51 47.99 N   2 19 09.98 E
 Pont du Gard   The Pont du Gard is a Roman aqueduct bridge near Nîmes, France.        43 56 50.28 N   4 32 07.8 E
-Pont Flavien   The Pont Flavien is a Roman bridge in Saint-Chamas, Bouches-du-Rhône department, Provence-Alpes-Côte d'Azur, France.  43 32 29 N      5 02 35 E
-Pont Julien    The Pont Julien is a Roman bridge near Bonnieux, Vaucluse department, Provence-Alpes-Côte d’Azur, France.    43 51 45 N      5 18 28 E
-Pont Neuf              48 51 26.81 N   2 20 29.82 E
-Pont sur la Laye       Roadway 43 55 48 N      5 45 23 E
 Ponte de Rande The Rande Bridge is a cable-stayed bridge near Vigo, Galicia, Spain.    42 17 18.66 N   8 39 37.45 W
-Ponte Sant'Angelo (Rome)       The Ponte Sant'Angelo is a Roman bridge across the Tiber in Rome, Italy.        41 54 06.46 N   12 27 59.24 E
 Pontedeume             43 24 13.68 N   8 09 46.85 W
+Ponte Sant'Angelo (Rome)       The Ponte Sant'Angelo is a Roman bridge across the Tiber in Rome, Italy.        41 54 06.46 N   12 27 59.24 E
 Pontevedra             42 25 50.84 N   8 38 56.27 W
+Pont Flavien   The Pont Flavien is a Roman bridge in Saint-Chamas, Bouches-du-Rhône department, Provence-Alpes-Côte d'Azur, France.  43 32 29 N      5 02 35 E
+Pont Julien    The Pont Julien is a Roman bridge near Bonnieux, Vaucluse department, Provence-Alpes-Côte d’Azur, France.    43 51 45 N      5 18 28 E
+Pont Neuf              48 51 26.81 N   2 20 29.82 E
+Pont sur la Laye       The Pont sur la Laye is an old bridge across the Laye near Mane, Alpes-de-Haute-Provence department, Provence, France.  43 55 48 N      5 45 23.04 E
 Pordoi Pass    The Pordoi Pass is an Alpine pass in the Dolomites.     46 29 19.33 N   11 48 52.54 E
-Port of Kobe   Port of Kobe in Kobe, Hyōgo Prefecture, Japan  34 40 39.17 N   135 13 36.97 E
 Porta Pia              41 54 33 N      12 30 04 E
 Porta san Sebastiano           41 52 25 N      12 30 07 E
 Porta Soprana (Genova) Porta Soprana a Genova. 44 24 19.76 N   8 56 05.6 E
 Porta Westfalica               52 14 22.66 N   8 55 14.31 E
 Porto antico di Genova         44 24 34.22 N   8 55 04.26 E
 Porto Azzurro          42 46 05.02 N   10 23 48.33 E
+Port of Kobe   Port of Kobe in Kobe, Hyōgo Prefecture, Japan  34 40 39.17 N   135 13 36.97 E
 Portor, Negreira               42 54 45.44 N   8 41 52.17 W
 Potemkin Stairs                46 29 18.75 N   30 44 31.18 E
+Potter Marsh Anchorage         61 04 39 N      149 49 37 W
 Praia de Cabanas               43 24 55.21 N   8 10 23.62 W
 Prinzenbau Stuttgart           48 46 38.55 N   9 10 40.96 E
 Promenade du Peyrou            43 36 40 N      3 52 15 E
 Prytanée national militaire           47 42 10.09 N   0 04 35.77 W
-Puerto de Navacerrada          40 47 19.04 N   4 00 13.23 W
+Puerto de Navacerrada  El puerto de Navacerrada es un puerto de montaña a 1858 msnm de altitud, que alberga una estación de esquí y que está situado en la sierra de Guadarrama (Sistema Central). 40 47 19.04 N   4 00 13.23 W
 Puits Arthur-de-Buyer          47 40 37.23 N   6 36 51.29 E
 Punta Manara   Manara Bivouac  44 15 19.08 N   9 24 20.88 E
 Punxín        Punxín is a municipality in Galicia, in the province of Ourense.       42 22 06.15 N   8 00 03.16 W
 Quartier de Beaugrenelle               48 51 03.87 N   2 17 07.61 E
+Radweg Arnsdorf-Guteborn               51 25 49.66 N   13 53 18.08 E
+Rainy Glacier  Chugach National Forest, Alaska 60 38 39 N      148 32 37 W
 Rairiz de Veiga                42 04 57.65 N   7 49 56.92 W
 Ravensberger Bahn      Die Ravensberger Bahn ist eine Eisenbahnstrecke von Bielefeld nach Rahden.      52 13 36.48 N   8 31 20.75 E
 Regattastrecke Oberschleißheim        Die Regattastrecke Oberschleißheim ist ein künstlicher, rechteckiger Grundwassersee im Norden von München, angelegt für die Olympischen Sommerspiele 1972.  48 14 33.67 N   11 30 54.38 E
 Reggia di Caserta      La Reggia di Caserta, Palazzo Reale, è stata la dimora della dinastia dei Borboni, sovrani del Regno delle due Sicilie. È situata a Caserta, in Campania (Italia).    41 04 26.27 N   14 19 36.92 E
 Reservoir in Stara Morawa      Reservoir in Stara Morawa near Stronie Śląskie (Lower Silesian Voivodeship, Poland)   50 16 31.15 N   16 52 47.84 E
+Resurrection Peninsula Kenai Peninsula, Alaska 59 56 53 N      149 16 41 W
 Rianxo Rianxo is a port town in Galicia, Spain, in the province of A Coruña.  42 38 38.62 N   8 48 44.67 W
 Ribadavia              42 17 13.06 N   8 08 34.54 W
 Ribadumia      Ribadumia is a municipality in Galicia, Spain in the province of Pontevedra.    42 30 50.38 N   8 45 25.68 W
-Ribeira        Ribeira is a municipality in the province A Coruña, Galicia, Spain.    42 32 38.31 N   9 00 06.92 W
 Ribeira, Ribeira               42 33 16.32 N   8 59 27.37 W
+Ribeira        Ribeira is a municipality in the province A Coruña, Galicia, Spain.    42 32 38.31 N   9 00 06.92 W
 Ricetto di Candelo             45 32 46.68 N   8 06 48.96 E
 Rio Marina     Rio Marina is a village in Isola d'Elba Toscana in Italy        42 48 44.2 N    10 25 39.87 E
-Risiera di San Sabba   La Risiera di San Sabba è stato un campo di concentramento nazista, attivo negli ultimi anni della seconda guerra mondiale a Trieste, Italia.  45 37 26.09 N   13 47 22.1 E
 Riós  Riós is a municipality in Galicia, in the province of Ourense. 41 58 29.53 N   7 16 55.68 W
+Río Tambre            42 54 20.32 N   8 41 43.21 W
+Risiera di San Sabba   La Risiera di San Sabba è stato un campo di concentramento nazista, attivo negli ultimi anni della seconda guerra mondiale a Trieste, Italia.  45 37 26.09 N   13 47 22.1 E
 Robben Island  Robben Island, Cape Town, South Africa  33 48 24.24 S   18 21 58.4 E
 Rocca Grimalda Rocca Grimalda è un comune dell'Alto Monferrato, in provincia di Alessandria, Piemonte, Italia.        44 40 17.48 N   8 38 55.11 E
 Rodeiro        Rodeiro is a municipality in Galicia, Spain in the province of Pontevedra.      42 39 00.44 N   7 56 59.94 W
 Roman Bridge (Saint-Thibéry)  Old mill nearby 43 23 34.39 N   3 25 58.21 E
 Roman Bridge (Vaison-la-Romaine)       The Roman Bridge at Vaison-la-Romaine is a bridge across the Ouvèze in the Vaucluse department, Provence, France.      44 14 20.3 N    5 04 28.7 E
 Roman Theatre of Catania               37 30 10.4 N    15 05 00.9 E
-Roujan         43 30 32.5 N    3 17 15.15 E
-Río Tambre            42 54 20.32 N   8 41 43.21 W
+Roujan Roujan is a commune of the Hérault département in the Region of Languedoc-Roussillon - France.        43 30 32.5 N    3 17 15.15 E
+Rudyerd Bay    Borough di Ketchikan Gateway, Alaska    55 35 23 N      130 44 45 W
+Ruhlsdorf (Teltow)     Former town hall        52 22 28.71 N   13 16 04.56 E
+Russian Jack Springs Park, Anchorage, Alaska           61 12 21 N      149 47 18 W
 Sacrario Militare di Redipuglia                45 51 05.58 N   13 29 22.49 E
 Sada   Sada is a municipality in the province A Coruña, Galicia, Spain.       43 21 01.43 N   8 15 16.23 W
-Safranbolu     Safranbolu is a city and World Heritage site of Karabük Province, Turkey.      41 14 41 N      32 41 37 E
-Sagrada Família               41 24 12.82 N   2 10 27.64 E
-Église Saint-Gervais-Saint-Protais            48 51 19.8 N    2 21 16.6 E
-Saint-Michel de Nahuze Prieuré du XIe siècle, situé sur la commune de Lagrasse (département de l'Aude), dont les ruines ont été inscrites comme monument historique      43 07 56.82 N   2 37 06.38 E
-Saint-Nazaire-de-Ladarez               43 30 37 N      3 04 36 E
+Safranbolu     Safranbolu is a city and district of Karabük Province, Turkey. 41 14 41 N      32 41 37 E
+Sagrada Família               41 24 13 N      2 10 27.05 E
 Sainte-Chapelle                48 51 20 N      2 20 41 E
-Château de Saissac    The Château de Saissac is a Cathar castle in the Saissac commune, Aude département of France. 43 21 25 N      2 10 04.7 E
-Salt Lake Temple       The Salt Lake Temple, the sixth temple built by the church overall, and the fourth operating temple, is the largest and best-known temple of The Church of Jesus Christ of Latter-day Saints.   40 46 14.45 N   111 53 31.18 W
+Saint-Michel de Nahuze Prieuré du XIe siècle, situé sur la commune de Lagrasse (département de l'Aude), dont les ruines ont été inscrites comme monument historique      43 07 56.82 N   2 37 06.38 E
+Saint-Nazaire-de-Ladarez       Saint-Nazaire-de-Ladarez is a commune of the Hérault département, France.     43 30 37 N      3 04 36 E
+Salt Lake Temple       The Salt Lake Temple, the sixth temple built by the church overall, and the fourth operating temple, is the largest and best-known temple of The Church of Jesus Christ of Latter-day Saints.   40 46 13.69 N   111 53 31.06 W
 San Amaro      San Amaro is a municipality in Galicia, in the province of Ourense.     42 22 20.07 N   8 04 23.65 W
 San Clodio, Leiro              42 22 02.61 N   8 06 54.12 W
 San Cristovo de Cea    San Cristovo de Cea is a municipality in Galicia, in the province of Ourense.   42 28 33.22 N   7 59 07.24 W
+Sandiás       Sandiás is a municipality in Galicia, in the province of Ourense.      42 06 38.53 N   7 45 28.41 W
 San Giorgio in Lemine  San Giorgio in Lemine is a church in the comune of Almenno San Salvatore, Bergamo, Lombardy, Italy      45 44 46 N      9 35 50 E
+Sankt Martini          53 04 30 N      8 48 15 E
 San Marco (Milan)              45 28 23.77 N   9 11 20 E
 San Sadurniño San Sadurniño is a municipality of Spain in the province of A Coruña, in the autonomous community of Galicia. 43 33 44.93 N   8 03 17.21 W
-Sandiás       Sandiás is a municipality in Galicia, in the province of Ourense.      42 06 38.53 N   7 45 28.41 W
-Sankt Martini          53 04 30 N      8 48 15 E
-Sant'Anastasia Sant'Anastasia è una chiesa di Roma.   41 53 17.6 N    12 29 03 E
 Santa Maria degli Scalzi (Venice)              45 26 29.4 N    12 19 19.56 E
 Santa Maria dei Servi (Padua)          45 24 16.56 N   11 52 32.63 E
+Sant'Anastasia Sant'Anastasia è una chiesa di Roma.   41 53 17.6 N    12 29 03 E
 Santiago de Chile      Santiago is the capital of Chile, it is also the country's industrial and commercial center.    33 27 00 S      70 40 00 W
 Sanxenxo               42 24 19.2 N    8 48 23.66 W
 Sarreaus               42 05 13.93 N   7 36 10.99 W
 Sarria         42 46 38.13 N   7 24 54.31 W
 Schallenberg           46 49 34 N      7 47 50 E
 Schenkendorfstraße    The Schenkendorfstraße is a street in Munich, part of the Mittlerer Ring around the city centre.       48 10 34.21 N   11 35 29.04 E
+Schenkenhorst (Stahnsdorf)     Former town hall        52 20 28.05 N   13 11 46.85 E
 Schloss Eutin  The Castle of Eutin is located in Eutin in Schleswig-Holstein.  54 08 15.75 N   10 37 13.22 E
 Schloss Hüffe Schloss Hüffe ist ein Ende des 13. Jahrhunderts errichtetes Wasserschloss in der Ortschaft Lashorst der Stadt Preußisch Oldendorf im Kreis Minden-Lübbecke.  52 20 05.99 N   8 30 55.72 E
 Schloss Kalkum Schloss Kalkum is a water castle in Kalkum in the north of Düsseldorf, about two kilometers northeast of Kaiserwerth.  51 18 14.9 N    6 45 26.7 E
+Schlosskirche (Neustrelitz)    Die Neustrelitzer Schlosskirche wurde durch Friedrich Wilhelm Buttel erbaut und ist dessen Hauptwerk in der Stadt.      53 21 35 N      13 03 32 E
 Schloss Nymphenburg    Nymphenburg Palace is a château in Munich.     48 09 29 N      11 30 13 E
 Schloss Petershagen    Das Schloss Petershagen in Petershagen ist ein Wasserschloss im Stil der Weserrenaissance.      52 22 46.16 N   8 58 18.62 E
-Schloss Rosenstein             48 48 15 N 9 11 30 E
-Schlosskirche (Neustrelitz)    Die Neustrelitzer Schlosskirche wurde durch Friedrich Wilhelm Buttel erbaut und ist dessen Hauptwerk in der Stadt.      53 21 35 N      13 03 32 E
 Schlossplatz Stuttgart         48 46 42.81 N   9 10 47.45 E
-Serres d'Auteuil       The Jardin des serres d'Auteuil is a botanical garden in the Bois de Boulogne, Paris 16th, located at 3 avenue de la Porte d'Auteuil and 1 avenue Gordon-Bennett.         48 50 49 N 2 15 8 E
+Schloss Rosenstein             48 48 26 N      9 11 22 E
+Schönfließ (Mühlenbecker Land)              52 39 23.04 N   13 20 21.84 E
+Serpentine Glacier     Chugach National Forest, Alaska 61 07 41 N      148 16 02 W
+Serres d'Auteuil       The Jardin des serres d'Auteuil is a botanical garden in the Bois de Boulogne, Paris 16th, located at 3 avenue de la Porte d'Auteuil and 1 avenue Gordon-Bennett.       48 50 49 N      2 15 8 E
 Sestri Levante Sestri Levante is a town in Liguria in Italy.   44 16 17.76 N   9 23 33 E
 Shokeda        Shokeda is a religious settlement in Israel, in north-west part of Negev, south to Sderot and east to the Gaza Strip.   31 25 19.56 N   34 31 28.2 E
-Sidi Okba              34 45 00 N      5 54 00 E
 Sigüeiro, A Barciela, Oroso           42 58 06.42 N   8 26 33.39 W
 Silleda                42 41 49.46 N   8 14 50.28 W
 Singapore      Singapore is a city state at the southern tip of peninsular Malaysia. It is an island approximately 40 by 20 km in size inhabited by more than five million people.     1 18 00 N       103 48 00 E
-Singapore Zoo          1 24 15.9 N     103 47 28.1 E
+Singapore Zoo  Singapore Zoo / Mandai Zoo      1 24 15.9 N     103 47 28.1 E
 Sistiana       Sistiana is a town near Trieste.        45 46 09.98 N   13 38 01.98 E
 Sistine Chapel The Sistine Chapel is located in the Vatican and is decorated with frescoes by Michelangelo.    41 54 11 N      12 27 16 E
+Site des missiles Plutons Bourogne-Meroux              47 34 54.94 N   6 54 17.69 E
+Sixmile Creek (Alaska) Kenai Peninsula, Alaska 60 54 18 N      149 25 36 W
 Sohland am Rotstein    Sohland am Rotstein is a municipality in Saxony, Germany.       51 07 00 N      14 47 00 E
 Sopron Sopron (pronounced "shop-ron"; German: Ödenburg) is a city in Hungary near the Austrian border.        47 41 12 N      16 34 49 E
 Spenge Spenge is a northrhine-westphalian town in the administrative district Kreis Herford.   52 08 33.29 N   8 28 59.9 E
 Spišský hrad The ruins of Spiš Castle are situated above the town of Spišské Podhradie and the village of Žehra in the Spiš region in eastern Slovakia. 48 59 58.5 N    20 46 03.3 E
-St. Jürgenskirche (Lilienthal)        The church of St. Jürgen is in the same named district of Lilienthal in the county of Osterholz in Lower Saxony, Germany.      53 10 36 N      8 48 29 E
-St. Maria in der Kupfergasse   St. Maria in der Kupfergasse is a baroque church in Cologne.    50 56 23.2 N    6 57 01.04 E
+Spreenhagen    Village Pub     52 20 28.62 N   13 52 50.12 E
+Sputendorf     Former town hall        52 20 20.99 N   13 13 11.05 E
+Stadium of Epidaurus           37 35 51.77 N   23 04 27.8 E
+Städtisches Lapidarium Stuttgart              48 46 03.36 N   9 10 04.58 E
 Stadtplatz (Steyr)             48 02 20.42 N   14 25 08.89 E
-Stalis         35 17 47.4 N    25 25 25.9 E
+Staffelde              52 43 47.5 N    12 59 23.57 E
+Stalis Stalis is a small resort village on the island of Crete thirty kilometers from the capital Heraklion, located on the north side of the island.  35 17 47.4 N    25 25 25.9 E
+State Bank of Indiana, Terre Haute branch              39 27 55 N      87 24 52.5 W
 Stefanskyrkan, Stockholm               59 20 51.38 N   18 03 16.7 E
 Steigfriedhof  The Steigfriedhof is a cemetery in the Stadtbezirk Bad Cannstatt in Stuttgart.  48 48 41.9 N    9 12 28.95 E
 Stift Göttweig        Göttweig Abbey is a Benedictine monastery in Lower Austria.    48 22 00.2 N    15 36 45.5 E
+St. Jürgenskirche (Lilienthal)        The church of St. Jürgen is in the same named district of Lilienthal in the county of Osterholz in Lower Saxony, Germany.      53 10 36 N      8 48 29 E
+St. Maria in der Kupfergasse   St. Maria in der Kupfergasse is a baroque church in Cologne.    50 56 23.2 N    6 57 01.04 E
 Stockholms stadshus            59 19 38.57 N   18 03 15.67 E
 Stockholms universitet Stockholm University, founded 1878, with about 37,000 students. 59 21 46.68 N   18 03 31.4 E
-Städtisches Lapidarium Stuttgart              48 46 03.36 N   9 10 04.58 E
-Sultanahmet Camii      The Sultan Ahmed Mosque (in Turkish Sultanahmet Camii, in English commonly called the Blue Mosque) is a mosque in Istanbul.     41 00 19.3 N    28 58 36.6 E
-Synchrotron Soleil             48 42 33 N      2 08 41 E
+St. Peter und Paul (Grettstadt)                49 59 06.21 N   10 18 44.87 E
 Süleymaniye camii     The Mosque of Suleiman I in Istanbul.   41 00 58.3 N    28 57 50 E
+Sultanahmet Camii      The Sultan Ahmed Mosque (in Turkish Sultanahmet Camii, in English commonly called the Blue Mosque) is a mosque in Istanbul.     41 00 19.39 N   28 58 36.57 E
+Synchrotron Soleil             48 42 33 N      2 08 41 E
 Tarancón      Tarancón village and municipality in the province of Cuenca, part of the autonomous community of Castile-La Mancha, Spain.     40 00 45.89 N   3 00 14.85 W
 Teixido, Cedeira               43 42 36.72 N   7 59 00.44 W
-Villa romana de Tejada The ancient roman villa of La Tejada is an archaeological site from II to V centuries in Quintanilla de la Cueza, Cervatos de la Cueza (Palencia, Spain).       40 58 36 N      4 48 25 W
 Templer Cemetery, Jerusalem    Jerusalem, German Colony, Emek Refaim street 39 31 45 47.46 N   35 13 08.68 E
 Texas State Capitol    The Texas State Capitol, located in Downtown Austin, Texas, is the fourth building to serve as the seat of Texas government.    30 16 29 N      97 44 26 W
-The Dormition Cathedral in Odessa              46 28 31.07 N   30 43 55.42 E
-The Spice Bazaar, Istanbul             41 01 00.7 N    28 58 15.13 E
 Théâtre municipal de Besançon               47 14 03.84 N   6 01 33.89 E
+The Dormition Cathedral in Odessa              46 28 30.98 N   30 43 54.89 E
+The Spice Bazaar, Istanbul             41 01 00.7 N    28 58 15.13 E
+Thunderbird Falls      Chugach Mountains, Alaska       61 26 31 N      149 21 28 W
 Tiberias               32 47 20.04 N   35 31 20.28 E
 Toblinger Knoten       The Toblinger Knoten is a mountain in the Sexten Dolomites in South Tyrol.      46 38 31 N      12 18 29 E
 Tomiño        Tomiño is a municipality in Galicia, Spain in the province of Pontevedra.      41 59 31.78 N   8 44 32.54 W
 Toosa  Toosa is a village in Punjab.   30 44 45.31 N   75 41 14.53 E
 Topkapı Sarayı       İznik tiles: camp of the Mount Arafat  41 00 45.7 N    28 59 03.25 E
-Torre de San Sadurniño                42 30 25 N      8 49 16 W
+Torre de San Sadurniño                42 30 36 N      8 49 12 W
 Torre de Vilanova dos Infantes         42 09 58.36 N   7 57 16.62 W
+Torreón dos Andrade           43 24 27.5 N    8 10 19.25 W
 Torres de Altamira             42 52 39.02 N   8 41 15.17 W
 Torres de Oeste                42 40 35.81 N   8 43 32.46 W
-Torreón dos Andrade           43 24 27.98 N   8 10 17.88 W
-Toshkent               41 18 00 N      69 16 00 E
+Tour de la Chaîne     The tour de la Chaîne (XIVth century) is, with the tour Saint-Nicolas and the tour de la Lanterne, one of the three towers located on the seafront of La Rochelle, and one of the two towers that is representative of the city old harbour.   46 09 21.24 N   1 09 15.52 W
+Tour de la Lanterne    The tour de la Lanterne (XVth century) is, with the tour Saint-Nicolas and the tour de la Chaîne, one of the three towers located on the seafront of La Rochelle. It was added to the historical monument list of France in 1879.      46 09 20.88 N   1 09 25.42 W
 Tour Eiffel            48 51 30 N      2 17 39 E
 Tour Goguin            46 59 03.84 N   3 09 19.91 E
+Tour Saint-Jacques     Saint-Jacques Tower is located in the IVe arrondissement of Paris. This gothic tower is all that remains of the former church of Saint-Jacques-de-la-Boucherie. 48 51 27.95 N   2 20 55.6 E
+Tour Saint-Nicolas             46 09 20.88 N   1 09 11.99 W
+Trail Glacier, Alaska  Kenai Peninsula, Alaska 60 33 14 N      148 54 32 W
 Transfiguration Cathedral in Odessa    Odessa Cathedral of God's Transfiguration       46 28 59.44 N   30 43 51.75 E
-Trappentreustraße     The Trappentreustraße is a street in Munich, part of the Mittlerer Ring around the city centre.        48 08 12.34 N   11 32 03.84 E
-Trappentreutunnel      The Trappentreutunnel is a tunnel that runs beneath the Trappentreustraße in the Borough Schwanthalerhöhe in Munich.  48 08 08.78 N   11 32 03.17 E
+Trappentreustraße     The Trappentreustraße is a street in Munich, part of the Mittlerer Ring around the city centre.        48 08 12.48 N   11 32 03.84 E
+Trappentreutunnel      The Trappentreutunnel is a tunnel that runs beneath the Trappentreustraße in the Borough Schwanthalerhöhe in Munich.  48 08 08.88 N   11 32 03.12 E
 Trastevere     Restaurant in Via della Lungaretta      41 53 22.54 N   12 28 12.76 E
 Travemünde    Travemünde is a part of Lübeck in Germany at the Baltic Sea.  53 58 00 N      10 52 00 E
+Třebechovice pod Orebem       Třebechovice pod Orebem is a town in Czech Republic in Hradec Králové Region 50 12 07 N      15 59 38 E
+Treskow-Platane        The Treskow-Platane is a old hybrid plane and natural monument in Berlin-Friedrichsfelde, so called in memorial of Johann Carl Sigismund von Treskow.   52 30 23.69 N   13 31 17.47 E
+Treuners Altstadtmodell        The Treuner brothers' Altstadtmodell is a scale model which shows the oldtown of Frankfurt am Main prior to the air-raid damages in 1943 and 1944. The ruin model shows the destroyed old town of Frankfurt in spring 1945.     50 06 35 N      8 40 57 E
 Trinitatisfriedhof, Dresden    Cemetery „Trinitatisfriedhof“ in Dresden-Johannstadt        51 03 15.08 N   13 46 20.93 E
 Twierdza Osowiec       Dry moat around the fort No 3   53 27 44 N      22 37 38 E
-Třebechovice pod Orebem       Třebechovice pod Orebem is a town in Czech Republic in Hradec Králové Region 50 12 07 N      15 59 38 E
 Uetersen               53 41 14 N      9 40 09 E
 Université Lille Nord de France               50 36 33.38 N   3 08 29.72 E
+University of Alaska Museum of the North       Fairbanks, Alaska       64 51 30 N      147 50 32 W
 Upper Darby, Pennsylvania              39 57 40.2 N    75 15 32.06 W
 Urgnano                45 35 50 N      9 41 42 E
 Valdoviño     Valdoviño is a municipality in the province A Coruña, Galicia, Spain. 43 36 32.23 N   8 08 30.84 W
@@ -750,9 +924,9 @@ Varigotti   Varigotti è una frazione del comune di Finale Ligure, in provincia di
 Verducido, Pontevedra          42 28 35.96 N   8 37 06.66 W
 Verín Verín is a municipality in Galicia, in the province of Ourense.        41 56 22.47 N   7 26 19.59 W
 Via dell'Amore (Cinque Terre)  The Via dell'Amore (=way of love) is a hiking path above the sea linking the villages of Riomaggiore and Manarola in the Cinque Terre (Liguria, Italia).        44 06 06.07 N   9 44 00.37 E
+Via Dolorosa signs     third fall of Jesus (not in the Gospels).       31 46 46.48 N   35 13 56.63 E
 Viana do Bolo          42 10 46.42 N   7 06 44.81 W
 Vieilles prisons d'Annecy      Ancient Jails or the Palais de l'Île of Annecy.        45 53 54.89 N   6 07 36.59 E
-Vigo   Vigo is a Spanish municipality and the largest city in Galicia. 42 14 00.05 N   8 42 37.59 W
 Vilagarcía de Arousa          42 35 33.08 N   8 46 36.13 W
 Vilamarín     Vilamarín is a municipality in Galicia, in the province of Ourense.    42 27 51.29 N   7 53 23.64 W
 Vilanova de Arousa     Vilanova de Arousa is a municipality in Galicia, Spain in the province of Pontevedra.   42 33 48.42 N   8 49 26.69 W
@@ -764,203 +938,81 @@ Vilassar de Mar  Vilassar de Mar is a village in the county of the Maresme, Catal
 Villa Berg             48 47 31.34 N   9 12 27.17 E
 Villa d'Este (Tivoli)  The Villa d'Este in Tivoli is a masterpiece of Italian architecture and garden design.  41 57 45 N      12 47 46 E
 Villa Ephrussi de Rothschild           43 41 48 N      7 19 42.5 E
-Villa Les Glycines               48 40 46 N 6 10 56 E
-Villa Majorelle                  48 41 8 N 6 9 50 E
-Villa Schneider        Villa Schneider è un palazzo storico di Biella (Piemonte, Italia), servito come quartier generale delle SS durante la seconda guerra mondiale. 45 33 49.52 N   8 03 04.87 E
 Village Vanguard       The Village Vanguard is a jazzclub in Greenwich Village (New York City).        40 44 09.64 N   74 00 05.81 W
+Villa Les Glycines     Villa Les Glycines (1902-1904)  48 40 46 N      6 10 56 E
+Villa Majorelle                48 41 8 N       6 9 50 E
+Villa romana de Tejada The ancient roman villa of La Tejada is an archaeological site from II to V centuries in Quintanilla de la Cueza, Cervatos de la Cueza (Palencia, Spain).       40 58 36 N      4 48 25 W
+Villa Schneider        Villa Schneider è un palazzo storico di Biella (Piemonte, Italia), servito come quartier generale delle SS durante la seconda guerra mondiale. 45 33 49.52 N   8 03 04.87 E
 Villeneuve-d'Ascq      Villeneuve-d'Ascq is a commune within Lille Metropolis, in northern France      50 37 24 N      3 08 42 E
 Walhalla, Victoria             37 56 37.43 S   146 27 02.75 E
 Walt Disney Concert Hall               34 03 19.36 N   118 14 59.61 W
 Wayside Cross Villenstraße, Bonn-Dottendorf           50 42 15.73 N   7 06 43.18 E
 Weckschnapp            50 56 57.48 N   6 57 55.5 E
+Westchester Lagoon, Anchorage, Alaska          61 12 16 N      149 54 58 W
 West Lake              30 15 00 N      120 09 00 E
 Whitemarsh Hall                40 04 42 N      75 07 44 W
 Wilhelmsstift Tübingen                48 31 16.19 N   9 03 18.53 E
 Woodlawn Cemetery (Bronx)      Gate on Jerome Avenue   40 53 30 N      73 52 12 W
-Xinzo de Limia Xinzo de Limia is a municipality in Galicia, in the province of Ourense.        42 03 36 N      7 43 19.87 W
 Xàbia Xàbia is a village in the province of Alicante.        38 47 21 N      0 09 47 E
+Xinzo de Limia Xinzo de Limia is a municipality in Galicia, in the province of Ourense.        42 03 36 N      7 43 19.87 W
 Yad Vashem             31 46 23.55 N   35 10 29.2 E
-Yao    Yao (八尾市, Yao-shi) is a city in Osaka, Japan.     34 37 36.9 N    135 36 03 E
+Yao    Yao (八尾市, Yao-shi)  is a city in Osaka, Japan.    34 37 36.9 N    135 36 03 E
 Zwehrenturm    The Zwehrenturm from 1330 is a remain of Kassel's medieval defensive wall.      51 18 49 N      9 29 54 E
-Äußerer Plauenscher Friedhof Cemetery „Äußerer Plauenscher Friedhof“ in Dresden-Plauen 51 01 11.89 N   13 42 26.03 E
-École centrale de Lille       École Centrale de Lille is a graduate engineering school located in campus Lille I within Université Lille Nord de France.    50 36 21.62 N   3 08 13.63 E
-Église de l'Assomption simultanée (La Petite-Pierre)         48 51 25.2 N    7 18 55.84 E
-Église de la Sainte-Trinité (Lauterbourg)            48 58 30.1 N    8 10 40.77 E
-Église de Saint-Lothain               46 49 27.84 N   5 38 30.12 E
-Église de Saint-Paul de Frontignan            43 26 50.47 N   3 45 18.66 E
-Église des Augustins (Ribeauvillé)           48 11 43.44 N   7 19 08.87 E
-Église des Jésuites (Molsheim)               48 32 25.3 N    7 29 45 E
-Église des Saints-Innocents (Blienschwiller)          48 20 25.8 N    7 25 06.17 E
-Église Notre-Dame (Guebwiller)                47 54 20.75 N   7 12 52.56 E
-Église Notre-Dame de la Dalbade               43 35 51.36 N   1 26 32.89 E
-Église Notre-Dame-de-l'Assomption (Bergheim)          48 12 18 N      7 21 53.28 E
-Église Notre-Dame-de-l'Assomption (Bernardswiller)            48 27 10.08 N   7 27 49.57 E
-Église Notre-Dame-de-l'Assomption (Monswiller)                48 45 17.61 N   7 22 39.66 E
-Église Notre-Dame-de-l'Assomption (Rosenwiller)               48 30 21.96 N   7 26 25.48 E
-Église Notre-Dame-de-l'Assomption (Rouffach)          47 57 24 N      7 18 02 E
-Église Notre-Dame-de-la-Nativité (Saverne)           48 44 28.32 N   7 21 50.36 E
-Église protestante (Balbronn)         48 35 05.28 N   7 26 15.97 E
-Église protestante (Baldenheim)               48 14 15 N      7 32 14.35 E
-Église protestante (Berg)             48 53 52.08 N   7 09 24.01 E
-Église protestante (Bischheim)                48 36 55.08 N   7 45 21.89 E
-Église protestante (Fouday)           48 25 17.76 N   7 11 12.95 E
-Église protestante (Harskirchen)              48 56 02.04 N   7 02 20.15 E
-Église protestante (Scharrachbergheim)                48 35 35.52 N   7 29 55.9 E
-Église protestante (Schiltigheim)             48 36 21.96 N   7 45 05.04 E
-Église protestante (Weiterswiller)            48 51 10.44 N   7 24 50.9 E
-Église protestante du Temple Neuf (Strasbourg)                48 35 00 N      7 44 54 E
-Église Saint-Eustache de Paris                48 51 48 N      2 20 42 E
-Église Saint-Laurent (Paris)          48 52 29.45 N   2 21 29.92 E
-Église Saint-Michel d'Ernolsheim-lès-Saverne Bells   48 47 27.85 N   7 22 47.57 E
-Église Saint-Nicolas-du-Chardonnet    St. Nicolas du Chardonnet is a church in the centre of Paris, France located in the 5th arrondissement. 48 50 57 N      2 21 01 E
-Église Saint-Pierre de Montmartre     Saint-Pierre de Montmartre is a church in Paris 48 53 12 N      2 20 31 E
-Église Saint-Pierre-de-Rhèdes                43 35 16.22 N   3 04 43.64 E
-Église Saint-Pierre-Saint-Paul de Rueil-Malmaison             48 52 35.4 N    2 10 53.15 E
-Église Saint-Sulpice          48 51 04 N      2 20 05 E
-Église Saint-Étienne-du-Mont Saint-Étienne-du-Mont church is located in Paris, nearby Panthéon.    48 50 47 N      2 20 52 E
-Église Sainte-Marie-Madeleine de Rennes-le-Château           42 55 41.05 N   2 15 45.69 E
-Église Saints-Pierre-et-Paul (Andlau)         48 23 16.3 N    7 24 54.3 E
-Église Saints-Pierre-et-Paul (Eguisheim)              48 02 32.28 N   7 18 21.2 E
-Église Saints-Pierre-et-Paul (Hohatzenheim)           48 42 44.64 N   7 36 59.11 E
-Église Saints-Pierre-et-Paul (Neuwiller-lès-Saverne)         48 49 25 N      7 24 20 E
-Église Saints-Pierre-et-Paul (Obernai)                48 27 47.88 N   7 28 54.48 E
-Église Saints-Pierre-et-Paul (Ottmarsheim)            47 47 13.2 N    7 30 25.2 E
-Église Saints-Pierre-et-Paul (Rosheim)                48 29 48 N      7 28 14 E
-Église Saints-Pierre-et-Paul (Sigolsheim)             48 08 04.2 N    7 18 03.1 E
-Église Saints-Pierre-et-Paul (Wissembourg)            49 02 14 N      7 56 30 E
-Église St Antoine de Padoue (Saverne) The cloister    48 44 29.4 N    7 21 40.82 E
-Église St Arbogast (Offenheim)                48 37 53.76 N   7 36 59.54 E
-Église St Barthélemy (Sarrewerden)           48 55 22.8 N    7 04 56.93 E
-Église St Benoît (Bergholtzzell)             47 55 51.34 N   7 13 54.48 E
-Église St Blaise (Valff)              48 25 12.36 N   7 31 06.96 E
-Église St Cyriaque (Altorf)           48 31 22.7 N    7 31 50 E
-Église St Gall (Niedermorschwihr)             48 05 57.84 N   7 16 26.47 E
-Église St Gall protestante (Domfessel)                48 57 06.48 N   7 09 07.56 E
-Église St Georges (Châtenois)                48 16 09.12 N   7 23 51 E
-Église St Georges (Sélestat)         48 15 36 N      7 27 24.12 E
-Église St Grégoire (Ribeauvillé)            48 11 49.2 N    7 19 00.41 E
-Église St Guillaume protestante (Strasbourg)          48 34 55.5 N    7 45 28 E
-Église St Hippolyte (Saint-Hippolyte)         48 14 01.68 N   7 22 04.01 E
-Église St Jacques-le-Majeur (Kuttolsheim)             48 38 37.32 N   7 31 41.34 E
-Église St Jacques-le-Majeur simultanée (Dettwiller)          48 45 12.6 N    7 27 56.77 E
-Église St Jacques-le-Majeur simultanée (Hunawihr)            48 10 42.24 N   7 18 38.02 E
-Église St Jean (Strasbourg)           48 35 04 N      7 44 25 E
-Église St Jean protestante (Wissembourg)              49 02 18.96 N   7 56 33.36 E
-Église St Jean-Baptiste (Saint-Jean-Saverne)          48 46 18.7 N    7 21 48.5 E
-Église St Jean-Baptiste (Surbourg)            48 54 34.2 N    7 50 50.28 E
-Église St Jean-Baptiste (Wattwiller)          47 50 07.72 N   7 10 37.27 E
-Église St Jean-Baptiste simultanée (Hohwiller)               48 45 12.78 N   7 27 56.77 E
-Église St Laurent (Dieffenbach-au-Val)                48 18 44.64 N   7 19 41.34 E
-Église St Laurent protestante (Dorlisheim)            48 31 30 N      7 29 13.99 E
-Église St Léger (Guebwiller)         47 54 42.1 N    7 12 33.75 E
-Église St Léger (Murbach)            47 55 24 N      7 09 29 E
-Église St Martin (Ammerschwihr)               48 07 37.92 N   7 16 54.01 E
-Église St Martin (Ebersheim)          48 18 14.04 N   7 30 14.08 E
-Église St Martin (Pfaffenheim)                47 59 05.28 N   7 17 08.59 E
-Église St Martin protestante (Barr)           48 24 33.84 N   7 26 51.47 E
-Église St Martin protestante (Westhoffen)             48 36 01.8 N    7 26 30.3 E
-Église St Maurice (Ebersmunster)              48 18 39.5 N    7 31 37 E
-Église St Maurice (Fegersheim)                48 29 23.64 N   7 40 50.27 E
-Église St Maurice (Orschwiller)               48 14 27.24 N   7 22 44.62 E
-Église St Maurice (Soultz-Haut-Rhin)          47 53 13.2 N    7 13 48.29 E
-Église St Maurice (Soultz-les-Bains)          48 34 17.4 N    7 29 09.35 E
-Église St Maurice (Willgottheim)              48 40 14.52 N   7 30 33.23 E
-Église St Michel (Reichshoffen)               48 55 54.84 N   7 39 52.02 E
-Église St Michel (Weyersheim)         48 43 06.24 N   7 48 07.96 E
-Église St Médard (Bœrsch)           48 28 40.44 N   7 26 24.4 E
-Église St Nicolas (Haguenau)          48 49 13 N      7 47 32 E
-Église St Nicolas (Neuve-Église)             48 19 50.88 N   7 18 48.24 E
-Église St Nicolas (Wingersheim)               48 43 18.84 N   7 38 08.02 E
-Église St Pantaléon (Gueberschwihr)          48 00 16.92 N   7 16 29.78 E
-Église St Paul protestante (Strasbourg)               48 35 11 N      7 45 35 E
-Église St Pierre "Dompeter" (Molsheim, Avolsheim)             48 33 24.12 N   7 30 19.59 E
-Église St Pierre le Jeune catholique (Strasbourg)             48 35 18.35 N   7 44 55.75 E
-Église St Pierre le Jeune protestante (Strasbourg)            48 35 08 N      7 44 47 E
-Église St Rémi (Itterswiller)                48 21 51.48 N   7 25 37.42 E
-Église St Sébastien (Soultzmatt)             47 57 37.08 N   7 14 15.36 E
-Église St Thomas protestante (Strasbourg)             48 34 47 N      7 44 44 E
-Église St Trophime (Eschau)           48 29 25.08 N   7 42 57.96 E
-Église St Ulrich (Altenstadt)         49 01 49.8 N    7 58 05.88 E
-Église St Ulrich (Wittersheim)                48 46 53.04 N   7 39 27.47 E
-Église St Étienne (Rosheim)          48 29 43.8 N    7 27 59.72 E
-Église St Étienne (Seltz)            48 53 37.32 N   8 06 28.44 E
-Église St Étienne simultanée (Wangen)               48 37 01.56 N   7 27 53.68 E
-Église Ste Anne (Turckheim)           48 05 15.72 N   7 16 41.12 E
-Église Ste Aurélie protestante (Strasbourg)          48 34 53 N      7 44 00 E
-Église Ste Colombe (Hattstatt)                48 00 44.28 N   7 18 06.01 E
-Église Ste Croix (Kaysersberg)        Lamentation of Christ   48 08 20.04 N   7 15 48.56 E
-Église Ste Croix (Rountzenheim)               48 49 08.76 N   8 00 26.39 E
-Église Ste Foy (Sélestat)            48 15 33.67 N   7 27 21.81 E
-Église Ste Lucie (Niederhergheim)             47 59 10.32 N   7 23 48.41 E
-Église Ste Madeleine (Strasbourg)             48 34 48 N      7 45 17 E
-Église Ste Marguerite (Geispolsheim)          48 30 50.4 N    7 38 36.06 E
-Église Ste Odile (Lapoutroie)         48 09 08.64 N   7 10 03.97 E
-Église Ste Odile (Wintzfelden)                47 58 32.88 N   7 11 49.92 E
-Église Ste Walburge (Walbourg)                48 53 05.51 N   7 47 21.97 E
-Églises St Pierre le Vieux (Strasbourg)               48 34 58 N      7 44 24 E
-Đình Bảng  Bảng Communal House (Đình Bảng in Vietnamese) is one of largest and finest village communal houses in Việt Nam. It is located in Đình Bảng commune, Từ Sơn district, Bắc Ninh province.        21 06 29.99 N   105 57 06.31 E
-Архангельск         64 33 00 N      40 32 00 E
-Астана           51 11 00 N      71 24 00 E
-Астрахань             46 20 00 N      48 01 00 E
-Барнаул         53 21 24 N      83 47 14 E
-Боровск Borovsk 55 12 27.19 N   36 29 05.05 E
-Душанбе         38 34 23 N      68 47 11 E
-Екатеринбург               59 57 00 N      30 19 00 E
-Москва           55 45 21 N      37 37 04 E
-Нижний Новгород          56 19 37 N      44 00 27 E
-Санкт-Петербург          59 57 00 N      30 19 00 E
-Северодвинск               64 34 00 N      39 51 00 E
-กรุงเทพมหานคร        Bangkok 13 45 00 N      100 31 00 E
+Архангельск         3 64 33 00 N    40 31 48 E
+Астана           1 51 07 48 N    71 25 48 E
+Астрахань             46 19 59.88 N   48 01 00.12 E
+Боровск         55 12 27.19 N   36 29 05.05 E
+Душанбе Dushanbe is the capital city of Tajikistan.     38 34 23.16 N   68 47 11.04 E
+Екатеринбург               56 49 59.88 N   60 34 59.88 E
+Москва           55 45 20.88 N   37 37 04.08 E
+Нижний Новгород          56 19 36.84 N   44 00 27 E
+Санкт-Петербург          59 57 00 N      30 19 12 E
 სვეტიცხოველი           41 50 31 N      44 43 16 E
 ჯვარი                41 30 06.84 N   44 26 24.72 E
-鹿児島市   Kagoshima(鹿児島市; -shi) is a city in Japan and the capital city of Kagoshima Prefecture.      31 35 48.5 N    130 33 25.7 E
-薩摩川内市        Satsumasendai is a city in Kagoshima prefecture, Japan. 31 48 48.5 N    130 18 14.3 E
-上海 Shanghai is the largest city in China and is divided into 18 districts and one county (the island in the Yangtze River). It is located on the coast of eastern China at the mouth of the Chang Jiang (Yangtze River), and borders the provinces of Jiangsu and Zhejiang.        31 10 00 N      121 28 00 E
-东平 Daqing River    35 54 30 N      116 18 00 E
+চট্টগ্রাম            22 19 12 N      91 49 12 E
+上海         1 31 10 12 N    121 28 12 E
 中南海      Zhongnanhai (Chinese: 中南海; pinyin: Zhōngnánhăi) is a complex of buildings in Beijing, China which serves as the central headquarters for the Communist Party of China and the government of the People's Republic of China.    39 54 41 N      116 22 50 E
 九寨沟      Jiuzhaigou Valley (Chinese: 九寨沟; pinyin: Jiǔzhàigōu; lit. "Nine Stockades Gully") is a nature reserve in Aba(阿坝) Tibetan and Qiang Autonomous District, northern Sichuan province, China.  33 09 34 N      103 52 40 E
 云南 Yunnan(云南) is a Chinese southwest border province, with the most varied nationalities in China. There are 52 nationalities of people living in Yunnan, out of 56 total throughout China.    25 03 00 N      101 52 00 E
-京都市      Kyoto is a city in Japan. It was the capital of Japan from 794 to 1869. 35 00 42 N      135 46 05 E
+京都市      Kyoto is a city in Japan. It was the capital of Japan from 794 to 1869. 35 00 42.12 N   135 46 05.16 E
 兵馬俑      Terracotta Army 34 23 05.7 N    109 16 23.1 E
 別府市      Beppu is a famous onsen city in Oita Prefecture on the island of Kyushu in Japan.       33 17 04.6 N    131 29 28.6 E
 北九州市   Kitakyūshū is a city in Fukuoka Prefecture on the island of Kyushu, Japan.    33 53 00.3 N    130 52 30.7 E
 北京动物园        beijing zoo lies west of Xizhimen and is the western part of the Beijing, China. It is one of the largest zoos in mainland china.       39 56 19 N      116 20 00 E
 北海公园   中文: 北海公园位于中国北京市城区的中偏北部,故宫和景山的西北侧,始建于辽代,是世界上现存建园时间最早的皇家宫苑。 39 55 28 N      116 22 59 E
-南京 Nanjing (南京) is the capital of Jiangsu Province of China. It was the Chinese capital from 1927-1949.        32 03 00 N      118 46 00 E
+南京 Nanjing (南京) is the capital of Jiangsu Province of China. It was the Chinese capital from 1927-1949.        32 03 00 N      118 46 00.12 E
 南法華寺   Minamihokke-ji is the Buddhist temple in Takatori, Nara prefecture, Japan.      34 25 35.1 N    135 48 35.5 E
-台南市              22 59 00 N      120 11 00 E
-名古屋市           35 07 00 N      136 56 00 E
-和歌山市   Wakayama (和歌山市, Wakayama-shi) is the capital city of Wakayama Prefecture in the Kansai region of Japan. 34 13 49.3 N    135 10 14.7 E
+台南市              22 58 59.88 N   120 10 59.88 E
+和歌山市   Wakayama (和歌山市, Wakayama-shi)  is the capital city of Wakayama Prefecture in the Kansai region of Japan.        34 13 49.3 N    135 10 14.7 E
 哈尔滨      Harbin is a sub-provincial city in north-east China and the capital of the Heilongjiang Province.       45 48 05 N      126 31 45 E
-四川 Nature reserve in Aba(阿坝) Tibetan and Qiang Autonomous District, northern Sichuan province, China. It is known for its many multi-level waterfalls and colorful lakes, and was declared a UNESCO World Heritage Site in 1992.       30 08 00 N      102 56 00 E
+四川 Nature reserve in Aba(阿坝) Tibetan and Qiang Autonomous District, northern Sichuan province, China.  30 08 00 N      102 56 00 E
 圆明园      Yuanmingyuan (pinyin: Yuanmingyuan, 圆明园), or the old Summer Palace in Peking.     40 00 26 N      116 17 33 E
 大津市      Ōtsu is a city in Japan. It was the capital of Japan from 667 to 672.  35 01 04.1 N    135 51 17 E
-大阪市      Osaka   34 41 37.5 N    135 30 07.6 E
+大阪市              34 41 37.5 N    135 30 07.6 E
 天坛 Temple of Heaven in Beijing.    39 52 56.1 N    116 24 23.7 E
 天安門      Tiananmen (Gate of Heavenly Peace) in Beijing was the southern gate of the Imperial City in Beijing.    39 54 26.4 N    116 23 27.9 E
 天安门广场        Mausoleum of Mao Zedong 39 54 12 N      116 23 30 E
 宇治市      Uji is a city in Kyoto prefecture. The Byodoin (an ancient Buddhist temple) and the Ujigami Shrine are famous landmarks in Uji. 34 53 03.7 N    135 47 59.3 E
-小田原市   Odawara, Kanagawa       35 15 52.6 N    139 09 08 E
 屋久島      Yakushima island        30 20 00 N      130 30 00 E
 广东 Guangdong (广东) is a coastal province in southern China adjacent to Hongkong and Macao.      23 24 00 N      113 30 00 E
-广州 Guangzhou is the capital of Guangdong Province in southern China. The city was formerly known internationally as Canton City or simply Canton.  23 07 43.66 N   113 15 32.31 E
-広島市      Hiroshima is one of largest cities in Japan and the capital of Hiroshima prefecture.    34 23 06.9 N    132 27 19.1 E
+广州         23 07 43.66 N   113 15 32.31 E
+広島市      Hiroshima is one of largest cities in Japan and the capital of Hiroshima prefecture. During World War II, it was the first city in the world to have an atomic bomb dropped on it.      34 23 06.9 N    132 27 19.1 E
 徳島市      Tokushima is the capital city of Tokushima prefecture on the island of Kyushu in Japan. 34 04 13 N      134 33 17.8 E
-成都 Chengdu is the capital city and prefecture-level division of Sichuan Province, in southwestern China.   30 39 49 N      104 04 00 E
+成都 Chengdu is the capital city and prefecture-level division of Sichuan Province, in southwestern China.   30 39 48.96 N   104 04 00.12 E
 景山公园   Jingshan Park, Dongcheng District, Beijing.     39 55 24.5 N    116 23 26.2 E
-杭州 Hangzhou (杭州) is a picturesque city in south China. It is the capital of Zhejiang Province and was visited by Marco Polo.   30 15 00 N      120 10 00 E
-武汉 Wuhan is the capital of the Chinese province of Hubei   30 34 21 N      114 16 45 E
-深圳 Shenzhen is a major city in Guangdong Province, China.  22 32 06 N      114 03 14.4 E
-滕王阁      The Pavilion of Prince Teng or Tengwang Pavilion is a building in the north west of the city of Nanchang, in Jiangxi province, China.   28 41 02.76 N   115 52 32.88 E
+杭州         30 15 00 N      120 10 03 E
+武汉 Wuhan is the capital of the Chinese province of Hubei   30 35 13.92 N   114 17 17.16 E
+滕王阁              28 41 02.76 N   115 52 32.88 E
 相模原市   Sagamihara, Kanagawa    35 34 17.1 N    139 22 23.3 E
 祇園 Gion (祇園) is a district of Kyoto, Japan, originally developed in the middle ages.   35 00 13 N      135 46 30 E
 福岡市      Fukuoka, Fukuoka        33 35 24.5 N    130 24 06.2 E
+福建 Lu You Statue in Ningde中文(简体)‎: 宁德的陆游雕像     25 54 00 N      118 18 00 E
 紫禁城      The Forbidden City (紫禁城), located at the centre of Beijing, China, was the imperial palace of the last two imperial dynasties of China (from 1420 to 1924).       39 54 50.1 N    116 23 27.6 E
-西安 Xi'an is an ancient city located in north central China. It was the capital of various dynasties from 1046 B.C. to 907 A.D, and it has been known under a number of different names including most notably Chang'an during the Tang dynasty.    34 16 00 N      108 57 00 E
+薩摩川内市        Satsumasendai is a city in Kagoshima prefecture, Japan. 31 48 48.5 N    130 18 14.3 E
+西安 Xi'an is an ancient city located in north central China. It was the capital of various dynasties from 1046 B.C. to 907 A.D, and it has been known under a number of different names including most notably Chang'an during the Tang dynasty. Today it is the capital of Shaanxi province.       34 16 00.12 N   108 54 00 E
 逗子市      Zushi (逗子市 Zushi-shi) is a city located in Kanagawa, Japan.       35 17 44.2 N    139 34 49.2 E
-重庆 Chongqing is located in the southwest of China, is China's largest and most populous municipality.      29 33 00 N      106 33 00 E
-鎌倉 Zeniarai Benten shrine  35 19 09.3 N    139 32 48.1 E
+重庆 Chongqing is located in the southwest of China, is China's largest and most populous municipality.      29 33 00 N      106 30 24.84 E
 颐和园      The Summer Palace is a former imperial palace in northwest of Beijing, China. It has been transformed in a public garden.       39 59 51 N      116 16 08.04 E
-香港         22 16 01 N      114 11 17 E
-高雄市      Kaohsiung is a city in Taiwan.  22 38 00 N      120 16 00 E
-서울특별시        Seoul is the capital of South Korea.    37 35 00 N      127 00 00 E
+香港         22 16 48 N      114 09 36 E
+高雄市      Kaohsiung is a city in Taiwan.  22 37 00.01 N   120 18 00 E
+鹿児島市   Kagoshima(鹿児島市; -shi) is a city in Japan and the capital city of Kagoshima Prefecture.      31 35 48.12 N   130 33 25.92 E
index d4490512d8599bd80688081208bc73c8f0cc0796..b737bd2671cb98d22efe0e63d0742dd15c682915 100644 (file)
@@ -1,24 +1,11 @@
 package tim.prune.function.settings;
 
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.FlowLayout;
-import java.awt.GridLayout;
 import java.awt.Rectangle;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Properties;
 
-import javax.swing.BorderFactory;
-import javax.swing.JButton;
-import javax.swing.JDialog;
 import javax.swing.JFileChooser;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
 
 import tim.prune.App;
 import tim.prune.GenericFunction;
@@ -30,8 +17,6 @@ import tim.prune.config.Config;
  */
 public class SaveConfig extends GenericFunction
 {
-       private JDialog _dialog = null;
-
        /**
         * Constructor
         * @param inApp application object for callback
@@ -50,86 +35,6 @@ public class SaveConfig extends GenericFunction
         * Begin the function
         */
        public void begin()
-       {
-               // Make new dialog window (don't reuse it)
-               _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
-               _dialog.setLocationRelativeTo(_parentFrame);
-               _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
-               _dialog.getContentPane().add(makeDialogComponents());
-               _dialog.pack();
-               _dialog.setVisible(true);
-       }
-
-
-       /**
-        * Create dialog components
-        * @return Panel containing all gui elements in dialog
-        */
-       private Component makeDialogComponents()
-       {
-               JPanel dialogPanel = new JPanel();
-               dialogPanel.setLayout(new BorderLayout());
-               dialogPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 15));
-               JLabel descLabel = new JLabel(I18nManager.getText("dialog.saveconfig.desc"));
-               dialogPanel.add(descLabel, BorderLayout.NORTH);
-
-               // Grid panel in centre
-               JPanel mainPanel = new JPanel();
-               mainPanel.setLayout(new GridLayout(0, 2, 15, 2));
-               mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
-               Properties conf = Config.getAllConfig();
-               Enumeration<Object> keys = conf.keys();
-               while (keys.hasMoreElements())
-               {
-                       String key = keys.nextElement().toString();
-                       String keyLabel = I18nManager.getText("dialog.saveconfig." + key);
-                       if (!keyLabel.equals("dialog.saveconfig." + key))
-                       {
-                               mainPanel.add(new JLabel(keyLabel));
-                               String val = conf.getProperty(key);
-                               String tipText = val;
-                               if (Config.isKeyBoolean(key)) {
-                                       val = Config.getConfigBoolean(key)?I18nManager.getText("dialog.about.yes"):I18nManager.getText("dialog.about.no");
-                               }
-                               else if (val != null && val.length() > 30) {
-                                       val = val.substring(0, 30) + " ...";
-                               }
-                               JLabel label = new JLabel(val);
-                               label.setToolTipText(tipText);
-                               mainPanel.add(label);
-                       }
-               }
-               dialogPanel.add(mainPanel, BorderLayout.CENTER);
-
-               // button panel at bottom
-               JPanel buttonPanel = new JPanel();
-               buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
-               JButton okButton = new JButton(I18nManager.getText("button.ok"));
-               okButton.addActionListener(new ActionListener() {
-                       public void actionPerformed(ActionEvent e)
-                       {
-                               finish();
-                       }
-               });
-               buttonPanel.add(okButton);
-               JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
-               cancelButton.addActionListener(new ActionListener() {
-                       public void actionPerformed(ActionEvent e)
-                       {
-                               _dialog.dispose();
-                               _dialog = null;
-                       }
-               });
-               buttonPanel.add(cancelButton);
-               dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
-               return dialogPanel;
-       }
-
-
-       /**
-        * Finish the dialog when OK pressed
-        */
-       private void finish()
        {
                File configFile = Config.getConfigFile();
                if (configFile == null) {configFile = Config.HOME_CONFIG_FILE;}
@@ -141,8 +46,6 @@ public class SaveConfig extends GenericFunction
                        File saveFile = chooser.getSelectedFile();
                        saveConfig(saveFile);
                }
-               _dialog.dispose();
-               _dialog = null;
        }
 
        /**
@@ -153,6 +56,24 @@ public class SaveConfig extends GenericFunction
                saveConfig(Config.getConfigFile());
        }
 
+       /**
+        * Autosave has been turned on or off, so maybe need to save
+        * @param inSaveOn true if autosave was switched on
+        */
+       public void autosaveSwitched(boolean inSaveOn)
+       {
+               File configFile = Config.getConfigFile();
+               if (inSaveOn && configFile == null)
+               {
+                       begin();
+               }
+               else if (!inSaveOn && configFile != null)
+               {
+                       // TODO: Ask whether to save or not?
+                       silentSave();
+               }
+       }
+
        /**
         * Actually save the config file
         * @param inSaveFile file to save to
@@ -165,7 +86,6 @@ public class SaveConfig extends GenericFunction
                        + currBounds.width + "x" + currBounds.height;
                Config.setConfigString(Config.KEY_WINDOW_BOUNDS, windowBounds);
 
-               // TODO: Check for null inSaveFile, then just call finish() ?
                FileOutputStream outStream = null;
                try
                {
@@ -180,5 +100,7 @@ public class SaveConfig extends GenericFunction
                finally {
                        try {outStream.close();} catch (Exception e) {}
                }
+               // Remember where it was saved to
+               Config.setConfigFile(inSaveFile);
        }
 }
index 63286c5e86dcddce24736afe427a4bfc410bcb97..fd15a5097399cacd20ff8640954746889c045504 100644 (file)
@@ -93,8 +93,11 @@ public class SetDisplaySettings extends GenericFunction
        private JCheckBox _antialiasCheckbox = null;
        private JComboBox<Integer> _wpIconCombobox = null;
        private JRadioButton[] _sizeRadioButtons = null;
+       private JRadioButton[] _windowStyleRadios = null;
        private JButton _okButton = null;
 
+       private static final String STYLEKEY_NIMBUS = "javax.swing.plaf.nimbus.NimbusLookAndFeel";
+
 
        /**
         * Constructor
@@ -176,6 +179,25 @@ public class SetDisplaySettings extends GenericFunction
                waypointsPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
                midPanel.add(waypointsPanel);
 
+               // Panel for window style
+               JPanel windowStylePanel = new JPanel();
+               windowStylePanel.setBorder(BorderFactory.createCompoundBorder(
+                       BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(3, 3, 3, 3))
+               );
+               windowStylePanel.setLayout(new FlowLayout(FlowLayout.CENTER));
+               windowStylePanel.add(new JLabel(I18nManager.getText("dialog.displaysettings.windowstyle")));
+               windowStylePanel.add(Box.createHorizontalStrut(10));
+               ButtonGroup styleGroup = new ButtonGroup();
+               final String[] styleKeys = {"default", "nimbus"};
+               _windowStyleRadios = new JRadioButton[2];
+               for (int i=0; i<2; i++)
+               {
+                       _windowStyleRadios[i] = new JRadioButton(
+                               I18nManager.getText("dialog.displaysettings.windowstyle." + styleKeys[i]));
+                       styleGroup.add(_windowStyleRadios[i]);
+                       windowStylePanel.add(_windowStyleRadios[i]);
+               }
+               midPanel.add(windowStylePanel);
                mainPanel.add(midPanel, BorderLayout.CENTER);
 
                // button panel at bottom
@@ -221,6 +243,7 @@ public class SetDisplaySettings extends GenericFunction
                _antialiasCheckbox.setSelected(Config.getConfigBoolean(Config.KEY_ANTIALIAS));
                _wpIconCombobox.setSelectedIndex(Config.getConfigInt(Config.KEY_WAYPOINT_ICONS));
                selectIconSizeRadio(Config.getConfigInt(Config.KEY_WAYPOINT_ICON_SIZE));
+               selectWindowStyleRadio(Config.getConfigString(Config.KEY_WINDOW_STYLE));
                _dialog.setVisible(true);
        }
 
@@ -240,6 +263,20 @@ public class SetDisplaySettings extends GenericFunction
                }
        }
 
+       /**
+        * Select the corresponding radio button according to the selected style
+        * @param inValue style string saved in Config
+        */
+       private void selectWindowStyleRadio(String inValue)
+       {
+               int selectedRadio = 0;
+               if (inValue != null && inValue.equals(STYLEKEY_NIMBUS))
+               {
+                       selectedRadio = 1;
+               }
+               _windowStyleRadios[selectedRadio].setSelected(true);
+       }
+
        /**
         * @return numeric value of selected icon size according to radio buttons
         */
@@ -267,6 +304,8 @@ public class SetDisplaySettings extends GenericFunction
                Config.setConfigBoolean(Config.KEY_ANTIALIAS, _antialiasCheckbox.isSelected());
                Config.setConfigInt(Config.KEY_WAYPOINT_ICONS, _wpIconCombobox.getSelectedIndex());
                Config.setConfigInt(Config.KEY_WAYPOINT_ICON_SIZE, getSelectedIconSize());
+               final String styleString = (_windowStyleRadios[1].isSelected() ? STYLEKEY_NIMBUS : null);
+               Config.setConfigString(Config.KEY_WINDOW_STYLE, styleString);
                // refresh display
                UpdateMessageBroker.informSubscribers(DataSubscriber.MAPSERVER_CHANGED);
                _dialog.dispose();
index 642e71553834f97064416163ebad2b7ac37a1905..d6edd8b9b475086414eb1b604afd8adf72e20f55 100644 (file)
@@ -44,12 +44,11 @@ public class SetLanguage extends GenericFunction
        private static final String[] LANGUAGE_NAMES = {"afrikaans", "\u010de\u0161tina", "deutsch", "english", "american english",
                "espa\u00F1ol", "fran\u00E7ais", "italiano", "magyar", "nederlands", "polski", "portugu\u00EAs", "rom\u00E2n\u0103",
                "suomi", "\u0440\u0443\u0441\u0441\u043a\u0438\u0439 (russian)", "\u4e2d\u6587 (chinese)",
-               "\u65E5\u672C\u8A9E (japanese)", "\uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean)", "schwiizerd\u00FC\u00FCtsch",
-               "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430 \u043c\u043e\u0432\u0430 (ukrainian)"
+               "\u65E5\u672C\u8A9E (japanese)", "\uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean)", "schwiizerd\u00FC\u00FCtsch"
        };
        /** Associated language codes (must be in same order as names!) */
        private static final String[] LANGUAGE_CODES = {"af", "cz", "de", "en", "en_us", "es", "fr", "it", "hu",
-               "nl", "pl", "pt", "ro", "fi", "ru", "zh", "ja", "ko", "de_ch", "uk"
+               "nl", "pl", "pt", "ro", "fi", "ru", "zh", "ja", "ko", "de_ch"
        };
 
 
index a5d08711e61841fe21f8763b899870c2d7bd0ba0..e8faeb1e7cf407f95a725e144587a7bbf35cc995 100644 (file)
@@ -95,7 +95,7 @@ public class SetPathsFunction extends GenericFunction
                _installedLabels = new JLabel[NUM_KEYS];
                for (int i=0; i<NUM_KEYS; i++)
                {
-                       JLabel label = new JLabel(I18nManager.getText("dialog.saveconfig.prune." + LABEL_KEYS[i] + "path"));
+                       JLabel label = new JLabel(I18nManager.getText("dialog.paths.prune." + LABEL_KEYS[i] + "path"));
                        label.setHorizontalAlignment(SwingConstants.RIGHT);
                        mainPanel.add(label);
                        String configVal = Config.getConfigString(CONFIG_KEYS[i]);
@@ -167,4 +167,4 @@ public class SetPathsFunction extends GenericFunction
                }
                _dialog.dispose();
        }
-}
\ No newline at end of file
+}
index 6fec0754155f7cb667466234b19434229506633a..282dcb2267cbff2a2267dde65fe7458265b78932 100644 (file)
@@ -19,7 +19,7 @@ public class SplitSegmentsFunction extends DistanceTimeLimitFunction
         * Constructor
         */
        public SplitSegmentsFunction(App inApp) {
-               super(inApp);
+               super(inApp, false);
        }
 
        /**
index 15997448e038e6f4bb6e9f4b9437c99491b18a6e..c48af016b889f0df84a094de2df84db0db0ef272 100644 (file)
@@ -173,7 +173,7 @@ public class LookupSrtmFunction extends GenericFunction implements Runnable
                String errorMessage = null;
                // Get urls for each tile
                URL[] urls = TileFinder.getUrls(inTileList);
-               for (int t=0; t<inTileList.size() && !_progress.isCancelled(); t++)
+               for (int t=0; t<inTileList.size() && !_progress.isCancelled() && urls != null; t++)
                {
                        if (urls[t] != null)
                        {
@@ -209,54 +209,11 @@ public class LookupSrtmFunction extends GenericFunction implements Runnable
 
                                        if (entryOk)
                                        {
-                                               // Loop over all points in track, try to apply altitude from array
-                                               for (int p = 0; p < _track.getNumPoints(); p++)
-                                               {
-                                                       DataPoint point = _track.getPoint(p);
-                                                       if (!point.hasAltitude()
-                                                               || (inOverwriteZeros && point.getAltitude().getValue() == 0))
-                                                       {
-                                                               if (new SrtmTile(point).equals(tile))
-                                                               {
-                                                                       double x = (point.getLongitude().getDouble() - tile.getLongitude()) * 1200;
-                                                                       double y = 1201 - (point.getLatitude().getDouble() - tile.getLatitude()) * 1200;
-                                                                       int idx1 = ((int)y)*1201 + (int)x;
-                                                                       try
-                                                                       {
-                                                                               int[] fouralts = {heights[idx1], heights[idx1+1], heights[idx1-1201], heights[idx1-1200]};
-                                                                               int numVoids = (fouralts[0]==VOID_VAL?1:0) + (fouralts[1]==VOID_VAL?1:0)
-                                                                                       + (fouralts[2]==VOID_VAL?1:0) + (fouralts[3]==VOID_VAL?1:0);
-                                                                               // if (numVoids > 0) System.out.println(numVoids + " voids found");
-                                                                               double altitude = 0.0;
-                                                                               switch (numVoids)
-                                                                               {
-                                                                                       case 0: altitude = bilinearInterpolate(fouralts, x, y); break;
-                                                                                       case 1: altitude = bilinearInterpolate(fixVoid(fouralts), x, y); break;
-                                                                                       case 2:
-                                                                                       case 3: altitude = averageNonVoid(fouralts); break;
-                                                                                       default: altitude = VOID_VAL;
-                                                                               }
-                                                                               // Special case for terrain tracks, don't interpolate voids yet
-                                                                               if (!_normalTrack && numVoids > 0) {
-                                                                                       altitude = VOID_VAL;
-                                                                               }
-                                                                               if (altitude != VOID_VAL)
-                                                                               {
-                                                                                       point.setFieldValue(Field.ALTITUDE, ""+altitude, false);
-                                                                                       // depending on settings, this value may have been added as feet, we need to force metres
-                                                                                       point.getAltitude().reset(new Altitude((int)altitude, UnitSetLibrary.UNITS_METRES));
-                                                                                       numAltitudesFound++;
-                                                                               }
-                                                                       }
-                                                                       catch (ArrayIndexOutOfBoundsException obe) {
-                                                                               // System.err.println("lat=" + point.getLatitude().getDouble() + ", x=" + x + ", y=" + y + ", idx=" + idx1);
-                                                                       }
-                                                               }
-                                                       }
-                                               }
+                                               numAltitudesFound += applySrtmTileToWholeTrack(tile, heights, inOverwriteZeros);
                                        }
                                }
-                               catch (IOException ioe) {errorMessage = ioe.getClass().getName() + " - " + ioe.getMessage();
+                               catch (IOException ioe) {
+                                       errorMessage = ioe.getClass().getName() + " - " + ioe.getMessage();
                                }
                        }
                }
@@ -319,6 +276,65 @@ public class LookupSrtmFunction extends GenericFunction implements Runnable
                return new ZipInputStream(inUrl.openStream());
        }
 
+       /**
+        * Given the height data read in from file, apply the given tile to all points
+        * in the track with missing altitude
+        * @param inTile tile being applied
+        * @param inHeights height data read in from file
+        * @param inOverwriteZeros true to overwrite zero altitude values
+        * @return number of altitudes found
+        */
+       private int applySrtmTileToWholeTrack(SrtmTile inTile, int[] inHeights, boolean inOverwriteZeros)
+       {
+               int numAltitudesFound = 0;
+               // Loop over all points in track, try to apply altitude from array
+               for (int p = 0; p < _track.getNumPoints(); p++)
+               {
+                       DataPoint point = _track.getPoint(p);
+                       if (!point.hasAltitude()
+                               || (inOverwriteZeros && point.getAltitude().getValue() == 0))
+                       {
+                               if (new SrtmTile(point).equals(inTile))
+                               {
+                                       double x = (point.getLongitude().getDouble() - inTile.getLongitude()) * 1200;
+                                       double y = 1201 - (point.getLatitude().getDouble() - inTile.getLatitude()) * 1200;
+                                       int idx1 = ((int)y)*1201 + (int)x;
+                                       try
+                                       {
+                                               int[] fouralts = {inHeights[idx1], inHeights[idx1+1], inHeights[idx1-1201], inHeights[idx1-1200]};
+                                               int numVoids = (fouralts[0]==VOID_VAL?1:0) + (fouralts[1]==VOID_VAL?1:0)
+                                                       + (fouralts[2]==VOID_VAL?1:0) + (fouralts[3]==VOID_VAL?1:0);
+                                               // if (numVoids > 0) System.out.println(numVoids + " voids found");
+                                               double altitude = 0.0;
+                                               switch (numVoids)
+                                               {
+                                                       case 0: altitude = bilinearInterpolate(fouralts, x, y); break;
+                                                       case 1: altitude = bilinearInterpolate(fixVoid(fouralts), x, y); break;
+                                                       case 2:
+                                                       case 3: altitude = averageNonVoid(fouralts); break;
+                                                       default: altitude = VOID_VAL;
+                                               }
+                                               // Special case for terrain tracks, don't interpolate voids yet
+                                               if (!_normalTrack && numVoids > 0) {
+                                                       altitude = VOID_VAL;
+                                               }
+                                               if (altitude != VOID_VAL)
+                                               {
+                                                       point.setFieldValue(Field.ALTITUDE, ""+altitude, false);
+                                                       // depending on settings, this value may have been added as feet, we need to force metres
+                                                       point.getAltitude().reset(new Altitude((int)altitude, UnitSetLibrary.UNITS_METRES));
+                                                       numAltitudesFound++;
+                                               }
+                                       }
+                                       catch (ArrayIndexOutOfBoundsException obe) {
+                                               // System.err.println("lat=" + point.getLatitude().getDouble() + ", x=" + x + ", y=" + y + ", idx=" + idx1);
+                                       }
+                               }
+                       }
+               }
+               return numAltitudesFound;
+       }
+
        /**
         * Perform a bilinear interpolation on the given altitude array
         * @param inAltitudes array of four altitude values on corners of square (bl, br, tl, tr)
index 60a9479d1289faae0523e0fd7d025b56e816d37e..5ada68ca1b65e5428c3d6f961db1086e6b8086db 100644 (file)
@@ -30,6 +30,11 @@ public abstract class TileFinder
                URL[] urls = new URL[inTiles.size()];
                // Read dat file into array
                byte[] lookup = readDatFile();
+               if (lookup == null)
+               {
+                       System.err.println("Build error: resource srtmtiles.dat missing!");
+                       return null;
+               }
                for (int t=0; t<inTiles.size(); t++)
                {
                        SrtmTile tile = inTiles.get(t);
diff --git a/src/tim/prune/gui/CoordDisplay.java b/src/tim/prune/gui/CoordDisplay.java
new file mode 100644 (file)
index 0000000..45a749a
--- /dev/null
@@ -0,0 +1,58 @@
+package tim.prune.gui;
+
+import tim.prune.data.Coordinate;
+
+/**
+ * Functions for display of coordinates in gui
+ */
+public abstract class CoordDisplay
+{
+
+       /**
+        * Construct an appropriate coordinate label using the selected format
+        * @param inCoordinate coordinate
+        * @param inFormat selected display format
+        * @return language-sensitive string
+        */
+       public static String makeCoordinateLabel(Coordinate inCoordinate, int inFormat)
+       {
+               String coord = inCoordinate.output(inFormat);
+               // Fix broken degree signs (due to unicode mangling)
+               final char brokenDeg = 65533;
+               if (coord.indexOf(brokenDeg) >= 0)
+               {
+                       coord = coord.replaceAll(String.valueOf(brokenDeg), "\u00B0");
+               }
+               return restrictDP(coord);
+       }
+
+
+       /**
+        * Restrict the given coordinate to a limited number of decimal places for display
+        * @param inCoord coordinate string
+        * @return chopped string
+        */
+       private static String restrictDP(String inCoord)
+       {
+               final int DECIMAL_PLACES = 7;
+               if (inCoord == null) return "";
+               String result = inCoord;
+               final int dotPos = Math.max(inCoord.lastIndexOf('.'), inCoord.lastIndexOf(','));
+               if (dotPos >= 0)
+               {
+                       final int chopPos = dotPos + DECIMAL_PLACES;
+                       if (chopPos < (inCoord.length()-1))
+                       {
+                               result = inCoord.substring(0, chopPos);
+                               // Maybe there's an exponential in there too which needs to be appended
+                               int expPos = inCoord.toUpperCase().indexOf("E", chopPos);
+                               if (expPos > 0 && expPos < (inCoord.length()-1))
+                               {
+                                       result += inCoord.substring(expPos);
+                               }
+                       }
+               }
+               return result;
+       }
+
+}
index 2fa98dc9c0907d52e19489372c15eff227f5e37a..1b8148d5d925f43991901ea8f58c4673223bd80c 100644 (file)
@@ -306,6 +306,9 @@ public class DetailsDisplay extends GenericDisplay
                if (_timezone == null || (inUpdateType | UNITS_CHANGED) > 0) {
                        _timezone = TimezoneHelper.getSelectedTimezone();
                }
+               if ((inUpdateType | UNITS_CHANGED) > 0) {
+                       Config.setConfigString(Config.KEY_COORD_DISPLAY_FORMAT, "" + getSelectedCoordFormat());
+               }
 
                if (_track == null || currentPoint == null)
                {
@@ -327,8 +330,10 @@ public class DetailsDisplay extends GenericDisplay
                        _indexLabel.setText(LABEL_POINT_SELECTED
                                + (currentPointIndex+1) + " " + I18nManager.getText("details.index.of")
                                + " " + _track.getNumPoints());
-                       _latLabel.setText(makeCoordinateLabel(LABEL_POINT_LATITUDE, currentPoint.getLatitude(), _coordFormatDropdown.getSelectedIndex()));
-                       _longLabel.setText(makeCoordinateLabel(LABEL_POINT_LONGITUDE, currentPoint.getLongitude(), _coordFormatDropdown.getSelectedIndex()));
+                       _latLabel.setText(LABEL_POINT_LATITUDE
+                               + CoordDisplay.makeCoordinateLabel(currentPoint.getLatitude(), getSelectedCoordFormat()));
+                       _longLabel.setText(LABEL_POINT_LONGITUDE
+                               + CoordDisplay.makeCoordinateLabel(currentPoint.getLongitude(), getSelectedCoordFormat()));
                        Unit altUnit = Config.getUnitSet().getAltitudeUnit();
                        _altLabel.setText(currentPoint.hasAltitude()?
                                (LABEL_POINT_ALTITUDE + currentPoint.getAltitude().getValue(altUnit) + " " +
@@ -346,7 +351,8 @@ public class DetailsDisplay extends GenericDisplay
                        }
                        // Maybe the point has a description?
                        String pointDesc = currentPoint.getFieldValue(Field.DESCRIPTION);
-                       if (pointDesc == null || pointDesc.equals("") || currentPoint.hasMedia()) {
+                       if (pointDesc == null || pointDesc.equals("") || currentPoint.hasMedia())
+                       {
                                _descLabel.setText("");
                                _descLabel.setToolTipText("");
                        }
@@ -409,11 +415,13 @@ public class DetailsDisplay extends GenericDisplay
                                        filename = info.getName();
                                }
                        }
-                       if (filename != null) {
+                       if (filename != null)
+                       {
                                _filenameLabel.setText(LABEL_POINT_FILENAME + filename);
                                _filenameLabel.setToolTipText(filename);
                        }
-                       else {
+                       else
+                       {
                                _filenameLabel.setText("");
                                _filenameLabel.setToolTipText("");
                        }
@@ -442,7 +450,8 @@ public class DetailsDisplay extends GenericDisplay
                                _aveSpeedLabel.setText(I18nManager.getText("details.range.avespeed") + ": "
                                        + DisplayUtils.roundedNumber(selection.getMovingDistance()/numMovingSeconds*3600.0) + " " + speedUnitsStr);
                        }
-                       else {
+                       else
+                       {
                                _durationLabel.setText("");
                                _aveSpeedLabel.setText("");
                        }
@@ -502,7 +511,9 @@ public class DetailsDisplay extends GenericDisplay
                        _photoThumbnail.setVisible(true);
                        _photoThumbnail.setPhoto(currentPhoto);
                        _rotationButtons.setVisible(true);
-                       if ((inUpdateType & DataSubscriber.PHOTOS_MODIFIED) > 0) {_photoThumbnail.refresh();}
+                       if ((inUpdateType & DataSubscriber.PHOTOS_MODIFIED) > 0) {
+                               _photoThumbnail.refresh();
+                       }
                }
                _photoThumbnail.repaint();
 
@@ -538,63 +549,6 @@ public class DetailsDisplay extends GenericDisplay
        }
 
 
-       /**
-        * Construct an appropriate coordinate label using the selected format
-        * @param inPrefix prefix of label
-        * @param inCoordinate coordinate
-        * @param inFormat index of format selection dropdown
-        * @return language-sensitive string
-        */
-       private static String makeCoordinateLabel(String inPrefix, Coordinate inCoordinate, int inFormat)
-       {
-               String coord = null;
-               switch (inFormat) {
-                       case 1: // degminsec
-                               coord = inCoordinate.output(Coordinate.FORMAT_DEG_MIN_SEC); break;
-                       case 2: // degmin
-                               coord = inCoordinate.output(Coordinate.FORMAT_DEG_MIN); break;
-                       case 3: // degrees
-                               coord = inCoordinate.output(Coordinate.FORMAT_DEG); break;
-                       default: // just as it was
-                               coord = inCoordinate.output(Coordinate.FORMAT_NONE);
-               }
-               // Fix broken degree signs (due to unicode mangling)
-               final char brokenDeg = 65533;
-               if (coord.indexOf(brokenDeg) >= 0) {
-                       coord = coord.replaceAll(String.valueOf(brokenDeg), "\u00B0");
-               }
-               return inPrefix + restrictDP(coord);
-       }
-
-
-       /**
-        * Restrict the given coordinate to a limited number of decimal places for display
-        * @param inCoord coordinate string
-        * @return chopped string
-        */
-       private static String restrictDP(String inCoord)
-       {
-               final int DECIMAL_PLACES = 7;
-               if (inCoord == null) return "";
-               String result = inCoord;
-               final int dotPos = Math.max(inCoord.lastIndexOf('.'), inCoord.lastIndexOf(','));
-               if (dotPos >= 0)
-               {
-                       final int chopPos = dotPos + DECIMAL_PLACES;
-                       if (chopPos < (inCoord.length()-1))
-                       {
-                               result = inCoord.substring(0, chopPos);
-                               // Maybe there's an exponential in there too which needs to be appended
-                               int expPos = inCoord.toUpperCase().indexOf("E", chopPos);
-                               if (expPos > 0 && expPos < (inCoord.length()-1))
-                               {
-                                       result += inCoord.substring(expPos);
-                               }
-                       }
-               }
-               return result;
-       }
-
        /**
         * Make a details subpanel
         * @param inNameKey key to use for top label
@@ -657,4 +611,22 @@ public class DetailsDisplay extends GenericDisplay
                // string is too long
                return inString.substring(0, 20) + "...";
        }
+
+       /**
+        * @return the currently selected coordinate display format
+        */
+       private int getSelectedCoordFormat()
+       {
+               switch (_coordFormatDropdown.getSelectedIndex())
+               {
+                       case 1: // degminsec
+                               return Coordinate.FORMAT_DEG_MIN_SEC;
+                       case 2: // degmin
+                               return Coordinate.FORMAT_DEG_MIN;
+                       case 3: // degrees
+                               return Coordinate.FORMAT_DEG;
+                       default: // just as it was
+                               return Coordinate.FORMAT_NONE;
+               }
+       }
 }
index bce3b4d67b0a6df980b66882f175245af1134155..d289b7828fca0086eacf58a6ce74275b1471c786 100644 (file)
@@ -30,10 +30,14 @@ import tim.prune.data.Selection;
 import tim.prune.data.Track;
 import tim.prune.data.TrackInfo;
 import tim.prune.function.ChooseSingleParameter;
+import tim.prune.function.PasteCoordinateList;
+import tim.prune.function.PasteCoordinates;
+import tim.prune.function.PlusCodeFunction;
 import tim.prune.function.SearchOpenCachingDeFunction;
 import tim.prune.function.browser.UrlGenerator;
 import tim.prune.function.browser.WebMapFunction;
 import tim.prune.function.search.SearchMapillaryFunction;
+import tim.prune.function.settings.SaveConfig;
 
 /**
  * Class to manage the menu bar and tool bar,
@@ -74,6 +78,7 @@ public class MenuManager implements DataSubscriber
        private JMenuItem _selectEndItem = null;
        private JMenuItem _findWaypointItem = null;
        private JMenuItem _duplicatePointItem = null;
+       private JMenuItem _projectPointItem = null;
        private JMenuItem _reverseItem = null;
        private JMenuItem _addTimeOffsetItem = null;
        private JMenuItem _addAltitudeOffsetItem = null;
@@ -90,8 +95,6 @@ public class MenuManager implements DataSubscriber
        private JMenu     _browserMapMenu = null;
        private JMenuItem _routingGraphHopperItem = null;
        private JMenuItem _chartItem = null;
-       private JMenuItem _getGpsiesItem = null;
-       private JMenuItem _uploadGpsiesItem = null;
        private JMenuItem _lookupSrtmItem = null;
        private JMenuItem _downloadSrtmItem = null;
        private JMenuItem _nearbyWikipediaItem = null;
@@ -103,7 +106,7 @@ public class MenuManager implements DataSubscriber
        private JMenuItem _downloadOsmItem = null;
        private JMenuItem _getWeatherItem = null;
        private JMenuItem _distanceItem = null;
-       private JMenuItem _fullRangeDetailsItem = null;
+       private JMenuItem _viewFullDetailsItem = null;
        private JMenuItem _estimateTimeItem = null;
        private JMenuItem _learnEstimationParams = null;
        private JMenuItem _autoplayTrack = null;
@@ -259,12 +262,6 @@ public class MenuManager implements DataSubscriber
                onlineMenu.add(_lookupSrtmItem);
                _downloadSrtmItem = makeMenuItem(FunctionLibrary.FUNCTION_DOWNLOAD_SRTM, false);
                onlineMenu.add(_downloadSrtmItem);
-               // Get gpsies tracks
-               _getGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_GET_GPSIES, false);
-               onlineMenu.add(_getGpsiesItem);
-               // Upload to gpsies
-               _uploadGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_UPLOAD_GPSIES, false);
-               onlineMenu.add(_uploadGpsiesItem);
 
                onlineMenu.addSeparator();
                // browser submenu
@@ -491,9 +488,17 @@ public class MenuManager implements DataSubscriber
                // duplicate current point
                _duplicatePointItem = makeMenuItem(FunctionLibrary.FUNCTION_DUPLICATE_POINT, false);
                pointMenu.add(_duplicatePointItem);
+               // project current point
+               _projectPointItem = makeMenuItem(FunctionLibrary.FUNCTION_PROJECT_POINT, false);
+               pointMenu.add(_projectPointItem);
                // paste coordinates function
-               JMenuItem pasteCoordsItem = makeMenuItem(FunctionLibrary.FUNCTION_PASTE_COORDINATES);
+               JMenuItem pasteCoordsItem = makeMenuItem(new PasteCoordinates(_app));
                pointMenu.add(pasteCoordsItem);
+               JMenuItem pasteCoordsListItem = makeMenuItem(new PasteCoordinateList(_app));
+               pointMenu.add(pasteCoordsListItem);
+               // pluscodes function
+               JMenuItem plusCodeItem = makeMenuItem(new PlusCodeFunction(_app));
+               pointMenu.add(plusCodeItem);
                menubar.add(pointMenu);
 
                // Add view menu
@@ -530,8 +535,8 @@ public class MenuManager implements DataSubscriber
                _distanceItem = makeMenuItem(FunctionLibrary.FUNCTION_DISTANCES, false);
                viewMenu.add(_distanceItem);
                // full range details
-               _fullRangeDetailsItem = makeMenuItem(FunctionLibrary.FUNCTION_FULL_RANGE_DETAILS, false);
-               viewMenu.add(_fullRangeDetailsItem);
+               _viewFullDetailsItem = makeMenuItem(FunctionLibrary.FUNCTION_FULL_DETAILS, false);
+               viewMenu.add(_viewFullDetailsItem);
                // estimate time
                _estimateTimeItem = makeMenuItem(FunctionLibrary.FUNCTION_ESTIMATE_TIME, false);
                viewMenu.add(_estimateTimeItem);
@@ -659,7 +664,10 @@ public class MenuManager implements DataSubscriber
                _autosaveSettingsCheckbox.setSelected(Config.getConfigBoolean(Config.KEY_AUTOSAVE_SETTINGS));
                _autosaveSettingsCheckbox.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
-                               Config.setConfigBoolean(Config.KEY_AUTOSAVE_SETTINGS, _autosaveSettingsCheckbox.isSelected());
+                               final boolean autosaveOn = _autosaveSettingsCheckbox.isSelected();
+                               Config.setConfigBoolean(Config.KEY_AUTOSAVE_SETTINGS, autosaveOn);
+                               // Maybe want to save config?
+                               new SaveConfig(_app).autosaveSwitched(autosaveOn);
                        }
                });
                settingsMenu.add(_autosaveSettingsCheckbox);
@@ -868,7 +876,7 @@ public class MenuManager implements DataSubscriber
                _markRectangleItem.setEnabled(hasData);
                _markUphillLiftsItem.setEnabled(hasData && _track.hasAltitudeData());
                _deleteMarkedPointsItem.setEnabled(hasData && _track.hasMarkedPoints());
-               _rearrangeWaypointsItem.setEnabled(hasData && _track.hasTrackPoints() && _track.hasWaypoints());
+               _rearrangeWaypointsItem.setEnabled(hasData && _track.hasWaypoints() && _track.getNumPoints() > 1);
                final boolean hasSeveralTrackPoints = hasData && _track.hasTrackPoints() && _track.getNumPoints() > 3;
                _splitSegmentsItem.setEnabled(hasSeveralTrackPoints);
                _sewSegmentsItem.setEnabled(hasSeveralTrackPoints);
@@ -880,8 +888,6 @@ public class MenuManager implements DataSubscriber
                _browserMapMenu.setEnabled(hasData);
                _distanceItem.setEnabled(hasData);
                _autoplayTrack.setEnabled(hasData && _track.getNumPoints() > 3);
-               _getGpsiesItem.setEnabled(hasData);
-               _uploadGpsiesItem.setEnabled(hasData && _track.hasTrackPoints());
                _lookupSrtmItem.setEnabled(hasData);
                _nearbyWikipediaItem.setEnabled(hasData);
                _nearbyOsmPoiItem.setEnabled(hasData);
@@ -911,6 +917,7 @@ public class MenuManager implements DataSubscriber
                _selectEndItem.setEnabled(hasPoint);
                _selectEndButton.setEnabled(hasPoint);
                _duplicatePointItem.setEnabled(hasPoint);
+               _projectPointItem.setEnabled(hasPoint);
                _showPeakfinderItem.setEnabled(hasPoint);
                _showGeohackItem.setEnabled(hasPoint);
                _searchOpencachingDeItem.setEnabled(hasPoint);
@@ -958,7 +965,7 @@ public class MenuManager implements DataSubscriber
                _addAltitudeOffsetItem.setEnabled(hasRange);
                _convertNamesToTimesItem.setEnabled(hasRange && _track.hasWaypoints());
                _deleteFieldValuesItem.setEnabled(hasRange);
-               _fullRangeDetailsItem.setEnabled(hasRange);
+               _viewFullDetailsItem.setEnabled(hasRange || hasPoint);
                _estimateTimeItem.setEnabled(hasRange);
                _learnEstimationParams.setEnabled(hasData && _track.hasTrackPoints() && _track.hasData(Field.TIMESTAMP)
                        && _track.hasAltitudeData());
index a5462ed1bd078db252167b18aab5116bd9c78d29..1839d87bfe8801310980e49259f145f122c05c6c 100644 (file)
@@ -59,7 +59,8 @@ public class StatusBar extends JPanel implements Runnable, DataSubscriber
                _label.setText(" " + inMessage);
                _timer = System.currentTimeMillis() + DEFAULT_CLEAR_INTERVAL;
                // If necessary, start a new checker thread
-               if (_thread == null || !_thread.isAlive()) {
+               if (_thread == null || !_thread.isAlive())
+               {
                        _thread = new Thread(this);
                        _thread.start();
                }
index 25eba2fb1847306d41aed63021c7cbe3e4ed2cf0..38620e474ce6b78b7d72a06e2ce35303d7acbd3d 100644 (file)
@@ -7,7 +7,7 @@ import tim.prune.gui.map.MapUtils;
 /**
  * Class to provide access to current viewport
  * The point of this class is to decouple the view from the MapCanvas object
- * so that when the GetGpsies function needs to know the area currently viewed, it doesn't
+ * so that when a search function needs to know the area currently viewed, it doesn't
  * need to have a direct connection to the MapCanvas.  Instead it asks the App for the viewport,
  * which is then able to get the map position from the MapCanvas.
  * I'm still not sure whether this is ugly or not, but it's more efficient than constantly listening.
index 767456eead95c533c1bf772cb9811ae3b57256a1..8c8829fd8a38d5dc2792d5a5f12238bbcbc7d9aa 100644 (file)
@@ -130,7 +130,7 @@ public abstract class ColourerFactory
         * @param inColourer PointColourer object
         * @return string describing object (for later re-creation) or null
         */
-       public static String PointColourerToString(PointColourer inColourer)
+       public static String pointColourerToString(PointColourer inColourer)
        {
                if (inColourer != null)
                {
index 2a0e8cb9903c205d3703cbdf6da6e5453a96a9ed..4f0891843dea2632127a1ef9ae2dbab2aa9d0b30 100644 (file)
@@ -26,13 +26,13 @@ public class FileColourer extends DiscretePointColourer
 
        /**
         * Calculate the colours for each of the points in the given track
-        * @param inTrack track object
+        * @param inTrackInfo track info object
         */
        @Override
        public void calculateColours(TrackInfo inTrackInfo)
        {
                // initialise the array to the right size
-               final int numPoints = inTrackInfo == null ? 0 : inTrackInfo.getTrack().getNumPoints();
+               final int numPoints = inTrackInfo.getTrack().getNumPoints();
                init(numPoints);
 
                // loop over track points
index fd2042a7714acfe2ca1f5b47693ce9df06b0a79f..875fcc3b7feb5d0bbad49f55774ba257369f0451 100644 (file)
@@ -25,10 +25,20 @@ public class DiskTileCacher implements Runnable
        private File _file = null;
        /** Observer to be notified */
        private ImageObserver _observer = null;
+       /** True if cacher is active, false if blocked */
+       private boolean _active = false;
+
        /** 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>();
+       /**Hashset of files which are currently being processed */
+       private static final HashSet<String> DOWNLOADING_FILES = new HashSet<String>();
+       /** Number of currently active threads */
+       private static int NUMBER_ACTIVE_THREADS = 0;
+       /** Flag to remember whether any server connection is possible */
+       private static boolean CONNECTION_ACTIVE = true;
+
 
        /**
         * Private constructor
@@ -40,6 +50,7 @@ public class DiskTileCacher implements Runnable
                _url = inUrl;
                _file = inFile;
                _observer = inObserver;
+               _active = registerCacher(inFile.getAbsolutePath());
        }
 
        /**
@@ -81,63 +92,97 @@ public class DiskTileCacher implements Runnable
                if (inBasePath == null || inTilePath == null) {return;}
                // save file if possible
                File basePath = new File(inBasePath);
-               if (!basePath.exists() || !basePath.isDirectory() || !basePath.canWrite()) {
+               if (!basePath.exists() || !basePath.isDirectory() || !basePath.canWrite())
+               {
                        // Can't write to base path
                        return;
                }
                File tileFile = new File(basePath, inTilePath);
-               // Check if this file is already being loaded
-               if (isBeingLoaded(tileFile)) {return;}
+
                // Check if it has already failed
-               if (BLOCKED_URLS.contains(inUrl.toString())) {return;}
+               if (BLOCKED_URLS.contains(inUrl.toString())) {
+                       return;
+               }
 
                File dir = tileFile.getParentFile();
-               // Start a new thread to load the image if necessary
+               // Construct a cacher to load the image if necessary
                if ((dir.exists() || dir.mkdirs()) && dir.canWrite())
                {
-                       new Thread(new DiskTileCacher(inUrl, tileFile, inObserver)).start();
+                       DiskTileCacher cacher = new DiskTileCacher(inUrl, tileFile, inObserver);
+                       cacher.startDownloading();
                }
        }
 
        /**
-        * Check whether the given tile is already being loaded
-        * @param inFile desired file
-        * @return true if temporary file with this name exists
+        * Start downloading the configured tile
         */
-       private static boolean isBeingLoaded(File inFile)
+       private void startDownloading()
        {
-               File tempFile = new File(inFile.getAbsolutePath() + ".temp");
-               if (!tempFile.exists()) {
-                       return false;
+               if (_active)
+               {
+                       new Thread(this).start();
                }
-               // File exists, so check if it was created recently
-               final long fileAge = System.currentTimeMillis() - tempFile.lastModified();
-               return fileAge < 1000000L; // overwrite if the temp file is still there after 1000s
        }
 
        /**
         * Run method for loading URL asynchronously and saving to file
         */
        public void run()
+       {
+               waitUntilAllowedToRun();
+               if (doDownload())
+               {
+                       if (!CONNECTION_ACTIVE)
+                       {
+                               // wasn't active before but this download worked - we've come back online
+                               BLOCKED_URLS.clear();
+                               CONNECTION_ACTIVE = true;
+                       }
+               }
+               // Release file and thread
+               unregisterCacher(_file.getAbsolutePath());
+               threadFinished();
+       }
+
+       /**
+        * Blocks (in separate thread) until allowed by concurrent thread limit
+        */
+       private void waitUntilAllowedToRun()
+       {
+               while (!canStartNewThread())
+               {
+                       try {
+                               Thread.sleep(400);
+                       }
+                       catch (InterruptedException e) {}
+               }
+       }
+
+       /**
+        * @return true if download was successful
+        */
+       private boolean doDownload()
        {
                boolean finished = false;
                InputStream in = null;
                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)
+
+               if (tempFile.exists())
                {
-                       if (tempFile.exists()) {tempFile.delete();}
-                       try {
-                               if (!tempFile.createNewFile()) {return;}
-                       }
-                       catch (Exception e) {return;}
+                       tempFile.delete();
                }
+               try
+               {
+                       if (!tempFile.createNewFile()) {return false;}
+               }
+               catch (Exception e) {return false;}
+
                try
                {
                        // Open streams from URL and to file
                        out = new FileOutputStream(tempFile);
-                       //System.out.println("Opening URL: " + _url.toString());
+                       //System.out.println("DiskTileCacher opening URL: " + _url.toString());
                        // Set http user agent on connection
                        URLConnection conn = _url.openConnection();
                        conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER);
@@ -148,27 +193,97 @@ public class DiskTileCacher implements Runnable
                                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());
+                       CONNECTION_ACTIVE = false;
                }
                finally
                {
                        // clean up files
                        try {in.close();} catch (Exception e) {} // ignore
                        try {out.close();} catch (Exception e) {} // ignore
-                       if (!finished) {
+                       if (!finished)
+                       {
                                tempFile.delete();
                        }
                }
+               boolean success = false;
                // Move temp file to desired file location
-               if (tempFile.exists() && !tempFile.renameTo(_file))
+               if (tempFile.exists() && tempFile.length() > 0L)
                {
-                       // File couldn't be moved - delete both to be sure
-                       tempFile.delete();
-                       _file.delete();
+                       if (tempFile.renameTo(_file))
+                       {
+                               success = true;
+                       }
+                       else
+                       {
+                               // File couldn't be moved - delete both to be sure
+                               System.out.println("Failed to rename temp file: " + tempFile.getAbsolutePath());
+                               tempFile.delete();
+                               _file.delete();
+                       }
                }
+
                // Tell parent that load is finished (parameters ignored)
                _observer.imageUpdate(null, ImageObserver.ALLBITS, 0, 0, 0, 0);
+               return success;
+       }
+
+       // Blocking of cachers working on same file
+
+       /**
+        * Register a cacher writing to the specified file path
+        * @param inFilePath destination path to tile file
+        * @return true if nobody else has claimed this file yet
+        */
+       private synchronized static boolean registerCacher(String inFilePath)
+       {
+               if (DOWNLOADING_FILES.contains(inFilePath))
+               {
+                       return false;
+               }
+               // Nobody has claimed this file yet
+               DOWNLOADING_FILES.add(inFilePath);
+               return true;
+       }
+
+       /**
+        * Cacher has finished dealing with the specified file
+        * @param inFilePath destination path to tile file
+        */
+       private synchronized static void unregisterCacher(String inFilePath)
+       {
+               DOWNLOADING_FILES.remove(inFilePath);
+       }
+
+       // Limiting of active threads
+
+       /**
+        * @return true if another thread is allowed to become active
+        */
+       private synchronized static boolean canStartNewThread()
+       {
+               final int MAXIMUM_NUM_THREADS = 8;
+               if (NUMBER_ACTIVE_THREADS < MAXIMUM_NUM_THREADS)
+               {
+                       NUMBER_ACTIVE_THREADS++;
+                       return true;
+               }
+               // Already too many threads active
+               return false;
+       }
+
+       /**
+        * Inform that one of the previously active threads has now completed
+        */
+       private synchronized static void threadFinished()
+       {
+               if (NUMBER_ACTIVE_THREADS > 0)
+               {
+                       NUMBER_ACTIVE_THREADS--;
+               }
        }
 }
index aa25dbcd939e39b96a6642f188b68665d4c74c4f..d305d1c4f7bd3b9dae59066bf4f32423b9426c39 100644 (file)
@@ -720,8 +720,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                                final double pointSeparationSqd = (prevX-px) * (prevX-px) + (prevY-py) * (prevY-py);
                                                if (pointSeparationSqd > pointSeparationForArrowsSqd)
                                                {
-                                                       final double midX = (prevX + px) / 2;
-                                                       final double midY = (prevY + py) / 2;
+                                                       final double midX = (prevX + px) / 2.0;
+                                                       final double midY = (prevY + py) / 2.0;
                                                        final boolean midPointVisible = midX >= 0 && midX < winWidth && midY >= 0 && midY < winHeight;
                                                        if (midPointVisible)
                                                        {
index 331d8fe94007b27045cc53b15920cd3270be8df3..08ab4bcf6e42dc7baf430edf27a45ac3574bfbd8 100644 (file)
@@ -42,10 +42,10 @@ public abstract class MapSourceLibrary
                _sourceList.add(new OsmMapSource("Cycling Trails", "https://[abc].tile.openstreetmap.org/", "png",
                        "https://tile.waymarkedtrails.org/cycling/", "png", 18));
                _sourceList.add(new OsmMapSource("Reitkarte", "http://topo[234].wanderreitkarte.de/topo/"));
-               _sourceList.add(new MffMapSource("Mapsforfree", "http://maps-for-free.com/layer/relief/", "jpg",
-                       "http://maps-for-free.com/layer/water/", "gif", 11));
-               _sourceList.add(new OsmMapSource("Hikebikemap", "http://[abc].tiles.wmflabs.org/hikebike/",
-                       "http://[abc].tiles.wmflabs.org/hillshading/", 18));
+               _sourceList.add(new MffMapSource("Mapsforfree", "https://maps-for-free.com/layer/relief/", "jpg",
+                       "https://maps-for-free.com/layer/water/", "gif", 11));
+               _sourceList.add(new OsmMapSource("Hikebikemap", "https://tiles.wmflabs.org/hikebike/",
+                       "https://tiles.wmflabs.org/hillshading/", 18));
                _sourceList.add(new OsmMapSource("OpenSeaMap", "http://tile.openstreetmap.org/",
                        "http://tiles.openseamap.org/seamark/", 18));
        }
index f7370c5c90c833e7f053fc786eafdae37ab7f843..8c2c6eed9e3f7e70ccf251ba91e01ebe4f550be9 100644 (file)
@@ -162,6 +162,7 @@ public class MapTileManager implements ImageObserver
                        tempCache = _tempCaches[inLayer]; // Should probably guard array indexes here
                        tileImage = tempCache.getTile(inX, inY);
                        if (tileImage != null) {
+                               //System.out.println("Got tile from memory: " + inX + ", " + inY);
                                return tileImage;
                        }
                }
@@ -195,7 +196,6 @@ public class MapTileManager implements ImageObserver
                        try
                        {
                                URL tileUrl = new URL(_mapSource.makeURL(inLayer, _zoom, inX, inY));
-                               //System.out.println("Trying to fetch: " + tileUrl);
                                if (useDisk)
                                {
                                        DiskTileCacher.saveTile(tileUrl, diskCachePath,
index 7c7540066c839d86105f71a0a95b3af1398d17de..7ec6d91eb58db07faaa8c8a52421f5da5a8cf544 100644 (file)
@@ -21,10 +21,13 @@ public class TileDownloader implements Runnable
        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>();
+       /** Flag to maintain whether connection is active or not */
+       private static boolean CONNECTION_ACTIVE = true;
 
 
        /**
@@ -67,6 +70,9 @@ public class TileDownloader implements Runnable
                                LOADING_URLS.add(url);
                                new Thread(new TileDownloader(inManager, inUrl, inLayer, inX, inY, inZoom)).start();
                        }
+                       else {
+                               System.out.println("Already blocked: " + url);
+                       }
                }
        }
 
@@ -98,6 +104,17 @@ public class TileDownloader implements Runnable
 
                                // Pass back to manager so it can be stored in its memory cache
                                _manager.notifyImageLoaded(tile, _layer, _x, _y, _zoom);
+
+                               if (!CONNECTION_ACTIVE)
+                               {
+                                       // We've just come back online, so forget which tiles gave 404 before
+                                       System.out.println("Deleting blocked urls, currently holds " + BLOCKED_URLS.size());
+                                       synchronized(this.getClass())
+                                       {
+                                               BLOCKED_URLS.clear();
+                                       }
+                                       CONNECTION_ACTIVE = true;
+                               }
                        }
                }
                catch (IOException e)
@@ -108,6 +125,7 @@ public class TileDownloader implements Runnable
                                BLOCKED_URLS.add(_url.toString());
                        }
                        try {in.close();} catch (Exception e2) {}
+                       CONNECTION_ACTIVE = false;      // lost connection?
                }
                LOADING_URLS.remove(_url.toString());
        }
index 466fda2175de2418569297c0722c6cfb1a2fd3c0..5d18e1e9892b5c40f0fffca9338f8ecc4aca6f0d 100644 (file)
@@ -61,7 +61,7 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                        if (!other.hasValue) {return;}
                        if (!hasValue) {
                                index = other.index;
-                               hasValue = other.hasValue;
+                               hasValue = true;
                        }
                        else {
                                index = Math.min(index, other.index);
@@ -73,7 +73,7 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                        if (!other.hasValue) {return;}
                        if (!hasValue) {
                                index = other.index;
-                               hasValue = other.hasValue;
+                               hasValue = true;
                        }
                        else {
                                index = Math.max(index, other.index);
@@ -239,7 +239,8 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                int selectedPoint = _trackInfo.getSelection().getCurrentPointIndex();
                // selection start, end
                int selectionStart = -1, selectionEnd = -1;
-               if (_trackInfo.getSelection().hasRangeSelected()) {
+               if (_trackInfo.getSelection().hasRangeSelected())
+               {
                        selectionStart = _trackInfo.getSelection().getStart();
                        selectionEnd = _trackInfo.getSelection().getEnd();
                }
@@ -289,12 +290,14 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                                                y = (int) (yScaleFactor * (value - minValue));
                                                g.fillRect(BORDER_WIDTH+x, height-BORDER_WIDTH - y, barWidth, y);
                                        }
-                                       else if (value >= 0.0) {
+                                       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 {
+                                       else
+                                       {
                                                // Bar downwards from the zero line
                                                int barHeight = (int) (yScaleFactor * value);
                                                g.fillRect(BORDER_WIDTH+x, zeroY, barWidth, -barHeight);
@@ -317,7 +320,8 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                                }
                        }
                }
-               catch (NullPointerException npe) { // ignore, probably due to data being changed
+               catch (NullPointerException npe)
+               { // ignore, probably due to data being changed
                }
                // Draw numbers on top of the graph to mark scale
                if (lineScale >= 1)
@@ -458,29 +462,32 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                if ((inUpdateType & DATA_ADDED_OR_REMOVED) > 0) {
                        makePopup();
                }
-               if (inUpdateType == SELECTION_CHANGED) {
-                       triggerPartialRepaint();
+
+               ChartParameters currentParameters = new ChartParameters();
+               currentParameters.selectedPoint.set(_trackInfo.getSelection().getCurrentPointIndex());
+               if (_trackInfo.getSelection().hasRangeSelected())
+               {
+                       currentParameters.rangeStart.set(_trackInfo.getSelection().getStart());
+                       currentParameters.rangeEnd.set(_trackInfo.getSelection().getEnd());
+               }
+               if (inUpdateType == SELECTION_CHANGED)
+               {
+                       triggerPartialRepaint(currentParameters);
                }
                else
                {
                        repaint();
                }
+               _previousParameters = currentParameters;
        }
 
        /**
         * For performance reasons, only repaint the part of the graphics affected by
         * the change in selection
+        * @param currentParameters - contains the current selected point, range
         */
-       private void triggerPartialRepaint()
+       private void triggerPartialRepaint(ChartParameters currentParameters)
        {
-               ChartParameters currentParameters = new ChartParameters();
-               currentParameters.selectedPoint.set(_trackInfo.getSelection().getCurrentPointIndex());
-               if (_trackInfo.getSelection().hasRangeSelected())
-               {
-                       currentParameters.rangeStart.set(_trackInfo.getSelection().getStart());
-                       currentParameters.rangeEnd.set(_trackInfo.getSelection().getEnd());
-               }
-
                int minPointIndex = currentParameters.getMinChangedIndex(_previousParameters);
                minPointIndex = Math.max(minPointIndex, 0);
                int maxPointIndex = currentParameters.getMaxChangedIndex(_previousParameters);
@@ -488,10 +495,10 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                        maxPointIndex = _trackInfo.getTrack().getNumPoints() - 1;
                }
                // System.out.println("Redraw from index: " + minPointIndex + " to " + maxPointIndex);
-               _previousParameters = currentParameters;
-               final int region_x = (int) (_xScaleFactor * minPointIndex) + BORDER_WIDTH;
-               final int region_width = (int) (_xScaleFactor * (maxPointIndex-minPointIndex+2)) + 2;
+               final int region_x = (int) (_xScaleFactor * minPointIndex) + BORDER_WIDTH - 2;
+               final int region_width = (int) (_xScaleFactor * (maxPointIndex-minPointIndex+2)) + 6;
                repaint(region_x, 0, region_width, getHeight());
+               // System.out.println("Partial repaint, x=" + region_x + ", region_width=" + region_width);
        }
 
        /**
@@ -520,7 +527,8 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                                }
                        }
                }
-               else {
+               else
+               {
                        // right clicks
                        _popup.show(this, e.getX(), e.getY());
                }
@@ -538,12 +546,14 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                                _data = new AltitudeData(_track);
                        }
                }
-               else if (inField == Field.SPEED) {
+               else if (inField == Field.SPEED)
+               {
                        if (!(_data instanceof SpeedData)) {
                                _data = new SpeedData(_track);
                        }
                }
-               else if (inField == Field.VERTICAL_SPEED) {
+               else if (inField == Field.VERTICAL_SPEED)
+               {
                        if (!(_data instanceof VerticalSpeedData)) {
                                _data = new VerticalSpeedData(_track);
                        }
index a98e720328939c27dcc13666938333200247b602..130a78a7ab42fe3a881e54852c2dc5423bca9bd6 100644 (file)
@@ -21,9 +21,9 @@ public class ExifTiffHandler
        private long _thumbnailOffset = -1L, _thumbnailLength = -1L;
 
        /** This tag is a pointer to the Exif SubIFD. */
-       final int DIR_EXIF_SUB_IFD_OFFSET = 0x8769;
+       private static final int DIR_EXIF_SUB_IFD_OFFSET = 0x8769;
        /** This tag is a pointer to the Exif GPS IFD. */
-       final int DIR_GPS_INFO_OFFSET = 0x8825;
+       private static final int DIR_GPS_INFO_OFFSET = 0x8825;
 
        private static final int TAG_GPS_LATITUDE_REF  = 0x0001;
        private static final int TAG_GPS_LATITUDE      = 0x0002;
@@ -142,6 +142,9 @@ public class ExifTiffHandler
                        case TAG_THUMBNAIL_LENGTH:
                                _thumbnailLength = intVal;
                                break;
+                       case TAG_GPS_BEARING:
+                               _jpegData.setBearing(intVal);
+                               break;
                }
        }
 
index 54c713a96c696034603bac7b96562cc5d574e7ad..e12df2c1362834ccc79a69df9248012ca3631d67 100644 (file)
@@ -100,7 +100,7 @@ function.pastecoordinates=Verskaf nuwe koordinate
 function.charts=Grafieke
 function.show3d=Vertoon 3D
 function.distances=Afstande
-function.fullrangedetails=Vol reeks besonderhede
+function.viewfulldetails=Vol besonderhede
 function.estimatetime=Skat tyd
 function.learnestimationparams=Leer tyd skatings paramters
 function.setmapbg=Stel kaart agtergrond
@@ -108,8 +108,6 @@ function.setpaths=Stel program paaie
 function.selectsegment=Selekteer huidige segment
 function.splitsegments=Verdeel baan in segmente
 function.sewsegments=Naai baan segmente aanmekaar
-function.getgpsies=Kry Spsies spore
-function.uploadgpsies=Laai baan op na Gpsies
 function.lookupsrtm=Kry hoogtes vanaf SRTM
 function.downloadsrtm=Laai SRTM te\u00ebls af
 function.getwikipedia=Kry nabye Wikipedia artikels
@@ -360,18 +358,6 @@ dialog.gpsies.column.length=Lengte
 dialog.gpsies.description=Beskrywing
 dialog.gpsies.nodescription=Geen beskrywing
 dialog.gpsies.nonefound=Geen bane gevind
-dialog.gpsies.username=Gpsies gebruikersnaam
-dialog.gpsies.password=Spsies wagwoord
-dialog.gpsies.keepprivate=Hou baan privaat
-dialog.gpsies.confirmopenpage=Maak web blad oop vir opgelaaide baan
-dialog.gpsies.activities=Aktiwiteits tipes
-dialog.gpsies.activity.trekking=Stap
-dialog.gpsies.activity.walking=Loop
-dialog.gpsies.activity.jogging=Hardloop
-dialog.gpsies.activity.biking=Fietsry
-dialog.gpsies.activity.motorbiking=Moterfietsry
-dialog.gpsies.activity.sailing=Seiljagwedvaart
-dialog.gpsies.activity.skating=Skaats
 dialog.wikipedia.column.name=Artikel naam
 dialog.wikipedia.column.distance=Afstand
 dialog.wikipedia.nonefound=Geen wikipedia insetsels gevind
@@ -472,25 +458,9 @@ dialog.keys.intro=Jy kan die volgende kortpadsleutels gebruik in plaas van om di
 dialog.keys.keylist=<table><tr><td>Pylkie sleutels</td><td>Skuif kaart links regs, op, af</td></tr><tr><td>Ctrl + links, regs pylkie</td><td>Selekteer vorige of volgende punt</td></tr><tr><td>Ctrl + op, af pylkie</td><td>Vergroot in of uit</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Selekteer vorige, volgende segment</td></tr><tr><td>Ctrl + Home, Einde</td><td>Selekteer eerste, laaste punt</td></tr><tr><td>Del</td><td>Verwyder huidige punt</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=Die volgende stelligns kan gestoor word na 'n konfigurasie le\u00ear
-dialog.saveconfig.prune.trackdirectory=Baan gids
-dialog.saveconfig.prune.photodirectory=foto gids
-dialog.saveconfig.prune.languagecode=Taal kode (AF)
-dialog.saveconfig.prune.languagefile=Taal le\u00ear
-dialog.saveconfig.prune.gpsdevice=GPS apparaat
-dialog.saveconfig.prune.gpsformat=GPS formaat
-dialog.saveconfig.prune.povrayfont=Pocray font
-dialog.saveconfig.prune.gnuplotpath=Pad na gnuplot
-dialog.saveconfig.prune.gpsbabelpath=Pad na gpsbabel
-dialog.saveconfig.prune.exiftoolpath=Pad na exitool
-dialog.saveconfig.prune.mapsource=Geselekteerde kaart bron
-dialog.saveconfig.prune.mapsourcelist=Kaarte bronne
-dialog.saveconfig.prune.diskcache=Kaart stoorarea
-dialog.saveconfig.prune.kmzimagewidth=KMZ beeld groote
-dialog.saveconfig.prune.colourscheme=Kleur skema
-dialog.saveconfig.prune.linewidth=Lyn dikte
-dialog.saveconfig.prune.kmltrackcolour=KML baan kleur
-dialog.saveconfig.prune.autosavesettings=Autostoor stellings
+dialog.paths.prune.gnuplotpath=Pad na gnuplot
+dialog.paths.prune.gpsbabelpath=Pad na gpsbabel
+dialog.paths.prune.exiftoolpath=Pad na exitool
 dialog.setpaths.intro=As jy wil, kan jy die paie kies na die eksterne programme:
 dialog.setpaths.found=Pad gefind?
 dialog.addaltitude.noaltitudes=Die geselekteerde reeks bevat nie hoogtes nie
@@ -593,7 +563,7 @@ confirm.rearrangephotos=Fotos ge-herrangskik
 confirm.splitsegments=%d segment verdelings is gemaak
 confirm.sewsegments=%d segment las is gemaak
 confirm.cutandmove=Seleksie geskuif
-confirm.interpolate=Punte bygevoeg
+confirm.pointsadded=%d punte bygevoeg
 confirm.convertnamestotimes=Baken name aangepas
 confirm.saveexif.ok=%d fotos gestoor
 confirm.undo.single=operasie ongedaan
@@ -645,7 +615,6 @@ button.selectall=Selekteer almal
 button.selectnone=Selekter geen
 button.preview=Voorskou
 button.load=Laai
-button.upload=Oplaai
 button.guessfields=Raai velde
 button.showwebpage=Wys webblad
 button.check=Kontroleer
diff --git a/src/tim/prune/lang/prune-texts_cy.properties b/src/tim/prune/lang/prune-texts_cy.properties
new file mode 100644 (file)
index 0000000..1c2d752
--- /dev/null
@@ -0,0 +1,96 @@
+# Text entries for the GpsPrune application
+# Welsh entries
+
+# Menu entries
+menu.file=Ffeil
+menu.file.exit=Gadael
+menu.online=Rhyngrwyd
+menu.track=Wysg
+menu.track.undo=Dadwneud
+menu.point=Pwynt
+menu.photo=Llun
+menu.photo.saveexif=Cadw Exif
+menu.audio=Awdio
+menu.view=Golygu
+menu.settings=Dewisiadau
+menu.help=Cymorth
+
+# Alt keys for menus
+altkey.menu.file=F
+altkey.menu.online=R
+altkey.menu.range=N
+altkey.menu.track=T
+altkey.menu.point=P
+altkey.menu.view=G
+altkey.menu.photo=L
+altkey.menu.audio=A
+altkey.menu.settings=D
+altkey.menu.help=C
+
+# Functions
+function.open=Agor ffeil
+function.exportkml=Cadw KML
+function.exportgpx=Cadw GPX
+function.exportpov=Cadw POV
+function.exportimage=Cadw llun
+function.charts=Siartiau
+function.distances=Pellterau
+function.help=Cymorth
+function.about=Ynghylych GpsPrune
+
+# Dialogs
+dialog.exit.confirm.title=Gadael GpsPrune
+dialog.delimiter.comma=Coma ,
+dialog.delimiter.semicolon=Hannercolon ;
+dialog.gpsload.format=Fformat
+dialog.gpsload.save=Cadw ffeil
+dialog.save.table.save=Cadw
+dialog.exportgpx.name=Enw
+dialog.exportgpx.encoding.system=System
+dialog.exportgpx.encoding.utf8=UTF-8
+dialog.exportpov.camerax=Camera X
+dialog.exportpov.cameray=Camera Y
+dialog.exportpov.cameraz=Camera Z
+dialog.saveexif.title=Cadw Exif
+dialog.saveexif.table.save=Cadw
+dialog.estimatetime.results=Canlyniadau
+dialog.wikipedia.column.distance=Pellter
+dialog.osmpois.column.name=Enw
+dialog.about.version=Fersiwn
+dialog.about.translatedby=Testunau yn Cymraeg ...
+dialog.about.credits.thanks=Diolch a
+dialog.setcolours.text=Testun
+dialog.colourchooser.red=Coch
+dialog.colourchooser.green=Gwyrdd
+dialog.colourchooser.blue=Glas
+dialog.colourer.type.none=Dim
+dialog.setlanguage.language=Iaith
+dialog.diskcache.table.megabytes=Megabeitiau
+dialog.displaysettings.size.small=Bach
+dialog.displaysettings.size.large=Mawr
+dialog.weather.day.today=Heddiw
+dialog.weather.day.tomorrow=Yfory
+
+# Buttons
+button.ok=Iawn
+button.cancel=Diddymu
+button.exit=Gadael
+button.yes=Ie
+button.no=Na
+
+# Display components
+details.track.file=Ffeil
+details.lists.audio=Awdio
+
+# Field names
+fieldname.waypointname=Enw
+
+# How to combine conditions, such as filters
+logic.and=a
+logic.or=neu
+
+# External urls
+url.googlemaps=maps.google.co.uk
+wikipedia.lang=cy
+openweathermap.lang=en
+
index 6957b1d5ed8a40921354a36cfada74cf1b3b9cb6..4d4b5c01fb0e74c9023d148d9ccff7d8226f3cbb 100644 (file)
@@ -99,15 +99,12 @@ function.pastecoordinates=Zadat sou\u0159adnice
 function.charts=Grafy
 function.show3d=Trojrozm\u011brn\u011b
 function.distances=Vzd\u00e1lenosti
-function.fullrangedetails=Detaily rozmez\u00ed
 function.estimatetime=Odhad \u010dasu
 function.learnestimationparams=Anal\u00fdza stopy pro odhad \u010dasu
 function.setmapbg=Nastavit pozad\u00ed
 function.setpaths=Nastavit cestu k program\u016fm
 function.splitsegments=Rozd\u011blit stopu na \u010d\u00e1sti
 function.sewsegments=Spojit \u010d\u00e1sti stopy
-function.getgpsies=St\u00e1hnout stopy z Gpsies
-function.uploadgpsies=Nahr\u00e1t stopu na Gpsies
 function.lookupsrtm=Na\u010d\u00edst nadm. v\u00fd\u0161ku ze SRTM
 function.downloadsrtm=St\u00e1hnout dla\u017edice ze SRTM
 function.getwikipedia=Hledat na Wikipedii podle vzd\u00e1lenosti
@@ -359,19 +356,6 @@ dialog.gpsies.column.length=D\u00e9lka
 dialog.gpsies.description=Popis
 dialog.gpsies.nodescription=Bez popisu
 dialog.gpsies.nonefound=Nenalezeny \u017e\u00e1dn\u00e9 stopy
-dialog.gpsies.username=U\u017eiv. jm\u00e9no k gpsies
-dialog.gpsies.password=Heslo k gpsies
-dialog.gpsies.keepprivate=Stopu nezve\u0159ej\u0148ovat
-dialog.gpsies.confirmopenpage=Otev\u0159\u00edt nahranou stopu v internetov\u00e9m prohl\u00ed\u017ee\u010di?
-dialog.gpsies.activities=Aktivita
-dialog.gpsies.activity.trekking=Turistika
-dialog.gpsies.activity.walking=Ch\u016fze
-dialog.gpsies.activity.jogging=B\u011bh
-dialog.gpsies.activity.biking=Kolo
-dialog.gpsies.activity.motorbiking=Motorka
-dialog.gpsies.activity.snowshoe=Sn\u011b\u017enice
-dialog.gpsies.activity.sailing=Lo\u010f
-dialog.gpsies.activity.skating=Bruslen\u00ed
 dialog.mapillary.nonefound=Nenalezeny \u017e\u00e1dn\u00e9 fotografie
 dialog.wikipedia.column.name=N\u00e1zev \u010dl\u00e1nku
 dialog.wikipedia.column.distance=Vzd\u00e1lenost
@@ -476,25 +460,9 @@ dialog.keys.intro=M\u00edsto my\u0161i m\u016f\u017eete pou\u017e\u00edvat n\u00
 dialog.keys.keylist=<table><tr><td>\u0160ipky</td><td>Posunout mapu vlevo, vpravo, nahoru, dol\u016f</td></tr><tr><td>Ctrl + \u0161ipka vlevo, vpravo</td><td>Vybrat p\u0159edchoz\u00ed nebo n\u00e1sleduj\u00edc\u00ed bod</td></tr><tr><td>Ctrl + \u0161ipka nahoru, dol\u016f</td><td>P\u0159ibl\u00ed\u017eit, odd\u00e1lit</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Vybrat p\u0159edchoz\u00ed, n\u00e1sleduj\u00edc\u00ed \u010d\u00e1st stopy</td></tr><tr><td>Ctrl + Home, End</td><td>Vybrat prvn\u00ed, posledn\u00ed bod</td></tr><tr><td>Del</td><td>Smazat aktu\u00e1ln\u00ed bod</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=N\u00e1sleduj\u00edc\u00ed volby mohou b\u00fdt ulo\u017eeny do konfigura\u010dn\u00edho souboru :
-dialog.saveconfig.prune.trackdirectory=Adres\u00e1\u0159 s stopami
-dialog.saveconfig.prune.photodirectory=Ad\u0159es\u00e1\u0159 s fotografiemi
-dialog.saveconfig.prune.languagecode=K\u00f3d jazyka
-dialog.saveconfig.prune.languagefile=Soubor jazyka
-dialog.saveconfig.prune.gpsdevice=Za\u0159\u00edzen\u00ed GPS
-dialog.saveconfig.prune.gpsformat=Form\u00e1t GPS
-dialog.saveconfig.prune.povrayfont=Font Povray
-dialog.saveconfig.prune.gnuplotpath=Cesta k gnuplot
-dialog.saveconfig.prune.gpsbabelpath=Cesta k gpsbabel
-dialog.saveconfig.prune.exiftoolpath=Cesta k exiftool
-dialog.saveconfig.prune.mapsource=Vybran\u00fd zdroj map
-dialog.saveconfig.prune.mapsourcelist=Zdroje map
-dialog.saveconfig.prune.diskcache=Cache s mapami
-dialog.saveconfig.prune.kmzimagewidth=\u0160\u00ed\u0159ka bitmapy KMZ
-dialog.saveconfig.prune.colourscheme=Barevn\u00e9 sch\u00e9ma
-dialog.saveconfig.prune.linewidth=Tlou\u0161\u0165ka \u010d\u00e1ry
-dialog.saveconfig.prune.kmltrackcolour=Barva stopy v KML
-dialog.saveconfig.prune.autosavesettings=Mo\u017enosti ukl\u00e1d\u00e1n\u00ed
+dialog.paths.prune.gnuplotpath=Cesta k gnuplot
+dialog.paths.prune.gpsbabelpath=Cesta k gpsbabel
+dialog.paths.prune.exiftoolpath=Cesta k exiftool
 dialog.setpaths.intro=Je-li to t\u0159eba, m\u016f\u017eete nastavit cesty k extern\u00edm aplikac\u00edm:
 dialog.setpaths.found=Cesta nalezena?
 dialog.addaltitude.noaltitudes=Vybran\u00e9 rozmez\u00ed neobsahuje nadmo\u0159skou v\u00fd\u0161ku
@@ -585,7 +553,7 @@ confirm.rearrangephotos=Fotografie p\u0159euspo\u0159\u00e1d\u00e1ny
 confirm.splitsegments=\u00dasp\u011b\u0161n\u011b rozd\u011bleno v %d bodech
 confirm.sewsegments=\u00dasp\u011b\u0161n\u011b spojeno v %d bodech
 confirm.cutandmove=V\u00fdb\u011br p\u0159esunut
-confirm.interpolate=Body p\u0159id\u00e1ny
+confirm.pointsadded=%d body p\u0159id\u00e1ny
 confirm.convertnamestotimes=N\u00e1zvy bod\u016f p\u0159evedeny
 confirm.saveexif.ok=Ulo\u017eeno %d fotografi\u00ed
 confirm.undo.single=operace vr\u00e1cena
@@ -641,7 +609,6 @@ button.selectall=Vybrat v\u0161e
 button.selectnone=Zru\u0161it v\u00fdb\u011br
 button.preview=N\u00e1hled
 button.load=Na\u010d\u00edst
-button.upload=Upload
 button.guessfields=Odhadnout pole
 button.showwebpage=Zobrazit str\u00e1nku
 button.check=Zkontrolovat
index e975e29317d5d167a07ecac6b3022df95a89df6c..2b8e26cd9a503551d824fa1e041ad9d737bc3f38 100644 (file)
@@ -77,7 +77,6 @@ function.pastecoordinates=Indf\u00f8j nye koordinater
 function.charts=Kort
 function.show3d=3-D view
 function.distances=Afstande
-function.fullrangedetails=Vis alle detaljer
+function.viewfulldetails=Vis alle detaljer
 function.setmapbg=V\u00e6lg kort som baggrund
 function.setpaths=V\u00e6lg sti til programmer
-function.getgpsies=Se liste af GPS-spor
index 1c35d2557ced81caf09564c570a4b5436aa1818d..d1f6976ac07aa891535aa05092754c87984d2d4e 100644 (file)
@@ -96,11 +96,13 @@ function.addaltitudeoffset=H\u00f6henverschiebung aufrechnen
 function.convertnamestotimes=Namen der Wegpunkte in Zeitstempel umwandeln
 function.deletefieldvalues=Werte eines Feldes l\u00f6schen
 function.findwaypoint=Wegpunkt finden
-function.pastecoordinates=Neuen Wegpunkt anlegen
+function.pastecoordinates=Koordinaten eingeben
+function.pastecoordinatelist=Koordinatenliste eingeben
+function.enterpluscode=Pluscode eingeben
 function.charts=Diagramme
 function.show3d=3D Ansicht
 function.distances=Entfernungen
-function.fullrangedetails=Zus\u00e4tzliche Bereichdetails
+function.viewfulldetails=Zus\u00e4tzliche Details
 function.estimatetime=Zeit absch\u00e4tzen
 function.learnestimationparams=Zeitparameter erlernen
 function.autoplay=Track abspielen
@@ -110,8 +112,6 @@ function.selectsegment=Aktuellen Abschnitt markieren
 function.splitsegments=In Trackabschnitte schneiden
 function.sewsegments=Trackabschnitte zusammenf\u00fcgen
 function.createmarkerwaypoints=Wegpunkte im bestimmten Abstand kreieren
-function.getgpsies=Tracks bei GPSies.com herunterladen
-function.uploadgpsies=Track zu GPSies.com hochladen
 function.lookupsrtm=H\u00f6hendaten von SRTM nachschlagen
 function.downloadsrtm=SRTM Dateien herunterladen
 function.getwikipedia=Wikipediaartikel in der N\u00e4he nachschlagen
@@ -121,6 +121,7 @@ function.searchopencachingde=OpenCaching.de durchsuchen
 function.mapillary=Mapillary nach Fotos durchsuchen
 function.downloadosm=OSM-Daten f\u00fcr dieses Gebiet herunterladen
 function.duplicatepoint=Punkt verdoppeln
+function.projectpoint=Punkt projizieren
 function.setcolours=Farben einstellen
 function.setdisplaysettings=Darstellungsoptionen
 function.setlanguage=Sprache einstellen
@@ -367,19 +368,6 @@ dialog.gpsies.column.length=L\u00e4nge
 dialog.gpsies.description=Beschreibung
 dialog.gpsies.nodescription=Keine Beschreibung
 dialog.gpsies.nonefound=Keine Tracks gefunden
-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.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.mapillary.nonefound=Keine Fotos gefunden
 dialog.wikipedia.column.name=Artikelname
 dialog.wikipedia.column.distance=Entfernung
@@ -447,6 +435,10 @@ 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.pastecoordinatelist.desc=Liste von Koordinaten eingeben mit einem Punkt pro Zeile
+dialog.pluscode.desc=Pluscode hier eingeben
+dialog.pluscode.code=Pluscode
+dialog.pluscode.nothingfound=Bitte pr\u00fcfen Sie den Code und versuchen Sie es nochmals
 dialog.help.help=Weitere Informationen und Benutzeranleitungen finden Sie unter\n https://gpsprune.activityworkshop.net/
 dialog.about.version=Version
 dialog.about.build=Build
@@ -486,25 +478,9 @@ dialog.keys.intro=Anstelle der Maus k\u00f6nnen Sie folgende Tastenkombinationen
 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>Zum vorherigen oder n\u00e4chsten Abschnitt</td></tr><tr><td>Strg + Pos1, Ende</td><td>Ersten oder letzten Punkt markieren</td></tr><tr><td>Entf</td><td>Aktuellen Punkt entfernen</td></tr></table>
 dialog.keys.normalmodifier=Strg
 dialog.keys.macmodifier=Kommando
-dialog.saveconfig.desc=Die folgende Einstellungen k\u00f6nnen gespeichert werden:
-dialog.saveconfig.prune.trackdirectory=Datenverzeichnis
-dialog.saveconfig.prune.photodirectory=Fotoverzeichnis
-dialog.saveconfig.prune.languagecode=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.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=Bildgr\u00f6\u00dfe in KMZ
-dialog.saveconfig.prune.colourscheme=Farbschema
-dialog.saveconfig.prune.linewidth=Liniedicke
-dialog.saveconfig.prune.kmltrackcolour=KML-Trackfarbe
-dialog.saveconfig.prune.autosavesettings=Einstellungen speichern
+dialog.paths.prune.gnuplotpath=Gnuplot-Pfad
+dialog.paths.prune.gpsbabelpath=GPSBabel-Pfad
+dialog.paths.prune.exiftoolpath=ExifTool-Pfad
 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
@@ -571,6 +547,9 @@ dialog.displaysettings.wpicon.pin=Sto\u00dfnadel
 dialog.displaysettings.size.small=Klein
 dialog.displaysettings.size.medium=Mittel
 dialog.displaysettings.size.large=Gro\u00df
+dialog.displaysettings.windowstyle=Fensterstil (Neustart n\u00f6tig)
+dialog.displaysettings.windowstyle.default=Standart
+dialog.displaysettings.windowstyle.nimbus=Nimbus
 dialog.downloadosm.desc=Die OpenStreetMap-Daten f\u00fcr das folgende Gebiet werden heruntergeladen (.osm-Datei):
 dialog.searchwikipedianames.search=Suche nach:
 dialog.weather.location=Ort
@@ -613,6 +592,12 @@ dialog.autoplay.usetimestamps=Zeitstempeln verwenden
 dialog.autoplay.rewind=Zum Anfang
 dialog.autoplay.pause=Pause
 dialog.autoplay.play=Abspielen
+dialog.markers.halves=Punkte auf halben Weg
+dialog.markers.half.distance=Halbe Distanz
+dialog.markers.half.climb=Halber Aufstieg
+dialog.markers.half.descent=Halber Abstieg
+dialog.projectpoint.desc=Geben Sie die Azimut und Distanz f\u00fcr die Projizierung
+dialog.projectpoint.bearing=Azimut (Grad von N)
 
 # 3d window
 dialog.3d.title=GpsPrune-3D-Ansicht
@@ -634,7 +619,7 @@ confirm.rearrangephotos=Fotos neu angeordnet
 confirm.splitsegments=Es wurden %d Schnitte gemacht
 confirm.sewsegments=Es wurden %d Verbindungen gemacht
 confirm.cutandmove=Bereich verschoben
-confirm.interpolate=Punkte eingef\u00fcgt
+confirm.pointsadded=%d Punkte eingef\u00fcgt
 confirm.convertnamestotimes=Wegpunktnamen umgewandelt
 confirm.saveexif.ok=Es wurden %d Fotodateien geschrieben
 confirm.undo.single=Operation r\u00fcckg\u00e4ngig gemacht
@@ -690,7 +675,6 @@ button.selectall=Alle ausw\u00e4hlen
 button.selectnone=Nichts ausw\u00e4hlen
 button.preview=Vorschau
 button.load=Laden
-button.upload=Hochladen
 button.guessfields=Felder erraten
 button.showwebpage=Webseite anzeigen
 button.check=Pr\u00fcfen
@@ -764,6 +748,7 @@ map.overzoom=Keine Karten f\u00fcr diesen Zoomfaktor verf\u00fcgbar
 # Field names
 fieldname.latitude=Breitengrad
 fieldname.longitude=L\u00e4ngengrad
+fieldname.coordinates=Koordinaten
 fieldname.altitude=H\u00f6he
 fieldname.timestamp=Zeitstempel
 fieldname.time=Zeit
@@ -778,6 +763,7 @@ fieldname.duration=Zeitdauer
 fieldname.speed=Geschwindigkeit
 fieldname.verticalspeed=Vertikale Geschwindigkeit
 fieldname.description=Beschreibung
+fieldname.comment=Anmerkung
 fieldname.mediafilename=Foto- / Audioname
 
 # Measurement units
@@ -871,6 +857,7 @@ error.load.nopoints=Keine g\u00fcltigen Daten in Datei gefunden
 error.load.unknownxml=Unbekanntes XML-Format:
 error.load.noxmlinzip=Keine XML-Datei in Zip-Datei gefunden
 error.load.othererror=Fehler beim Lesen der Datei:
+error.load.nopointsintext=Keine g\u00fcltigen Daten gefunden
 error.jpegload.dialogtitle=Fehler beim Laden von Fotos
 error.jpegload.nofilesfound=Keine Dateien gefunden
 error.jpegload.nojpegsfound=Keine JPG-Dateien gefunden
index acd393a781eab96cbdd8f34c87926201cba98ccb..e2172ee69f5b430879f3298ef20a39553ff2d75c 100644 (file)
@@ -95,11 +95,13 @@ 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.pastecoordinates=Noii Koordinate iigeh
+function.pastecoordinatelist=Liste vo Koordinatene iigeh
+function.enterpluscode=Pluscode iigeh
 function.charts=Diagramme
 function.show3d=Dr\u00fc\u00fc-D Aasicht
 function.distances=Entf\u00e4rnige
-function.fullrangedetails=Zues\u00e4tzlichi Beriichinfos
+function.viewfulldetails=No meh Infos
 function.estimatetime=Ziit absch\u00e4tze
 function.learnestimationparams=Ziitparameter erlerne
 function.autoplay=Track abschpiel\u00e4
@@ -108,8 +110,6 @@ function.selectsegment=Aktuelli Segm\u00e4nt selektiere
 function.splitsegments=In Tracksegm\u00e4nte schniide
 function.sewsegments=Tracksegm\u00e4nte z\u00e4mef\u00fcge
 function.createmarkerwaypoints=Waypoints inem bestimmten Abstand kreiere
-function.getgpsies=Gpsies Tracks hol\u00e4
-function.uploadgpsies=Date zum Gpsies uufalad\u00e4
 function.lookupsrtm=H\u00f6hendate vonem SRTM hole
 function.downloadsrtm=SRTM Files abalade
 function.getwikipedia=Im Wikipedia in dr N\u00f6chi naaluege
@@ -119,6 +119,7 @@ function.searchopencachingde=OpenCaching.de durasueche
 function.mapillary=Mapillary na F\u00f6telis durasueche
 function.downloadosm=OSM-Date f\u00fcr dere Gebiet abalad\u00e4
 function.duplicatepoint=Punkt verdoppl\u00e4
+function.projectpoint=Punkt projizier\u00e4
 function.correlatephotos=F\u00f6telis korrelier\u00e4
 function.rearrangephotos=F\u00f6telis reorganisier\u00e4
 function.rotatephotoleft=F\u00f6teli nach Links dr\u00e4y\u00e4
@@ -363,19 +364,6 @@ 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.confirmopenpage=Websiite f\u00fcrn uufagladenen Track \u00f6ffne?
-dialog.gpsies.activities=Aktivit\u00e4ten
-dialog.gpsies.activity.trekking=Wandere
-dialog.gpsies.activity.walking=Z'Fuess gah
-dialog.gpsies.activity.jogging=Seggle
-dialog.gpsies.activity.biking=Velotour
-dialog.gpsies.activity.motorbiking=Motorrad
-dialog.gpsies.activity.snowshoe=Schneeschuh
-dialog.gpsies.activity.sailing=Segle
-dialog.gpsies.activity.skating=Inline-Skate
 dialog.mapillary.nonefound=Kei F\u00f6telis gfunde
 dialog.wikipedia.column.name=Artikelname
 dialog.wikipedia.column.distance=Entf\u00e4rnig
@@ -443,6 +431,10 @@ dialog.deletemarked.nonefound=Kei P\u00fcnkte h\u00e4tte gel\u00f6scht werde k\u
 dialog.pastecoordinates.desc=G\u00e4bet Sie hier die Koordinaten inn\u00e4
 dialog.pastecoordinates.coords=Koordinate
 dialog.pastecoordinates.nothingfound=Pr\u00fcefet Sie die Koordinate und versuechet nomal
+dialog.pastecoordinatelist.desc=G\u00e4bet Sie hier die Koordinaten inn\u00e4, j\u00e4de Ziile git n Punkt
+dialog.pluscode.desc=G\u00e4bet Sie hier den Code ii
+dialog.pluscode.code=Pluscode
+dialog.pluscode.nothingfound=Tut mer leid, n\u00fc\u00fct gfunde
 dialog.help.help=Lueget Sie na\n https://gpsprune.activityworkshop.net/\nf\u00fcr wiitere Information und Benutzeraaleitige.
 dialog.about.version=Version
 dialog.about.build=Build
@@ -482,25 +474,9 @@ 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, \u00c4nde</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.saveconfig.desc=Die folgendi Iistellige k\u00f6nne gspeicheret werde :
-dialog.saveconfig.prune.trackdirectory=Trackverzeichnis
-dialog.saveconfig.prune.photodirectory=F\u00f6teliverzeichnis
-dialog.saveconfig.prune.languagecode=Sprochecode (DE_ch)
-dialog.saveconfig.prune.languagefile=Sprochedatei
-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=Kartenservers
-dialog.saveconfig.prune.diskcache=Kartenordner
-dialog.saveconfig.prune.kmzimagewidth=Bildr\u00f6sse 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.paths.prune.gnuplotpath=Gnuplot Pfad
+dialog.paths.prune.gpsbabelpath=Gpsbabel Pfad
+dialog.paths.prune.exiftoolpath=Exiftool Pfad
 dialog.setpaths.intro=Sie k\u00f6nnet dann die Pfade f\u00fcr dia Applikatione setz\u00e4:
 dialog.setpaths.found=Pfad gfunde?
 dialog.addaltitude.noaltitudes=Dr sel\u00e4ktierte Beriich h\u00e4t keini H\u00f6chiinformation
@@ -566,6 +542,9 @@ dialog.displaysettings.wpicon.pin=Stossnadeli
 dialog.displaysettings.size.small=Chli
 dialog.displaysettings.size.medium=Mittel
 dialog.displaysettings.size.large=Gross
+dialog.displaysettings.windowstyle=F\u00e4nsterstil (Neustart n\u00f6tig)
+dialog.displaysettings.windowstyle.default=Standart
+dialog.displaysettings.windowstyle.nimbus=Nimbus
 dialog.downloadosm.desc=Best\u00e4tige um rohi OSM Date f\u00fcrn Gebiet aba zlade:
 dialog.searchwikipedianames.search=Sueche na:
 dialog.weather.location=Ort
@@ -608,6 +587,12 @@ dialog.autoplay.usetimestamps=Ziitst\u00e4mple verw\u00e4nde
 dialog.autoplay.rewind=Zum Aafang
 dialog.autoplay.pause=Pause
 dialog.autoplay.play=Abschpiele
+dialog.markers.halves=P\u00fcnkt ufem halben Weg
+dialog.markers.half.distance=Halbe Distanz
+dialog.markers.half.climb=Halber Uufstieg
+dialog.markers.half.descent=Halber Abstieg
+dialog.projectpoint.desc=Richtig und Distanz iigeh, mit dene s zu projizieren isch
+dialog.projectpoint.bearing=Azimut (Grad vo N)
 
 # 3d window
 dialog.3d.title=GpsPrune Dr\u00fc\u00fc-d Aasicht
@@ -629,7 +614,7 @@ confirm.rearrangephotos=Fotos umorganisiert
 confirm.splitsegments=Es sin %d Schnitte gmacht worde
 confirm.sewsegments=Es sin %d Verbindige gemacht worde
 confirm.cutandmove=Beriich gmoved
-confirm.interpolate=P\u00fcnkte iigf\u00fcgt worde
+confirm.pointsadded=%d P\u00fcnkte iigf\u00fcgt worde
 confirm.convertnamestotimes=Waypointname verwondlet
 confirm.saveexif.ok=Es sin %d F\u00f6telis gschriebe worde
 confirm.undo.single=Operation r\u00fcckg\u00e4ngig gmacht worde.
@@ -686,7 +671,6 @@ 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
@@ -759,6 +743,7 @@ map.overzoom=Kei Karte mit diesem Zoom
 # Field names
 fieldname.latitude=Breitegrad
 fieldname.longitude=L\u00e4ngegrad
+fieldname.coordinates=Koordinate
 fieldname.altitude=H\u00f6chi
 fieldname.timestamp=Ziitst\u00e4mpel
 fieldname.time=Ziit
@@ -773,6 +758,7 @@ fieldname.duration=Ziitl\u00e4ngi
 fieldname.speed=Gschwindikeit
 fieldname.verticalspeed=Uf/Ab Gschwindikeit
 fieldname.description=Bschriibig
+fieldname.comment=Aamerkig
 fieldname.mediafilename=F\u00f6teli- / Audioname
 
 # Measurement units
@@ -866,6 +852,7 @@ 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.othererror=F\u00e4hle bim L\u00e4se:
+error.load.nopointsintext=Kei g\u00fcltigi Koordinate gfunde
 error.jpegload.dialogtitle=F\u00e4hle bim Lade von F\u00f6telis
 error.jpegload.nofilesfound=Kei Files gfunde
 error.jpegload.nojpegsfound=Kei Jpegs gfunde
index 76939263c9d8af07fa36db1f1686cf99550180dd..dbc4be4a59d3cff49a9dbea409a07beab1dca1cc 100644 (file)
@@ -98,11 +98,13 @@ function.findwaypoint=Find waypoint
 function.rearrangewaypoints=Rearrange waypoints
 function.convertnamestotimes=Convert waypoint names to times
 function.deletefieldvalues=Delete field values
-function.pastecoordinates=Enter new coordinates
+function.pastecoordinates=Enter point coordinates
+function.pastecoordinatelist=Enter list of coordinates
+function.enterpluscode=Enter pluscode
 function.charts=Charts
 function.show3d=Three-D view
 function.distances=Distances
-function.fullrangedetails=Full range details
+function.viewfulldetails=Full details
 function.estimatetime=Estimate time
 function.learnestimationparams=Learn time estimation parameters
 function.autoplay=Autoplay track
@@ -110,8 +112,6 @@ function.selectsegment=Select current segment
 function.splitsegments=Split track into segments
 function.sewsegments=Sew track segments together
 function.createmarkerwaypoints=Create marker waypoints
-function.getgpsies=Get Gpsies tracks
-function.uploadgpsies=Upload track to Gpsies
 function.lookupsrtm=Get altitudes from SRTM
 function.downloadsrtm=Download SRTM tiles
 function.getwikipedia=Get nearby Wikipedia articles
@@ -121,6 +121,7 @@ function.searchopencachingde=Search OpenCaching.de
 function.mapillary=Search for photos in Mapillary
 function.downloadosm=Download OSM data for area
 function.duplicatepoint=Duplicate point
+function.projectpoint=Project point
 function.connecttopoint=Connect to point
 function.disconnectfrompoint=Disconnect from point
 function.removephoto=Remove photo
@@ -370,19 +371,6 @@ dialog.gpsies.column.length=Length
 dialog.gpsies.description=Description
 dialog.gpsies.nodescription=No description
 dialog.gpsies.nonefound=No tracks found
-dialog.gpsies.username=Gpsies username
-dialog.gpsies.password=Gpsies password
-dialog.gpsies.keepprivate=Keep track private
-dialog.gpsies.confirmopenpage=Open the web page for the uploaded track?
-dialog.gpsies.activities=Activity types
-dialog.gpsies.activity.trekking=Hiking
-dialog.gpsies.activity.walking=Walking
-dialog.gpsies.activity.jogging=Running
-dialog.gpsies.activity.biking=Cycling
-dialog.gpsies.activity.motorbiking=Motorbiking
-dialog.gpsies.activity.snowshoe=Snowshoeing
-dialog.gpsies.activity.sailing=Sailing
-dialog.gpsies.activity.skating=Skating
 dialog.mapillary.nonefound=No photos found
 dialog.wikipedia.column.name=Article name
 dialog.wikipedia.column.distance=Distance
@@ -450,6 +438,10 @@ 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.pastecoordinatelist.desc=Enter the coordinates for the new points with one point per line
+dialog.pluscode.desc=Enter or paste the pluscode here
+dialog.pluscode.code=Pluscode
+dialog.pluscode.nothingfound=Please check the code and try again
 dialog.help.help=Please see\n https://gpsprune.activityworkshop.net/\nfor more information and tips,\nincluding a PDF user guide you can buy.
 dialog.about.version=Version
 dialog.about.build=Build
@@ -489,25 +481,9 @@ dialog.keys.intro=You can use the following shortcut keys instead of using the m
 dialog.keys.keylist=<table><tr><td>Arrow keys</td><td>Pan map left right, up, down</td></tr><tr><td>Ctrl + left, right arrow</td><td>Select previous or next point</td></tr><tr><td>Ctrl + up, down arrow</td><td>Zoom in or out</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Select previous, next segment</td></tr><tr><td>Ctrl + Home, End</td><td>Select first, last point</td></tr><tr><td>Del</td><td>Delete current point</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=The following settings can be saved to a configuration file :
-dialog.saveconfig.prune.trackdirectory=Track directory
-dialog.saveconfig.prune.photodirectory=Photo directory
-dialog.saveconfig.prune.languagecode=Language code (EN)
-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.gnuplotpath=Path to gnuplot
-dialog.saveconfig.prune.gpsbabelpath=Path to gpsbabel
-dialog.saveconfig.prune.exiftoolpath=Path to exiftool
-dialog.saveconfig.prune.mapsource=Selected map source
-dialog.saveconfig.prune.mapsourcelist=Map sources
-dialog.saveconfig.prune.diskcache=Map cache
-dialog.saveconfig.prune.kmzimagewidth=KMZ image size
-dialog.saveconfig.prune.colourscheme=Colour scheme
-dialog.saveconfig.prune.linewidth=Line width
-dialog.saveconfig.prune.kmltrackcolour=KML track colour
-dialog.saveconfig.prune.autosavesettings=Autosave settings
+dialog.paths.prune.gnuplotpath=Path to gnuplot
+dialog.paths.prune.gpsbabelpath=Path to gpsbabel
+dialog.paths.prune.exiftoolpath=Path to exiftool
 dialog.setpaths.intro=If you need to, you can choose the paths to the external applications:
 dialog.setpaths.found=Path found?
 dialog.addaltitude.noaltitudes=The selected range does not contain altitudes
@@ -574,6 +550,9 @@ dialog.displaysettings.wpicon.pin=Board pin
 dialog.displaysettings.size.small=Small
 dialog.displaysettings.size.medium=Medium
 dialog.displaysettings.size.large=Large
+dialog.displaysettings.windowstyle=Window style (requires restart)
+dialog.displaysettings.windowstyle.default=Default
+dialog.displaysettings.windowstyle.nimbus=Nimbus
 dialog.downloadosm.desc=Confirm to download the raw OSM data for the specified area:
 dialog.searchwikipedianames.search=Search for:
 dialog.weather.location=Location
@@ -616,6 +595,12 @@ dialog.autoplay.usetimestamps=Use point timestamps
 dialog.autoplay.rewind=Back to beginning
 dialog.autoplay.pause=Pause
 dialog.autoplay.play=Play
+dialog.markers.halves=Halfway points
+dialog.markers.half.distance=Half distance
+dialog.markers.half.climb=Half climb
+dialog.markers.half.descent=Half descent
+dialog.projectpoint.desc=Enter the direction and distance to project this point
+dialog.projectpoint.bearing=Bearing (degrees from N)
 
 # 3d window
 dialog.3d.title=GpsPrune Three-d view
@@ -637,7 +622,7 @@ confirm.rearrangephotos=Photos rearranged
 confirm.splitsegments=%d segment splits were made
 confirm.sewsegments=%d segment joins were made
 confirm.cutandmove=Selection moved
-confirm.interpolate=Points added
+confirm.pointsadded=%d points added
 confirm.convertnamestotimes=Waypoint names converted
 confirm.saveexif.ok=Saved %d photo files
 confirm.undo.single=operation undone
@@ -693,7 +678,6 @@ button.selectall=Select all
 button.selectnone=Select none
 button.preview=Preview
 button.load=Load
-button.upload=Upload
 button.guessfields=Guess fields
 button.showwebpage=Show webpage
 button.check=Check
@@ -767,6 +751,7 @@ map.overzoom=No maps available at this zoom level
 # Field names
 fieldname.latitude=Latitude
 fieldname.longitude=Longitude
+fieldname.coordinates=Coordinates
 fieldname.altitude=Altitude
 fieldname.timestamp=Time
 fieldname.time=Time
@@ -781,6 +766,7 @@ fieldname.duration=Duration
 fieldname.speed=Speed
 fieldname.verticalspeed=Vertical speed
 fieldname.description=Description
+fieldname.comment=Comment
 fieldname.mediafilename=Filename
 
 # Measurement units
@@ -880,6 +866,7 @@ error.load.nopoints=No coordinate information found in the file
 error.load.unknownxml=Unrecognised xml format:
 error.load.noxmlinzip=No xml file found inside zip file
 error.load.othererror=Error reading file:
+error.load.nopointsintext=No coordinate information found
 error.jpegload.dialogtitle=Error loading photos
 error.jpegload.nofilesfound=No files found
 error.jpegload.nojpegsfound=No jpeg files found
index d6724aba79ac694a595f345e8f84bad3ab3e1a3f..e70c8d38213609e134ec220b0d56985a42aa2b2f 100644 (file)
@@ -6,9 +6,6 @@ function.setcolours=Set colors
 
 # Dialogs
 dialog.exportkml.trackcolour=Track color
-dialog.saveconfig.prune.languagecode=Language code (EN_US)
-dialog.saveconfig.prune.colourscheme=Color scheme
-dialog.saveconfig.prune.kmltrackcolour=KML track color
 dialog.setcolours.intro=Click on a color patch to change the color
 dialog.colourchooser.title=Choose color
 dialog.colourer.intro=A point colorer can give track points different colors
index 07cfeca4ecefde9d59cbbb35de48d5d7133025fa..e4676f684a2c61730722ab78fbdd5a6418a22dd8 100644 (file)
@@ -102,7 +102,7 @@ function.pastecoordinates=Insertar nuevas coordenadas
 function.charts=Diagramas
 function.show3d=Mostrar en 3-D
 function.distances=Distancias
-function.fullrangedetails=Detalles adicionales de rango
+function.viewfulldetails=Detalles adicionales
 function.estimatetime=Estimar duraci\u00f3n
 function.learnestimationparams=Apprender parametros por la estimaci\u00f3n del tiempo
 function.autoplay=Jugar track
@@ -111,8 +111,6 @@ function.setpaths=Configurar rutas del programas
 function.selectsegment=Seleccionar segmento actual
 function.splitsegments=Segmentar el track
 function.sewsegments=Ensamblar los segmentos
-function.getgpsies=Bajar ruta de Gpsies
-function.uploadgpsies=Subir recorrido a Gpsies
 function.lookupsrtm=Obtener altitudes de SRTM
 function.downloadsrtm=Descargar datos de SRTM
 function.getwikipedia=Obtener art\u00edculos de Wikipedia cercanos
@@ -367,19 +365,6 @@ dialog.gpsies.column.length=Distancia
 dialog.gpsies.description=Descripci\u00f3n
 dialog.gpsies.nodescription=Sin descripci\u00f3n
 dialog.gpsies.nonefound=No se encontraron pistas
-dialog.gpsies.username=Nombre de usuario en Gpsies
-dialog.gpsies.password=Contrase\u00f1a de Gpsies
-dialog.gpsies.keepprivate=Mantener el recorrido como privado
-dialog.gpsies.confirmopenpage=Abrir la p\u00e1gina web del recorrido subido
-dialog.gpsies.activities=Apto para
-dialog.gpsies.activity.trekking=Excursi\u00f3n
-dialog.gpsies.activity.walking=Caminar
-dialog.gpsies.activity.jogging=Correr
-dialog.gpsies.activity.biking=En bicicleta
-dialog.gpsies.activity.motorbiking=En moto
-dialog.gpsies.activity.snowshoe=Raquetas de nieve
-dialog.gpsies.activity.sailing=Vela
-dialog.gpsies.activity.skating=Patinaje
 dialog.mapillary.nonefound=No se encontraron fotos
 dialog.wikipedia.column.name=Nombre del art\u00edculo
 dialog.wikipedia.column.distance=Distancia
@@ -486,25 +471,9 @@ dialog.keys.intro=Usted puede usar el siguiente atajo en lugar de usar el rat\u0
 dialog.keys.keylist=<table><tr><td>Teclas de cursor</td><td>Desplazar a la izquierde, derecha, arriba, abajo</td></tr><tr><td>Ctrl + cursor izquierda, derecha</td><td>Seleccionar punto siguiente o anterior</td></tr><tr><td>Ctrl + cursor arriba, abajo</td><td>Ampliar o reducir zoom</td></tr><tr><td>Ctrl + Av Pag, Re Pag</td><td>Seleccionar segmento siguiente, anterior</td></tr><tr><td>Ctrl + Inicio, Fin</td><td>Seleccionar primer, \u00faltimo punto</td></tr><tr><td>Supr</td><td>Eliminar punto actual</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=La siguiente configuraci\u00f3n puede ser salvada en un archivo de configuraci\u00f3n
-dialog.saveconfig.prune.trackdirectory=Directorio de pista
-dialog.saveconfig.prune.photodirectory=Directorio de foto
-dialog.saveconfig.prune.languagecode=C\u00f3digo de lenguaje (ES)
-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.gnuplotpath=Ruta a gnuplot
-dialog.saveconfig.prune.gpsbabelpath=Ruta a gpsbabel
-dialog.saveconfig.prune.exiftoolpath=Ruta a exiftool
-dialog.saveconfig.prune.mapsource=Proveedor de mapas seleccionado
-dialog.saveconfig.prune.mapsourcelist=Proveedor de mapas
-dialog.saveconfig.prune.diskcache=Memoria intermedia de mapas
-dialog.saveconfig.prune.kmzimagewidth=Ancho de im\u00e1genes en KMZ
-dialog.saveconfig.prune.colourscheme=Color de esquema
-dialog.saveconfig.prune.linewidth=Ancho de l\u00ednea
-dialog.saveconfig.prune.kmltrackcolour=Color de pista de KML
-dialog.saveconfig.prune.autosavesettings=Guardar preferencias al salir
+dialog.paths.prune.gnuplotpath=Ruta a gnuplot
+dialog.paths.prune.gpsbabelpath=Ruta a gpsbabel
+dialog.paths.prune.exiftoolpath=Ruta a exiftool
 dialog.setpaths.intro=Si usted necesita, puede escoger las rutas a aplicaciones externas
 dialog.setpaths.found=\u00bfRuta encontrada?
 dialog.addaltitude.noaltitudes=Los rangos seleccionados no contienen altitudes
@@ -619,10 +588,10 @@ confirm.addtimeoffset=A\u00f1adido margen de tiempo
 confirm.addaltitudeoffset=A\u00f1adido margen de altitud
 confirm.rearrangewaypoints=Waypoints reorganizados
 confirm.rearrangephotos=Fotos reacomodadas
-confirm.splitsegments=%d escisiones fueron hechas
-confirm.sewsegments=%d conexiones fueron hechas
+confirm.splitsegments=Se han hecho %d divisiones
+confirm.sewsegments=Se han hecho %d uniones
 confirm.cutandmove=Mover selecci\u00f3n
-confirm.interpolate=Puntos insertados
+confirm.pointsadded=%d puntos insertados
 confirm.convertnamestotimes=Nombres de "waypoint" convertidos
 confirm.saveexif.ok=Guardado %d fotos
 confirm.undo.single=operaci\u00f3n deshecha
@@ -648,9 +617,6 @@ confirm.correlateaudios.multi=Los audios fueron correlacionados
 
 ## Tips, shown just once when appropriate
 tip.title=Sugerencia
-tip.useamapcache=By setting up a disk cache (Preferencias -> Guardar mapas en disco)\nyou can speed up the display and reduce network traffic.
-tip.learntimeparams=The results will be more accurate if you use\nTrack -> Apprender parametros por la estimaci\u00f3n del tiempo\non your recorded tracks.
-tip.downloadsrtm=You can speed this up by calling\nOnline -> Descargar datos de SRTM\nto save the data in your map cache.
 tip.manuallycorrelateone=Correlacionando al menos una foto manualmente, el margen de tiempo se calcula autom\u00e1ticamente.
 
 ## Buttons
@@ -676,7 +642,6 @@ button.selectall=Seleccionar todo
 button.selectnone=Seleccionar nada
 button.preview=Previsualizaci\u00f3n
 button.load=Cargar
-button.upload=Subir
 button.guessfields=Adivinar campos
 button.showwebpage=Mostrar p\u00e1gina web
 button.check=Verificar
@@ -750,6 +715,7 @@ map.overzoom=No existen mapas disponibles con este nivel de enfoque
 ## Field names
 fieldname.latitude=Latitud
 fieldname.longitude=Longitud
+fieldname.coordinates=Coordenadas
 fieldname.altitude=Altitud
 fieldname.timestamp=Informaci\u00f3n de tiempo
 fieldname.time=Tiempo
@@ -893,3 +859,29 @@ error.cache.cannotdelete=No se pudieron borrar recuadros
 error.tracksplit.nosplit=Imposible segmentar el track
 error.downloadsrtm.nocache=Imposible guardar los archivos.\nPor favor, compruebe el cache.
 error.sewsegments.nothingdone=Imposible ensamblar los segmentos.\nEl track tiene ahora %d segmentos.
+
+dialog.exportimage.noimagepossible=Las im\u00e1genes de mapas deben ser guardadas para poder usarlas para una exportaci\u00f3n.
+dialog.estimatetime.error.nodistance=Las estimaciones de tiempo necesitan puntos de v\u00eda conectados, para dar una distancia
+dialog.learnestimationparams.intro=Estos son los par\u00e1metros calculados a partir del track
+dialog.learnestimationparams.combine=Estos par\u00e1metros se pueden combinar con los valores actuales
+dialog.weather.creditnotice=Estos datos est\u00e1n disponibles en openweathermap.org. Su sitio web tiene m\u00e1s detalles.
+dialog.deletebydate.onlyonedate=Todos los puntos se registraron en la misma fecha.
+dialog.deletebydate.intro=Para cada fecha del track, puede elegir entre borrar o mantener los puntos
+confirm.downloadsrtm.none=No se descargaron archivos, ya estaban en la cache
+tip.useamapcache=Configurando una cach\u00e9 de disco (Preferencias -> Guardar mapas en disco)\npuede acelerar la visualizaci\u00f3n y reducir el tr\u00e1fico de la red.
+tip.learntimeparams=Los resultados ser\u00e1n m\u00e1s precisos si utiliza\nTrack -> Aprender par\u00e1metros de estimaci\u00f3n de tiempo\nen sus pistas grabadas.
+tip.downloadsrtm=Puede acelerar esto si llama a\nOnline -> Descargar datos de SRTM\npara guardar los datos en su cach\u00e9 de mapas.
+tip.usesrtmfor3d=Esta pista no tiene altitudes.\nPuede utilizar las funciones del SRTM\npara obtener altitudes aproximadas para la vista 3d.
+error.learnestimationparams.failed=No puede aprender los par\u00e1metros de esta pista.\nIntente cargar m\u00e1s pistas.
+function.enterpluscode=Insertar c\u00f3digo plus
+function.projectpoint=Proyectar punto
+dialog.pastecoordinatelist.desc=Introducir las coordenadas de los nuevos puntos con un punto por l\u00ednea
+dialog.pluscode.desc=Introduzca o pegue el c\u00f3digo plus aqu\u00ed
+dialog.pluscode.code=C\u00f3digo plus
+dialog.pluscode.nothingfound=Por favor, compruebe el c\u00f3digo e int\u00e9ntelo de nuevo
+dialog.displaysettings.windowstyle=Estilo de la ventana
+dialog.projectpoint.desc=Introduzca la direcci\u00f3n y la distancia para proyectar este punto
+dialog.projectpoint.bearing=Azimut (grados desde el Norte)
+fieldname.comment=Comentario
+dialog.settimezone.selectedzone=Zona horaria seleccionada
+function.selecttimezone=Seleccionar la zona horaria
index e6d686078ba049b2642ae823d1117864284c7df3..8b54aa65bc4c0993229655f5c790446b4344042c 100644 (file)
@@ -100,7 +100,6 @@ function.pastecoordinates=Anna uudet koordinaatit...
 function.charts=Kaaviot
 function.show3d=3D-n\u00e4kym\u00e4
 function.distances=V\u00e4limatkat
-function.fullrangedetails=Koko pistealueen tiedot
 function.estimatetime=Arvioi aika
 function.learnestimationparams=Opi aika-arvion parametrit
 function.autoplay=Animoi reitti
@@ -108,8 +107,6 @@ function.selectsegment=Valitse nykyinen lohko
 function.splitsegments=Pilko reitti lohkoihin
 function.sewsegments=Yhdist\u00e4 reittilohkot
 function.createmarkerwaypoints=Luo merkityt kohdepisteet
-function.getgpsies=Lataa reitit Gpsies.com:sta
-function.uploadgpsies=Vie reitti Gpsies.com:iin...
 function.lookupsrtm=Lue korkeysk\u00e4yr\u00e4t SRTM:st\u00e4
 function.downloadsrtm=Lataa SRTM-palat
 function.getwikipedia=Hae likeiset Wikipedia-artikkelit
@@ -362,18 +359,6 @@ dialog.gpsies.column.length=Pituus
 dialog.gpsies.description=Kuvaus
 dialog.gpsies.nodescription=Ei kuvausta
 dialog.gpsies.nonefound=Reittej\u00e4 ei l\u00f6ytynyt
-dialog.gpsies.username=Gpsies.com:n k\u00e4ytt\u00e4j\u00e4nimi
-dialog.gpsies.password=Gpsies.com:n salasana
-dialog.gpsies.keepprivate=Pid\u00e4 reitti yksityisen\u00e4
-dialog.gpsies.activities=Aktiviteettityypit
-dialog.gpsies.activity.trekking=Patikointi
-dialog.gpsies.activity.walking=K\u00e4vely
-dialog.gpsies.activity.jogging=Juoksu
-dialog.gpsies.activity.biking=Polkupy\u00f6r\u00e4ily
-dialog.gpsies.activity.motorbiking=Moottoripy\u00f6r\u00e4ily
-dialog.gpsies.activity.snowshoe=Lumikenk\u00e4ily
-dialog.gpsies.activity.sailing=Purjehdus
-dialog.gpsies.activity.skating=Luistelu
 dialog.mapillary.nonefound=Kuvia ei l\u00f6ytynyt
 dialog.wikipedia.column.name=Artikkelin nimi
 dialog.wikipedia.column.distance=V\u00e4limatka
@@ -480,25 +465,9 @@ dialog.keys.intro=Voit hiiren asemesta k\u00e4ytt\u00e4\u00e4 seuraavia n\u00e4p
 dialog.keys.keylist=<table><tr><td>Nuolin\u00e4pp\u00e4imill\u00e4</td><td>voit siirt\u00e4\u00e4 kartaa vasemmalle, oikealle, yl\u00f6s ja alas</td></tr><tr><td>Ctrl + vasen/oikea nuoli\u00e4pp\u00e4in</td><td>Valitse edellinen/seuraava reittipiste</td></tr><tr><td>Ctrl + yl\u00f6s/alas nuolin\u00e4pp\u00e4in</td><td>L\u00e4henn\u00e4 tai loitonna</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Valitse edellinen/seuraava pistelohko</td></tr><tr><td>Ctrl + Home, End</td><td>Valitse ensimm\u00e4inen/viimeinen reittipiste</td></tr><tr><td>Del</td><td>Poista valittu reittipiste</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=Seuraava asetukset voidaan tallentaa asetustiedostoon:
-dialog.saveconfig.prune.trackdirectory=Reittihakemisto
-dialog.saveconfig.prune.photodirectory=Kuvahakemisto
-dialog.saveconfig.prune.languagecode=Kielitunnus (FI)
-dialog.saveconfig.prune.languagefile=Kielitiedosto
-dialog.saveconfig.prune.gpsdevice=GPS-laite
-dialog.saveconfig.prune.gpsformat=GPS-formaatti
-dialog.saveconfig.prune.povrayfont=Povray fontti
-dialog.saveconfig.prune.gnuplotpath=Polku ohjelmaan gnuplot
-dialog.saveconfig.prune.gpsbabelpath=Polku ohjelmaan gpsbabel
-dialog.saveconfig.prune.exiftoolpath=Polku ohjelmaan exiftool
-dialog.saveconfig.prune.mapsource=Valittu karttal\u00e4hde
-dialog.saveconfig.prune.mapsourcelist=Karttal\u00e4hteet
-dialog.saveconfig.prune.diskcache=Karttojen v\u00e4limuisti
-dialog.saveconfig.prune.kmzimagewidth=KMZ:in kuvan leveys
-dialog.saveconfig.prune.colourscheme=V\u00e4rij\u00e4rjestelm\u00e4
-dialog.saveconfig.prune.linewidth=Viivan leveys
-dialog.saveconfig.prune.kmltrackcolour=KML:n reitin v\u00e4ri
-dialog.saveconfig.prune.autosavesettings=Tallenna asetukset automaattisesti
+dialog.paths.prune.gnuplotpath=Polku ohjelmaan gnuplot
+dialog.paths.prune.gpsbabelpath=Polku ohjelmaan gpsbabel
+dialog.paths.prune.exiftoolpath=Polku ohjelmaan exiftool
 dialog.setpaths.intro=Halutessasi voit valita hakemistopolut ulkoisiin sovelluksiin:
 dialog.setpaths.found=Polku l\u00f6ydetty?
 dialog.addaltitude.noaltitudes=Valittu alue ei sis\u00e4ll\u00e4 korkeustietoja
@@ -664,7 +633,6 @@ button.selectall=Valitse kaikki
 button.selectnone=Valitse 'ei mit\u00e4\u00e4n'
 button.preview=Esikatselu
 button.load=Lataa
-button.upload=Uppaa
 button.guessfields=Arvaa kent\u00e4t
 button.showwebpage=N\u00e4yt\u00e4 webbisivu
 button.check=Tarkista
index f884c0215623c2c1da16cd9cb8978b22baf7ef31..9c0f85a460b5bbf533012c907d1873402546a107 100644 (file)
@@ -100,7 +100,7 @@ function.pastecoordinates=Coller les coordonn\u00e9es
 function.charts=Graphiques
 function.show3d=Montrer en 3D
 function.distances=Distances
-function.fullrangedetails=Montrer tous les d\u00e9tails
+function.viewfulldetails=Montrer tous les d\u00e9tails
 function.estimatetime=Temps estim\u00e9
 function.learnestimationparams=Apprentissage de l'estimation
 function.setmapbg=D\u00e9finir le fond de carte
@@ -109,8 +109,6 @@ function.autoplay=Jouer la trace
 function.selectsegment=S\u00e9lectionner le segment courant
 function.splitsegments=S\u00e9pare les segments
 function.sewsegments=R\u00e9unis les segments
-function.getgpsies=R\u00e9cup\u00e9rer les traces Gpsies
-function.uploadgpsies=T\u00e9l\u00e9charger la trace sur Gpsies
 function.lookupsrtm=R\u00e9cup\u00e9rer les altitudes depuis SRTM
 function.downloadsrtm=T\u00e9l\u00e9charger les donn\u00e9es SRTM
 function.getwikipedia=Obtenir les articles de Wikip\u00e9dia \u00e0 proximit\u00e9
@@ -359,19 +357,6 @@ dialog.gpsies.column.length=Distance
 dialog.gpsies.description=Description
 dialog.gpsies.nodescription=Aucune description
 dialog.gpsies.nonefound=Aucune trace trouv\u00e9e
-dialog.gpsies.username=Nom d'utilisateur Gpsies
-dialog.gpsies.password=Mot de passe Gpsies
-dialog.gpsies.keepprivate=Trace priv\u00e9e
-dialog.gpsies.confirmopenpage=Ouvrir la page web de la trace t\u00e9l\u00e9charg\u00e9e ?
-dialog.gpsies.activities=Activit\u00e9
-dialog.gpsies.activity.trekking=Trekking
-dialog.gpsies.activity.walking=Randonn\u00e9e
-dialog.gpsies.activity.jogging=Jogging
-dialog.gpsies.activity.biking=V\u00e9lo
-dialog.gpsies.activity.motorbiking=Moto
-dialog.gpsies.activity.snowshoe=Raquette
-dialog.gpsies.activity.sailing=Volle
-dialog.gpsies.activity.skating=Skating
 dialog.mapillary.nonefound=Aucun foto trouv\u00e9
 dialog.wikipedia.column.name=Nom de l'article
 dialog.wikipedia.column.distance=Distance
@@ -478,25 +463,9 @@ dialog.keys.intro=Vous pouvez utiliser ces raccourcis clavier \u00e0 la place de
 dialog.keys.keylist=<table><tr><td>Touches-fl\u00e8ches</td><td>Faire d\u00e9filer la carte horizontalement et verticalement</td></tr><tr><td>Ctrl + gauche, Ctrl + droite</td><td>Choisir le point pr\u00e9c\u00e9dent ou suivant</td></tr><tr><td>Ctrl + haut, Ctrl + bas</td><td>Zoomer, s'\u00e9loigner</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Choisir le segment pr\u00e9c\u00e9dent ou suivant</td></tr><tr><td>Ctrl + Home, End</td><td>Choisir le point premier, dernier</td></tr><tr><td>Suppr</td><td>Effacer le point courant</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=Les param\u00e8tres suivants peuvent \u00eatre sauvegard\u00e9s dans un fichier de configuration:
-dialog.saveconfig.prune.trackdirectory=Dossier des traces
-dialog.saveconfig.prune.photodirectory=Dossier des Photos
-dialog.saveconfig.prune.languagecode=Code langue (FR)
-dialog.saveconfig.prune.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.gnuplotpath=Chemin gnuplot
-dialog.saveconfig.prune.gpsbabelpath=Chemin gpsbabel
-dialog.saveconfig.prune.exiftoolpath=Chemin exiftool
-dialog.saveconfig.prune.mapsource=Carte source s\u00e9lectionn\u00e9e
-dialog.saveconfig.prune.mapsourcelist=Sources de cartes
-dialog.saveconfig.prune.diskcache=Cache de carte
-dialog.saveconfig.prune.kmzimagewidth=Largeur de l'image KMZ
-dialog.saveconfig.prune.colourscheme=Mod\u00e8le de couleurs
-dialog.saveconfig.prune.linewidth=Largeur de ligne
-dialog.saveconfig.prune.kmltrackcolour=Couleur de la trace KML
-dialog.saveconfig.prune.autosavesettings=R\u00e9glages de sauvegarde automatique
+dialog.paths.prune.gnuplotpath=Chemin gnuplot
+dialog.paths.prune.gpsbabelpath=Chemin gpsbabel
+dialog.paths.prune.exiftoolpath=Chemin exiftool
 dialog.setpaths.intro=Si vous le souhaitez, vous pouvez d\u00e9finir les chemins des applications externes:
 dialog.setpaths.found=Chemin trouv\u00e9 ?
 dialog.addaltitude.noaltitudes=L'\u00e9tendue s\u00e9lectionn\u00e9e de contient pas d'altitudes
@@ -610,7 +579,7 @@ confirm.addaltitudeoffset=D\u00e9calage d'altitude ajout\u00e9
 confirm.rearrangewaypoints=Waypoints r\u00e9arrang\u00e9s
 confirm.rearrangephotos=Photos r\u00e9arrang\u00e9es
 confirm.cutandmove=S\u00e9lection d\u00e9plac\u00e9e
-confirm.interpolate=Points ajout\u00e9s
+confirm.pointsadded=%d points ajout\u00e9s
 confirm.convertnamestotimes=Noms de waypoints convertis
 confirm.saveexif.ok=Enregistr\u00e9 %d fichiers photo
 confirm.undo.single=op\u00e9ration annul\u00e9e
@@ -665,7 +634,6 @@ button.selectall=Tout s\u00e9lectionner
 button.selectnone=Ne rien s\u00e9lectionner
 button.preview=Aper\u00e7u
 button.load=T\u00e9l\u00e9charger
-button.upload=Envoyer
 button.guessfields=Deviner les champs
 button.showwebpage=Montrer page web
 button.check=V\u00e9rifier
@@ -739,6 +707,7 @@ map.overzoom=Aucune carte disponible \u00e0 ce niveau de zoom
 # Field names
 fieldname.latitude=Latitude
 fieldname.longitude=Longitude
+fieldname.coordinates=Coordonn\u00e9es
 fieldname.altitude=Altitude
 fieldname.timestamp=Date et heure
 fieldname.time=Temps
index 359ad21537623c10e61c0744bf572b9fe6e11497..021db5302dc8cbe002440f74130370f422bc36f5 100644 (file)
@@ -1,5 +1,5 @@
 # Text entries for the GpsPrune application
-# Hungarian entries thanks to Gy\u00f6rgy Ball\u00f3, Peter Bathory and Peter Gervai
+# Hungarian entries thanks to Gy\u00f6rgy Ball\u00f3, P\u00e9ter B\u00e1thory and Peter Gervai
 
 # Menu entries
 menu.file=F\u00e1jl
@@ -12,7 +12,6 @@ menu.track=Nyomvonal
 menu.track.undo=Visszavon\u00e1s
 menu.track.clearundo=Visszavon\u00e1si lista t\u00f6rl\u00e9se
 menu.track.markrectangle=N\u00e9gyzeten bel\u00fcli pontok megjel\u00f6l\u00e9se
-function.deletemarked=Jel\u00f6lt pontok t\u00f6rl\u00e9se
 menu.range=Tartom\u00e1ny
 menu.range.all=Mindet kijel\u00f6l
 menu.range.none=Kijel\u00f6l\u00e9s megsz\u00fcntet\u00e9se
@@ -38,7 +37,6 @@ menu.view.browser.yahoo=Yahoo! Maps
 menu.view.browser.bing=Bing Maps
 menu.settings=Be\u00e1ll\u00edt\u00e1sok
 menu.settings.onlinemode=T\u00e9rk\u00e9pek bet\u00f6lt\u00e9se internetr\u0151l
-dialog.displaysettings.antialias=\u00c9lsim\u00edt\u00e1s haszn\u00e1lata
 menu.settings.autosave=Be\u00e1ll\u00edt\u00e1sok automatikus ment\u00e9se kil\u00e9p\u00e9skor
 menu.help=S\u00fag\u00f3
 
@@ -86,6 +84,7 @@ function.exportpov=Export\u00e1l\u00e1s POV-ba
 function.exportimage=Export\u00e1l\u00e1s k\u00e9pbe
 function.editwaypointname=\u00datpont nev\u00e9nek szerkeszt\u00e9se
 function.compress=Nyomvonal t\u00f6m\u00f6r\u00edt\u00e9se
+function.deletemarked=Jel\u00f6lt pontok t\u00f6rl\u00e9se
 function.marklifts=S\u00edliftek megjel\u00f6l\u00e9se
 function.deleterange=Tartom\u00e1ny t\u00f6rl\u00e9se
 function.croptrack=Nyomvonal k\u00f6rbev\u00e1g\u00e1sa
@@ -101,7 +100,6 @@ function.pastecoordinates=\u00daj koordin\u00e1t\u00e1k megad\u00e1sa
 function.charts=Diagramok
 function.show3d=3D n\u00e9zet
 function.distances=T\u00e1vols\u00e1gok
-function.fullrangedetails=Teljes tartom\u00e1ny r\u00e9szletei
 function.estimatetime=Becs\u00fclt id\u0151
 function.learnestimationparams=Id\u0151becsl\u00e9s tanul\u00e1s\u00e1nak param\u00e9terei
 function.autoplay=Nyomvonal lej\u00e1tsz\u00e1sa
@@ -110,17 +108,18 @@ function.setpaths=Program\u00fatvonalak be\u00e1ll\u00edt\u00e1sa
 function.selectsegment=Aktu\u00e1lis szakasz kiv\u00e1laszt\u00e1sa
 function.splitsegments=Nyomvonal kett\u00e9v\u00e1g\u00e1sa szakaszokk\u00e1
 function.sewsegments=Nyomvonalszakaszok \u00f6sszevon\u00e1sa
-function.getgpsies=Gpsies nyomvonalak let\u00f6lt\u00e9se
-function.uploadgpsies=Nyomvonal felt\u00f6lt\u00e9se Gpsiesra
+function.createmarkerwaypoints=\u00datpont jel\u00f6l\u0151k k\u00e9sz\u00edt\u00e9se
 function.lookupsrtm=Magass\u00e1gok let\u00f6lt\u00e9se SRTM-r\u0151l
 function.downloadsrtm=SRTM csemp\u00e9k let\u00f6lt\u00e9se
 function.getwikipedia=K\u00f6zeli Wikip\u00e9dia sz\u00f3cikkek let\u00f6lt\u00e9se
 function.searchwikipedianames=Keres\u00e9s a Wikip\u00e9di\u00e1ban n\u00e9v szerint
+function.searchosmpois=K\u00f6zeli OSM pontok
 function.searchopencachingde=Keres\u00e9s az OpenCaching.de-n
 function.mapillary=F\u00e9nyk\u00e9pek keres\u00e9se Mapillary-n
 function.downloadosm=OSM adatok let\u00f6lt\u00e9se a ter\u00fcletr\u0151l
 function.duplicatepoint=Pont kett\u0151z\u00e9se
 function.setcolours=Sz\u00ednek be\u00e1ll\u00edt\u00e1sa
+function.setdisplaysettings=Megjelen\u00edt\u00e9s be\u00e1ll\u00edt\u00e1sa
 function.setlanguage=Nyelv be\u00e1ll\u00edt\u00e1sa
 function.connecttopoint=Kapcsol\u00e1s ponthoz
 function.disconnectfrompoint=Lev\u00e1laszt\u00e1s pontr\u00f3l
@@ -145,6 +144,7 @@ function.diskcache=T\u00e9rk\u00e9pek ment\u00e9se lemezre
 function.managetilecache=Csempegyors\u00edt\u00f3t\u00e1r kezel\u00e9se
 function.getweatherforecast=Id\u0151j\u00e1r\u00e1s el\u0151rejelz\u00e9s
 function.setaltitudetolerance=Magass\u00e1gi t\u0171r\u00e9s be\u00e1ll\u00edt\u00e1sa
+function.selecttimezone=Id\u0151z\u00f3na be\u00e1ll\u00edt\u00e1sa
 
 # Dialogs
 dialog.exit.confirm.title=Kil\u00e9p\u00e9s a GpsPrune-b\u00f3l
@@ -173,7 +173,7 @@ dialog.openoptions.deliminfo.norecords=Nincsenek rekordok
 dialog.openoptions.altitudeunits=Magass\u00e1g m\u00e9rt\u00e9kegys\u00e9ge
 dialog.openoptions.speedunits=Sebess\u00e9g m\u00e9rt\u00e9kegys\u00e9ge
 dialog.openoptions.vertspeedunits=F\u00fcgg\u0151leges sebess\u00e9g m\u00e9rt\u00e9kegys\u00e9ge
-dialog.openoptions.vspeed.positiveup=Pozit\u00edv sebess\u00e9g m\u00e9rt\u00e9kegys\u00e9ge
+dialog.openoptions.vspeed.positiveup=Pozit\u00edv sebess\u00e9g felfel\u00e9
 dialog.openoptions.vspeed.positivedown=Pozit\u00edv sebess\u00e9g lefel\u00e9
 dialog.open.contentsdoubled=Ez a f\u00e1jl minden egyes pont k\u00e9t p\u00e9ld\u00e1ny\u00e1t tartalmazza,\negyszer mint \u00fatpont, m\u00e1sodszor mint nyompont.
 dialog.selecttracks.intro=Nyomvonal vagy nyomvonalak kiv\u00e1laszt\u00e1sa bet\u00f6lt\u00e9shez
@@ -364,24 +364,14 @@ dialog.gpsies.column.length=Hossz
 dialog.gpsies.description=Le\u00edr\u00e1s
 dialog.gpsies.nodescription=Nincs le\u00edr\u00e1s
 dialog.gpsies.nonefound=Nem tal\u00e1lhat\u00f3 nyomvonal
-dialog.gpsies.username=Gpsies felhaszn\u00e1l\u00f3n\u00e9v
-dialog.gpsies.password=Gpsies jelsz\u00f3
-dialog.gpsies.keepprivate=A nyomvonal maradjon priv\u00e1t
-dialog.gpsies.confirmopenpage=Megnyitja a weboldalt a felt\u00f6lt\u00f6tt nyomvonal sz\u00e1m\u00e1ra?
-dialog.gpsies.activities=Tev\u00e9kenys\u00e9gt\u00edpusok
-dialog.gpsies.activity.trekking=T\u00far\u00e1z\u00e1s
-dialog.gpsies.activity.walking=S\u00e9ta
-dialog.gpsies.activity.jogging=Fut\u00e1s
-dialog.gpsies.activity.biking=Ker\u00e9kp\u00e1roz\u00e1s
-dialog.gpsies.activity.motorbiking=Motorker\u00e9kp\u00e1roz\u00e1s
-dialog.gpsies.activity.snowshoe=H\u00f3talpas s\u00e9ta
-dialog.gpsies.activity.sailing=Vitorl\u00e1z\u00e1s
-dialog.gpsies.activity.skating=Korcsoly\u00e1z\u00e1s
 dialog.mapillary.nonefound=Nem tal\u00e1lhat\u00f3k f\u00e9nyk\u00e9pek
 dialog.wikipedia.column.name=Sz\u00f3cikk neve
 dialog.wikipedia.column.distance=T\u00e1vols\u00e1g
 dialog.wikipedia.nonefound=Nem tal\u00e1lhat\u00f3 Wikip\u00e9dia sz\u00f3cikk
 dialog.wikipedia.gallery=Gal\u00e9ria
+dialog.osmpois.column.name=N\u00e9v
+dialog.osmpois.column.type=T\u00edpus
+dialog.osmpois.nonefound=Nem tal\u00e1lhat\u00f3k pontok
 dialog.geocaching.nonefound=Nem tal\u00e1lhat\u00f3 geol\u00e1da
 dialog.correlate.notimestamps=Nincsenek id\u0151b\u00e9lyegek az adatpontokon, \u00edgy nem feleltethet\u0151 meg semmi a f\u00e9nyk\u00e9pekkel.
 dialog.correlate.nouncorrelatedphotos=Nincsenek megfeleltetlen f\u00e9nyk\u00e9pek.\nBiztos benne, hogy folytatja?
@@ -480,25 +470,9 @@ dialog.keys.intro=A k\u00f6vetkez\u0151 gyorsbillenty\u0171k haszn\u00e1lhat\u00
 dialog.keys.keylist=<table><tr><td>Ny\u00edlbillenty\u0171k</td><td>T\u00e9rk\u00e9p mozgat\u00e1sa balra, jobbra, fel, le</td></tr><tr><td>Ctrl + bal, jobb ny\u00edl</td><td>El\u0151z\u0151 vagy k\u00f6vetkez\u0151 pont kiv\u00e1laszt\u00e1sa</td></tr><tr><td>Ctrl + fel, le ny\u00edl</td><td>Nagy\u00edt\u00e1s vagy kicsiny\u00edt\u00e9s</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>El\u0151z\u0151, k\u00f6vetkez\u0151 szakasz kiv\u00e1laszt\u00e1sa</td></tr><tr><td>Ctrl + Home, End</td><td>Els\u0151, utols\u00f3 pont kiv\u00e1laszt\u00e1sa</td></tr><tr><td>Del</td><td>Jelenlegi pont t\u00f6rl\u00e9se</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=A k\u00f6vetkez\u0151 be\u00e1ll\u00edt\u00e1sok menthet\u0151k egy konfigur\u00e1ci\u00f3s f\u00e1jlba
-dialog.saveconfig.prune.trackdirectory=Nyomvonalak k\u00f6nyvt\u00e1ra
-dialog.saveconfig.prune.photodirectory=F\u00e9nyk\u00e9pek k\u00f6nyvt\u00e1ra
-dialog.saveconfig.prune.languagecode=Nyelv k\u00f3dja (HU)
-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.gnuplotpath=\u00datvonal a gnuplothoz
-dialog.saveconfig.prune.gpsbabelpath=\u00datvonal a gpsbabelhez
-dialog.saveconfig.prune.exiftoolpath=\u00datvonal az exiftoolhoz
-dialog.saveconfig.prune.mapsource=Kiv\u00e1lasztott t\u00e9rk\u00e9pforr\u00e1s
-dialog.saveconfig.prune.mapsourcelist=T\u00e9rk\u00e9pforr\u00e1sok
-dialog.saveconfig.prune.diskcache=T\u00e9rk\u00e9p-gyors\u00edt\u00f3t\u00e1r
-dialog.saveconfig.prune.kmzimagewidth=KMZ k\u00e9psz\u00e9less\u00e9g
-dialog.saveconfig.prune.colourscheme=Sz\u00edns\u00e9ma
-dialog.saveconfig.prune.linewidth=Vonalsz\u00e9less\u00e9g
-dialog.saveconfig.prune.kmltrackcolour=KML nyomvonal sz\u00edne
-dialog.saveconfig.prune.autosavesettings=Automatikus ment\u00e9s be\u00e1ll\u00edt\u00e1sai
+dialog.paths.prune.gnuplotpath=\u00datvonal a gnuplothoz
+dialog.paths.prune.gpsbabelpath=\u00datvonal a gpsbabelhez
+dialog.paths.prune.exiftoolpath=\u00datvonal az exiftoolhoz
 dialog.setpaths.intro=Ha sz\u00fcks\u00e9ges, kiv\u00e1laszthatja a k\u00fcls\u0151 alkalmaz\u00e1sok \u00fatvonalait:
 dialog.setpaths.found=\u00datvonal megtal\u00e1lhat\u00f3?
 dialog.addaltitude.noaltitudes=A kiv\u00e1lasztott tartom\u00e1ny nem tartalmaz magass\u00e1gi \u00e9rt\u00e9keket
@@ -555,6 +529,16 @@ dialog.diskcache.deleted=%d f\u00e1jl t\u00f6r\u00f6lve a gyors\u00edt\u00f3t\u0
 dialog.deletefieldvalues.intro=V\u00e1lassza ki a t\u00f6rlend\u0151 mez\u0151t a jelenlegi tartom\u00e1nyban
 dialog.deletefieldvalues.nofields=Nincs t\u00f6r\u00f6lhet\u0151 mez\u0151 a tartom\u00e1nyban
 dialog.displaysettings.linewidth=Adja meg a rajzoland\u00f3 vonalak vastags\u00e1g\u00e1t a nyomvonalak sz\u00e1m\u00e1ra (1-4)
+dialog.displaysettings.antialias=\u00c9lsim\u00edt\u00e1s haszn\u00e1lata
+dialog.displaysettings.waypointicons=\u00datpont ikon
+dialog.displaysettings.wpicon.default=Alap\u00e9rtelmezett
+dialog.displaysettings.wpicon.ringpt=Kerek
+dialog.displaysettings.wpicon.plectrum=Penget\u0151
+dialog.displaysettings.wpicon.ring=Gy\u0171r\u0171
+dialog.displaysettings.wpicon.pin=Gombost\u0171
+dialog.displaysettings.size.small=Kicsi
+dialog.displaysettings.size.medium=K\u00f6zepes
+dialog.displaysettings.size.large=Nagy
 dialog.downloadosm.desc=Nyers OSM adatok let\u00f6lt\u00e9s\u00e9nek meger\u0151s\u00edt\u00e9se a megadott ter\u00fcletre:
 dialog.searchwikipedianames.search=Keres\u00e9s erre:
 dialog.weather.location=Helysz\u00edn
@@ -586,6 +570,10 @@ dialog.deletebydate.column.keep=Megtart
 dialog.deletebydate.column.delete=T\u00f6r\u00f6l
 dialog.setaltitudetolerance.text.metres=Az a hat\u00e1r (m\u00e9terben) ami alatt a kis s\u00fcllyed\u00e9seket \u00e9s emelked\u00e9seket figyelmen k\u00edv\u00fcl hagyjuk
 dialog.setaltitudetolerance.text.feet=Az a hat\u00e1r (l\u00e1bban) ami alatt a kis s\u00fcllyed\u00e9seket \u00e9s emelked\u00e9seket figyelmen k\u00edv\u00fcl hagyjuk
+dialog.settimezone.intro=Kiv\u00e1laszthatja, hogy az \u00fatvonalpontok id\u0151b\u00e9lyegz\u0151i milyen id\u0151z\u00f3na szerint jelenjenek meg
+dialog.settimezone.system=Rendszer id\u0151z\u00f3na haszn\u00e1lata
+dialog.settimezone.custom=Az al\u00e1bbi id\u0151z\u00f3na haszn\u00e1lata
+dialog.settimezone.list.toomany=T\u00fal sok lehet\u0151s\u00e9g
 dialog.autoplay.duration=Id\u0151tartam (mp)
 dialog.autoplay.usetimestamps=Nyompontok id\u0151b\u00e9lyege alapj\u00e1n
 dialog.autoplay.rewind=Vissza az elej\u00e9re
@@ -612,7 +600,7 @@ confirm.rearrangephotos=F\u00e9nyk\u00e9pek \u00fajrarendezve
 confirm.splitsegments=%d szakasz v\u00e1g\u00e1s elv\u00e9gezve
 confirm.sewsegments=%d szakasz egyes\u00edt\u00e9se elv\u00e9gezve
 confirm.cutandmove=Kijel\u00f6l\u00e9s \u00e1thelyezve
-confirm.interpolate=Pontok hozz\u00e1adva
+confirm.pointsadded=%d pontok hozz\u00e1adva
 confirm.convertnamestotimes=\u00datpont nevei konvert\u00e1lva
 confirm.saveexif.ok=Mentve %d k\u00e9pf\u00e1jl
 confirm.undo.single=m\u0171velet visszavonva
@@ -668,7 +656,6 @@ button.selectall=Mindent kijel\u00f6l
 button.selectnone=Kijel\u00f6l\u00e9s megsz\u00fcntet\u00e9se
 button.preview=El\u0151n\u00e9zet
 button.load=Bet\u00f6lt\u00e9s
-button.upload=Felt\u00f6lt\u00e9s
 button.guessfields=Mez\u0151k kital\u00e1l\u00e1sa
 button.showwebpage=Weboldal megjelen\u00edt\u00e9se
 button.check=Ellen\u0151rz\u00e9s
@@ -783,9 +770,9 @@ units.feetpersec.short=ft/s
 units.hours=\u00f3ra
 units.minutes=perc
 units.seconds=m\u00e1sodperc
-units.degminsec=Sz\u00f6g-sz\u00f6gperc-sz\u00f6gm\u00e1sodperc
-units.degmin=Sz\u00f6g-sz\u00f6gperc
-units.deg=Sz\u00f6g
+units.degminsec=Fok-perc-m\u00e1sodperc
+units.degmin=Fok-perc
+units.deg=Fok
 units.iso8601=ISO 8601
 units.degreescelsius=Celsius
 units.degreescelsius.short=\u00b0C
index 6648b0e136dfec7eb3f6c7e0bbc2342f91f0ec9e..bc5a7b33defb0108ce424cfc9a49316c5c1a9ab3 100644 (file)
@@ -97,10 +97,12 @@ function.convertnamestotimes=Converti nomi dei waypoint in orari
 function.deletefieldvalues=Cancella i valori del campo
 function.findwaypoint=Trova waypoint
 function.pastecoordinates=Aggiungi coordinate
+function.pastecoordinatelist=Inserisci lista di coordinate
+function.enterpluscode=Inserisci pluscode
 function.charts=Diagrammi
 function.show3d=Mostra in 3D
 function.distances=Mostra distanze
-function.fullrangedetails=Mostra dettagli
+function.viewfulldetails=Mostra dettagli
 function.estimatetime=Stima durata
 function.learnestimationparams=Apprendi parametri di stima
 function.autoplay=Riproduci traccia
@@ -110,8 +112,6 @@ function.selectsegment=Seleziona segmento corrente
 function.splitsegments=Dividi traccia in segmenti
 function.sewsegments=Riorganizza segmenti insieme
 function.createmarkerwaypoints=Crea marcatori
-function.getgpsies=Ottieni tracce da Gpsies
-function.uploadgpsies=Carica traccia su Gpsies
 function.lookupsrtm=Ottieni quote da SRTM
 function.downloadsrtm=Scarica file da SRTM
 function.getwikipedia=Ottieni i punti Wikipedia nelle vicinanze
@@ -148,6 +148,7 @@ function.managetilecache=Gestione del cache di tasselli
 function.getweatherforecast=Ottieni previsioni del tempo
 function.setaltitudetolerance=Configura tolleranza di altitudini
 function.selecttimezone=Seleziona fuso orario
+function.projectpoint=Proiettare il punto
 
 # Dialogs
 dialog.exit.confirm.title=Esci da GpsPrune
@@ -367,19 +368,6 @@ dialog.gpsies.column.length=Lunghezza
 dialog.gpsies.description=Descrizione
 dialog.gpsies.nodescription=Senza descrizione
 dialog.gpsies.nonefound=Nessuna traccia trovata
-dialog.gpsies.username=Gpsies username
-dialog.gpsies.password=Gpsies password
-dialog.gpsies.keepprivate=Rendi la traccia privata
-dialog.gpsies.confirmopenpage=Apri la pagina web per caricare la traccia?
-dialog.gpsies.activities=Attivit\u00e0
-dialog.gpsies.activity.trekking=Trekking
-dialog.gpsies.activity.walking=Camminare
-dialog.gpsies.activity.jogging=Jogging
-dialog.gpsies.activity.biking=Ciclismo
-dialog.gpsies.activity.motorbiking=Motocicletta
-dialog.gpsies.activity.snowshoe=Trekking sulla neve
-dialog.gpsies.activity.sailing=Navigazione
-dialog.gpsies.activity.skating=Pattinaggio
 dialog.mapillary.nonefound=Nessuna foto trovata
 dialog.wikipedia.column.name=Titolo articolo
 dialog.wikipedia.column.distance=Distanza
@@ -447,6 +435,10 @@ 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.pastecoordinatelist.desc=Inserisci le coordinate per i nuovi punti, utilizzando un linea per punto
+dialog.pluscode.desc=Inserisci o incolla qui il pluscode
+dialog.pluscode.code=Pluscode
+dialog.pluscode.nothingfound=Per favore, controlla il codice e riprova
 dialog.help.help=Per favore vedi\n https://gpsprune.activityworkshop.net/\nper maggiori informazioni e per la guida utente.
 dialog.about.version=Versione
 dialog.about.build=Build
@@ -486,25 +478,9 @@ dialog.keys.intro=Puoi utilizzare i seguenti tast di scelta rapida al posto del
 dialog.keys.keylist=<table><tr><td>Tasti freccia</td><td>Muovi mappa destra, sinistra, su, giu'</td></tr><tr><td>Ctrl + freccia destra, sinistra</td><td>Selezione punto successivo o precedente</td></tr><tr><td>Ctrl + freccia su, giu'</td><td>Zoom in o out</td></tr><tr><td>Ctrl + pagina su, giu'</td><td>Segmento successivo o precedente</tr><tr><td>Ctrl + Home, End</td><td>Punto primo o ultimo</td></tr><tr><td>Del</td><td>Cancella punto attuale</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Comando
-dialog.saveconfig.desc=Le configurazioni seguenti possono essere salvati in un file di configurazione:
-dialog.saveconfig.prune.trackdirectory=Cartella tracce
-dialog.saveconfig.prune.photodirectory=Cartella foto
-dialog.saveconfig.prune.languagecode=Codice lingua (IT)
-dialog.saveconfig.prune.languagefile=File lingua
-dialog.saveconfig.prune.gpsdevice=Nome del Dispositivo GPS
-dialog.saveconfig.prune.gpsformat=Formato GPS
-dialog.saveconfig.prune.povrayfont=Font povray
-dialog.saveconfig.prune.gnuplotpath=Path gnuplot
-dialog.saveconfig.prune.gpsbabelpath=Path gpsbabel
-dialog.saveconfig.prune.exiftoolpath=Path exiftool
-dialog.saveconfig.prune.mapsource=Selezionale la fonte delle mappe
-dialog.saveconfig.prune.mapsourcelist=Fonte delle mappe
-dialog.saveconfig.prune.diskcache=Cache delle mappe
-dialog.saveconfig.prune.kmzimagewidth=larghezza immagine KMZ
-dialog.saveconfig.prune.colourscheme=Schema colori
-dialog.saveconfig.prune.linewidth=Spessore linea
-dialog.saveconfig.prune.kmltrackcolour=Colore della traccia KML
-dialog.saveconfig.prune.autosavesettings=Salvare settaggi automaticamente
+dialog.paths.prune.gnuplotpath=Path gnuplot
+dialog.paths.prune.gpsbabelpath=Path gpsbabel
+dialog.paths.prune.exiftoolpath=Path exiftool
 dialog.setpaths.intro=Se necessario, puoi indicare il percorso delle applicazioni esterne:
 dialog.setpaths.found=trovato?
 dialog.addaltitude.noaltitudes=L'intervallo selezionato non contiene altitudini
@@ -571,6 +547,9 @@ dialog.displaysettings.wpicon.pin=Spillo da lavagna
 dialog.displaysettings.size.small=Piccole
 dialog.displaysettings.size.medium=Medie
 dialog.displaysettings.size.large=Grandi
+dialog.displaysettings.windowstyle=Stile della finestra (è necessario il riavvio)
+dialog.displaysettings.windowstyle.default=Normale
+dialog.displaysettings.windowstyle.nimbus=Nimbus
 dialog.downloadosm.desc=Conferma lo scarico dei dati raw OSM per l'area specificata:
 dialog.searchwikipedianames.search=Cerca per:
 dialog.weather.location=Localit\u00e0
@@ -613,6 +592,12 @@ dialog.autoplay.usetimestamps=Usa dati temporali
 dialog.autoplay.rewind=Riavvolga
 dialog.autoplay.pause=Pausa
 dialog.autoplay.play=Riproduci
+dialog.markers.halves=Punti a metà strada
+dialog.markers.half.distance=Metà della distanza
+dialog.markers.half.climb=Metà della salita
+dialog.markers.half.descent=Metà della discesa
+dialog.projectpoint.bearing=Azimut (gradi da nord)
+dialog.projectpoint.desc=Inserire l'azimut e la distanza per la proiezione
 
 # 3d window
 dialog.3d.title=Visione GpsPrune in 3D
@@ -634,7 +619,7 @@ confirm.rearrangephotos=Foto riorganizzate
 confirm.splitsegments=%d segmenti sono stati suddivisi
 confirm.sewsegments=%d segmenti sono stati raggruppati
 confirm.cutandmove=Selezione spostata
-confirm.interpolate=Aggiungi punto
+confirm.pointsadded=Aggiungi %d punto
 confirm.convertnamestotimes=Nome del waypoint convertito
 confirm.saveexif.ok=Salvato %d foto
 confirm.undo.single=operazione annullate
@@ -690,7 +675,6 @@ button.selectall=Seleziona tutto
 button.selectnone=Deseleziona tutto
 button.preview=Anteprima
 button.load=Carica
-button.upload=Caricato
 button.guessfields=Campi soluzione
 button.showwebpage=Mostra pagina
 button.check=Controlla
@@ -764,6 +748,7 @@ map.overzoom=Mappa non disponibile a questo livello di zoom
 # Field names
 fieldname.latitude=Latitudine
 fieldname.longitude=Longitudine
+fieldname.coordinates=Coordinate
 fieldname.altitude=Altitudine
 fieldname.timestamp=Dati temporali
 fieldname.time=Tempo
@@ -778,6 +763,7 @@ fieldname.duration=Durata
 fieldname.speed=Velocit\u00e0
 fieldname.verticalspeed=Velocit\u00e0 verticale
 fieldname.description=Descrizione
+fieldname.comment=Commento
 fieldname.mediafilename=File
 
 # Measurement units
@@ -877,6 +863,7 @@ error.load.nopoints=Non ci sono coordinate nel file
 error.load.unknownxml=Formato xml non riconosciuto:
 error.load.noxmlinzip=File xml non trovato all'interno del zip file
 error.load.othererror=Errore nella lettura del file:
+error.load.nopointsintext=Non ci sono coordinate
 error.jpegload.dialogtitle=Errore nel caricamento delle foto
 error.jpegload.nofilesfound=File non trovato
 error.jpegload.nojpegsfound=File jpeg non trovato
index 738a1014733768153243fa4505f5a054c07bcde2..f698abae427d72739fc344164a11deec6ab2dcce 100644 (file)
@@ -93,11 +93,8 @@ function.pastecoordinates=\u65b0\u3057\u3044\u5ea7\u6a19\u3092\u5165\u529b
 function.charts=\u9ad8\u5ea6\u901f\u5ea6\u30c1\u30e3\u30fc\u30c8
 function.show3d=3-D\u30d3\u30e5\u30fc
 function.distances=\u8ddd\u96e2
-function.fullrangedetails=\u5168\u7bc4\u56f2\u8a73\u7d30
 function.setmapbg=\u80cc\u666f\u5730\u56f3
 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
@@ -270,17 +267,6 @@ 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.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.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
@@ -369,24 +355,9 @@ dialog.keys.intro=\u30de\u30a6\u30b9\u306e\u4ee3\u308f\u308a\u306b\u6b21\u306e\u
 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.prune.languagecode=\u8a00\u8a9e\u30b3\u30fc\u30c9(JA)
-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.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.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.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.paths.prune.gnuplotpath=gnuplot\u3078\u306e\u30d1\u30b9
+dialog.paths.prune.gpsbabelpath=gpsbabel\u3078\u306e\u30d1\u30b9
+dialog.paths.prune.exiftoolpath=exiftool\u3078\u306e\u30d1\u30b9
 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.addaltitude.desc=\u52a0\u3048\u305f\u9ad8\u5ea6\u504f\u4f4d
@@ -475,7 +446,6 @@ 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.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
index b748f07fee5812a5dbbef3395982033b70e38cf1..75332e4df5b1046944c47f33af852838b144f37e 100644 (file)
@@ -88,11 +88,8 @@ function.pastecoordinates=\uc0c8 \uc88c\ud45c \ub123\uae30
 function.charts=\ucc28\ud2b8
 function.show3d=3\ucc28\uc6d0 \ubcf4\uae30
 function.distances=\uac70\ub9ac
-function.fullrangedetails=\uc5f0\uacb0\uc120 \uc0c1\uc138 \uc815\ubcf4 \ubcf4\uae30
 function.setmapbg=\ubc30\uacbd \uc9c0\ub3c4 \uc9c0\uc815
 function.setpaths=\uc678\ubd80\ud504\ub85c\uadf8\ub7a8 \uc9c0\uc815
-function.getgpsies=gpsies\uc5d0\uc11c \ud2b8\ub799\ubaa9\ub85d \uc5bb\uae30
-function.uploadgpsies=gpsies\ub85c \ud2b8\ub799 \uc62c\ub9ac\uae30
 function.lookupsrtm=SRTM\uc5d0\uc11c \uace0\ub3c4 \ucc3e\uae30
 function.getwikipedia=\uc704\ud0a4\ud53c\ub514\uc544\uc5d0\uc11c \uadfc\ucc98 \uc815\ubcf4 \ucc3e\uae30
 function.searchwikipedianames=\uc774\ub984\uc73c\ub85c \uc704\ud0a4\ud53c\ub514\uc544 \uac80\uc0c9
@@ -263,19 +260,6 @@ dialog.gpsies.column.length=\uae38\uc774
 dialog.gpsies.description=\uc124\uba85
 dialog.gpsies.nodescription=\uc124\uba85 \uc5c6\uc74c
 dialog.gpsies.nonefound=\ud2b8\ub799\uc744 \ucc3e\uc744 \uc218 \uc5c6\uc74c
-dialog.gpsies.username=Gpsies username
-dialog.gpsies.password=Gpsies \ube44\ubc00\ubc88\ud638
-dialog.gpsies.keepprivate=\ud2b8\ub799 \uac1c\uc778\uc815\ubcf4\ubcf4\ud638
-dialog.gpsies.confirmopenpage=\uc5c5\ub85c\ub4dc\ud55c \ud2b8\ub799\uc744 \uc6f9\ud398\uc774\uc9c0\uc5d0\uc11c \ubcf4\uc2dc\uaca0\uc5b4\uc694?
-dialog.gpsies.activities=\ud65c\ub3d9 \ud615\ud0dc
-dialog.gpsies.activity.trekking=\ub3c4\ubcf4\uc5ec\ud589
-dialog.gpsies.activity.walking=\uac77\uae30
-dialog.gpsies.activity.jogging=\ub2ec\ub9ac\uae30
-dialog.gpsies.activity.biking=\uc790\uc804\uac70\ud0c0\uae30
-dialog.gpsies.activity.motorbiking=\uc624\ud1a0\ubc14\uc774\ud0c0\uae30
-dialog.gpsies.activity.snowshoe=\ub208\uae38\uac77\uae30
-dialog.gpsies.activity.sailing=\ubc30\ud0c0\uae30
-dialog.gpsies.activity.skating=\uc2a4\ucf00\uc774\ud2b8\ud0c0\uae30
 dialog.wikipedia.column.name=\uac8c\uc2dc\ubb3c \uc774\ub984
 dialog.wikipedia.column.distance=\uac70\ub9ac
 dialog.correlate.notimestamps=\uc9c0\uc810 \ub370\uc774\ud130\uc5d0 \uc2dc\uac04\uc815\ubcf4\uac00 \uc5c6\uc5b4\uc11c \uc0ac\uc9c4\uc744 \uc5f0\uacb0 \ud560 \uc218 \uc5c6\uc5b4\uc694.
@@ -368,24 +352,9 @@ dialog.keys.intro=\ub9c8\uc6b0\uc2a4\ub97c \uc0ac\uc6a9\ud558\uc9c0 \ub9c8\uc2dc
 dialog.keys.keylist=<table><tr><td>\ud654\uc0b4\ud45c \ud0a4</td><td>\uc88c,\uc6b0,\uc544\ub798,\uc704\ub85c \uc9c0\ub3c4 \uc774\ub3d9</td></tr><tr><td>Ctrl + \uc67c\ucabd, \uc624\ub978\ucabd \ud654\uc0b4\ud45c</td><td>\uc9c0\uc810 \uc120\ud0dd \uc774\ub3d9</td></tr><tr><td>Ctrl + \uc704, \uc544\ub798 \ud654\uc0b4\ud45c</td><td>\uc9c0\ub3c4 \ud655\ub300 \ucd95\uc18c</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>\uc774\uc804 \uc774\ud6c4 \ubd80\ubd84 \uc120\ud0dd</td></tr><tr><td>Ctrl + Home, End</td><td>\ucc98\uc74c \uc9c0\uc810, \ub9c8\uc9c0\ub9c9 \uc9c0\uc810 \uc120\ud0dd</td></tr><tr><td>Del</td><td>\ud604\uc7ac \uc9c0\uc810 \uc0ad\uc81c</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=\uc544\ub798 \uc124\uc815\ub4e4\uc740 \uc124\uc815\ud30c\uc77c\uc5d0 \uc800\uc7a5\ud560 \uc218 \uc788\uc5b4\uc694:
-dialog.saveconfig.prune.trackdirectory=\ud2b8\ub809 \ud3f4\ub354
-dialog.saveconfig.prune.photodirectory=\uc0ac\uc9c4 \ud3f4\ub354
-dialog.saveconfig.prune.languagecode=\uc5b8\uc5b4\ucf54\ub4dc (KO)
-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.gnuplotpath=gnjuplot \uacbd\ub85c
-dialog.saveconfig.prune.gpsbabelpath=gpsbabel \uacbd\ub85c
-dialog.saveconfig.prune.exiftoolpath=exiftool \uacbd\ub85c
-dialog.saveconfig.prune.mapsource=\uc120\ud0dd\ub41c \uc9c0\ub3c4 \uc704\uce58
-dialog.saveconfig.prune.mapsourcelist=\uc9c0\ub3c4 \uc18c\uc2a4
-dialog.saveconfig.prune.diskcache=\uc9c0\ub3c4 \uce90\uc2dc
-dialog.saveconfig.prune.kmzimagewidth=KMZ \uc774\ubbf8\uc9c0 \ub113\uc774
-dialog.saveconfig.prune.colourscheme=\uc0c9 \uad6c\uc131
-dialog.saveconfig.prune.linewidth=\ud2b8\ub799\uc120 \ub450\uaed8
-dialog.saveconfig.prune.kmltrackcolour=KML \ud2b8\ub799 \uc0c9
+dialog.paths.prune.gnuplotpath=gnjuplot \uacbd\ub85c
+dialog.paths.prune.gpsbabelpath=gpsbabel \uacbd\ub85c
+dialog.paths.prune.exiftoolpath=exiftool \uacbd\ub85c
 dialog.setpaths.intro=\uc678\ubd80 \ud504\ub85c\uadf8\ub7a8\uc758 \uacbd\ub85c\ub97c \uc120\ud0dd\ud560 \uc218 \uc788\uc5b4\uc694.
 dialog.setpaths.found=\uacbd\ub85c\ub97c \ucc3e\uc73c\uc168\ub098\uc694?
 dialog.addaltitude.noaltitudes=\uc120\ud0dd\ub41c \ubc94\uc704\uc5d0 \uace0\ub3c4\uac00 \ud3ec\ud568\ub418\uc5b4\uc788\uc9c0 \uc54a\ub124\uc694.
@@ -483,7 +452,6 @@ button.selectall=\uc804\ubd80\uc120\ud0dd
 button.selectnone=\uc544\ubb34\uac83\ub3c4 \uc120\ud0dd\ud558\uc9c0\uc54a\uae30
 button.preview=\ubbf8\ub9ac\ubcf4\uae30
 button.load=\ubd88\ub7ec\uc624\uae30
-button.upload=\uc62c\ub9ac\uae30
 button.guessfields=\ucd94\uce21 \ud544\ub4dc
 button.showwebpage=\uc6f9\ud398\uc774\uc9c0 \ubcf4\uae30
 button.check=\uccb4\ud06c
index 2e0f72772922487200bb5f4528489b02248e6f63..cde8d6ea4b1cdd2baabe5b0da649efc66cc3ea01 100644 (file)
@@ -1,7 +1,7 @@
 # Text entries for the GpsPrune application
 # Dutch entries thanks to Jeroen
 
-# Menu entries
+## Menu entries
 menu.file=Bestand
 menu.file.addphotos=Foto's toevoegen
 menu.file.recentfiles=Onlangs geopend
@@ -12,7 +12,6 @@ menu.track=Route
 menu.track.undo=Ongedaan maken
 menu.track.clearundo=Ongedaan-maken lijst wissen
 menu.track.markrectangle=Makeer alle punten in een vierkant
-function.deletemarked=Verwijderen gemarkeerde punten
 menu.range=Reeks
 menu.range.all=Selecteer alles
 menu.range.none=Selecteer geen
@@ -36,12 +35,14 @@ menu.view.browser.openstreetmap=Openstreetmap
 menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Yahoo maps
 menu.view.browser.bing=Bing maps
+menu.view.browser.inlinemap=Inline kaart
+menu.view.browser.graphhopper=GraphHopper
 menu.settings=Instellingen
 menu.settings.onlinemode=Kaarten van internet ophalen
 menu.settings.autosave=Automatisch opslaan bij afsluiten
 menu.help=Help
 
-# Popup menu for map
+## Popup menu for map
 menu.map.zoomin=Zoom +
 menu.map.zoomout=Zoom -
 menu.map.zoomfull=Zoom alles
@@ -53,7 +54,7 @@ menu.map.showmap=Toon kaart
 menu.map.showscalebar=Toon schaal
 menu.map.editmode=Wijzigen
 
-# Alt keys for menus
+## Alt keys for menus
 altkey.menu.file=F
 altkey.menu.online=O
 altkey.menu.track=R
@@ -65,7 +66,7 @@ altkey.menu.audio=A
 altkey.menu.settings=I
 altkey.menu.help=H
 
-# Ctrl shortcuts for menu items
+## Ctrl shortcuts for menu items
 shortcut.menu.file.open=O
 shortcut.menu.file.load=L
 shortcut.menu.file.save=S
@@ -75,7 +76,7 @@ shortcut.menu.range.all=A
 shortcut.menu.point.edit=W
 shortcut.menu.help.help=H
 
-# Functions
+## Functions
 function.open=Open bestand
 function.importwithgpsbabel=Bestand importeren met GPSBabel
 function.loadfromgps=Gegevens lezen van GPS
@@ -86,6 +87,7 @@ function.exportpov=Export POV
 function.exportimage=Bestand exporteren
 function.editwaypointname=Hernoem waypoint
 function.compress=Route comprimeren
+function.deletemarked=Verwijderen gemarkeerde punten
 function.marklifts=Markeer opgaande liften
 function.deleterange=Verwijder reeks
 function.croptrack=Route bijknippen
@@ -98,10 +100,12 @@ function.convertnamestotimes=Converteer waypointnamen naar tijden
 function.deletefieldvalues=Verwijder veldwaarden
 function.findwaypoint=Zoek waypoint
 function.pastecoordinates=Nieuwe co\u00f6rdinaten ingeven
+function.pastecoordinatelist=Lijst met co\u00f6rdinaten invoeren
+function.enterpluscode=Pluscode invoeren
 function.charts=Diagram
 function.show3d=3D beeld
 function.distances=Afstanden
-function.fullrangedetails=Reeks details
+function.viewfulldetails=Alle details
 function.estimatetime=Geschatte tijd
 function.learnestimationparams=Parameters voor geschatte tijd
 function.autoplay=Route automatisch afspelen
@@ -111,8 +115,6 @@ function.selectsegment=Selecteer huidige segment
 function.splitsegments=Splits route in segmenten
 function.sewsegments=Voeg segmenten samen
 function.createmarkerwaypoints=aak waypoints voor markering
-function.getgpsies=Routes van Gpsies ophalen
-function.uploadgpsies=Upload routes naar Gpsies
 function.lookupsrtm=Hoogtes van SRTM ophalen
 function.downloadsrtm=Downloaden SRTM tegels
 function.getwikipedia=Wikipedia artikelen uit de buurt ophalen
@@ -122,6 +124,7 @@ function.searchopencachingde=Doorzoek OpenCaching.de
 function.mapillary=Zoek naar foto's op Mapillary
 function.downloadosm=Downloaden OSM data voor gebied
 function.duplicatepoint=Dupliceer punt
+function.projectpoint=Bereken punt
 function.setcolours=Instellen kleuren
 function.setdisplaysettings=Instellen afbeeldingopties
 function.setlanguage=Instellen taal
@@ -150,7 +153,7 @@ function.getweatherforecast=Ophalen weersvoorspelling
 function.setaltitudetolerance=Instellen hoogtetolerantie
 function.selecttimezone=Instellen tijdzone
 
-# Dialogs
+## Dialogs
 dialog.exit.confirm.title=GpsPrune afsluiten
 dialog.exit.confirm.text=Uw data is niet opgeslagen. Weet u zeker dat u wilt afsluiten?
 dialog.openappend.title=Toevoegen aan bestaande data
@@ -368,19 +371,6 @@ dialog.gpsies.column.length=Lengte
 dialog.gpsies.description=Omschrijving
 dialog.gpsies.nodescription=Geen omschrivjing
 dialog.gpsies.nonefound=Geen routes gevonden
-dialog.gpsies.username=Gpsies gebruikersnaam
-dialog.gpsies.password=Gpsies wachtwoord
-dialog.gpsies.keepprivate=Houd route priv\u00e9
-dialog.gpsies.confirmopenpage=Webpagina van de ge\u00fcploade route openen?
-dialog.gpsies.activities=Aktiviteit
-dialog.gpsies.activity.trekking=Trekking
-dialog.gpsies.activity.walking=Lopen
-dialog.gpsies.activity.jogging=Hardlopen
-dialog.gpsies.activity.biking=Fietsen
-dialog.gpsies.activity.motorbiking=Motorrijden
-dialog.gpsies.activity.snowshoe=Sneeuwschoen-lopen
-dialog.gpsies.activity.sailing=Zeilen
-dialog.gpsies.activity.skating=Skating
 dialog.mapillary.nonefound=Geen foto's gevonden
 dialog.wikipedia.column.name=Artikelnaam
 dialog.wikipedia.column.distance=Afstand
@@ -448,6 +438,10 @@ 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.pastecoordinatelist.desc=Geef de co\u00f6rdinaten voor nieuwe punten met \u00e9\u00e9n punt per regel
+dialog.pluscode.desc=Type of plak hier de pluscode
+dialog.pluscode.code=Pluscode
+dialog.pluscode.nothingfound=Controleer de code en probeer het nogmaals
 dialog.help.help=Ga naar\n https://gpsprune.activityworkshop.net/\nvoor meer informatie en handleidingen.
 dialog.about.version=Versie
 dialog.about.build=Build
@@ -461,9 +455,9 @@ dialog.about.systeminfo.os=Besturingssysteem
 dialog.about.systeminfo.java=Java Runtime
 dialog.about.systeminfo.java3d=Java3d ge\u00efnstalleerd
 dialog.about.systeminfo.povray=Povray ge\u00efnstalleerd
-dialog.about.systeminfo.exiftool=Exiftool ge\u00efnstalleer
-dialog.about.systeminfo.gpsbabel=Gpsbabel ge\u00efnstalleer
-dialog.about.systeminfo.gnuplot=Gnuplot ge\u00efnstalleer
+dialog.about.systeminfo.exiftool=Exiftool ge\u00efnstalleerd
+dialog.about.systeminfo.gpsbabel=Gpsbabel ge\u00efnstalleerd
+dialog.about.systeminfo.gnuplot=Gnuplot ge\u00efnstalleerd
 dialog.about.yes=Ja
 dialog.about.no=Nee
 dialog.about.credits=Credits
@@ -487,25 +481,9 @@ dialog.keys.intro=De volgende sneltoetsen vervangen muisacties
 dialog.keys.keylist=<table><tr><td>Pijltjestoetsen</td><td>verschuif de kaart links, rechts, omhoog, omlaag</td></tr><tr><td>Ctrl + pijltje naar links, rechts</td><td>Selecteer volgende, vorige punt</td></tr><tr><td>Ctrl + pijltje omhoog, omlaag</td><td>Zoom in of uit</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Selecteer vorig, volgend segment</td></tr><tr><td>Ctrl + Home, End</td><td>Select eerste, laatste punt</td></tr><tr><td>Del</td><td>Verwijder huidige punt</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=De volgende instellingen kunnen worden opgeslagen in een configuratiebestand:
-dialog.saveconfig.prune.trackdirectory=Route map
-dialog.saveconfig.prune.photodirectory=Foto map
-dialog.saveconfig.prune.languagecode=Taalcode (NL)
-dialog.saveconfig.prune.languagefile=Taal bestand
-dialog.saveconfig.prune.gpsdevice=GPS apparaat
-dialog.saveconfig.prune.gpsformat=GPS formaat
-dialog.saveconfig.prune.povrayfont=Povray lettertype
-dialog.saveconfig.prune.gnuplotpath=Pad naar gnuplot
-dialog.saveconfig.prune.gpsbabelpath=Pad naar gpsbabel
-dialog.saveconfig.prune.exiftoolpath=Pad naar exiftool
-dialog.saveconfig.prune.mapsource=Geselecteerde kaartbron
-dialog.saveconfig.prune.mapsourcelist=Kaartbronnen
-dialog.saveconfig.prune.diskcache=Kaartcache
-dialog.saveconfig.prune.kmzimagewidth=KMZ afbeelding breedte
-dialog.saveconfig.prune.colourscheme=Kleurenschema
-dialog.saveconfig.prune.linewidth=Lijndikte
-dialog.saveconfig.prune.kmltrackcolour=KML routekleur
-dialog.saveconfig.prune.autosavesettings=Instellingen automatisch opslaan
+dialog.paths.prune.gnuplotpath=Pad naar gnuplot
+dialog.paths.prune.gpsbabelpath=Pad naar gpsbabel
+dialog.paths.prune.exiftoolpath=Pad naar exiftool
 dialog.setpaths.intro=Indien nodig kan je de paden naar externe applicaties kiezen:
 dialog.setpaths.found=Pad gevonden?
 dialog.addaltitude.noaltitudes=De geselecteerde reeks bevat geen hoogtes
@@ -572,6 +550,9 @@ dialog.displaysettings.wpicon.pin=Punaise
 dialog.displaysettings.size.small=Klein
 dialog.displaysettings.size.medium=Middel
 dialog.displaysettings.size.large=Groot
+dialog.displaysettings.windowstyle=Windows stijl (herstart nodig)
+dialog.displaysettings.windowstyle.default=Standaard
+dialog.displaysettings.windowstyle.nimbus=Nimbus
 dialog.downloadosm.desc=Bevestig het downloaden van ruwe OSM data voor dit gebied:
 dialog.searchwikipedianames.search=Zoeken naar:
 dialog.weather.location=Locatie
@@ -614,12 +595,18 @@ dialog.autoplay.usetimestamps=Gebruik tijdinfo van punt
 dialog.autoplay.rewind=Terug naar begin
 dialog.autoplay.pause=Pauze
 dialog.autoplay.play=Afspelen
+dialog.markers.halves=Punt op halve afstand
+dialog.markers.half.distance=Halve afstand
+dialog.markers.half.climb=Halve klim
+dialog.markers.half.descent=Halve afdaling
+dialog.projectpoint.desc=Geef de richting en afstand om dit punt te berekenen
+dialog.projectpoint.bearing=Richting (graden Noord)
 
-# 3d window
+## 3d window
 dialog.3d.title=GpsPrune in 3D
 dialog.3d.altitudefactor=Hoogte overdrijvingsfactor
 
-# Confirm messages
+## Confirm messages
 confirm.loadfile=Data van schijf geladen
 confirm.save.ok1=Succesvol opgeslagen
 confirm.save.ok2=Punten naar bestand
@@ -635,7 +622,7 @@ confirm.rearrangephotos=Foto herschikt
 confirm.splitsegments=Er zijn %d opdelingen gemaakt
 confirm.sewsegments=Er zijn %d samenvoegingen gemaakt
 confirm.cutandmove=Selectie verplaatst
-confirm.interpolate=Punten toegevoegd
+confirm.pointsadded=%d punten toegevoegd
 confirm.convertnamestotimes=Namen waypoint geconverteerd
 confirm.saveexif.ok=Opgeslagen %d foto bestanden
 confirm.undo.single=Actie geannuleerd
@@ -660,7 +647,7 @@ confirm.audioload=Audiobestanden toegevoegd
 confirm.correlateaudios.single=audiobestand gecorreleerd
 confirm.correlateaudios.multi=audiobestanden gecorreleerd
 
-# Tips, shown just once when appropriate
+## Tips, shown just once when appropriate
 tip.title=Tip
 tip.useamapcache=Door het instellen van een schijfcache (Instellingen -> Kaart opslaan op schijf)\nkan je de afbeeldsnelheid verbeteren en het netwerkverkeer verminderen.
 tip.learntimeparams=De resultaten zullen nauwkeuriger zijn als je \nRoute -> Parameters voor geschatte tijd\ngebruikt op je opgenomen routes.
@@ -668,7 +655,7 @@ tip.downloadsrtm=Je kan dit versnellen door hier\nOnline -> Download SRTM tegels
 tip.usesrtmfor3d=Deze route heeft geen hoogten.\nJe kan de SRTM functies gebruiken om een geschatte hoogte\nop te halen voor het 3d beeld.
 tip.manuallycorrelateone=Door handmatig een foto te koppelen kan het tijdsverschil voor u berekend worden.
 
-# Buttons
+## Buttons
 button.ok=OK
 button.back=Terug
 button.next=Volgende
@@ -691,7 +678,6 @@ button.selectall=Selecteer alles
 button.selectnone=Selecteer niets
 button.preview=Voorbeeld
 button.load=Laden
-button.upload=Upload
 button.guessfields=Raad velden
 button.showwebpage=Toon webpagina
 button.check=Controleren
@@ -702,7 +688,7 @@ button.delete=Verwijderen
 button.manage=Beheer
 button.combine=Samenvoegen
 
-# File types
+## File types
 filetype.txt=TXT bestand
 filetype.jpeg=JPG bestand
 filetype.kmlkmz=KML, KMZ bestand
@@ -714,7 +700,7 @@ filetype.svg=SVG bestand
 filetype.png=PNG bestand
 filetype.audio=MP3, OGG, WAV bestanden
 
-# Display components
+## Display components
 display.nodata=Geen gegevens geladen
 display.noaltitudes=Route gegevens bevatten geen hoogte
 display.notimestamps=Route gegevens bevatten geen tijdinformatie
@@ -762,9 +748,10 @@ details.audio.file=Audiobestand
 details.audio.playing=Afspelen...
 map.overzoom=Geen kaarten beschikbaar op dit zoom-niveau
 
-# Field names
+## Field names
 fieldname.latitude=Breedtegraad
 fieldname.longitude=Lengtegraad
+fieldname.coordinates=Co\u00f6rdinaten
 fieldname.altitude=Hoogte
 fieldname.timestamp=Tijd
 fieldname.time=Tijd
@@ -779,9 +766,10 @@ fieldname.duration=Duur
 fieldname.speed=Snelheid
 fieldname.verticalspeed=Verticale snelheid
 fieldname.description=Omschrijving
+fieldname.comment=Commentaar
 fieldname.mediafilename=Bestandsnaam
 
-# Measurement units
+## Measurement units
 units.original=Oorspronkelijke
 units.default=Default
 units.metres=Meters
@@ -815,24 +803,24 @@ units.degreescelsius.short=\u00baC
 units.degreesfahrenheit=Fahrenheit
 units.degreesfahrenheit.short=\u00baF
 
-# How to combine conditions, such as filters
+## How to combine conditions, such as filters
 logic.and=en
 logic.or=of
 
-# External urls and services
+## External urls and services
 url.googlemaps=maps.google.nl
 wikipedia.lang=nl
 openweathermap.lang=nl
 webservice.peakfinder=Open Peakfinder.org
 webservice.geohack=Open Geohack pagina
 
-# Cardinals for 3d plots
+## Cardinals for 3d plots
 cardinal.n=N
 cardinal.s=Z
 cardinal.e=O
 cardinal.w=W
 
-# Undo operations
+## Undo operations
 undo.load=gegevens laden
 undo.loadphotos=foto's laden
 undo.loadaudios=audiobestanden laden
@@ -863,7 +851,7 @@ undo.lookupsrtm=opzoeken hoogtes in SRTM
 undo.deletefieldvalues=verwijder veldwaarden
 undo.correlateaudios=correleer audiobestanden
 
-# Error messages
+## Error messages
 error.save.dialogtitle=Fout bij opslaan gegevens
 error.save.nodata=Geen gegevens om op te slaan
 error.save.failed=Kon de gegevens niet naar bestand wegschrijven
@@ -878,6 +866,7 @@ error.load.nopoints=Geen co\u00f6rdinaat informatie gevonden in bestand
 error.load.unknownxml=Onbekend xml-formaat:
 error.load.noxmlinzip=Geen xml-bestand gevonden in zipbestand
 error.load.othererror=Fout bij lezen bestand:
+error.load.nopointsintext=Geen co\u00f6rdinaten informatie gevonden
 error.jpegload.dialogtitle=Fout bij inlezen foto's
 error.jpegload.nofilesfound=Bestanden niet gevonden
 error.jpegload.nojpegsfound=Geen jpeg-bestanden gevonden
index c90acb7a34d5f5cd07a922638bd886c5905ce482..86aac6f28ef8c8d947bf635d7cea8b6489c2aa12 100644 (file)
@@ -99,7 +99,7 @@ function.pastecoordinates=Legg til nye koordinater
 function.charts=Grafer
 function.show3d=3-D visning
 function.distances=Avstander
-function.fullrangedetails=Vis alle detaljer
+function.viewfulldetails=Vis alle detaljer
 function.estimatetime=
 function.learnestimationparams=
 function.setmapbg=Velg grunnlagskart
@@ -107,8 +107,6 @@ function.setpaths=Angi plassering av programmer
 function.selectsegment=
 function.splitsegments=
 function.sewsegments=
-function.getgpsies=Vis spor fra gpsies.com
-function.uploadgpsies=Last opp spor til gpsies.com
 function.lookupsrtm=Hent h\u00f8yde fra SRTM
 function.downloadsrtm=
 function.getwikipedia=Vis Wikipedia info for omegn
index eb0a727c3f4141d3f5024dff42205efab37ee0d1..d3b72e775c26c25fc7be63b65ee4dbca76040b25 100644 (file)
@@ -100,7 +100,7 @@ function.pastecoordinates=Wprowad\u017a nowe wsp\u00f3\u0142rz\u0119dne
 function.charts=Wykres
 function.show3d=Poka\u017c model 3D
 function.distances=Odleg\u0142o\u015bci
-function.fullrangedetails=Wszystkie detale
+function.viewfulldetails=Wszystkie detale
 function.estimatetime=Przewidywany czas
 function.learnestimationparams=Skoryguj wsp\u00f3\u0142czynniki szacowania czasu
 function.autoplay=Gra\u0107 \u015bcie\u017ck\u0119
@@ -110,8 +110,6 @@ function.selectsegment=Wybierz bie\u017c\u0105cy fragment
 function.splitsegments=Podziel \u015bcie\u017ck\u0119 na fragmenty
 function.sewsegments=Po\u0142\u0105cz fragmenty
 function.createmarkerwaypoints=Stw\u00f3rz markery podzia\u0142u
-function.getgpsies=Pobierz \u015bcie\u017cki z Gpsies
-function.uploadgpsies=Wy\u015blij \u015bcie\u017cki do Gpsies
 function.lookupsrtm=Pobierz wysoko\u015bci z SRTM
 function.downloadsrtm=Zapisz dane z SRTM
 function.getwikipedia=Szukaj w Wikipedii o okolicy
@@ -366,19 +364,6 @@ dialog.gpsies.column.length=D\u0142ugo\u015b\u0107
 dialog.gpsies.description=Opis
 dialog.gpsies.nodescription=Brak opisu
 dialog.gpsies.nonefound=Nie znalaz\u0142em \u015bcie\u017cek
-dialog.gpsies.username=nazwa u\u017cytkownika w Gpsies
-dialog.gpsies.password=has\u0142o u\u017cytkownika w Gpsies
-dialog.gpsies.keepprivate=Zaznacz \u015bcie\u017cki jako prywatne
-dialog.gpsies.confirmopenpage=Otw\u00f3rz stron\u0119 z za\u0142adowan\u0105 \u015bcie\u017ck\u0105
-dialog.gpsies.activities=Aktywno\u015b\u0107
-dialog.gpsies.activity.trekking=W\u0119drowa\u0107
-dialog.gpsies.activity.walking=Spacer
-dialog.gpsies.activity.jogging=Bieganie
-dialog.gpsies.activity.biking=Wycieczka rowerowa
-dialog.gpsies.activity.motorbiking=Wycieczka motocyklowa
-dialog.gpsies.activity.snowshoe=Snowshoeing
-dialog.gpsies.activity.sailing=\u017beglarstwo
-dialog.gpsies.activity.skating=Wrotki/rolki
 dialog.mapillary.nonefound=Nic nie zosta\u0142o znalezione
 dialog.wikipedia.column.name=Tytu\u0142 artyku\u0142u
 dialog.wikipedia.column.distance=Odleg\u0142o\u015b\u0107
@@ -483,25 +468,9 @@ dialog.keys.intro=U\u017cuwaj nast\u0119puj\u0105cych klawiszy skr\u00f3t\u00f3w
 dialog.keys.keylist=<table><tr><td>klawisze strza\u0142ek</td><td>Przesuwa map\u0119 w lewo, w prawo, w g\u00f3r\u0119, w d\u00f3\u0142</td></tr><tr><td>Ctrl + lewa, prawa strza\u0142ka</td><td>Wybierz punkt poprzedni lub nast\u0119pny</td></tr><tr><td>Ctrl + strza\u0142ka w g\u00f3r\u0119, w d\u00f3\u0142</td><td>Powi\u0119ksz, pomniejsz</td></tr><tr><td>Del</td><td>Usun bie\u017c\u0105cy punkt</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=Nast\u0119puj\u0105ce ustawienia mog\u0105 zosta\u0107 zapisane w pliku konfiguracyjnym:
-dialog.saveconfig.prune.trackdirectory=Katalog ze \u015bcie\u017ckami
-dialog.saveconfig.prune.photodirectory=Katalog ze zdj\u0119ciami
-dialog.saveconfig.prune.languagecode=Kod j\u0119zyka (PL)
-dialog.saveconfig.prune.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.gnuplotpath=\u015bcie\u017cka do gnuplot
-dialog.saveconfig.prune.gpsbabelpath=\u015bcie\u017cka do gpsbabel
-dialog.saveconfig.prune.exiftoolpath=\u015bcie\u017cka do exiftool
-dialog.saveconfig.prune.mapsource=Wybrany dostawca map
-dialog.saveconfig.prune.mapsourcelist=Dostawcy map
-dialog.saveconfig.prune.diskcache=Pami\u0119\u0107 podr\u0119czna map
-dialog.saveconfig.prune.kmzimagewidth=szeroko\u015b\u0107 obrazka w KMZ
-dialog.saveconfig.prune.colourscheme=Schemat kolor\u00f3w
-dialog.saveconfig.prune.linewidth=Szeroko\u015b\u0107 linii
-dialog.saveconfig.prune.kmltrackcolour=Kolor \u015bcie\u017cki w pliku KML
-dialog.saveconfig.prune.autosavesettings=ustawienia autozapisu
+dialog.paths.prune.gnuplotpath=\u015bcie\u017cka do gnuplot
+dialog.paths.prune.gpsbabelpath=\u015bcie\u017cka do gpsbabel
+dialog.paths.prune.exiftoolpath=\u015bcie\u017cka do exiftool
 dialog.setpaths.intro=Je\u015bli zachodzi tak potrzeba, mo\u017cesz wybra\u0107 \u015bcie\u017cki do aplikacji zewn\u0119trznych
 dialog.setpaths.found=Znalezione \u015bcie\u017cki?
 dialog.addaltitude.noaltitudes=Wybrany zakres nie zawiera danych o wysoko\u015bciach
@@ -620,7 +589,7 @@ confirm.rearrangephotos=Zmieniono kolejno\u015b\u0107 zdj\u0119\u0107
 confirm.splitsegments=Podzielono na %d fragmenty/\u00f3w
 confirm.sewsegments=Po\u0142\u0105czono %d fragmenty/\u00f3w
 confirm.cutandmove=Przesuni\u0119to zaznaczenie
-confirm.interpolate=Dodano punkty
+confirm.pointsadded=Dodano %d punkty
 confirm.convertnamestotimes=Zmieniono nazwy punkt\u00f3w po\u015brednich
 confirm.saveexif.ok=Zapisano %d plik(\u00f3w) zdj\u0119\u0107
 confirm.undo.single=cofni\u0119to operacj\u0119
@@ -676,7 +645,6 @@ button.selectall=Zaznacz wszystko
 button.selectnone=Odznacz
 button.preview=Podgl\u0105d
 button.load=\u0141aduj
-button.upload=Wy\u015blij
 button.guessfields=Zgadnij pola
 button.showwebpage=Poka\u017c stron\u0119 web
 button.check=Sprawd\u017a
index bab5623c85b05696f95c3e9f725b90e5d7fd19ac..fd785bf94773d6d04666b76b873a7ba8c32b8544 100644 (file)
@@ -99,7 +99,7 @@ function.pastecoordinates=Inserir novas coordenadas
 function.charts=Gr\u00e1ficos
 function.show3d=Visualizar 3D
 function.distances=Dist\u00e2ncias
-function.fullrangedetails=Todos os detalhes
+function.viewfulldetails=Todos os detalhes
 function.estimatetime=Tempo estimado
 function.learnestimationparams=Aprender os par\u00e2metros para estimativa de tempo
 function.setmapbg=Definir como fundo do mapa
@@ -107,8 +107,6 @@ function.setpaths=Definir caminhos do programa
 function.selectsegment=Selecionar segmento atual
 function.splitsegments=Dividir rota em segmentos
 function.sewsegments=Reunir segmentos em rota
-function.getgpsies=Obter rotas Gpsies
-function.uploadgpsies=Enviar rotas para o Gpsies
 function.lookupsrtm=Obter altitudes a partir do SRTM
 function.downloadsrtm=Baixar arquivos SRTM
 function.getwikipedia=Obter artigos da Wikip\u00e9dia das redondezas
@@ -360,19 +358,6 @@ dialog.gpsies.column.length=Extens\u00e3o
 dialog.gpsies.description=Descri\u00e7\u00e3o
 dialog.gpsies.nodescription=Sem descri\u00e7\u00e3o
 dialog.gpsies.nonefound=Nenhuma rota encontrada
-dialog.gpsies.username=Nome do usu\u00e1rio Gpsies
-dialog.gpsies.password=Senha do Gpsies
-dialog.gpsies.keepprivate=Manter rota privada
-dialog.gpsies.confirmopenpage=Abrir a p\u00e1gina para rotas enviadas?
-dialog.gpsies.activities=Tipos de atividade
-dialog.gpsies.activity.trekking=Trilha
-dialog.gpsies.activity.walking=Caminhada
-dialog.gpsies.activity.jogging=Corrida
-dialog.gpsies.activity.biking=Ciclismo
-dialog.gpsies.activity.motorbiking=Motocross
-dialog.gpsies.activity.snowshoe=Snowshoeing
-dialog.gpsies.activity.sailing=Sailing
-dialog.gpsies.activity.skating=Patina\u00e7\u00e3o
 dialog.mapillary.nonefound=Nenhuma foto encontrada
 dialog.wikipedia.column.name=Nome do artigo
 dialog.wikipedia.column.distance=Dist\u00e2ncia
@@ -473,25 +458,9 @@ dialog.keys.intro=Voc\u00ea pode usar os seguintes atalhos de teclado ao inv\u00
 dialog.keys.keylist=<table><tr><td>Cursores</td><td>Move o mapa para esquerda, direita, acima e abaixo</td></tr><tr><td>Ctrl + cursores esquerdo e direito</td><td>Seleciona o pr\u00f3ximo ponto ou o anterior</td></tr><tr><td>Ctrl + cursores acima e abaixo</td><td>Amplia ou reduz</td></tr><tr><td>Del</td><td>Remove o ponto atual</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=As seguintes configura\u00e7\u00f5es podem ser salvas para um arquivo de configura\u00e7\u00e3o.
-dialog.saveconfig.prune.trackdirectory=Pasta de rotas
-dialog.saveconfig.prune.photodirectory=Pasta de fotos
-dialog.saveconfig.prune.languagecode=C\u00f3digo do idioma (PT_BR)
-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.gnuplotpath=Caminho para o gnuplot
-dialog.saveconfig.prune.gpsbabelpath=Caminho para o gpsbabel
-dialog.saveconfig.prune.exiftoolpath=Caminho para o exiftool
-dialog.saveconfig.prune.mapsource=Selecionar fonte de mapas
-dialog.saveconfig.prune.mapsourcelist=Fontes de mapas
-dialog.saveconfig.prune.diskcache=Cache de mapas
-dialog.saveconfig.prune.kmzimagewidth=Largura da imagem KMZ
-dialog.saveconfig.prune.colourscheme=Esquema de cores
-dialog.saveconfig.prune.linewidth=Espessura da linha
-dialog.saveconfig.prune.kmltrackcolour=Cor da rota KML
-dialog.saveconfig.prune.autosavesettings=Configura\u00e7\u00f5es para salvamento autom\u00e1tico
+dialog.paths.prune.gnuplotpath=Caminho para o gnuplot
+dialog.paths.prune.gpsbabelpath=Caminho para o gpsbabel
+dialog.paths.prune.exiftoolpath=Caminho para o exiftool
 dialog.setpaths.intro=Se voc\u00ea precisar, voc\u00ea pode escolher os caminhos para as aplica\u00e7\u00f5es externas:
 dialog.setpaths.found=Caminho encontrado?
 dialog.addaltitude.noaltitudes=O intervalo selecionado n\u00e3o cont\u00e9m altitudes
@@ -587,7 +556,7 @@ confirm.rearrangephotos=Fotos rearrumadas
 confirm.splitsegments=%d divis\u00f5es de segmentos feitas
 confirm.sewsegments=%d reuni\u00f5es de segmentos feitas
 confirm.cutandmove=Sele\u00e7\u00e3o movida
-confirm.interpolate=Pontos adicionados
+confirm.pointsadded=%d pontos adicionados
 confirm.convertnamestotimes=Nomes dos pontos convertidos
 confirm.saveexif.ok=Salvo %d arquivos de foto
 confirm.undo.single=opera\u00e7\u00e3o desfeita
@@ -643,7 +612,6 @@ button.selectall=Selecionar todos
 button.selectnone=Selecionar nenhum
 button.preview=Previs\u00e3o
 button.load=Carregar
-button.upload=Enviar
 button.guessfields=Campos adivinhados
 button.showwebpage=Mostrar p\u00e1gina Web
 button.check=Verificar
index 9c62dbe42d08ebfafc28257fd56034cfc0f1d177..70ceab6c9ff2df677bbb34a6b93b21a50998095b 100644 (file)
@@ -102,7 +102,7 @@ function.pastecoordinates=Introdu coordonate noi
 function.charts=Grafice
 function.show3d=Vizualizare 3D
 function.distances=Distan\u0163e
-function.fullrangedetails=Informa\u0163ie complet\u0103
+function.viewfulldetails=Informa\u0163ie complet\u0103
 function.estimatetime=Estimare durat\u0103
 function.learnestimationparams=\u00cenva\u021b\u0103 parametri de estimare timpi
 function.autoplay=Parcurge traseu
@@ -111,8 +111,6 @@ function.setpaths=Seteaz\u0103 calea c\u0103tre aplica\u021bii
 function.selectsegment=Selecteaz\u0103 segment curent
 function.splitsegments=Divizeaz\u0103 traseul \u00een segmente
 function.sewsegments=Combin\u0103 segmentele traseului
-function.getgpsies=\u00cencarc\u0103 trasee Gpsies
-function.uploadgpsies=Trimite date spre Gpsies
 function.lookupsrtm=Descarc\u0103 date SRTM \u00een cache
 function.downloadsrtm=Descarc\u0103 date SRTM
 function.getwikipedia=Caut\u0103 articole Wikipedia din proximitate
@@ -365,19 +363,6 @@ dialog.gpsies.column.length=Lungime
 dialog.gpsies.description=Descriere
 dialog.gpsies.nodescription=F\u0103r\u0103 descriere
 dialog.gpsies.nonefound=Nu a fost g\u0103sit niciun traseu
-dialog.gpsies.username=Gpsies username
-dialog.gpsies.password=Gpsies parol\u0103
-dialog.gpsies.keepprivate=Traseu privat
-dialog.gpsies.confirmopenpage=Deschid pagin\u0103 web pentru traseul \u00eenc\u0103rcat?
-dialog.gpsies.activities=Activit\u0103\u0163i
-dialog.gpsies.activity.trekking=Mers pe munte
-dialog.gpsies.activity.walking=Mers pe jos
-dialog.gpsies.activity.jogging=Alergare
-dialog.gpsies.activity.biking=Biciclet\u0103
-dialog.gpsies.activity.motorbiking=Motociclet\u0103
-dialog.gpsies.activity.snowshoe=Mers cu rachete de z\u0103pad\u0103
-dialog.gpsies.activity.sailing=Navigare
-dialog.gpsies.activity.skating=Role
 dialog.mapillary.nonefound=Nicio fotografie nu a fost g\u0103sit\u0103
 dialog.wikipedia.column.name=Nume
 dialog.wikipedia.column.distance=Distan\u0163\u0103
@@ -481,25 +466,9 @@ dialog.keys.intro=Pute\u021bi folosi urm\u0103toarele scurt\u0103turi \u00een lo
 dialog.keys.keylist=<table><tr><td>Taste s\u0103ge\u021bi</td><td>Mut\u0103 harta st\u00e2nga, dreapta, sus, jos</td></tr><tr><td>Ctrl + s\u0103geat\u0103 st\u00e2nga, dreapta</td><td>Selecteaz\u0103 punctul anterior sau urm\u0103tor</td></tr><tr><td>Ctrl + s\u0103geat\u0103 sus, jos</td><td>Aproprie sau \u00eendep\u0103rteaz\u0103</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Selecteaz\u0103 segmentul anterior sau urm\u0103tor</td></tr><tr><td>Ctrl + Home, End</td><td>Selecteaz\u0103 primul, ultimul punct</td></tr><tr><td>Del</td><td>\u0218terge punctul curent</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=Urm\u0103toarele set\u0103ri pot fi salvate \u00eentr-un fi\u0219ier de configur\u0103ri :
-dialog.saveconfig.prune.trackdirectory=Director trasee
-dialog.saveconfig.prune.photodirectory=Director foto
-dialog.saveconfig.prune.languagecode=Limb\u0103 (RO)
-dialog.saveconfig.prune.languagefile=Fi\u015fier de limba
-dialog.saveconfig.prune.gpsdevice=Dispozitiv GPS
-dialog.saveconfig.prune.gpsformat=Format GPS
-dialog.saveconfig.prune.povrayfont=Font Povray
-dialog.saveconfig.prune.gnuplotpath=Calea c\u0103tre gnuplot
-dialog.saveconfig.prune.gpsbabelpath=Calea c\u0103tre gpsbabel
-dialog.saveconfig.prune.exiftoolpath=Calea c\u0103tre exiftool
-dialog.saveconfig.prune.mapsource=Surs\u0103 hart\u0103 selectat\u0103
-dialog.saveconfig.prune.mapsourcelist=Surse hart\u0103
-dialog.saveconfig.prune.diskcache=Cache hart\u0103
-dialog.saveconfig.prune.kmzimagewidth=Dimensiuni imagini \u00een KMZ
-dialog.saveconfig.prune.colourscheme=Schem\u0103 de culoare
-dialog.saveconfig.prune.linewidth=Grosime linie
-dialog.saveconfig.prune.kmltrackcolour=Culoar track KML
-dialog.saveconfig.prune.autosavesettings=Set\u0103ri salv\u0103ri automate
+dialog.paths.prune.gnuplotpath=Calea c\u0103tre gnuplot
+dialog.paths.prune.gpsbabelpath=Calea c\u0103tre gpsbabel
+dialog.paths.prune.exiftoolpath=Calea c\u0103tre exiftool
 dialog.setpaths.intro=Dac\u0103 dori\u021bi pute\u021bi alege calea c\u0103tre aplica\u021bii externe
 dialog.setpaths.found=Cale g\u0103sit\u0103?
 dialog.addaltitude.noaltitudes=Intervalul nu con\u021bine altitudini
@@ -613,7 +582,7 @@ confirm.rearrangephotos=Fotografiile au fost rearanjate
 confirm.splitsegments=Au fost f\u0103cute %d diviz\u0103ri de segmente
 confirm.sewsegments=Au fost combinate %d segmente
 confirm.cutandmove=Selec\u021bia a fost mutat\u0103
-confirm.interpolate=Punctele au fost ad\u0103ugate
+confirm.pointsadded=%d punctele au fost ad\u0103ugate
 confirm.convertnamestotimes=Numele waypoint-urile au fost convertite
 confirm.saveexif.ok=Au fost salvate %d fi\u0219iere foto
 confirm.undo.single=opera\u021bia a fost anulat\u0103
@@ -669,7 +638,6 @@ button.selectall=Selecteaz\u0103 tot
 button.selectnone=Deselecteaz\u0103 tot
 button.preview=Previzualizare
 button.load=Descarc\u0103
-button.upload=Trimite
 button.guessfields=Ghice\u0219te c\u00e2mpuri
 button.showwebpage=Deschide pagina web
 button.check=Verific\u0103
index ea4286bf80553430799f65e9f88c10b4a08dc9b6..6f99f0f952aa669053c1ca4c981bdb557f6a3a6d 100644 (file)
@@ -12,7 +12,6 @@ menu.track=\u0422\u0440\u0435\u043a
 menu.track.undo=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c
 menu.track.clearundo=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439
 menu.track.markrectangle=\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0438 \u0432 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0435
-function.deletemarked=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0442\u043e\u0447\u043a\u0438
 menu.range=\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b
 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
@@ -86,6 +85,7 @@ function.exportpov=\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 POV
 function.exportimage=\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u0301\u043d\u0438\u0435
 function.editwaypointname=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u0443\u0442\u0435\u0432\u043e\u0439 \u0442\u043e\u0447\u043a\u0438
 function.compress=\u0421\u0436\u0430\u0442\u044c \u0442\u0440\u0435\u043a
+function.deletemarked=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0442\u043e\u0447\u043a\u0438
 function.marklifts=\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043f\u043e\u0434\u044a\u0451\u043c\u043d\u0438\u043a\u0438 \u0432 \u0433\u043e\u0440\u0443
 function.deleterange=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b
 function.croptrack=\u041e\u0431\u0440\u0435\u0437\u0430\u0442\u044c \u0442\u0440\u0435\u043a
@@ -98,10 +98,12 @@ function.convertnamestotimes=\u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0
 function.deletefieldvalues=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f
 function.findwaypoint=\u041d\u0430\u0439\u0442\u0438 \u043f\u0443\u0442\u0435\u0432\u0443\u044e \u0442\u043e\u0447\u043a\u0443
 function.pastecoordinates=\u0412\u0432\u043e\u0434 \u043d\u043e\u0432\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442
+function.pastecoordinatelist=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442
+function.enterpluscode=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 pluscode
 function.charts=\u0413\u0440\u0430\u0444\u0438\u043a\u0438
 function.show3d=3D-\u0432\u0438\u0434
 function.distances=\u0420\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u044f
-function.fullrangedetails=\u0414\u0435\u0442\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0443
+function.viewfulldetails=\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0435 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f
 function.estimatetime=\u0421\u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0440\u0435\u043c\u044f
 function.learnestimationparams=\u0417\u0430\u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430 \u0432\u0440\u0435\u043c\u0435\u043d\u0438
 function.autoplay=\u0410\u0432\u0442\u043e\u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u043a\u0430
@@ -111,8 +113,6 @@ function.selectsegment=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0442\u0435\u
 function.splitsegments=\u0420\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u0442\u0440\u0435\u043a \u043d\u0430 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u044b
 function.sewsegments=\u0421\u043a\u043b\u0435\u0438\u0442\u044c \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u044b \u0442\u0440\u0435\u043a\u0430 \u0432\u043e\u0435\u0434\u0438\u043d\u043e
 function.createmarkerwaypoints=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043c\u0430\u0440\u043a\u0435\u0440\u044b \u043f\u0443\u0442\u0435\u0432\u044b\u0445 \u0442\u043e\u0447\u0435\u043a
-function.getgpsies=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0442\u0440\u0435\u043a\u0438
-function.uploadgpsies=\u0412\u044b\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0442\u0440\u0435\u043a \u043d\u0430 gpsies.com
 function.lookupsrtm=\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u044b\u0441\u043e\u0442\u0443 \u0438\u0437 SRTM
 function.downloadsrtm=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c SRTM-\u0442\u0430\u0439\u043b\u044b
 function.getwikipedia=\u0421\u0442\u0430\u0442\u044c\u044f \u043e \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432 \u0412\u0438\u043a\u0438
@@ -122,6 +122,7 @@ function.searchopencachingde=\u041f\u043e\u0438\u0441\u043a \u0442\u0430\u0439\u
 function.mapillary=\u041f\u043e\u0438\u0441\u043a \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0438\u0445 \u0444\u043e\u0442\u043e
 function.downloadosm=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c OSM \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u044c
 function.duplicatepoint=\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u0447\u043a\u0443 \u0432 \u043a\u043e\u043d\u0435\u0446 \u0442\u0440\u0435\u043a\u0430
+function.projectpoint=\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u0447\u043a\u0443
 function.setcolours=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0446\u0432\u0435\u0442\u0430
 function.setdisplaysettings=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f
 function.setlanguage=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u044f\u0437\u044b\u043a
@@ -369,19 +370,6 @@ dialog.gpsies.column.length=\u0414\u043b\u0438\u043d\u0430
 dialog.gpsies.description=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435
 dialog.gpsies.nodescription=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e
 dialog.gpsies.nonefound=\u0422\u0440\u0435\u043a\u043e\u0432 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e
-dialog.gpsies.username=\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432 Gpsies
-dialog.gpsies.password=\u043f\u0430\u0440\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f Gpsies
-dialog.gpsies.keepprivate=\u0427\u0430\u0441\u0442\u043d\u044b\u0439 \u0442\u0440\u0435\u043a
-dialog.gpsies.confirmopenpage=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0442\u0440\u0435\u043a\u0430 \u043d\u0430 \u0441\u0430\u0439\u0442 gpsies.com?
-dialog.gpsies.activities=\u0422\u0438\u043f\u044b \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438
-dialog.gpsies.activity.trekking=\u041f\u0435\u0448\u0438\u0439 \u0442\u0443\u0440\u0438\u0437\u043c
-dialog.gpsies.activity.walking=\u0425\u043e\u0434\u044c\u0431\u0430
-dialog.gpsies.activity.jogging=\u0411\u0435\u0433
-dialog.gpsies.activity.biking=\u041d\u0430 \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434\u0435
-dialog.gpsies.activity.motorbiking=\u041d\u0430 \u043c\u043e\u0442\u043e\u0446\u0438\u043a\u043b\u0435
-dialog.gpsies.activity.snowshoe=\u041d\u0430 \u0441\u043d\u0435\u0433\u043e\u0441\u0442\u0443\u043f\u0430\u0445
-dialog.gpsies.activity.sailing=\u041f\u0430\u0440\u0443\u0441\u043d\u044b\u0439 \u0441\u043f\u043e\u0440\u0442
-dialog.gpsies.activity.skating=\u041d\u0430 \u043a\u043e\u043d\u044c\u043a\u0430\u0445
 dialog.mapillary.nonefound=\u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u044b
 dialog.wikipedia.column.name=\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u044c\u0438
 dialog.wikipedia.column.distance=\u0420\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435
@@ -449,6 +437,9 @@ dialog.deletemarked.nonefound=\u041d\u0435\u0442 \u043f\u043e\u043c\u0435\u0447\
 dialog.pastecoordinates.desc=\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0437\u0434\u0435\u0441\u044c
 dialog.pastecoordinates.coords=\u041a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b
 dialog.pastecoordinates.nothingfound=\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0435 \u0440\u0430\u0437
+dialog.pastecoordinatelist.desc=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0434\u043b\u044f \u043d\u043e\u0432\u044b\u0445 \u0442\u043e\u0447\u0435\u043a \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0435 \u043d\u0430 \u043f\u0440\u044f\u043c\u043e\u0439
+dialog.pluscode.desc=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043b\u0438 \u0432\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u043b\u044e\u0441-\u043a\u043e\u0434 \u0437\u0434\u0435\u0441\u044c
+dialog.pluscode.nothingfound=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u043a\u043e\u0434 \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437
 dialog.help.help=\u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443\nhttps://gpsprune.activityworkshop.net/
 dialog.about.version=\u0412\u0435\u0440\u0441\u0438\u044f
 dialog.about.build=\u0420\u0435\u0432\u0438\u0437\u0438\u044f
@@ -488,25 +479,9 @@ dialog.keys.intro=\u0412\u043c\u0435\u0441\u0442\u043e \u043c\u044b\u0448\u0438
 dialog.keys.keylist=<table><tr><td></td><td>\u0421\u0434\u0432\u0438\u0433 \u043a\u0430\u0440\u0442\u044b \u0432\u043b\u0435\u0432\u043e, \u0432\u043f\u0440\u0430\u0432\u043e, \u0432\u0432\u0435\u0440\u0445, \u0432\u043d\u0438\u0437</td><td><tr><td>Ctrl + \u043b\u0435\u0432\u0430\u044f, \u043f\u0440\u0430\u0432\u0430\u044f \u0441\u0442\u0440\u0435\u043b\u043a\u0430</td><td>\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u0438\u043b\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0442\u043e\u0447\u043a\u0443</td></tr><tr><td>Ctrl + \u0441\u0442\u0440\u0435\u043b\u043a\u0438 \u0432\u0432\u0435\u0440\u0445, \u0432\u043d\u0438\u0437 </td><td> \u0423\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u0435 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439, \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0441\u0435\u0433\u043c\u0435\u043d\u0442</td></tr><tr><td>Ctrl + Home, End</td><td>\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043f\u0435\u0440\u0432\u0443\u044e, \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0442\u043e\u0447\u043a\u0443</td></tr><tr><td>Del</td><td>\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0442\u043e\u0447\u043a\u0443</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b \u0432 \u0444\u0430\u0439\u043b:
-dialog.saveconfig.prune.trackdirectory=\u041f\u0430\u043f\u043a\u0430 \u0441 \u0442\u0440\u0435\u043a\u0430\u043c\u0438
-dialog.saveconfig.prune.photodirectory=\u041f\u0430\u043f\u043a\u0430 \u0441 \u0444\u043e\u0442\u043e
-dialog.saveconfig.prune.languagecode=\u041a\u043e\u0434 \u044f\u0437\u044b\u043a\u0430 (RU)
-dialog.saveconfig.prune.languagefile=\u042f\u0437\u044b\u043a\u043e\u0432\u043e\u0439 \u0444\u0430\u0439\u043b
-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.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.mapsource=\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u043a\u0430\u0440\u0442\u044b
-dialog.saveconfig.prune.mapsourcelist=\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u043a\u0430\u0440\u0442
-dialog.saveconfig.prune.diskcache=\u041a\u0435\u0448 \u043a\u0430\u0440\u0442\u044b
-dialog.saveconfig.prune.kmzimagewidth=\u0440\u0430\u0437\u043c\u0435\u0440 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f KMZ
-dialog.saveconfig.prune.colourscheme=\u0426\u0432\u0435\u0442\u043e\u0432\u0430\u044f \u0441\u0445\u0435\u043c\u0430
-dialog.saveconfig.prune.linewidth=\u0422\u043e\u043b\u0449\u0438\u043d\u0430 \u043b\u0438\u043d\u0438\u0438
-dialog.saveconfig.prune.kmltrackcolour=\u0446\u0432\u0435\u0442 \u0442\u0440\u0435\u043a\u0430 KML
-dialog.saveconfig.prune.autosavesettings=\u0410\u0432\u0442\u043e\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043e\u043a
+dialog.paths.prune.gnuplotpath=\u041f\u0443\u0442\u044c \u043a GNUPLOT
+dialog.paths.prune.gpsbabelpath=\u041f\u0443\u0442\u044c \u043a GPSBabel
+dialog.paths.prune.exiftoolpath=\u041f\u0443\u0442\u044c \u043a ExifTool
 dialog.setpaths.intro=\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u043a \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c:
 dialog.setpaths.found=\u041f\u0443\u0442\u044c \u043d\u0430\u0439\u0434\u0435\u043d?
 dialog.addaltitude.noaltitudes=\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u044b\u0441\u043e\u0442
@@ -573,6 +548,8 @@ dialog.displaysettings.wpicon.pin=\u0417\u0430\u043a\u043e\u043b\u043a\u0430
 dialog.displaysettings.size.small=\u041c\u0430\u043b\u044b\u0439
 dialog.displaysettings.size.medium=\u0421\u0440\u0435\u0434\u043d\u0438\u0439
 dialog.displaysettings.size.large=\u0411\u043e\u043b\u044c\u0448\u043e\u0439
+dialog.displaysettings.windowstyle=\u0441\u0442\u0438\u043b\u044c \u043e\u043a\u043d\u0430
+dialog.displaysettings.windowstyle.default=\u0441\u0442\u0438\u043b\u044c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e
 dialog.downloadosm.desc=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 OSM \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438:
 dialog.searchwikipedianames.search=\u041f\u043e\u0438\u0441\u043a \u0434\u043b\u044f:
 dialog.weather.location=\u041c\u0435\u0441\u0442\u043e
@@ -615,6 +592,12 @@ dialog.autoplay.usetimestamps=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u
 dialog.autoplay.rewind=\u041d\u0430\u0437\u0430\u0434
 dialog.autoplay.pause=\u0414\u0435\u0301\u043b\u0430\u0442\u044c \u043f\u0430\u0301\u0443\u0437\u0443
 dialog.autoplay.play=\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438
+dialog.markers.halves=\u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u0442\u043e\u0447\u043a\u0438
+dialog.markers.half.distance=\u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0430 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u044f
+dialog.markers.half.climb=\u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0430 \u043f\u043e\u0434\u044a\u0451\u043c\u0430
+dialog.markers.half.descent=\u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0430 \u0441\u043f\u0443\u0441\u043a\u0430
+dialog.projectpoint.desc=\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0446\u0438\u0438 \u044d\u0442\u043e\u0439 \u0442\u043e\u0447\u043a\u0438
+dialog.projectpoint.bearing=\u0430\u0437\u0438\u043c\u0443\u0442 (\u0433\u0440\u0430\u0434\u0443\u0441\u044b \u0441 \u0441\u0435\u0432\u0435\u0440\u0430)
 
 # 3d window
 dialog.3d.title=GpsPrune 3D-\u0432\u0438\u0434
@@ -636,7 +619,7 @@ confirm.rearrangephotos=\u0424\u043e\u0442\u043e \u043f\u0435\u0440\u0435\u0434\
 confirm.splitsegments=\u0421\u0434\u0435\u043b\u0430\u043d\u043e %d \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0439 \u043d\u0430 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u044b
 confirm.sewsegments=\u0421\u0434\u0435\u043b\u0430\u043d\u043e %d \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u043e\u0432
 confirm.cutandmove=\u041e\u0442\u043e\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u043e
-confirm.interpolate=\u0422\u043e\u0447\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b
+confirm.pointsadded=%d \u0422\u043e\u0447\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b
 confirm.convertnamestotimes=\u0418\u043c\u044f \u043f\u0443\u0442\u0435\u0432\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0435\u043d\u043e
 confirm.saveexif.ok=\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043e %d \u0444\u0430\u0439\u043b\u044b \u0441 \u0444\u043e\u0442\u043e
 confirm.undo.single=\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043e\u0442\u043c\u0435\u043d\u044b
@@ -692,7 +675,6 @@ button.selectall=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435
 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.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
@@ -766,6 +748,7 @@ map.overzoom=\u041d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b
 # Field names
 fieldname.latitude=\u0428\u0438\u0440\u043e\u0442\u0430
 fieldname.longitude=\u0414\u043e\u043b\u0433\u043e\u0442\u0430
+fieldname.coordinates=\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0301\u0442\u044b
 fieldname.altitude=\u0412\u044b\u0441\u043e\u0442\u0430
 fieldname.timestamp=\u0412\u0440\u0435\u043c\u044f
 fieldname.time=\u0412\u0440\u0435\u043c\u044f
@@ -780,6 +763,7 @@ fieldname.duration=\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u0435\
 fieldname.speed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c
 fieldname.verticalspeed=\u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c
 fieldname.description=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435
+fieldname.comment=\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0301\u0440\u0438\u0439
 fieldname.mediafilename=\u0424\u0430\u0439\u043b
 
 # Measurement units
@@ -879,6 +863,7 @@ error.load.nopoints=\u041d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u04
 error.load.unknownxml=\u041d\u0435\u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u043d\u044b\u0439 XML- \u0444\u043e\u0440\u043c\u0430\u0442:
 error.load.noxmlinzip=\u0412 zip-\u0430\u0440\u0445\u0438\u0432\u0435 \u043d\u0435\u0442 XML-\u0444\u0430\u0439\u043b\u0430
 error.load.othererror=\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0447\u0442\u0435\u043d\u0438\u0438 \u0444\u0430\u0439\u043b\u0430:
+error.load.nopointsintext=\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u0445 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430
 error.jpegload.dialogtitle=\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0444\u043e\u0442\u043e
 error.jpegload.nofilesfound=\u0424\u0430\u0439\u043b\u044b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u044b
 error.jpegload.nojpegsfound=JPEG-\u0444\u0430\u0439\u043b\u044b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u044b
index d149f98baa82de4fd77e0a37ca0bc27cb36fb912..e2115aac56fdf23fb4d013d0dd92bd8432c277c8 100644 (file)
@@ -100,7 +100,7 @@ function.pastecoordinates=Infoga koordinater
 function.charts=Diagram
 function.show3d=3D-vy
 function.distances=Avst\u00e5nd
-function.fullrangedetails=Alla intevall-detaljer
+function.viewfulldetails=Alla detaljer
 function.estimatetime=Uppskatta tid
 function.learnestimationparams=L\u00e4r upp tidsuppskattningsparametrar
 function.setmapbg=V\u00e4lj bakgrundskarta
@@ -109,8 +109,6 @@ function.selectsegment=Markera aktuellt segment
 function.splitsegments=Dela upp sp\u00e5ret i segment
 function.sewsegments=Sy ihop sp\u00e5r-segment
 function.createmarkerwaypoints=Skapa markerings-waypoints
-function.getgpsies=H\u00e4mta Gpsies-sp\u00e5r
-function.uploadgpsies=Ladda upp sp\u00e5r till Gpsies
 function.lookupsrtm=H\u00e4mta h\u00f6jddata fr\u00e5n SRTM
 function.downloadsrtm=Ladda ner SRTM-h\u00f6jddata
 function.getwikipedia=H\u00e4mta n\u00e4rliggande Wikipedia-artiklar
@@ -356,7 +354,6 @@ button.selectall=Markera alla
 button.selectnone=Markera inget
 button.preview=F\u00f6rhandsvisa
 button.load=Ladda in
-button.upload=Ladda upp
 button.guessfields=Gissa f\u00e4lt
 button.showwebpage=Visa hemsida
 button.resettodefaults=\u00c5terst\u00e4ll till default
index 998c1126ad08b6afb2ddbffdff56305ad867eec4..72a718fd8e903b60c2b3c8559a10c4b84f55d1b7 100644 (file)
@@ -85,10 +85,8 @@ function.pastecoordinates=Yeni korrdinatlar gir
 function.charts=Krokiler
 function.show3d=3B g\u00fcr\u00fcnt\u00fcs\u00fc
 function.distances=Uzakl\u0131klar
-function.fullrangedetails=S\u0131ran\u0131n b\u00fct\u00fcn ayr\u0131nt\u0131lar
 function.setmapbg=Arkafonun haritas\u0131 se\u00e7
 function.setpaths=Uygulamalar\u0131n yollar\u0131 ayarla
-function.getgpsies=Gpsies.com'dan yolu al
 function.duplicatepoint=Noktay\u0131 kopyala
 function.setcolours=Renkleri ayarla
 function.setlanguage=Dil se\u00e7
@@ -213,13 +211,6 @@ dialog.gpsies.column.length=Uzunlu\u011fu
 dialog.gpsies.description=A\u00e7\u0131klama
 dialog.gpsies.nodescription=A\u00e7\u0131klama yok
 dialog.gpsies.nonefound=Herhangi bir yol bulunmad\u0131
-dialog.gpsies.activities=Etkinlik
-dialog.gpsies.activity.trekking=Y\u00fcr\u00fcy\u00fc\u015f
-dialog.gpsies.activity.walking=Y\u00fcr\u00fcme
-dialog.gpsies.activity.jogging=Ko\u015fma
-dialog.gpsies.activity.biking=Bisiklet
-dialog.gpsies.activity.sailing=Yelken
-dialog.gpsies.activity.skating=Paten
 dialog.correlate.select.photoname=Foto ad\u0131
 dialog.correlate.select.photolater=Foto sonra
 dialog.correlate.options.offset.hours=saat,
@@ -256,19 +247,9 @@ dialog.checkversion.releasedate2=.
 dialog.checkversion.download=Yeni s\u00fcr\u00fcm indirmek i\u00e7in https://gpsprune.activityworkshop.net/download.html adresine git.
 dialog.keys.intro=Fare yerinde a\u015fa\u011f\u0131daki k\u0131sayol tu\u015flar\u0131 kullanabilirsin:
 dialog.keys.keylist=<table><tr><td>Ok tu\u015flar\u0131</td><td>Haritay\u0131 sola/sa\u011fa/a\u015fa\u011f\u0131/yukar\u0131 kayd\u0131r</td></tr><tr><td>Ctrl + sol, sa\u011f</td><td>\u00d6nceki/sonraki noktay\u0131 se\u00e7</td></tr><tr><td>Ctrl + yukar/a\u015fa\u011f\u0131</td><td>Yak\u0131nla\u015ft\u0131r/Uzakla\u015ft\u0131r</td></tr><tr><td>Del</td><td>Se\u00e7ili noltay\u0131 sil</td></tr></table>
-dialog.saveconfig.desc=A\u011fa\u015f\u0131daki ayarlar\u0131 bir dasyada kaydedilir:
-dialog.saveconfig.prune.trackdirectory=\u0130z klas\u00f6r\u00fc
-dialog.saveconfig.prune.photodirectory=Foto klas\u00f6r\u00fc
-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.gnuplotpath=gnuplot'un yeriyolu
-dialog.saveconfig.prune.gpsbabelpath=gpsbabel'in yeriyolu
-dialog.saveconfig.prune.exiftoolpath=exiftool'un yeriyolu
-dialog.saveconfig.prune.mapserverindex=Harita sunucunun index
-dialog.saveconfig.prune.mapserverurl=Harita sunucunun adresi
-dialog.saveconfig.prune.kmzimagewidth=KMZ resim geni\u015fli\u011fi
+dialog.paths.prune.gnuplotpath=gnuplot'un yeriyolu
+dialog.paths.prune.gpsbabelpath=gpsbabel'in yeriyolu
+dialog.paths.prune.exiftoolpath=exiftool'un yeriyolu
 dialog.setpaths.intro=\u0130ste\u011fe ba\u011fl\u0131 a\u015fa\u011f\u0131daki uygulamalar\u0131n veriyolu kaydedebilirsin:
 dialog.addaltitude.noaltitudes=Se\u00e7ili s\u0131rada y\u00fckseklik bilgisi bulunmad\u0131
 dialog.addaltitude.desc=Eklenecek y\u00fckseklik ofseti
index 15b6b531597aebcc9d145366cfa5ab936e77f282..43ef43d6b54a34a922b3f6e9da3ea70c4bc87957 100644 (file)
@@ -98,7 +98,6 @@ function.pastecoordinates=\u0412\u0432\u0435\u0434\u0435\u043d\u043d\u044f \u043
 function.charts=\u0413\u0440\u0430\u0444\u0456\u043a\u0438
 function.show3d=3D-\u0432\u0438\u0433\u043b\u044f\u0434
 function.distances=\u0412\u0456\u0434\u0441\u0442\u0430\u043d\u0456
-function.fullrangedetails=\u0414\u0435\u0442\u0430\u043b\u0456\u0437\u0430\u0446\u0456\u044f \u043f\u043e \u0456\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0443
 function.estimatetime=\u041f\u0440\u0438\u0431\u043b\u0438\u0437\u043d\u0438\u0439 \u0447\u0430\u0441
 function.learnestimationparams=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438 \u0432\u0433\u0430\u0434\u0443\u0432\u0430\u043d\u043d\u044f \u043f\u0440\u0438\u0431\u043b\u0438\u0437\u043d\u043e\u0433\u043e \u0447\u0430\u0441\u0443
 function.setmapbg=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043c\u0430\u043f\u0443-\u043f\u0456\u0434\u043a\u043b\u0430\u0434\u043a\u0443
@@ -106,8 +105,6 @@ function.setpaths=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \
 function.selectsegment=\u0412\u0438\u0431\u0440\u0430\u0442\u0438 \u043f\u043e\u0442\u043e\u0447\u043d\u0438\u0439 \u0441\u0435\u0433\u043c\u0435\u043d\u0442
 function.splitsegments=\u0420\u043e\u0437\u0431\u0438\u0442\u0438 \u0442\u0440\u0435\u043a \u043d\u0430 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0438
 function.sewsegments=\u0417\u0448\u0438\u0442\u0438 \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0438 \u0442\u0440\u0435\u043a\u0456\u0432 \u0440\u0430\u0437\u043e\u043c
-function.getgpsies=\u0417\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0442\u0440\u0435\u043a\u0438 \u0437 Gpsies
-function.uploadgpsies=\u0412\u0438\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0442\u0440\u0435\u043a\u0438 \u043d\u0430 Gpsies
 function.lookupsrtm=\u041e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0432\u0438\u0441\u043e\u0442\u0438 \u0437 SRTM
 function.downloadsrtm=\u0417\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 SRTM-\u0442\u0430\u0439\u043b\u0438
 function.getwikipedia=\u041e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u043d\u0430\u0439\u0431\u043b\u0438\u0436\u0447\u0443 \u0441\u0442\u0430\u0442\u0442\u044e \u0437 \u0412\u0456\u043a\u0456\u043f\u0435\u0434\u0456\u0457
index c42fe08d5d6807fc3b5caee3f7447e06403554e4..eba2b714906cc5f9e6cbb5f4d16562d222b9305c 100644 (file)
@@ -98,7 +98,6 @@ function.pastecoordinates=\u8f93\u5165\u65b0\u5750\u6807
 function.charts=\u56fe\u8868
 function.show3d=3D\u89c6\u56fe
 function.distances=\u8ddd\u79bb
-function.fullrangedetails=\u5168\u822a\u6bb5\u8be6\u7ec6\u4fe1\u606f
 function.estimatetime=\u4f30\u8ba1\u65f6\u95f4
 function.learnestimationparams=\u4f7f\u7528\u5f53\u524d\u8f68\u8ff9\u53c2\u6570\u4f30\u8ba1\u65f6\u95f4
 function.setmapbg=\u80cc\u666f\u5730\u56fe
@@ -106,8 +105,6 @@ function.setpaths=\u8bbe\u7f6e\u7a0b\u5e8f\u8def\u5f84
 function.selectsegment=\u9009\u4e2d\u5f53\u524d\u8f68\u8ff9\u6bb5
 function.splitsegments=\u5206\u5272\u8f68\u8ff9
 function.sewsegments=\u63a5\u5408\u8f68\u8ff9\u7247\u6bb5
-function.getgpsies=\u83b7\u53d6Gpsies\u8f68\u8ff9
-function.uploadgpsies=\u4e0a\u4f20\u8f68\u8ff9\u5230Gpsies
 function.lookupsrtm=\u4eceSRTM\u83b7\u5f97\u9ad8\u5ea6\u4fe1\u606f
 function.downloadsrtm=\u4e0b\u8f7dSRTM\u6570\u636e
 function.getwikipedia=\u7ef4\u57fa\u767e\u79d1\u6709\u5173\u672c\u5730\u6587\u7ae0
@@ -358,19 +355,6 @@ dialog.gpsies.column.length=\u957f\u5ea6
 dialog.gpsies.description=\u63cf\u8ff0
 dialog.gpsies.nodescription=\u65e0\u63cf\u8ff0
 dialog.gpsies.nonefound=\u672a\u627e\u5230\u8f68\u8ff9
-dialog.gpsies.username=Gpsies\u7f51\u7ad9\u7528\u6237\u540d
-dialog.gpsies.password=Gpsies\u7f51\u7ad9\u5bc6\u7801
-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.activity.walking=\u6b65\u884c
-dialog.gpsies.activity.jogging=\u8dd1\u6b65
-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.wikipedia.nonefound=\u672a\u627e\u5230\u7ef4\u57fa\u767e\u79d1\u6761\u76ee
@@ -471,25 +455,9 @@ dialog.keys.intro=\u53ef\u7528\u4e0b\u5217\u5feb\u6377\u952e\u66ff\u4ee3\u9f20\u
 dialog.keys.keylist=<table><tr><td>\u7bad\u5934</td><td>\u4e0a\u4e0b\u5de6\u53f3\u79fb\u52a8\u5730\u56fe</td></tr><tr><td>Ctrl + \u5de6\u53f3\u7bad\u5934</td><td>\u9009\u53d6\u524d\uff0c\u540e\u70b9</td></tr><tr><td>Ctrl + \u4e0a\u4e0b\u7bad\u5934</td><td>\u653e\u5927\u7f29\u5c0f</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>\u9009\u62e9\u524d\u540e\u6bb5</td></tr><tr><td>Ctrl + Home, End</td><td>\u9009\u62e9\u9996\u672b\u70b9</td></tr><tr><td>Del</td><td>\u5220\u9664\u5f53\u524d\u70b9</td></tr></table>
 dialog.keys.normalmodifier=Ctrl
 dialog.keys.macmodifier=Command
-dialog.saveconfig.desc=\u4e0b\u5217\u8bbe\u7f6e\u5c06\u4fdd\u5b58\u5230\u8bbe\u7f6e\u6587\u4ef6
-dialog.saveconfig.prune.trackdirectory=\u8f68\u8ff9\u6587\u4ef6\u5939
-dialog.saveconfig.prune.photodirectory=\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.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\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.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.paths.prune.gnuplotpath=gnuplot\u8def\u5f84
+dialog.paths.prune.gpsbabelpath=gpsbabel\u8def\u5f84
+dialog.paths.prune.exiftoolpath=exiftool\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
@@ -598,7 +566,6 @@ confirm.rearrangephotos=\u7167\u7247\u5df2\u91cd\u6392
 confirm.splitsegments=\u8f68\u8ff9\u5df2\u5206\u5272\u4e3a %d \u6bb5
 confirm.sewsegments=%d \u8f68\u8ff9\u6bb5\u5df2\u5408\u5e76
 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.ok=\u5df2\u4fdd\u5b58 %d \u7167\u7247\u6587\u4ef6
 confirm.undo.single=\u5df2\u64a4\u9500\u7684\u64cd\u4f5c
@@ -654,7 +621,6 @@ button.selectall=\u5168\u9009
 button.selectnone=\u5168\u4e0d\u9009
 button.preview=\u9884\u89c8
 button.load=\u5bfc\u5165
-button.upload=\u4e0a\u8f7d
 button.guessfields=\u4f30\u6d4b\u6570\u636e\u6bb5
 button.showwebpage=\u663e\u793a\u7f51\u9875
 button.check=\u68c0\u67e5
diff --git a/src/tim/prune/load/ContentCacher.java b/src/tim/prune/load/ContentCacher.java
new file mode 100644 (file)
index 0000000..623abda
--- /dev/null
@@ -0,0 +1,90 @@
+package tim.prune.load;
+
+import java.util.ArrayList;
+
+/**
+ * General point data cacher
+ */
+public abstract class ContentCacher
+{
+       /** Array to hold lines of file */
+       private String[] _contentArray = null;
+
+
+       /**
+        * @return Contents of the file as array of non-blank Strings
+        */
+       public String[] getContents()
+       {
+               return _contentArray;
+       }
+
+
+       /**
+        * Get the top section of the file for preview
+        * @param inNumRows number of lines to extract
+        * @param inMaxWidth max length of Strings (longer ones will be chopped)
+        * @return String array containing non-blank lines from the file
+        */
+       public String[] getSnippet(int inNumRows, int inMaxWidth)
+       {
+               final int MIN_SNIPPET_SIZE = 3;
+               // Check size is within sensible limits
+               int numToCopy = inNumRows;
+               if (numToCopy > getNumLines()) numToCopy = getNumLines();
+               int size = numToCopy;
+               if (size < MIN_SNIPPET_SIZE) size = MIN_SNIPPET_SIZE;
+               String[] result = new String[size];
+               // Copy Strings across
+               System.arraycopy(_contentArray, 0, result, 0, numToCopy);
+               // Chop Strings to max width if necessary
+               if (inMaxWidth > 10)
+               {
+                       for (int i=0; i<size; i++)
+                       {
+                               if (result[i] == null)
+                                       result[i] = "";
+                               else
+                               {
+                                       if (result[i].length() > inMaxWidth)
+                                               result[i] = result[i].trim();
+                                       if (result[i].length() > inMaxWidth)
+                                               result[i] = result[i].substring(0, inMaxWidth);
+                               }
+                       }
+               }
+               return result;
+       }
+
+       /**
+        * @return the number of non-blank lines in the file
+        */
+       public int getNumLines()
+       {
+               return _contentArray.length;
+       }
+
+
+       /**
+        * Clear the memory
+        */
+       public void clear()
+       {
+               _contentArray = null;
+       }
+
+       /**
+        * Populate the string array
+        * @param inList list of lines
+        */
+       protected void setContents(ArrayList<String> inList)
+       {
+               // Convert into String array for keeps
+               int numLines = inList.size();
+               _contentArray = new String[numLines];
+               for (int i=0; i<numLines; i++)
+               {
+                       _contentArray[i] = inList.get(i);
+               }
+       }
+}
index a151c2e285022f48c5ffe8bbdf2c3d8433c09df0..ca7a4abba8f5abac4f855e4b4127a65b9b0c5ba1 100644 (file)
@@ -10,37 +10,30 @@ import java.util.ArrayList;
  * Class to load the contents of a file
  * into an array for later retrieval
  */
-public class FileCacher
+public class FileCacher extends ContentCacher
 {
-       /** File to cache */
-       private File _file = null;
-       /** Array to hold lines of file */
-       private String[] _contentArray = null;
-
-
        /**
         * Constructor
         * @param inFile File object to cache
         */
        public FileCacher(File inFile)
        {
-               _file = inFile;
-               loadFile();
+               loadFile(inFile);
        }
 
 
        /**
         * Load the specified file into memory
         */
-       private void loadFile()
+       private void loadFile(File inFile)
        {
                ArrayList<String> contentList = new ArrayList<String>();
-               if (_file != null && _file.exists() && _file.canRead())
+               if (inFile != null && inFile.exists() && inFile.canRead())
                {
                        BufferedReader reader = null;
                        try
                        {
-                               reader = new BufferedReader(new FileReader(_file));
+                               reader = new BufferedReader(new FileReader(inFile));
                                String currLine = reader.readLine();
                                if (currLine != null && currLine.startsWith("<?xml")) {
                                        return; // it's an xml file, it shouldn't use this cacher
@@ -68,74 +61,6 @@ public class FileCacher
                                catch (Exception e) {}
                        }
                }
-               // Convert into String array for keeps
-               int numLines = contentList.size();
-               _contentArray = new String[numLines];
-               for (int i=0; i<numLines; i++)
-                       _contentArray[i] = contentList.get(i);
-       }
-
-
-       /**
-        * @return Contents of the file as array of non-blank Strings
-        */
-       public String[] getContents()
-       {
-               return _contentArray;
-       }
-
-
-       /**
-        * Get the top section of the file for preview
-        * @param inNumRows number of lines to extract
-        * @param inMaxWidth max length of Strings (longer ones will be chopped)
-        * @return String array containing non-blank lines from the file
-        */
-       public String[] getSnippet(int inNumRows, int inMaxWidth)
-       {
-               final int MIN_SNIPPET_SIZE = 3;
-               // Check size is within sensible limits
-               int numToCopy = inNumRows;
-               if (numToCopy > getNumLines()) numToCopy = getNumLines();
-               int size = numToCopy;
-               if (size < MIN_SNIPPET_SIZE) size = MIN_SNIPPET_SIZE;
-               String[] result = new String[size];
-               // Copy Strings across
-               System.arraycopy(_contentArray, 0, result, 0, numToCopy);
-               // Chop Strings to max width if necessary
-               if (inMaxWidth > 10)
-               {
-                       for (int i=0; i<size; i++)
-                       {
-                               if (result[i] == null)
-                                       result[i] = "";
-                               else
-                               {
-                                       if (result[i].length() > inMaxWidth)
-                                               result[i] = result[i].trim();
-                                       if (result[i].length() > inMaxWidth)
-                                               result[i] = result[i].substring(0, inMaxWidth);
-                               }
-                       }
-               }
-               return result;
-       }
-
-       /**
-        * @return the number of non-blank lines in the file
-        */
-       public int getNumLines()
-       {
-               return _contentArray.length;
-       }
-
-
-       /**
-        * Clear the memory
-        */
-       public void clear()
-       {
-               _file = null;
-               _contentArray = null;
+               setContents(contentList);
        }
 }
index 60c2c5dbcf5e429e21d4d3d76a18460d273b0525..990279211edf23aa2385dd66d86a41504ed4ed7f 100644 (file)
@@ -6,7 +6,7 @@ package tim.prune.load;
  */
 public class FileSplitter
 {
-       private FileCacher _cacher = null;
+       private ContentCacher _cacher = null;
        private int _numRows = 0;
        private int _numColumns = 0;
        private boolean[] _columnStates = null;
@@ -15,9 +15,9 @@ public class FileSplitter
 
        /**
         * Constructor
-        * @param inCacher FileCacher object holding file contents
+        * @param inCacher cacher object holding file contents
         */
-       public FileSplitter(FileCacher inCacher)
+       public FileSplitter(ContentCacher inCacher)
        {
                _cacher = inCacher;
        }
index 3e22eba029ccb76ce341a2fffaea6327669a28f1..471226f2919dc15c634454a2ce352e69039b20df 100644 (file)
@@ -256,11 +256,9 @@ public class JpegLoader implements Runnable, Cancellable
                if (timestamp == null) {
                        timestamp = new TimestampUtc(inFile.lastModified());
                }
-               // Apply timestamp to photo and its point (if any)
+               // Apply timestamp to photo (but not its point)
                photo.setTimestamp(timestamp);
-               if (photo.getDataPoint() != null) {
-                       // photo.getDataPoint().setFieldValue(Field.TIMESTAMP, timestamp.getText(Timestamp.Format.ISO8601), false);
-               }
+
                return photo;
        }
 
diff --git a/src/tim/prune/load/TextCacher.java b/src/tim/prune/load/TextCacher.java
new file mode 100644 (file)
index 0000000..0945bfe
--- /dev/null
@@ -0,0 +1,42 @@
+package tim.prune.load;
+
+import java.util.ArrayList;
+
+/**
+ * Class to split a pasted text
+ * into an array for later retrieval
+ */
+public class TextCacher extends ContentCacher
+{
+       /**
+        * Constructor
+        * @param inText text to cache
+        */
+       public TextCacher(String inText)
+       {
+               splitText(inText);
+       }
+
+
+       /**
+        * Load and split the specified text
+        */
+       private void splitText(String inText)
+       {
+               ArrayList<String> contentList = new ArrayList<String>();
+               if (inText != null)
+               {
+                       for (String currLine : inText.split("\n"))
+                       {
+                               if (currLine != null)
+                               {
+                                       currLine = currLine.trim();
+                                       if (currLine.length() > 0) {
+                                               contentList.add(currLine);
+                                       }
+                               }
+                       }
+               }
+               setContents(contentList);
+       }
+}
index b4a0ca829efc6c75fe64b7c8478ff9b6f5f50c8f..f61af3993d0f49cc3ef2ba2864ffb8e544848a3b 100644 (file)
@@ -48,7 +48,7 @@ public class TextFileLoader
        private JTextField _otherDelimiterText = null;
        private JLabel _statusLabel = null;
        private DelimiterInfo[] _delimiterInfos = null;
-       private FileCacher _fileCacher = null;
+       private ContentCacher _contentCacher = null;
        private JList<String> _snippetBox = null;
        private FileExtractTableModel _fileExtractTableModel = null;
        private JTable _fieldTable;
@@ -117,29 +117,7 @@ public class TextFileLoader
                _file = inFile;
                if (preCheckFile(_file))
                {
-                       _dialog = new JDialog(_parentFrame, I18nManager.getText("dialog.openoptions.title"), true);
-                       _dialog.setLocationRelativeTo(_parentFrame);
-                       _dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
-                       // add closing listener
-                       _dialog.addWindowListener(new WindowAdapter() {
-                               public void windowClosing(WindowEvent e) {
-                                       _dialog.dispose();
-                                       _app.informNoDataLoaded();
-                               }
-                       });
-                       _dialog.getContentPane().add(makeDialogComponents());
-
-                       // select best separator according to row counts (more is better)
-                       int bestDelim = getBestOption(_delimiterInfos[0].getNumWinningRecords(),
-                               _delimiterInfos[1].getNumWinningRecords(), _delimiterInfos[2].getNumWinningRecords(),
-                               _delimiterInfos[3].getNumWinningRecords());
-                       if (bestDelim >= 0)
-                               _delimiterRadios[bestDelim].setSelected(true);
-                       else
-                               _delimiterRadios[_delimiterRadios.length-1].setSelected(true);
-                       informDelimiterSelected();
-                       _dialog.pack();
-                       _dialog.setVisible(true);
+                       showDialog();
                }
                else
                {
@@ -152,8 +130,38 @@ public class TextFileLoader
 
 
        /**
-        * Check the given file for readability and funny characters,
-        * and count the fields for the various separators
+        * Checks passed, so now build and show the dialog
+        */
+       private void showDialog()
+       {
+               _dialog = new JDialog(_parentFrame, I18nManager.getText("dialog.openoptions.title"), true);
+               _dialog.setLocationRelativeTo(_parentFrame);
+               _dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
+               // add closing listener
+               _dialog.addWindowListener(new WindowAdapter() {
+                       public void windowClosing(WindowEvent e) {
+                               _dialog.dispose();
+                               _app.informNoDataLoaded();
+                       }
+               });
+               _dialog.getContentPane().add(makeDialogComponents());
+
+               // select best separator according to row counts (more is better)
+               int bestDelim = getBestOption(_delimiterInfos[0].getNumWinningRecords(),
+                       _delimiterInfos[1].getNumWinningRecords(), _delimiterInfos[2].getNumWinningRecords(),
+                       _delimiterInfos[3].getNumWinningRecords());
+               if (bestDelim >= 0)
+                       _delimiterRadios[bestDelim].setSelected(true);
+               else
+                       _delimiterRadios[_delimiterRadios.length-1].setSelected(true);
+               informDelimiterSelected();
+               _dialog.pack();
+               _dialog.setVisible(true);
+       }
+
+
+       /**
+        * Check the given file for validity
         * @param inFile file to check
         */
        private boolean preCheckFile(File inFile)
@@ -164,11 +172,20 @@ public class TextFileLoader
                        return false;
                }
                // Use a FileCacher to read the file into an array
-               _fileCacher = new FileCacher(inFile);
+               _contentCacher = new FileCacher(inFile);
+
+               return preCheckContents();
+       }
 
+       /**
+        * Check the contents for readability and funny characters,
+        * and count the fields for the various separators
+        */
+       private boolean preCheckContents()
+       {
                // Check each line of the file
-               String[] fileContents = _fileCacher.getContents();
-               if (fileContents == null) {
+               String[] contents = _contentCacher.getContents();
+               if (contents == null) {
                        return false; // nothing cached, might be binary
                }
                boolean fileOK = true;
@@ -178,9 +195,9 @@ public class TextFileLoader
                String currLine = null;
                String[] splitFields = null;
                int commaFields = 0, semicolonFields = 0, tabFields = 0, spaceFields = 0;
-               for (int lineNum=0; lineNum<fileContents.length && fileOK; lineNum++)
+               for (int lineNum=0; lineNum<contents.length && fileOK; lineNum++)
                {
-                       currLine = fileContents[lineNum];
+                       currLine = contents[lineNum];
                        // check for invalid characters
                        if (currLine.indexOf('\0') >= 0) {fileOK = false;}
                        // check for commas
@@ -211,6 +228,39 @@ public class TextFileLoader
                return fileOK;
        }
 
+       /**
+        * @param inText text to load (as if it came from a file)
+        */
+       public void loadText(String inText)
+       {
+               _file = null;
+               if (preCheckText(inText))
+               {
+                       showDialog();
+               }
+               else
+               {
+                       // Didn't pass pre-check
+                       _app.showErrorMessage("error.load.dialogtitle", "error.load.nopointsintext");
+               }
+       }
+
+       /**
+        * Check the given text for validity
+        * @param inText (pasted) text to check
+        */
+       private boolean preCheckText(String inText)
+       {
+               if (inText == null || inText.length() < 6)
+               {
+                       return false;
+               }
+               // Use a cacher to split the text into an array
+               _contentCacher = new TextCacher(inText);
+
+               return preCheckContents();
+       }
+
 
        /**
         * Get the index of the best one in the list
@@ -326,7 +376,7 @@ public class TextFileLoader
                delimsPanel.add(_statusLabel);
                firstCard.add(delimsPanel, BorderLayout.SOUTH);
                // load snippet to show first few lines
-               _snippetBox = new JList<String>(_fileCacher.getSnippet(SNIPPET_SIZE, MAX_SNIPPET_WIDTH));
+               _snippetBox = new JList<String>(_contentCacher.getSnippet(SNIPPET_SIZE, MAX_SNIPPET_WIDTH));
                _snippetBox.setEnabled(false);
                firstCard.add(makeLabelledPanel("dialog.openoptions.filesnippet", _snippetBox), BorderLayout.CENTER);
 
@@ -531,11 +581,13 @@ public class TextFileLoader
         */
        public DelimiterInfo getSelectedDelimiterInfo()
        {
-               for (int i=0; i<4; i++)
+               for (int i=0; i<4; i++) {
                        if (_delimiterRadios[i].isSelected()) return _delimiterInfos[i];
+               }
                // must be "other" - build info if necessary
-               if (_delimiterInfos[4] == null)
+               if (_delimiterInfos[4] == null) {
                        _delimiterInfos[4] = new DelimiterInfo(_otherDelimiterText.getText().charAt(0));
+               }
                return _delimiterInfos[4];
        }
 
@@ -567,7 +619,7 @@ public class TextFileLoader
        private void prepareSecondPanel()
        {
                DelimiterInfo info = getSelectedDelimiterInfo();
-               FileSplitter splitter = new FileSplitter(_fileCacher);
+               FileSplitter splitter = new FileSplitter(_contentCacher);
                // Check info makes sense - num fields > 0, num records > 0
                // set "Finished" button to disabled if not ok
                // Add data to GUI elements
@@ -637,7 +689,7 @@ public class TextFileLoader
                _lastSelectedFields = _fieldTableModel.getFieldArray();
                // TODO: Remember all the units selections for next load?
                // Get the selected units for altitudes and speeds
-               SourceInfo sourceInfo = new SourceInfo(_file, SourceInfo.FILE_TYPE.TEXT);
+               SourceInfo sourceInfo = (_file == null ? null : new SourceInfo(_file, SourceInfo.FILE_TYPE.TEXT));
                PointCreateOptions options = new PointCreateOptions();
                options.setAltitudeUnits(_altitudeUnitsDropdown.getSelectedIndex() == 0 ? UnitSetLibrary.UNITS_METRES : UnitSetLibrary.UNITS_FEET);
                Unit hSpeedUnit = UnitSetLibrary.ALL_SPEED_UNITS[_hSpeedUnitsDropdown.getSelectedIndex()];
@@ -649,7 +701,7 @@ public class TextFileLoader
                _app.informDataLoaded(_fieldTableModel.getFieldArray(),
                        _fileExtractTableModel.getData(), options, sourceInfo, null);
                // clear up file cacher
-               _fileCacher.clear();
+               _contentCacher.clear();
                // dispose of dialog
                _dialog.dispose();
        }
index 0c5bf5c33987915d36f012cc929f77710549a950..0023c7426ed68dcb0527af98b360bac6cdd67036 100644 (file)
@@ -1,11 +1,11 @@
-GpsPrune version 19.2
-=====================
+GpsPrune version 20
+===================
 
 GpsPrune is an application for viewing, editing and managing coordinate data from GPS systems,
 including format conversion, charting, 3d visualisation, audio and photo correlation, and online resource lookup.
 Full details can be found at https://gpsprune.activityworkshop.net/
 
-GpsPrune is copyright 2006-2018 activityworkshop.net and distributed under the terms of the Gnu GPL version 2.
+GpsPrune is copyright 2006-2020 activityworkshop.net and distributed under the terms of the Gnu GPL version 2.
 You may freely use the software, and may help others to freely use it too.  For further information
 on your rights and how they are protected, see the included license.txt file.
 
@@ -17,7 +17,7 @@ Running
 =======
 
 To run GpsPrune from the jar file, simply call it from a command prompt or shell:
-   java -jar gpsprune_19.2.jar
+   java -jar gpsprune_20.jar
 
 If the jar file is saved in a different directory, you will need to include the path.
 Depending on your system settings, you may be able to click or double-click on the jar file
@@ -25,46 +25,37 @@ in a file manager window to execute it.  A shortcut, menu item, alias, desktop i
 or other link can of course be made should you wish.
 
 To specify a language other than the default, use an additional parameter, eg:
-   java -jar gpsprune_19.2.jar --lang=DE
+   java -jar gpsprune_20.jar --lang=DE
 
 
-New with version 19.2
-=====================
-The following fixes and additions were made since version 19.1:
-  - Fix right-click-and-drag bug for zooming with Java 9 and Java 10
-  - Fix export of timestamps when photo points don't have timestamps
-  - Lighting of 3d views from the northwest (thanks, PeHar)
-  - Remember the name tag from a loaded gpx file, suggest it again for gpx export
-  - Removal of the Thunderforest tile sources (OpenCycleMap, Outdoors)
-New with version 19.1
+New with version 20
 =====================
 The following fixes and additions were made since version 19:
-  - Performance improvements regarding scrolling through points
-  - Keyboard shortcut to access point edit dialog (part of Github issue #10)
-  - Online services Inlinemap.net and Graphhopper.com (routing)
-  - Cardinals in java3d view get billboard behaviour to always face camera (thanks, PeHar)
-  - Fix for PeakFinder urls
+  - Add option to use Nimbus look-and-feel (wishlist 77)
+  - Extend the marker waypoints function to include half the distance, half the climb and half the descent
+  - Remove Ukrainian language
+  - Add support for entering Pluscodes
+  - Add way to copy point details or range details to clipboard (wishlist 76)
+  - Project point using bearing and distance (wishlist 35)
+  - Possibility to paste a list of coordinates instead of just one
+  - Removal of Gpsies functions (both download and upload)
 
 New with version 19
 ===================
 The following fixes and additions were made since version 18:
-  - Fix for duration rounding bug affecting sub-second timestamps
   - Wikipedia search now also includes galleries from wikimedia
   - Photo popup window now gets updated when the track selection changes
-  - Remove export to SVG function as it has fallen behind the java3d and pov options
-  - Remove Turkish language because there haven't been any translators since early 2010
   - Function to add waypoints along the track at intervals of distance or time (eg every 5 km)
   - Optionally draw arrows on the track lines to show direction of travel
   - Waypoint rendering using icons (wishlist 71)
   - Allow user to select timezone in which timestamps are displayed (wishlist 61)
   - Provide call to geonames.org's OSM node search function, to find amenities (like bus stops) close to the current point
-  - Fix OSM download function using overpass API
-  - Fix opencyclemap URLs
-  - Fix reading of Exif data for some unusual cases (from Adobe Lightroom?)
-  - Remove Panoramio
-  - Update wikimedia catalogue
   - Debian and Ubuntu packages no longer rely on external libmetadata jar
+  - Keyboard shortcut to access point edit dialog (part of Github issue #10)
+  - Online services Inlinemap.net and Graphhopper.com (routing)
+  - Cardinals in java3d view get billboard behaviour to always face camera (thanks, PeHar)
+  - Lighting of 3d views from the northwest (thanks, PeHar)
+  - Remember the name tag from a loaded gpx file, suggest it again for gpx export
 
 New with version 18
 ===================
@@ -279,7 +270,7 @@ Further information and updates
 ===============================
 
 To obtain the source code (if it wasn't included in your jar file), or for further information,
-please visit the website:  http://gpsprune.activityworkshop.net/
+please visit the website:  https://gpsprune.activityworkshop.net/
 
 You will find there user guides, screenshots and demo videos illustrating the major features.
 As GpsPrune is further developed, subsequent versions of the program will also be made freely
index 8e7e9ae39ddeebd905f9561d78c34f7d1de20945..0623b1f72db89714f4ad7006e4bbca3c02d734da 100644 (file)
@@ -142,7 +142,7 @@ public class BaseImageConfigDialog implements Runnable
                {
                        for (int i=0; i<_zoomDropdown.getItemCount(); i++)
                        {
-                               String item = _zoomDropdown.getItemAt(i).toString();
+                               String item = _zoomDropdown.getItemAt(i);
                                try {
                                        if (Integer.parseInt(item) == zoomLevel)
                                        {
index ea188921d8b75b4612de63cd1c9335771216d2ed..eb5e6ef2d7dbba711f31a29eee6fb1feb84e5325 100644 (file)
@@ -300,6 +300,7 @@ public class ImageExporter extends GenericFunction implements BaseImageConsumer
                final Track track = _app.getTrackInfo().getTrack();
                final int numPoints = track.getNumPoints();
                int prevX = 0, prevY = 0;
+               boolean gotPreviousPoint = false;
                for (int i=0; i<numPoints; i++)
                {
                        DataPoint point = track.getPoint(i);
@@ -316,7 +317,7 @@ public class ImageExporter extends GenericFunction implements BaseImageConsumer
                                // use zoom level to calculate pixel coords on image
                                int px = (int) (x * zoomFactor * 256), py = (int) (y * zoomFactor * 256);
                                // System.out.println("Point: x=" + x + ", px=" + px + ", y=" + y + ", py=" + py);
-                               if (!point.getSegmentStart()) {
+                               if (!point.getSegmentStart() && gotPreviousPoint) {
                                        // draw from previous point to this one
                                        g.drawLine(prevX, prevY, px, py);
                                }
@@ -327,6 +328,7 @@ public class ImageExporter extends GenericFunction implements BaseImageConsumer
                                }
                                // save coordinates
                                prevX = px; prevY = py;
+                               gotPreviousPoint = true;
                        }
                }
 
@@ -364,7 +366,7 @@ public class ImageExporter extends GenericFunction implements BaseImageConsumer
                }
                // Set text size according to input
                int fontScalePercent = _textScaleField.getValue();
-               if (fontScalePercent > 10 && fontScalePercent <= 999)
+               if (fontScalePercent > 0 && fontScalePercent <= 999)
                {
                        Font gFont = g.getFont();
                        g.setFont(gFont.deriveFont((float) (gFont.getSize() * 0.01 * fontScalePercent)));
@@ -395,7 +397,7 @@ public class ImageExporter extends GenericFunction implements BaseImageConsumer
                for (int i=0; i<numPoints; i++)
                {
                        DataPoint point = track.getPoint(i);
-                       if (point.isWaypoint())
+                       if (point.isWaypoint() && fontScalePercent > 0)
                        {
                                double x = track.getX(i) - xRange.getMinimum();
                                double y = track.getY(i) - yRange.getMinimum();