]> gitweb.fperrin.net Git - GpsPrune.git/commitdiff
Version 18.5, July 2016
authoractivityworkshop <mail@activityworkshop.net>
Tue, 26 Jul 2016 19:28:53 +0000 (21:28 +0200)
committeractivityworkshop <mail@activityworkshop.net>
Tue, 26 Jul 2016 19:28:53 +0000 (21:28 +0200)
17 files changed:
README.md
tim/prune/GpsPrune.java
tim/prune/function/AboutScreen.java
tim/prune/function/gpsies/UploadGpsiesFunction.java
tim/prune/gui/map/DiskTileCacher.java
tim/prune/gui/map/MapCanvas.java
tim/prune/gui/map/MapTile.java [new file with mode: 0644]
tim/prune/gui/map/MapTileManager.java
tim/prune/gui/profile/ProfileChart.java
tim/prune/lang/prune-texts_cz.properties
tim/prune/lang/prune-texts_es.properties
tim/prune/lang/prune-texts_ru.properties
tim/prune/lang/prune-texts_uk.properties
tim/prune/readme.txt
tim/prune/save/GpsSaver.java
tim/prune/save/GpxExporter.java
tim/prune/save/SettingsForExport.java [new file with mode: 0644]

index c409f9ecb05f303e567180d8b78eb04d1861f752..f4d9cdeff0f76987d4d8571d89f327efda346777 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 http://gpsprune.activityworkshop.net .
 
-Here on github you'll find all the sources from version 1 to the current version 18.4, and in the wiki at https://github.com/activityworkshop/GpsPrune/wiki there's the beginning of a translation effort for anyone to contribute.
+Here on github you'll find all the sources from version 1 to the current version 18.5, 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.
index 606e61c16fdd63dd2791f823ffdc9a032102dc57..ad71987373366b1be282689581453ec50313ed4f 100644 (file)
@@ -36,9 +36,9 @@ import tim.prune.gui.profile.ProfileChart;
 public class GpsPrune
 {
        /** Version number of application, used in about screen and for version check */
-       public static final String VERSION_NUMBER = "18.4";
+       public static final String VERSION_NUMBER = "18.5";
        /** Build number, just used for about screen */
-       public static final String BUILD_NUMBER = "340";
+       public static final String BUILD_NUMBER = "342";
        /** Static reference to App object */
        private static App APP = null;
 
index c6bd75963b3d945fe7568509ebb3e1b487bd8577..d2f571250660664deabb6c7be0ae3c4c1a09e869 100644 (file)
@@ -168,6 +168,7 @@ public class AboutScreen extends GenericFunction
                creditsPanel.setLayout(gridBag);
                constraints = new GridBagConstraints();
                constraints.weightx = 0.0; constraints.weighty = 0.0;
+               constraints.ipady = 3;
 
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel(I18nManager.getText("dialog.about.credits.code") + " : "),
@@ -200,7 +201,7 @@ public class AboutScreen extends GenericFunction
                        new JLabel(" katpatuka, R\u00E9mi, Marcus, Ali, Javier, Jeroen, prot_d, Gy\u00F6rgy,"),
                        1, 5);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
-                       new JLabel(" HooAU, Sergey, P\u00E9ter, serhijdubyk, Peter, Cristian"),
+                       new JLabel(" HooAU, Sergey, P\u00E9ter, serhijdubyk, Peter, Cristian, Roman"),
                        1, 6);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel(I18nManager.getText("dialog.about.credits.translations") + " : "),
