From 79f3ca2954d7feb6052c21b3aa974c89b2b101d6 Mon Sep 17 00:00:00 2001 From: activityworkshop Date: Tue, 26 Jul 2016 21:28:53 +0200 Subject: [PATCH] Version 18.5, July 2016 --- README.md | 2 +- tim/prune/GpsPrune.java | 4 +- tim/prune/function/AboutScreen.java | 3 +- .../function/gpsies/UploadGpsiesFunction.java | 5 +- tim/prune/gui/map/DiskTileCacher.java | 35 +++--- tim/prune/gui/map/MapCanvas.java | 4 +- tim/prune/gui/map/MapTile.java | 32 ++++++ tim/prune/gui/map/MapTileManager.java | 41 ++++--- tim/prune/gui/profile/ProfileChart.java | 5 +- tim/prune/lang/prune-texts_cz.properties | 8 ++ tim/prune/lang/prune-texts_es.properties | 5 + tim/prune/lang/prune-texts_ru.properties | 29 +++-- tim/prune/lang/prune-texts_uk.properties | 10 ++ tim/prune/readme.txt | 15 ++- tim/prune/save/GpsSaver.java | 5 +- tim/prune/save/GpxExporter.java | 108 +++++++++--------- tim/prune/save/SettingsForExport.java | 66 +++++++++++ 17 files changed, 263 insertions(+), 114 deletions(-) create mode 100644 tim/prune/gui/map/MapTile.java create mode 100644 tim/prune/save/SettingsForExport.java diff --git a/README.md b/README.md index c409f9e..f4d9cde 100644 --- 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. diff --git a/tim/prune/GpsPrune.java b/tim/prune/GpsPrune.java index 606e61c..ad71987 100644 --- a/tim/prune/GpsPrune.java +++ b/tim/prune/GpsPrune.java @@ -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; diff --git a/tim/prune/function/AboutScreen.java b/tim/prune/function/AboutScreen.java index c6bd759..d2f5712 100644 --- a/tim/prune/function/AboutScreen.java +++ b/tim/prune/function/AboutScreen.java @@ -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") + " : "), diff --git a/tim/prune/function/gpsies/UploadGpsiesFunction.java b/tim/prune/function/gpsies/UploadGpsiesFunction.java index 9a4ae30..3cef9db 100644 --- a/tim/prune/function/gpsies/UploadGpsiesFunction.java +++ b/tim/prune/function/gpsies/UploadGpsiesFunction.java @@ -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) {} diff --git a/tim/prune/gui/map/DiskTileCacher.java b/tim/prune/gui/map/DiskTileCacher.java index 63dc684..fd2042a 100644 --- a/tim/prune/gui/map/DiskTileCacher.java +++ b/tim/prune/gui/map/DiskTileCacher.java @@ -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(); diff --git a/tim/prune/gui/map/MapCanvas.java b/tim/prune/gui/map/MapCanvas.java index 4221520..5711951 100644 --- a/tim/prune/gui/map/MapCanvas.java +++ b/tim/prune/gui/map/MapCanvas.java @@ -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 index 0000000..36a494d --- /dev/null +++ b/tim/prune/gui/map/MapTile.java @@ -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; + } +} diff --git a/tim/prune/gui/map/MapTileManager.java b/tim/prune/gui/map/MapTileManager.java index ed8849b..f7370c5 100644 --- a/tim/prune/gui/map/MapTileManager.java +++ b/tim/prune/gui/map/MapTileManager.java @@ -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; } /** diff --git a/tim/prune/gui/profile/ProfileChart.java b/tim/prune/gui/profile/ProfileChart.java index b2d0d0d..6e21996 100644 --- a/tim/prune/gui/profile/ProfileChart.java +++ b/tim/prune/gui/profile/ProfileChart.java @@ -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; } } diff --git a/tim/prune/lang/prune-texts_cz.properties b/tim/prune/lang/prune-texts_cz.properties index 0d8c177..c060e88 100644 --- a/tim/prune/lang/prune-texts_cz.properties +++ b/tim/prune/lang/prune-texts_cz.properties @@ -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 diff --git a/tim/prune/lang/prune-texts_es.properties b/tim/prune/lang/prune-texts_es.properties index f5d6214..d8c19aa 100644 --- a/tim/prune/lang/prune-texts_es.properties +++ b/tim/prune/lang/prune-texts_es.properties @@ -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 diff --git a/tim/prune/lang/prune-texts_ru.properties b/tim/prune/lang/prune-texts_ru.properties index 87a20b1..6e6e8d7 100644 --- a/tim/prune/lang/prune-texts_ru.properties +++ b/tim/prune/lang/prune-texts_ru.properties @@ -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 diff --git a/tim/prune/lang/prune-texts_uk.properties b/tim/prune/lang/prune-texts_uk.properties index 9624351..ddfb0ac 100644 --- a/tim/prune/lang/prune-texts_uk.properties +++ b/tim/prune/lang/prune-texts_uk.properties @@ -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 diff --git a/tim/prune/readme.txt b/tim/prune/readme.txt index d4996f7..afde04b 100644 --- a/tim/prune/readme.txt +++ b/tim/prune/readme.txt @@ -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: diff --git a/tim/prune/save/GpsSaver.java b/tim/prune/save/GpsSaver.java index 3fa66c3..6179a5c 100644 --- a/tim/prune/save/GpsSaver.java +++ b/tim/prune/save/GpsSaver.java @@ -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 diff --git a/tim/prune/save/GpxExporter.java b/tim/prune/save/GpxExporter.java index 9363616..7cac01c 100644 --- a/tim/prune/save/GpxExporter.java +++ b/tim/prune/save/GpxExporter.java @@ -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, "1\n", + numSaved += writeTrackPoints(inWriter, inInfo, inSettings, + true, inGpxCachers, "1\n", null, "\t\n"); // Output all track points, if any String trackStart = "\t\n\t\t" + trackName + "\n\t\t1\n\t\t\n"; - numSaved += writeTrackPoints(inWriter, inInfo, exportSelection, exportTrackpoints, exportPhotos, - exportAudios, exportTimestamps, false, inGpxCachers, "\n\t\n", "\t\t\n\t\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=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\n"); // altitude if available - if (inPoint.hasAltitude()) + if (inPoint.hasAltitude() || inSettings.getExportMissingAltitudesAsZero()) { inWriter.write("\t\t"); - inWriter.write("" + inPoint.getAltitude().getStringValue(UnitSetLibrary.UNITS_METRES)); + inWriter.write(inPoint.hasAltitude() ? inPoint.getAltitude().getStringValue(UnitSetLibrary.UNITS_METRES) : "0"); inWriter.write("\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