index 9a4ae30b7d4aa3d5c2506dd5c496d86a2485fad3..3cef9dbddde8677a29b1f960be7f13fb7f261219 100644 (file)
@@ -39,6 +39,7 @@ 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
@@ -279,9 +280,9 @@ public class UploadGpsiesFunction extends GenericFunction
                        _writer = new OutputStreamWriter(oStream);
                        new Thread(new Runnable() {
                                public void run() {
-                                       boolean[] saveFlags = {true, true, true, true, false, true}; // export everything
                                        try {
-                                               GpxExporter.exportData(_writer, _app.getTrackInfo(), _nameField.getText(), null, saveFlags, null);
+                                               GpxExporter.exportData(_writer, _app.getTrackInfo(), _nameField.getText(),
+                                                       null, new SettingsForExport(), null);
                                        } catch (IOException e) {}
                                        finally {
                                                try {_writer.close();} catch (IOException e) {}
index 63dc684c346900b3ca1cedda3c3d307a9693149d..fd2042a7714acfe2ca1f5b47693ce9df06b0a79f 100644 (file)
@@ -46,10 +46,9 @@ public class DiskTileCacher implements Runnable
         * Get the specified tile from the disk cache
         * @param inBasePath base path to whole disk cache
         * @param inTilePath relative path to requested tile
-        * @param inCheckAge true to check age of file, false to ignore
         * @return tile image if available, or null if not there
         */
-       public static Image getTile(String inBasePath, String inTilePath, boolean inCheckAge)
+       public static MapTile getTile(String inBasePath, String inTilePath)
        {
                if (inBasePath == null) {return null;}
                File tileFile = new File(inBasePath, inTilePath);
@@ -57,17 +56,17 @@ public class DiskTileCacher implements Runnable
                if (tileFile.exists() && tileFile.canRead() && tileFile.length() > 0)
                {
                        long fileStamp = tileFile.lastModified();
-                       if (!inCheckAge || ((System.currentTimeMillis()-fileStamp) < CACHE_TIME_LIMIT))
+                       boolean isExpired = ((System.currentTimeMillis()-fileStamp) > CACHE_TIME_LIMIT);
+                       try
                        {
-                               try {
-                                       image = Toolkit.getDefaultToolkit().createImage(tileFile.getAbsolutePath());
-                               }
-                               catch (Exception e) {
-                                       System.err.println("createImage: " + e.getClass().getName() + " _ " + e.getMessage());
-                               }
+                               image = Toolkit.getDefaultToolkit().createImage(tileFile.getAbsolutePath());
+                               return new MapTile(image, isExpired);
+                       }
+                       catch (Exception e) {
+                               System.err.println("createImage: " + e.getClass().getName() + " _ " + e.getMessage());
                        }
                }
-               return image;
+               return null;
        }
 
        /**
@@ -76,31 +75,28 @@ public class DiskTileCacher implements Runnable
         * @param inBasePath base path to disk cache
         * @param inTilePath relative path to this tile
         * @param inObserver observer to inform when load complete
-        * @return true if successful, false for failure
         */
-       public static boolean saveTile(URL inUrl, String inBasePath, String inTilePath, ImageObserver inObserver)
+       public static void saveTile(URL inUrl, String inBasePath, String inTilePath, ImageObserver inObserver)
        {
-               if (inBasePath == null || inTilePath == null) {return false;}
+               if (inBasePath == null || inTilePath == null) {return;}
                // save file if possible
                File basePath = new File(inBasePath);
                if (!basePath.exists() || !basePath.isDirectory() || !basePath.canWrite()) {
                        // Can't write to base path
-                       return false;
+                       return;
                }
                File tileFile = new File(basePath, inTilePath);
                // Check if this file is already being loaded
-               if (isBeingLoaded(tileFile)) {return true;}
+               if (isBeingLoaded(tileFile)) {return;}
                // Check if it has already failed
-               if (BLOCKED_URLS.contains(inUrl.toString())) {return true;}
+               if (BLOCKED_URLS.contains(inUrl.toString())) {return;}
 
                File dir = tileFile.getParentFile();
                // Start a new thread to load the image if necessary
                if ((dir.exists() || dir.mkdirs()) && dir.canWrite())
                {
                        new Thread(new DiskTileCacher(inUrl, tileFile, inObserver)).start();
-                       return true;
                }
-               return false; // couldn't write the file
        }
 
        /**
@@ -141,6 +137,7 @@ public class DiskTileCacher implements Runnable
                {
                        // Open streams from URL and to file
                        out = new FileOutputStream(tempFile);
+                       //System.out.println("Opening URL: " + _url.toString());
                        // Set http user agent on connection
                        URLConnection conn = _url.openConnection();
                        conn.setRequestProperty("User-Agent", "GpsPrune v" + GpsPrune.VERSION_NUMBER);
@@ -165,7 +162,7 @@ public class DiskTileCacher implements Runnable
                        }
                }
                // Move temp file to desired file location
-               if (!tempFile.renameTo(_file))
+               if (tempFile.exists() && !tempFile.renameTo(_file))
                {
                        // File couldn't be moved - delete both to be sure
                        tempFile.delete();
index 42215209ba3bfccf599fa2d9c000ebe1f89cf49f..57119517dec55f7f7a9f964b08460872f6d32981 100644 (file)
@@ -705,7 +705,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        anyWaypoints = anyWaypoints || isWaypoint;
                        if (!isWaypoint)
                        {
-                               if ((currPointVisible || prevPointVisible) && drawPoints)
+                               if (currPointVisible || (drawLines && prevPointVisible))
                                {
                                        // For track points, work out which colour to use
                                        if (_track.getPoint(i).getDeleteFlag()) {
@@ -722,7 +722,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                        }
 
                                        // Draw rectangle for track point if it's visible
-                                       if (currPointVisible)
+                                       if (currPointVisible && drawPoints)
                                        {
                                                inG.drawRect(px-2, py-2, 3, 3);
                                                pointsPainted++;
diff --git a/tim/prune/gui/map/MapTile.java b/tim/prune/gui/map/MapTile.java
new file mode 100644 (file)
index 0000000..36a494d
--- /dev/null
@@ -0,0 +1,32 @@
+package tim.prune.gui.map;
+
+import java.awt.Image;
+
+/**
+ * Simple wrapper to hold an image for a map tile
+ * and a boolean flag to show whether it's expired or not
+ */
+public class MapTile
+{
+       /** Image or null if no image available */
+       private Image _image = null;
+       /** True if image expired, false if still fresh */
+       private boolean _expired = false;
+
+       /** Constructor */
+       public MapTile(Image inImage, boolean inExpired)
+       {
+               _image = inImage;
+               _expired = inExpired;
+       }
+
+       /** Get the image */
+       public Image getImage() {
+               return _image;
+       }
+
+       /** Return true if image is too old */
+       public boolean isExpired() {
+               return _expired;
+       }
+}
index ed8849bd469118f5314322adbe77c1ba097523f4..f7370c5c90c833e7f053fc786eafdae37ab7f843 100644 (file)
@@ -155,14 +155,14 @@ public class MapTileManager implements ImageObserver
                inX = ((inX % _numTileIndices) + _numTileIndices) % _numTileIndices;
 
                // Check first in memory cache for tile
-               Image tile = null;
+               Image tileImage = null;
                MemTileCacher tempCache = null;
                if (_tempCaches != null)
                {
                        tempCache = _tempCaches[inLayer]; // Should probably guard array indexes here
-                       tile = tempCache.getTile(inX, inY);
-                       if (tile != null) {
-                               return tile;
+                       tileImage = tempCache.getTile(inX, inY);
+                       if (tileImage != null) {
+                               return tileImage;
                        }
                }
 
@@ -170,32 +170,37 @@ public class MapTileManager implements ImageObserver
                String diskCachePath = Config.getConfigString(Config.KEY_DISK_CACHE);
                boolean useDisk = (diskCachePath != null);
                boolean onlineMode = Config.getConfigBoolean(Config.KEY_ONLINE_MODE);
+               MapTile mapTile = null;
                if (useDisk)
                {
-                       tile = DiskTileCacher.getTile(diskCachePath, _mapSource.makeFilePath(inLayer, _zoom, inX, inY), onlineMode);
-                       if (tile != null)
+                       // Get the map tile from cache
+                       mapTile = DiskTileCacher.getTile(diskCachePath, _mapSource.makeFilePath(inLayer, _zoom, inX, inY));
+                       if (mapTile != null && mapTile.getImage() != null)
                        {
-                               if (_returnIncompleteImages) {return tile;}
+                               tileImage = mapTile.getImage();
+                               if (_returnIncompleteImages) {return tileImage;}
                                // Pass tile to memory cache
                                if (tempCache != null) {
-                                       tempCache.setTile(tile, inX, inY, _zoom);
+                                       tempCache.setTile(tileImage, inX, inY, _zoom);
                                }
-                               if (tile.getWidth(this) > 0) {return tile;}
-                               return null;
+                               tileImage.getWidth(this); // trigger the load from file
                        }
-                       // else System.out.println("DTC gave null tile for " + _zoom + ", " + inX + ", " + inY);
                }
-               // Tile wasn't in memory or on disk, so if online let's get it
-               if (onlineMode && _downloadTiles && inDownloadIfNecessary)
+               // Maybe we've got an image now, maybe it's expired
+               final boolean shouldDownload = (tileImage == null || mapTile == null || mapTile.isExpired());
+
+               // If we're online then try to download the tile
+               if (onlineMode && _downloadTiles && inDownloadIfNecessary && shouldDownload)
                {
                        try
                        {
                                URL tileUrl = new URL(_mapSource.makeURL(inLayer, _zoom, inX, inY));
-                               // System.out.println("Going to fetch: " + tileUrl);
-                               if (useDisk && DiskTileCacher.saveTile(tileUrl, diskCachePath,
-                                       _mapSource.makeFilePath(inLayer, _zoom, inX, inY), this))
+                               //System.out.println("Trying to fetch: " + tileUrl);
+                               if (useDisk)
                                {
-                                       // Image now copied directly from URL stream to disk cache
+                                       DiskTileCacher.saveTile(tileUrl, diskCachePath,
+                                               _mapSource.makeFilePath(inLayer, _zoom, inX, inY), this);
+                                       // Image will now be copied directly from URL stream to disk cache
                                }
                                else
                                {
@@ -206,7 +211,7 @@ public class MapTileManager implements ImageObserver
                        }
                        catch (MalformedURLException urle) {} // ignore
                }
-               return null;
+               return tileImage;
        }
 
        /**
index b2d0d0df7020c36964f692a4eb1378768b58abee..6e219967ad60748f460b416dc0539e3725cb4e52 100644 (file)
@@ -136,8 +136,7 @@ public class ProfileChart extends GenericDisplay implements MouseListener
 
                        // horizontal lines for scale - set to round numbers eg 500
                        int lineScale = getLineScale(minValue, maxValue);
-                       int scaleValue = (int) (minValue/lineScale + 1) * lineScale;
-                       if (minValue < 0.0) {scaleValue -= lineScale;}
+                       double scaleValue = Math.ceil(minValue/lineScale) * lineScale;
                        int x = 0, y = 0;
                        final int zeroY = height - BORDER_WIDTH - (int) (yScaleFactor * (0.0 - minValue));
 
@@ -223,7 +222,7 @@ public class ProfileChart extends GenericDisplay implements MouseListener
                                        if (y < (BORDER_WIDTH + textHeight)) {
                                                y = BORDER_WIDTH + textHeight;
                                        }
-                                       g.drawString(""+scaleValue, BORDER_WIDTH + 5, y);
+                                       g.drawString(""+(int)scaleValue, BORDER_WIDTH + 5, y);
                                        scaleValue += lineScale;
                                }
                        }
index 0d8c1774c6686b15ba6eeeeec75b78fc3f63c951..c060e880b28a06d9fae18dcca1cf3432b81d1b2d 100644 (file)
@@ -39,6 +39,7 @@ menu.view.browser.yahoo=Mapy Yahoo
 menu.view.browser.bing=Mapy Bing
 menu.settings=Nastaven\u00ed
 menu.settings.onlinemode=Na\u010d\u00edtat mapy z internetu
+menu.settings.antialias=Pou\u017e\u00edt antialiasing
 menu.settings.autosave=P\u0159i ukon\u010den\u00ed automaticky ukl\u00e1dat
 menu.help=Pomoc
 # Popup menu for map
@@ -111,6 +112,8 @@ 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
 function.searchwikipedianames=Hledat na Wikipedii podle jm\u00e9na
+function.searchopencachingde=Hledat na OpenCaching.de
+function.mapillary=Hledat fotografie v Mapillary
 function.downloadosm=St\u00e1hnout data OSM pro oblast
 function.duplicatepoint=Zdvojit bod
 function.setcolours=Nastavit barvy
@@ -376,6 +379,7 @@ dialog.gpsies.activity.sailing=Lo\u010f
 dialog.gpsies.activity.skating=Bruslen\u00ed
 dialog.wikipedia.column.name=N\u00e1zev \u010dl\u00e1nku
 dialog.wikipedia.column.distance=Vzd\u00e1lenost
+dialog.wikipedia.gallery=Galerie
 dialog.correlate.notimestamps=U bod\u016f nejsou \u010dasov\u00e9 zna\u010dky, tak\u017ee nen\u00ed s \u010d\u00edm fotografie sladit.
 dialog.correlate.nouncorrelatedphotos=V\u0161echny fotografie jsou slad\u011bn\u00e9.\nOpravdu chcete pokra\u010dovat?
 dialog.correlate.nouncorrelatedaudios=V\u0161echny audionahr\u00e1vky jsou slad\u011bn\u00e9.\nOpravdu chcete pokra\u010dovat?
@@ -562,6 +566,7 @@ dialog.weather.day.sunday=Ned\u011ble
 dialog.weather.temp=Teplota
 dialog.weather.humidity=Vlhkost
 dialog.weather.creditnotice=Data poskytuje slu\u017eba openweathermap.org, v\u00edce informac\u00ed na t\u00e9to adrese.
+dialog.deletebydate.column.delete=Smazat
 
 # 3d window
 dialog.3d.title=Trojrozm\u011brn\u00e9 zobrazen\u00ed GpsPrune
@@ -769,6 +774,9 @@ logic.or=nebo
 url.googlemaps=maps.google.cz
 wikipedia.lang=cs
 openweathermap.lang=en
+webservice.peakfinder=Otev\u0159\u00edt Peakfinder.org
+webservice.geohack=Otev\u0159\u00edt Geohack
+webservice.panoramio=Otev\u0159\u00edt Panoramio
 
 # Cardinals for 3d plots
 cardinal.n=N
index f5d621430775966de26dbe570ee88501b7bed999..d8c19aaae7675eef2a85293708a1fbeef479d797 100644 (file)
@@ -591,6 +591,8 @@ dialog.weather.humidity=Humedad
 dialog.deletebydate.nodate=Sin marcas de tiempo
 dialog.deletebydate.column.keep=Mantener
 dialog.deletebydate.column.delete=Eliminar
+dialog.setaltitudetolerance.text.metres=Limite (en metros) por debajo de cual pequeñas subidas o bajadas serán ignoradas
+dialog.setaltitudetolerance.text.feet=Limite (en pies) por debajo de cual pequeñas subidas o bajadas serán ignoradas
 dialog.autoplay.duration=Duraci\u00f3n (seg)
 dialog.autoplay.usetimestamps=Usar informaci\u00f3n de tiempo
 dialog.autoplay.rewind=Rebobinar
@@ -641,6 +643,9 @@ 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
index 87a20b1821db16bb16728df2fa577768104ea27d..6e6e8d7f67452f938c409ecf6c20e7c61fe5126a 100644 (file)
@@ -1,5 +1,5 @@
 # Text entries for the GpsPrune application
-# Russian entries thanks to Sergey
+# Russian entries thanks to Sergey, Roman
 
 # Menu entries
 menu.file=\u0424\u0430\u0439\u043b
@@ -13,7 +13,6 @@ 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 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\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
-function.rearrangewaypoints=\u041f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u044b
 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
@@ -38,19 +37,20 @@ menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Yahoo maps
 menu.view.browser.bing=Bing maps
 menu.settings=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438
-menu.settings.onlinemode=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043a\u0430\u0440\u0442\u0443 \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442
+menu.settings.onlinemode=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043a\u0430\u0440\u0442\u0443 \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430
+menu.settings.antialias=\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u043d\u0438\u0435
 menu.settings.autosave=\u0410\u0432\u0442\u043e\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0432\u044b\u0445\u043e\u0434\u0435
 menu.help=\u041f\u043e\u043c\u043e\u0449\u044c
 # Popup menu for map
 menu.map.zoomin=\u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c
 menu.map.zoomout=\u0423\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c
-menu.map.zoomfull=\u0423\u0432\u0435\u043b\u0447\u0438\u0442\u044c \u0434\u043e \u043f\u043e\u043b\u043d\u043e\u0439 \u0448\u043a\u0430\u043b\u044b
+menu.map.zoomfull=\u0423\u0432\u0435\u043b\u0447\u0438\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e
 menu.map.newpoint=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0434\u043d\u0443 \u0442\u043e\u0447\u043a\u0443
 menu.map.drawpoints=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0447\u0435\u043a
 menu.map.connect=\u0421\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0438 \u0442\u0440\u0435\u043a\u0430 \u0441 \u043b\u0438\u043d\u0438\u0435\u0439
 menu.map.autopan=\u041e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435
 menu.map.showmap=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u041e\u0421\u041c-\u043a\u0430\u0440\u0442\u0443
-menu.map.showscalebar=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043b\u0438\u043d\u0435\u0439\u043a\u0443 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430
+menu.map.showscalebar=\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0448\u043a\u0430\u043b\u0443 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430
 menu.map.editmode=\u0420\u0435\u0436\u0438\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f
 
 # Alt keys for menus
@@ -86,11 +86,14 @@ function.exportsvg=\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0432 SVG
 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.marklifts=\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043f\u043e\u0434\u044a\u0451\u043c\u0438\u043d\u0438\u043a \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
-function.interpolate=\u0418\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u044f \u0442\u043e\u0447\u0435\u043a
+function.interpolate=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u0447\u0435\u043a\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b
+function.deletebydate=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0438 \u043f\u043e \u0434\u0430\u0442\u0435
 function.addtimeoffset=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0442\u043c\u0435\u0442\u043a\u0443 \u0432\u0440\u0435\u043c\u0435\u043d\u0438
 function.addaltitudeoffset=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0442\u043c\u0435\u0442\u043a\u0443 \u0432\u044b\u0441\u043e\u0442\u044b
+function.rearrangewaypoints=\u041f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u044b
 function.convertnamestotimes=\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u0443\u0442\u0435\u0432\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f
 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
@@ -104,6 +107,7 @@ function.learnestimationparams=\u0417\u0430\u043f\u043e\u043c\u043d\u0438\u0442\
 function.autoplay=\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435
 function.setmapbg=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u0443-\u043f\u043e\u0434\u043b\u043e\u0436\u043a\u0443
 function.setpaths=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0443\u0442\u0438 \u043a \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430\u043c
+function.selectsegment=\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0441\u0435\u0433\u043c\u0435\u043d\u0442
 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.getgpsies=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0442\u0440\u0435\u043a\u0438
@@ -112,6 +116,8 @@ function.lookupsrtm=\u0412\u044b\u0441\u043e\u0442\u044b \u0432 SRTM
 function.downloadsrtm=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c STRM
 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
 function.searchwikipedianames=\u041f\u043e\u0438\u0441\u043a \u0441\u0442\u0430\u0442\u0435\u0439 \u0432 \u0412\u0438\u043a\u0438 \u043f\u043e \u0438\u043c\u0435\u043d\u0438
+function.searchopencachingde=\u041f\u043e\u0438\u0441\u043a OpenCaching.de
+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 \u0442\u0435\u0440\u0440\u0438\u0442\u043e\u0440\u0438\u044e
 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.setcolours=\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0446\u0432\u0435\u0442\u0430
@@ -139,6 +145,7 @@ function.saveconfig=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u044
 function.diskcache=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043a\u0430\u0440\u0442\u044b \u043d\u0430 \u0434\u0438\u0441\u043a
 function.managetilecache=\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0435\u0448\u0435\u043c
 function.getweatherforecast=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b
+function.setaltitudetolerance=\u0417\u0430\u0434\u0430\u0442\u044c \u043e\u0433\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0432\u044b\u0441\u043e\u0442\u044b
 
 # Dialogs
 dialog.exit.confirm.title=\u0412\u044b\u0445\u043e\u0434
@@ -186,6 +193,7 @@ dialog.gpssend.sendtracks=\u041f\u043e\u0441\u043b\u0430\u0442\u044c \u0442\u044
 dialog.gpssend.trackname=\u0418\u043c\u044f \u0442\u0440\u0435\u043a\u0430
 dialog.gpsbabel.filters=\u0424\u0438\u043b\u044c\u0442\u0440\u044b
 dialog.addfilter.title=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0438\u043b\u044c\u0442\u0440
+dialog.gpsbabel.filter.simplify=\u0421\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c
 dialog.gpsbabel.filter.distance=\u0420\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435
 dialog.gpsbabel.filter.interpolate=\u0418\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0438\u044f
 dialog.gpsbabel.filter.discard.numsats=\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043f\u0443\u0442\u043d\u0438\u043a\u043e\u0432 <
@@ -388,6 +396,7 @@ dialog.rearrange.toend=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0
 dialog.rearrange.tonearest=\u041f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043a \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0439
 dialog.rearrange.nosort=\u041d\u0435 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c
 dialog.rearrange.sortbyfilename=\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u0444\u0430\u0439\u043b\u0430
+dialog.rearrange.sortbyname=\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0438\u043c\u0435\u043d\u0438
 dialog.rearrange.sortbytime=\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438
 dialog.compress.closepoints.title=\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u0431\u043b\u0438\u0436\u0435\u043d\u043d\u044b\u0445 \u0442\u043e\u0447\u0435\u043a
 dialog.compress.closepoints.paramdesc=\u0420\u0430\u0437\u043c\u0430\u0445
@@ -534,7 +543,7 @@ dialog.weather.day.sunday=\u0412\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d
 dialog.weather.wind=\u0412\u0435\u0442\u0435\u0440
 dialog.weather.temp=\u0422\u00b0
 dialog.weather.humidity=\u0412\u043b\u0430\u0436\u043d\u043e\u0441\u0442\u044c
-dialog.weather.creditnotice=\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 openweathermap.org.
+dialog.weather.creditnotice=\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 openweathermap.org.
 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
@@ -688,6 +697,7 @@ fieldname.longitude=\u0414\u043e\u043b\u0433\u043e\u0442\u0430
 fieldname.altitude=\u0412\u044b\u0441\u043e\u0442\u0430
 fieldname.timestamp=\u0412\u0440\u0435\u043c\u044f
 fieldname.time=\u0412\u0440\u0435\u043c\u044f
+fieldname.date=\u0414\u0430\u0442\u0430
 fieldname.waypointname=\u0418\u043c\u044f
 fieldname.waypointtype=\u0422\u0438\u043f
 fieldname.newsegment=\u0421\u0435\u0433\u043c\u0435\u043d\u0442
@@ -738,10 +748,13 @@ units.degreesfahrenheit.short=\u00b0F
 logic.and=\u0438
 logic.or=\u0438\u043b\u0438
 
-# External urls
+# External urls and services
 url.googlemaps=maps.google.ru
 wikipedia.lang=ru
 openweathermap.lang=ru
+webservice.peakfinder=\u041e\u0442\u043a\u0440\u044b\u0442\u044c Peakfinder.org
+webservice.geohack=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 Geohack
+webservice.panoramio=\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043a\u0430\u0440\u0442\u0443 Panoramio
 
 # Cardinals for 3d plots
 cardinal.n=\u0421\u0435\u0432\u0435\u0440
index 9624351c7e6d1992b8d264b8716e73e00e0aab42..ddfb0ac7888bc2dd9d95d7f9e6b6953651882c28 100644 (file)
@@ -54,6 +54,7 @@ menu.map.editmode=\u0420\u0435\u0436\u0438\u043c \u0440\u0435\u0434\u0430\u0433\
 
 # Alt keys for menus
 altkey.menu.file=F
+altkey.menu.online=N
 altkey.menu.track=T
 altkey.menu.range=R
 altkey.menu.point=P
@@ -87,6 +88,7 @@ function.compress=\u0421\u0442\u0438\u0441\u043d\u0443\u0442\u0438 \u0442\u0440\
 function.deleterange=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0456\u043d\u0442\u0435\u0440\u0432\u0430\u043b
 function.croptrack=\u041e\u0431\u0440\u0456\u0437\u0430\u0442\u0438 \u0442\u0440\u0435\u043a
 function.interpolate=\u0406\u043d\u0442\u0435\u0440\u043f\u043e\u043b\u044f\u0446\u0456\u044f \u0442\u043e\u0447\u043e\u043a
+function.deletebydate=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u0442\u043e\u0447\u043a\u0438 \u0437\u0430 \u0434\u0430\u0442\u043e\u044e
 function.addtimeoffset=\u0414\u043e\u0434\u0430\u0442\u0438 \u043f\u043e\u0437\u043d\u0430\u0447\u043a\u0443 \u0447\u0430\u0441\u0443
 function.addaltitudeoffset=\u0414\u043e\u0434\u0430\u0442\u0438 \u043f\u043e\u0437\u043d\u0430\u0447\u043a\u0443 \u0432\u0438\u0441\u043e\u0442\u0438
 function.rearrangewaypoints=\u041f\u0435\u0440\u0435\u0432\u0438\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0456\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0438
@@ -102,9 +104,13 @@ function.estimatetime=\u041f\u0440\u0438\u0431\u043b\u0438\u0437\u043d\u0438\u04
 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
 function.setpaths=\u0412\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0448\u043b\u044f\u0445\u0438 \u0434\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c
+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
 function.searchwikipedianames=\u041f\u043e\u0448\u0443\u043a \u0441\u0442\u0430\u0442\u0435\u0439 \u0437 \u0412\u0456\u043a\u0456\u043f\u0435\u0434\u0456\u0457 \u0437\u0430 \u043d\u0430\u0437\u0432\u043e\u044e
 function.downloadosm=\u0417\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 OSM-\u0434\u0430\u043d\u0456 \u043d\u0430 \u0442\u0435\u0440\u0438\u0442\u043e\u0440\u0456\u044e
@@ -236,12 +242,16 @@ button.no=\u041d\u0456
 # Display components
 display.nodata=\u0416\u043e\u0434\u043d\u0438\u0445 \u0434\u0430\u043d\u0438\u0445 \u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043e
 details.trackdetails=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u0442\u0440\u0435\u043a\u0443
+details.notrack=\u0416\u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0440\u0435\u043a\u0443 \u043d\u0435 \u0437\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0435\u043d\u043e
 details.track.points=\u0422\u043e\u0447\u043a\u0438
 details.track.file=\u0424\u0430\u0439\u043b
 details.pointdetails=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u0442\u043e\u0447\u043a\u0438
 details.nopointselection=\u0422\u043e\u0447\u043a\u0443 \u043d\u0435 \u0432\u0438\u0431\u0440\u0430\u043d\u043e
 details.norangeselection=\u0414\u0456\u0430\u043f\u0430\u0437\u043e\u043d \u043d\u0435 \u0432\u0438\u0431\u0440\u0430\u043d\u043e
 details.rangedetails=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u0434\u0456\u0430\u043f\u0430\u0437\u043e\u043d\u0443
+details.coordformat=\u0424\u043e\u0440\u043c\u0430\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442
+details.distanceunits=\u041e\u0434\u0438\u043d\u0438\u0446\u0456 \u0432\u0456\u0434\u0441\u0442\u0430\u043d\u0456
+details.lists.waypoints=\u0428\u043b\u044f\u0445\u043e\u0432\u0456 \u0442\u043e\u0447\u043a\u0438
 details.lists.photos=\u0421\u0432\u0456\u0442\u043b\u0438\u043d\u0438
 details.photodetails=\u041f\u043e\u0434\u0440\u043e\u0431\u0438\u0446\u0456 \u0441\u0432\u0456\u0442\u043b\u0438\u043d\u0438
 details.nophoto=\u0421\u0432\u0456\u0442\u043b\u0438\u043d\u0443 \u043d\u0435 \u0432\u0438\u0431\u0440\u0430\u043d\u043e
index d4996f779a82ae2c600a5540b507dcfffd6e8a19..afde04bb8f9f85cb7572ca99c8aa326284769a61 100644 (file)
@@ -1,4 +1,4 @@
-GpsPrune version 18.4
+GpsPrune version 18.5
 =====================
 
 GpsPrune is an application for viewing, editing and managing coordinate data from GPS systems,
@@ -17,7 +17,7 @@ Running
 =======
 
 To run GpsPrune from the jar file, simply call it from a command prompt or shell:
-   java -jar gpsprune_18.4.jar
+   java -jar gpsprune_18.5.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,9 +25,18 @@ in a file manager window to execute it.  A shortcut, menu item, alias, desktop i
 or other link can of course be made should you wish.
 
 To specify a language other than the default, use an additional parameter, eg:
-   java -jar gpsprune_18.4.jar --lang=DE
+   java -jar gpsprune_18.5.jar --lang=DE
 
 
+New with version 18.5
+=====================
+The following fixes and additions were made since version 18.4:
+  - When points have no altitudes, send them to a GPS with altitude 0 (prevents weird values when reading back)
+  - When points are not displayed on map, still colour the lines according to the selected scheme
+  - When points all have crazy values, don't hang the profile chart
+  - When images can't be fetched from the internet, don't delete expired cache images
+  - Translation updates to es, uk, ru, cz
+
 New with version 18.4
 =====================
 The following fixes and additions were made since version 18.3:
index 3fa66c3096146e7fb57389e6816749e61eead45c..6179a5c1346db75b829467e9e4925206776d0232 100644 (file)
@@ -311,8 +311,9 @@ public class GpsSaver extends GenericFunction implements Runnable
                if (trackName == null || trackName.equals("")) {trackName = "gpsprune";}
                // Generate the GPX file and send to the GPS
                OutputStreamWriter writer = new OutputStreamWriter(process.getOutputStream());
-               boolean[] saveFlags = {true, true, true, true, false, true}; // export everything
-               GpxExporter.exportData(writer, _app.getTrackInfo(), trackName, null, saveFlags, null);
+               SettingsForExport settings = new SettingsForExport();
+               settings.setExportMissingAltitudesAsZero(true);
+               GpxExporter.exportData(writer, _app.getTrackInfo(), trackName, null, settings, null);
                writer.close();
 
                // Read the error stream to see if there's a better error message there
index 936361680495e30a75f528d62e465d32a72260c8..7cac01c8b71f1b8bf5d0040c70ed3479a93988ca 100644 (file)
@@ -290,12 +290,17 @@ public class GpxExporter extends GenericFunction implements Runnable
                                writer = new OutputStreamWriter(new FileOutputStream(_exportFile), "UTF-8");
                        else
                                writer = new OutputStreamWriter(new FileOutputStream(_exportFile));
-                       final boolean[] saveFlags = {_pointTypeSelector.getTrackpointsSelected(), _pointTypeSelector.getWaypointsSelected(),
-                               _pointTypeSelector.getPhotopointsSelected(), _pointTypeSelector.getAudiopointsSelected(),
-                               _pointTypeSelector.getJustSelection(), _timestampsCheckbox.isSelected()};
+                       // TODO: Move to new method
+                       SettingsForExport settings = new SettingsForExport();
+                       settings.setExportTrackPoints(_pointTypeSelector.getTrackpointsSelected());
+                       settings.setExportWaypoints(_pointTypeSelector.getWaypointsSelected());
+                       settings.setExportPhotoPoints(_pointTypeSelector.getPhotopointsSelected());
+                       settings.setExportAudiopoints(_pointTypeSelector.getAudiopointsSelected());
+                       settings.setExportJustSelection(_pointTypeSelector.getJustSelection());
+                       settings.setExportTimestamps(_timestampsCheckbox.isSelected());
                        // write file
                        final int numPoints = exportData(writer, _trackInfo, _nameField.getText(),
-                               _descriptionField.getText(), saveFlags, gpxCachers);
+                               _descriptionField.getText(), settings, gpxCachers);
 
                        // close file
                        writer.close();
@@ -334,13 +339,13 @@ public class GpxExporter extends GenericFunction implements Runnable
         * @param inInfo track info object
         * @param inName name of track (optional)
         * @param inDesc description of track (optional)
-        * @param inSaveFlags array of booleans to export tracks, waypoints, photos, audios, selection, timestamps
+        * @param inExportSettings flags for what to export and how
         * @param inGpxCachers list of Gpx cachers containing input data
         * @return number of points written
         * @throws IOException if io errors occur on write
         */
        public static int exportData(OutputStreamWriter inWriter, TrackInfo inInfo, String inName,
-               String inDesc, boolean[] inSaveFlags, GpxCacherList inGpxCachers) throws IOException
+               String inDesc, SettingsForExport inSettings, GpxCacherList inGpxCachers) throws IOException
        {
                // Write or copy headers
                inWriter.write(getXmlHeaderString(inWriter));
@@ -353,12 +358,9 @@ public class GpxExporter extends GenericFunction implements Runnable
                writeNameAndDescription(inWriter, trackName, desc, isVersion1_1);
 
                DataPoint point = null;
-               final boolean exportTrackpoints = inSaveFlags[0];
-               final boolean exportWaypoints = inSaveFlags[1];
-               final boolean exportPhotos = inSaveFlags[2];
-               final boolean exportAudios = inSaveFlags[3];
-               final boolean exportSelection = inSaveFlags[4];
-               final boolean exportTimestamps = inSaveFlags[5];
+               final boolean exportWaypoints = inSettings.getExportWaypoints();
+               final boolean exportSelection = inSettings.getExportJustSelection();
+               final boolean exportTimestamps = inSettings.getExportTimestamps();
                // Examine selection
                int selStart = -1, selEnd = -1;
                if (exportSelection) {
@@ -388,23 +390,23 @@ public class GpxExporter extends GenericFunction implements Runnable
                                                inWriter.write('\n');
                                        }
                                        else {
-                                               exportWaypoint(point, inWriter, exportTimestamps, exportPhotos, exportAudios);
+                                               exportWaypoint(point, inWriter, inSettings);
                                        }
                                        numSaved++;
                                }
                        }
                }
                // Export both route points and then track points
-               if (exportTrackpoints || exportPhotos || exportAudios)
+               if (inSettings.getExportTrackPoints() || inSettings.getExportPhotoPoints() || inSettings.getExportAudioPoints())
                {
                        // Output all route points (if any)
-                       numSaved += writeTrackPoints(inWriter, inInfo, exportSelection, exportTrackpoints, exportPhotos,
-                               exportAudios, exportTimestamps, true, inGpxCachers, "<rtept", "\t<rte><number>1</number>\n",
+                       numSaved += writeTrackPoints(inWriter, inInfo, inSettings,
+                               true, inGpxCachers, "<rtept", "\t<rte><number>1</number>\n",
                                null, "\t</rte>\n");
                        // Output all track points, if any
                        String trackStart = "\t<trk>\n\t\t<name>" + trackName + "</name>\n\t\t<number>1</number>\n\t\t<trkseg>\n";
-                       numSaved += writeTrackPoints(inWriter, inInfo, exportSelection, exportTrackpoints, exportPhotos,
-                               exportAudios, exportTimestamps, false, inGpxCachers, "<trkpt", trackStart,
+                       numSaved += writeTrackPoints(inWriter, inInfo, inSettings,
+                               false, inGpxCachers, "<trkpt", trackStart,
                                "\t</trkseg>\n\t<trkseg>\n", "\t\t</trkseg>\n\t</trk>\n");
                }
 
@@ -450,11 +452,7 @@ public class GpxExporter extends GenericFunction implements Runnable
         * Loop through the track outputting the relevant track points
         * @param inWriter writer object for output
         * @param inInfo track info object containing track
-        * @param inExportSelection true to just output current selection
-        * @param inExportTrackpoints true to output track points
-        * @param inExportPhotos true to output photo points
-        * @param inExportAudios true to output audio points
-        * @param inExportTimestamps true to include timestamps in export
+        * @param inSettings export settings defining what should be exported
         * @param inOnlyCopies true to only export if source can be copied
         * @param inCachers list of GpxCachers
         * @param inPointTag tag to match for each point
@@ -463,26 +461,30 @@ public class GpxExporter extends GenericFunction implements Runnable
         * @param inEndTag end tag to output
         */
        private static int writeTrackPoints(OutputStreamWriter inWriter,
-               TrackInfo inInfo, boolean inExportSelection, boolean inExportTrackpoints,
-               boolean inExportPhotos, boolean inExportAudios, boolean exportTimestamps,
+               TrackInfo inInfo, SettingsForExport inSettings,
                boolean inOnlyCopies, GpxCacherList inCachers, String inPointTag,
                String inStartTag, String inSegmentTag, String inEndTag)
        throws IOException
        {
-               // Note: far too many input parameters to this method but avoids duplication
+               // Note: Too many input parameters to this method but avoids duplication
                // of output functionality for writing track points and route points
                int numPoints = inInfo.getTrack().getNumPoints();
                int selStart = inInfo.getSelection().getStart();
                int selEnd = inInfo.getSelection().getEnd();
                int numSaved = 0;
+               final boolean exportSelection = inSettings.getExportJustSelection();
+               final boolean exportTrackPoints = inSettings.getExportTrackPoints();
+               final boolean exportPhotos = inSettings.getExportPhotoPoints();
+               final boolean exportAudios = inSettings.getExportAudioPoints();
+               final boolean exportTimestamps = inSettings.getExportTimestamps();
                // Loop over track points
                for (int i=0; i<numPoints; i++)
                {
                        DataPoint point = inInfo.getTrack().getPoint(i);
-                       if ((!inExportSelection || (i>=selStart && i<=selEnd)) && !point.isWaypoint())
+                       if ((!exportSelection || (i>=selStart && i<=selEnd)) && !point.isWaypoint())
                        {
-                               if ((point.getPhoto()==null && inExportTrackpoints) || (point.getPhoto()!=null && inExportPhotos)
-                                       || (point.getAudio()!=null && inExportAudios))
+                               if ((point.getPhoto()==null && exportTrackPoints) || (point.getPhoto()!=null && exportPhotos)
+                                       || (point.getAudio()!=null && exportAudios))
                                {
                                        // get the source from the point (if any)
                                        String pointSource = getPointSource(inCachers, point);
@@ -506,15 +508,20 @@ public class GpxExporter extends GenericFunction implements Runnable
                                                        inWriter.write(pointSource);
                                                        inWriter.write('\n');
                                                }
-                                               else {
-                                                       if (!inOnlyCopies) {exportTrackpoint(point, inWriter, exportTimestamps, inExportPhotos, inExportAudios);}
+                                               else
+                                               {
+                                                       if (!inOnlyCopies) {
+                                                               exportTrackpoint(point, inWriter, inSettings);
+                                                       }
                                                }
                                                numSaved++;
                                        }
                                }
                        }
                }
-               if (numSaved > 0) {inWriter.write(inEndTag);}
+               if (numSaved > 0) {
+                       inWriter.write(inEndTag);
+               }
                return numSaved;
        }
 
@@ -663,13 +670,11 @@ public class GpxExporter extends GenericFunction implements Runnable
         * Export the specified waypoint into the file
         * @param inPoint waypoint to export
         * @param inWriter writer object
-        * @param inTimestamps true to export timestamps too
-        * @param inPhoto true to export link to photo
-        * @param inAudio true to export link to audio
+        * @param inSettings export settings
         * @throws IOException on write failure
         */
-       private static void exportWaypoint(DataPoint inPoint, Writer inWriter, boolean inTimestamps,
-               boolean inPhoto, boolean inAudio)
+       private static void exportWaypoint(DataPoint inPoint, Writer inWriter,
+               SettingsForExport inSettings)
                throws IOException
        {
                inWriter.write("\t<wpt lat=\"");
@@ -678,14 +683,14 @@ public class GpxExporter extends GenericFunction implements Runnable
                inWriter.write(inPoint.getLongitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
                inWriter.write("\">\n");
                // altitude if available
-               if (inPoint.hasAltitude())
+               if (inPoint.hasAltitude() || inSettings.getExportMissingAltitudesAsZero())
                {
                        inWriter.write("\t\t<ele>");
-                       inWriter.write("" + inPoint.getAltitude().getStringValue(UnitSetLibrary.UNITS_METRES));
+                       inWriter.write(inPoint.hasAltitude() ? inPoint.getAltitude().getStringValue(UnitSetLibrary.UNITS_METRES) : "0");
                        inWriter.write("</ele>\n");
                }
-               // timestamp if available (point might have timestamp and then be turned into a waypoint)
-               if (inPoint.hasTimestamp() && inTimestamps)
+               // timestamp if available (some waypoints have timestamps, some not)
+               if (inPoint.hasTimestamp() && inSettings.getExportTimestamps())
                {
                        inWriter.write("\t\t<time>");
                        inWriter.write(inPoint.getTimestamp().getText(Timestamp.Format.ISO8601));
@@ -704,13 +709,13 @@ public class GpxExporter extends GenericFunction implements Runnable
                        inWriter.write("</desc>\n");
                }
                // Media links, if any
-               if (inPhoto && inPoint.getPhoto() != null)
+               if (inSettings.getExportPhotoPoints() && inPoint.getPhoto() != null)
                {
                        inWriter.write("\t\t");
                        inWriter.write(makeMediaLink(inPoint.getPhoto()));
                        inWriter.write('\n');
                }
-               if (inAudio && inPoint.getAudio() != null)
+               if (inSettings.getExportAudioPoints() && inPoint.getAudio() != null)
                {
                        inWriter.write("\t\t");
                        inWriter.write(makeMediaLink(inPoint.getAudio()));
@@ -736,12 +741,9 @@ public class GpxExporter extends GenericFunction implements Runnable
         * Export the specified trackpoint into the file
         * @param inPoint trackpoint to export
         * @param inWriter writer object
-        * @param inTimestamps true to export timestamps too
-        * @param inExportPhoto true to export photo link
-        * @param inExportAudio true to export audio link
+        * @param inSettings export settings
         */
-       private static void exportTrackpoint(DataPoint inPoint, Writer inWriter, boolean inTimestamps,
-               boolean inExportPhoto, boolean inExportAudio)
+       private static void exportTrackpoint(DataPoint inPoint, Writer inWriter, SettingsForExport inSettings)
                throws IOException
        {
                inWriter.write("\t\t\t<trkpt lat=\"");
@@ -750,24 +752,24 @@ public class GpxExporter extends GenericFunction implements Runnable
                inWriter.write(inPoint.getLongitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
                inWriter.write("\">\n");
                // altitude
-               if (inPoint.hasAltitude())
+               if (inPoint.hasAltitude() || inSettings.getExportMissingAltitudesAsZero())
                {
                        inWriter.write("\t\t\t\t<ele>");
-                       inWriter.write("" + inPoint.getAltitude().getStringValue(UnitSetLibrary.UNITS_METRES));
+                       inWriter.write(inPoint.hasAltitude() ? inPoint.getAltitude().getStringValue(UnitSetLibrary.UNITS_METRES) : "0");
                        inWriter.write("</ele>\n");
                }
                // timestamp if available (and selected)
-               if (inPoint.hasTimestamp() && inTimestamps)
+               if (inPoint.hasTimestamp() && inSettings.getExportTimestamps())
                {
                        inWriter.write("\t\t\t\t<time>");
                        inWriter.write(inPoint.getTimestamp().getText(Timestamp.Format.ISO8601));
                        inWriter.write("</time>\n");
                }
                // photo, audio
-               if (inPoint.getPhoto() != null && inExportPhoto) {
+               if (inPoint.getPhoto() != null && inSettings.getExportPhotoPoints()) {
                        inWriter.write(makeMediaLink(inPoint.getPhoto()));
                }
-               if (inPoint.getAudio() != null && inExportAudio) {
+               if (inPoint.getAudio() != null && inSettings.getExportAudioPoints()) {
                        inWriter.write(makeMediaLink(inPoint.getAudio()));
                }
                inWriter.write("\t\t\t</trkpt>\n");
diff --git a/tim/prune/save/SettingsForExport.java b/tim/prune/save/SettingsForExport.java
new file mode 100644 (file)
index 0000000..b7e3c69
--- /dev/null
@@ -0,0 +1,66 @@
+package tim.prune.save;
+
+/**
+ * Settings for controlling what gets exported,
+ * for example by the Gpx export functions
+ */
+public class SettingsForExport
+{
+       private boolean _exportTrackPoints = true;
+       private boolean _exportWaypoints   = true;
+       private boolean _exportJustSelection = false;
+       private boolean _exportTimestamps  = true;
+       private boolean _exportMissingAltitudes = false;
+       private boolean _exportPhotoPoints = true;
+       private boolean _exportAudioPoints = true;
+
+       /** Set to export track points or not */
+       public void setExportTrackPoints(boolean inExport) {
+               _exportTrackPoints = inExport;
+       }
+
+       /** Set to export waypoints or not */
+       public void setExportWaypoints(boolean inExport) {
+               _exportWaypoints = inExport;
+       }
+
+       /** Set to export just the selection or everything */
+       public void setExportJustSelection(boolean inExport) {
+               _exportJustSelection = inExport;
+       }
+
+       /** Set to export timestamps or not */
+       public void setExportTimestamps(boolean inExport) {
+               _exportTimestamps = inExport;
+       }
+
+       /** Set to export missing altitudes as zero or not */
+       public void setExportMissingAltitudesAsZero(boolean inExport) {
+               _exportMissingAltitudes = inExport;
+       }
+
+       /** Set to export photo points or not */
+       public void setExportPhotoPoints(boolean inExport) {
+               _exportPhotoPoints = inExport;
+       }
+
+       /** Set to export audio points or not */
+       public void setExportAudiopoints(boolean inExport) {
+               _exportAudioPoints = inExport;
+       }
+
+       /** @return true to export track points */
+       public boolean getExportTrackPoints() {return _exportTrackPoints;}
+       /** @return true to export waypoints */
+       public boolean getExportWaypoints() {return _exportWaypoints;}
+       /** @return true to export just the selection */
+       public boolean getExportJustSelection() {return _exportJustSelection;}
+       /** @return true to export timestamps */
+       public boolean getExportTimestamps() {return _exportTimestamps;}
+       /** @return true to export zeroes for missing altitudes */
+       public boolean getExportMissingAltitudesAsZero() {return _exportMissingAltitudes;}
+       /** @return true to export photo points */
+       public boolean getExportPhotoPoints() {return _exportPhotoPoints;}
+       /** @return true to export audio points */
+       public boolean getExportAudioPoints() {return _exportAudioPoints;}
+}