From: activityworkshop Date: Mon, 17 Aug 2015 19:48:48 +0000 (+0200) Subject: Version 18, July 2015 X-Git-Tag: v19.2~11 X-Git-Url: https://gitweb.fperrin.net/?p=GpsPrune.git;a=commitdiff_plain;h=0a2480df5845e2d7190dfdec9b2653b1609e853d Version 18, July 2015 --- diff --git a/tim/prune/App.java b/tim/prune/App.java index 7be8242..81e59cc 100644 --- a/tim/prune/App.java +++ b/tim/prune/App.java @@ -4,7 +4,6 @@ import java.io.File; import java.util.ArrayList; import java.util.EmptyStackException; import java.util.Set; -import java.util.Stack; import javax.swing.JFrame; import javax.swing.JOptionPane; @@ -27,8 +26,6 @@ import tim.prune.data.Unit; import tim.prune.function.AsyncMediaLoader; import tim.prune.function.SaveConfig; import tim.prune.function.SelectTracksFunction; -import tim.prune.function.browser.BrowserLauncher; -import tim.prune.function.browser.UrlGenerator; import tim.prune.function.edit.FieldEditList; import tim.prune.function.edit.PointEditor; import tim.prune.gui.MenuManager; @@ -121,7 +118,7 @@ public class App /** * @return the undo stack */ - public Stack getUndoStack() + public UndoStack getUndoStack() { return _undoStack; } @@ -303,7 +300,7 @@ public class App // pass to track for completion if (_track.editPoint(currentPoint, inEditList, false)) { - _undoStack.push(undo); + _undoStack.add(undo); // Confirm point edit UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.point.edit")); } @@ -351,7 +348,7 @@ public class App if (_trackInfo.deletePoint()) { // Delete was successful so add undo info to stack - _undoStack.push(undo); + _undoStack.add(undo); if (currentPhoto != null) { // delete photo if necessary @@ -378,27 +375,6 @@ public class App } - /** - * Finish the compression by deleting the marked points - */ - public void finishCompressTrack() - { - UndoDeleteMarked undo = new UndoDeleteMarked(_track); - // call track to do compress - int numPointsDeleted = _trackInfo.deleteMarkedPoints(); - // add to undo stack if successful - if (numPointsDeleted > 0) - { - undo.setNumPointsDeleted(numPointsDeleted); - _undoStack.add(undo); - UpdateMessageBroker.informSubscribers("" + numPointsDeleted + " " - + (numPointsDeleted==1?I18nManager.getText("confirm.deletepoint.single"):I18nManager.getText("confirm.deletepoint.multi"))); - } - else { - showErrorMessage("function.compress", "dialog.deletemarked.nonefound"); - } - } - /** * Reverse the currently selected section of the track */ @@ -891,7 +867,7 @@ public class App } else { - new UndoManager(this, _frame); + new UndoManager(this, _frame).show(); } } @@ -931,7 +907,7 @@ public class App { for (int i=0; i e = inBundle.getKeys(); + while (e.hasMoreElements()) + { + String key = e.nextElement(); + LocalTexts.setProperty(key, inBundle.getString(key)); + } + } /** * Add a language file @@ -92,26 +108,16 @@ public abstract class I18nManager String extText = ExternalPropsFile.getProperty(inKey); if (extText != null) return extText; } - // look in extra texts if available + // look in texts if available if (LocalTexts != null) { try { - String localText = LocalTexts.getString(inKey); + String localText = LocalTexts.getProperty(inKey); if (localText != null) return localText; } catch (MissingResourceException mre) {} } - // look in english texts - if (EnglishTexts != null) - { - try - { - String engText = EnglishTexts.getString(inKey); - if (engText != null) return engText; - } - catch (MissingResourceException mre) {} - } // return the key itself return inKey; } diff --git a/tim/prune/config/Config.java b/tim/prune/config/Config.java index ad3cc9c..8921332 100644 --- a/tim/prune/config/Config.java +++ b/tim/prune/config/Config.java @@ -81,6 +81,8 @@ public abstract class Config public static final String KEY_POINT_COLOURER = "prune.pointcolourer"; /** Key for line width used for drawing */ public static final String KEY_LINE_WIDTH = "prune.linewidth"; + /** Key for whether to use antialiasing or not */ + public static final String KEY_ANTIALIAS = "prune.antialias"; /** Key for kml track colour */ public static final String KEY_KML_TRACK_COLOUR = "prune.kmltrackcolour"; /** Key for autosaving settings */ @@ -184,6 +186,7 @@ public abstract class Config props.put(KEY_GPSBABEL_PATH, "gpsbabel"); props.put(KEY_IMPORT_FILE_FORMAT, "-1"); // no file format selected props.put(KEY_KMZ_IMAGE_SIZE, "240"); + props.put(KEY_ANTIALIAS, "1"); // antialias on by default props.put(KEY_AUTOSAVE_SETTINGS, "0"); // autosave false by default props.put(KEY_UNITSET_KEY, "unitset.kilometres"); // metric by default props.put(KEY_HEIGHT_EXAGGERATION, "100"); // 100%, no exaggeration @@ -345,9 +348,9 @@ public abstract class Config */ public static boolean isKeyBoolean(String inKey) { - // Only one boolean key so far (after metric flag was removed) return inKey != null && ( - inKey.equals(KEY_SHOW_MAP)); + inKey.equals(KEY_SHOW_MAP) || inKey.equals(KEY_AUTOSAVE_SETTINGS) || inKey.equals(KEY_ONLINE_MODE) + || inKey.equals(KEY_ANTIALIAS)); } /** diff --git a/tim/prune/copyright.txt b/tim/prune/copyright.txt index 7990765..f5bd232 100644 --- a/tim/prune/copyright.txt +++ b/tim/prune/copyright.txt @@ -1,4 +1,4 @@ -The source code of GpsPrune is copyright 2006-2014 activityworkshop.net +The source code of GpsPrune is copyright 2006-2015 activityworkshop.net and is distributed under the terms of the Gnu GPL version 2. Portions of the package jpeg.drew (if included in this package) were taken diff --git a/tim/prune/data/Field.java b/tim/prune/data/Field.java index d020a7e..7b9d779 100644 --- a/tim/prune/data/Field.java +++ b/tim/prune/data/Field.java @@ -22,8 +22,9 @@ public class Field public static final Field SPEED = new Field("fieldname.speed", true); public static final Field VERTICAL_SPEED = new Field("fieldname.verticalspeed", true); + public static final Field MEDIA_FILENAME = new Field("fieldname.mediafilename", true); - // TODO: Field for photo filename, ability to load (from text) and save (to text) + // TODO: Ability to load media (from text) and save (to text) /** List of all the available fields */ private static final Field[] ALL_AVAILABLE_FIELDS = { diff --git a/tim/prune/data/SourceInfo.java b/tim/prune/data/SourceInfo.java index b9609f1..5e40eee 100644 --- a/tim/prune/data/SourceInfo.java +++ b/tim/prune/data/SourceInfo.java @@ -9,7 +9,7 @@ import java.io.File; public class SourceInfo { /** File type of source file */ - public enum FILE_TYPE {TEXT, GPX, KML, NMEA, GPSBABEL, GPSIES}; + public enum FILE_TYPE {TEXT, GPX, KML, NMEA, GPSBABEL, GPSIES, JSON}; /** Source file */ private File _sourceFile = null; diff --git a/tim/prune/data/Timestamp.java b/tim/prune/data/Timestamp.java index d175c64..cfddffe 100644 --- a/tim/prune/data/Timestamp.java +++ b/tim/prune/data/Timestamp.java @@ -62,6 +62,7 @@ public class Timestamp FIXED_FORMAT5, FIXED_FORMAT6, FIXED_FORMAT7, + FIXED_FORMAT8, GENERAL_STRING } @@ -69,7 +70,7 @@ public class Timestamp private static ParseType[] ALL_PARSE_TYPES = {ParseType.NONE, ParseType.ISO8601_FRACTIONAL, ParseType.LONG, ParseType.FIXED_FORMAT0, ParseType.FIXED_FORMAT1, ParseType.FIXED_FORMAT2, ParseType.FIXED_FORMAT3, ParseType.FIXED_FORMAT4, ParseType.FIXED_FORMAT5, ParseType.FIXED_FORMAT6, ParseType.FIXED_FORMAT7, - ParseType.GENERAL_STRING}; + ParseType.FIXED_FORMAT8, ParseType.GENERAL_STRING}; // Static block to initialise offsets static @@ -95,6 +96,7 @@ public class Timestamp new SimpleDateFormat("dd MMM yyyy HH:mm:ss"), new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss"), new SimpleDateFormat("yyyy MMM dd HH:mm:ss"), + new SimpleDateFormat("MMM dd, yyyy hh:mm:ss aa"), ISO_8601_FORMAT, ISO_8601_FORMAT_NOZ }; for (DateFormat df : ALL_DATE_FORMATS) { @@ -180,6 +182,7 @@ public class Timestamp case FIXED_FORMAT5: return parseString(inString, ALL_DATE_FORMATS[5]); case FIXED_FORMAT6: return parseString(inString, ALL_DATE_FORMATS[6]); case FIXED_FORMAT7: return parseString(inString, ALL_DATE_FORMATS[7]); + case FIXED_FORMAT8: return parseString(inString, ALL_DATE_FORMATS[8]); case GENERAL_STRING: if (inString.length() == 19) diff --git a/tim/prune/data/Track.java b/tim/prune/data/Track.java index 31c9b4e..4ae47ff 100644 --- a/tim/prune/data/Track.java +++ b/tim/prune/data/Track.java @@ -178,21 +178,30 @@ public class Track /** * Delete the points marked for deletion + * @param inSplitSegments true to split segments at deleted points * @return number of points deleted */ - public int deleteMarkedPoints() + public int deleteMarkedPoints(boolean inSplitSegments) { int numCopied = 0; - // Copy selected points + // Copy selected points into a new point array DataPoint[] newPointArray = new DataPoint[_numPoints]; + boolean prevPointDeleted = false; for (int i=0; i<_numPoints; i++) { DataPoint point = _dataPoints[i]; // Don't delete photo points if (point.hasMedia() || !point.getDeleteFlag()) { + if (prevPointDeleted && inSplitSegments) { + point.setSegmentStart(true); + } newPointArray[numCopied] = point; numCopied++; + prevPointDeleted = false; + } + else { + prevPointDeleted = true; } } @@ -901,7 +910,7 @@ public class Track */ private static final double getMinXDist(double inX) { - // TODO: Can use some kind of floor here? + // TODO: Should be abs(mod(inX-0.5,1)-0.5) - means two adds, one mod, one abs instead of two adds, 3 abss and two compares return Math.min(Math.min(Math.abs(inX), Math.abs(inX-1.0)), Math.abs(inX+1.0)); } diff --git a/tim/prune/data/TrackInfo.java b/tim/prune/data/TrackInfo.java index 7bcbc64..00d6588 100644 --- a/tim/prune/data/TrackInfo.java +++ b/tim/prune/data/TrackInfo.java @@ -272,12 +272,14 @@ public class TrackInfo /** * Delete all the points which have been marked for deletion + * @param inSplitSegments true to split segments at deleted points * @return number of points deleted */ - public int deleteMarkedPoints() + public int deleteMarkedPoints(boolean inSplitSegments) { - int numDeleted = _track.deleteMarkedPoints(); - if (numDeleted > 0) { + int numDeleted = _track.deleteMarkedPoints(inSplitSegments); + if (numDeleted > 0) + { _selection.clearAll(); UpdateMessageBroker.informSubscribers(); } diff --git a/tim/prune/function/AboutScreen.java b/tim/prune/function/AboutScreen.java index 109d07e..c3a9f5b 100644 --- a/tim/prune/function/AboutScreen.java +++ b/tim/prune/function/AboutScreen.java @@ -98,8 +98,8 @@ public class AboutScreen extends GenericFunction descBuffer.append("

").append(I18nManager.getText("dialog.about.summarytext3")).append("

"); descBuffer.append("

").append(I18nManager.getText("dialog.about.languages")).append(" : ") .append("\u010de\u0161tina, deutsch, english, espa\u00F1ol, fran\u00E7ais, italiano, magyar,
" + - " nederlands, polski, portugu\u00EAs, \u0440\u0443\u0441\u0441\u043a\u0438\u0439 (russian), \u4e2d\u6587 (chinese), \u65E5\u672C\u8A9E (japanese),
" + - " \uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean), schwiizerd\u00FC\u00FCtsch, t\u00FCrk\u00E7e, afrikaans, rom\u00E2n\u0103, ukrainian

"); + " nederlands, polski, portugu\u00EAs, rom\u00E2n\u0103, \u0440\u0443\u0441\u0441\u043a\u0438\u0439 (russian), \u4e2d\u6587 (chinese),
" + + " \u65E5\u672C\u8A9E (japanese), \uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean), schwiizerd\u00FC\u00FCtsch, t\u00FCrk\u00E7e, afrikaans, ukrainian

"); descBuffer.append("

").append(I18nManager.getText("dialog.about.translatedby")).append("

"); JEditorPane descPane = new JEditorPane("text/html", descBuffer.toString()); descPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); @@ -200,7 +200,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"), + new JLabel(" HooAU, Sergey, P\u00E9ter, serhijdubyk, Peter, Cristian"), 1, 6); addToGridBagPanel(creditsPanel, gridBag, constraints, new JLabel(I18nManager.getText("dialog.about.credits.translations") + " : "), diff --git a/tim/prune/function/GetWikipediaFunction.java b/tim/prune/function/GetWikipediaFunction.java index 3ffdd06..be33a95 100644 --- a/tim/prune/function/GetWikipediaFunction.java +++ b/tim/prune/function/GetWikipediaFunction.java @@ -13,8 +13,8 @@ import tim.prune.data.DataPoint; import tim.prune.data.Field; import tim.prune.data.Latitude; import tim.prune.data.Longitude; -import tim.prune.function.gpsies.GenericDownloaderFunction; -import tim.prune.function.gpsies.GpsiesTrack; +import tim.prune.function.search.GenericDownloaderFunction; +import tim.prune.function.search.SearchResult; /** * Function to load nearby point information from Wikipedia @@ -128,7 +128,7 @@ public class GetWikipediaFunction extends GenericDownloaderFunction inStream.close(); } catch (Exception e) {} // Add track list to model - ArrayList trackList = xmlHandler.getTrackList(); + ArrayList trackList = xmlHandler.getTrackList(); _trackListModel.addTracks(trackList); // Show error message if any @@ -157,11 +157,11 @@ public class GetWikipediaFunction extends GenericDownloaderFunction int rowNum = rowNums[i]; if (rowNum >= 0 && rowNum < _trackListModel.getRowCount()) { - String coords = _trackListModel.getTrack(rowNum).getDownloadLink(); - String[] latlon = coords.split(","); - if (latlon.length == 2) + String lat = _trackListModel.getTrack(rowNum).getLatitude(); + String lon = _trackListModel.getTrack(rowNum).getLongitude(); + if (lat != null && lon != null) { - DataPoint point = new DataPoint(new Latitude(latlon[0]), new Longitude(latlon[1]), null); + DataPoint point = new DataPoint(new Latitude(lat), new Longitude(lon), null); point.setFieldValue(Field.WAYPT_NAME, _trackListModel.getTrack(rowNum).getTrackName(), false); _app.createPoint(point); } diff --git a/tim/prune/function/GetWikipediaXmlHandler.java b/tim/prune/function/GetWikipediaXmlHandler.java index f70e5f7..b5cb3f9 100644 --- a/tim/prune/function/GetWikipediaXmlHandler.java +++ b/tim/prune/function/GetWikipediaXmlHandler.java @@ -6,17 +6,17 @@ import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; -import tim.prune.function.gpsies.GpsiesTrack; +import tim.prune.function.search.SearchResult; /** - * XML handler for dealing with XML returned from the geonames api + * XML handler for dealing with XML returned from the geonames api, + * both from the search by name and search by location */ public class GetWikipediaXmlHandler extends DefaultHandler { private String _value = null; - private ArrayList _trackList = null; - private GpsiesTrack _track = null; - private String _lat = null, _lon = null; + private ArrayList _trackList = null; + private SearchResult _track = null; private String _errorMessage = null; @@ -27,12 +27,10 @@ public class GetWikipediaXmlHandler extends DefaultHandler Attributes inAttributes) throws SAXException { if (inTagName.equals("geonames")) { - _trackList = new ArrayList(); + _trackList = new ArrayList(); } else if (inTagName.equals("entry")) { - _track = new GpsiesTrack(); - _lat = null; - _lon = null; + _track = new SearchResult(); } else if (inTagName.equals("status")) { _errorMessage = inAttributes.getValue("message"); @@ -49,7 +47,6 @@ public class GetWikipediaXmlHandler extends DefaultHandler { if (inTagName.equals("entry")) { // end of the entry - _track.setDownloadLink(_lat + "," + _lon); _trackList.add(_track); } else if (inTagName.equals("title")) { @@ -59,10 +56,10 @@ public class GetWikipediaXmlHandler extends DefaultHandler _track.setDescription(_value); } else if (inTagName.equals("lat")) { - _lat = _value; + _track.setLatitude(_value); } else if (inTagName.equals("lng")) { - _lon = _value; + _track.setLongitude(_value); } else if (inTagName.equals("distance")) { try { @@ -90,7 +87,7 @@ public class GetWikipediaXmlHandler extends DefaultHandler /** * @return the list of tracks */ - public ArrayList getTrackList() + public ArrayList getTrackList() { return _trackList; } diff --git a/tim/prune/function/OpenCachingDeXmlHandler.java b/tim/prune/function/OpenCachingDeXmlHandler.java new file mode 100644 index 0000000..b4b28d5 --- /dev/null +++ b/tim/prune/function/OpenCachingDeXmlHandler.java @@ -0,0 +1,102 @@ +package tim.prune.function; + +import java.util.ArrayList; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import tim.prune.function.search.SearchResult; + +/** + * XML handler for dealing with XML returned from the opencaching.de api + */ +public class OpenCachingDeXmlHandler extends DefaultHandler +{ + private String _value = null; + private ArrayList _trackList = null; + private SearchResult _track = null; + private String _errorMessage = null; + + + /** + * React to the start of an XML tag + */ + public void startElement(String inUri, String inLocalName, String inTagName, + Attributes inAttributes) throws SAXException + { + if (inTagName.equals("result")) { + _trackList = new ArrayList(); + } + else if (inTagName.equals("cache")) + { + _track = new SearchResult(); + } +// else if (inTagName.equals("status")) { +// _errorMessage = inAttributes.getValue("message"); +// } + else _value = null; + super.startElement(inUri, inLocalName, inTagName, inAttributes); + } + + /** + * React to the end of an XML tag + */ + public void endElement(String inUri, String inLocalName, String inTagName) + throws SAXException + { + if (inTagName.equals("cache")) + { + // end of the entry + _trackList.add(_track); + } + else if (inTagName.equals("name")) { + _track.setTrackName(_value); + } + else if (inTagName.equals("desc")) { + _track.setDescription(_value); + } + else if (inTagName.equals("lat")) { + _track.setLatitude(_value); + } + else if (inTagName.equals("lon")) { + _track.setLongitude(_value); + } + else if (inTagName.equals("distance")) { + try { + _track.setLength(Double.parseDouble(_value) * 1000.0); // convert from km to m + } + catch (NumberFormatException nfe) {} + } + else if (inTagName.equals("link")) { + _track.setWebUrl(_value); + } + super.endElement(inUri, inLocalName, inTagName); + } + + /** + * React to characters received inside tags + */ + public void characters(char[] inCh, int inStart, int inLength) + throws SAXException + { + String value = new String(inCh, inStart, inLength); + _value = (_value==null?value:_value+value); + super.characters(inCh, inStart, inLength); + } + + /** + * @return the list of tracks + */ + public ArrayList getTrackList() + { + return _trackList; + } + + /** + * @return error message, if any + */ + public String getErrorMessage() { + return _errorMessage; + } +} diff --git a/tim/prune/function/RearrangePhotosFunction.java b/tim/prune/function/RearrangePhotosFunction.java index 466cd66..e278dbe 100644 --- a/tim/prune/function/RearrangePhotosFunction.java +++ b/tim/prune/function/RearrangePhotosFunction.java @@ -89,7 +89,7 @@ public class RearrangePhotosFunction extends RearrangeFunction System.arraycopy(nonPhotos, 0, neworder, 0, numNonPhotos); System.arraycopy(photos, 0, neworder, numNonPhotos, numPhotos); } - + // Give track the new point order pointsChanged = track.replaceContents(neworder); } diff --git a/tim/prune/function/SearchOpenCachingDeFunction.java b/tim/prune/function/SearchOpenCachingDeFunction.java new file mode 100644 index 0000000..20e2fc8 --- /dev/null +++ b/tim/prune/function/SearchOpenCachingDeFunction.java @@ -0,0 +1,152 @@ +package tim.prune.function; + +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import tim.prune.App; +import tim.prune.I18nManager; +import tim.prune.data.DataPoint; +import tim.prune.data.Field; +import tim.prune.data.Latitude; +import tim.prune.data.Longitude; +import tim.prune.function.search.GenericDownloaderFunction; +import tim.prune.function.search.SearchResult; + +/** + * Function to load information about geocaches nearby to the current point + * using the service at opencaching.de + */ +public class SearchOpenCachingDeFunction extends GenericDownloaderFunction +{ + /** Maximum distance from point in km */ + private static final int MAX_DISTANCE = 50; + + + /** + * Constructor + * @param inApp App object + */ + public SearchOpenCachingDeFunction(App inApp) { + super(inApp); + } + + /** + * @return name key + */ + public String getNameKey() { + return "function.searchopencachingde"; + } + + /** + * @param inColNum index of column, 0 or 1 + * @return key for this column + */ + protected String getColumnKey(int inColNum) + { + if (inColNum == 0) return "dialog.wikipedia.column.name"; + return "dialog.wikipedia.column.distance"; + } + + + /** + * Run method to call service in a separate thread + */ + public void run() + { + _statusLabel.setText(I18nManager.getText("confirm.running")); + // Get coordinates from current point + DataPoint point = _app.getTrackInfo().getCurrentPoint(); + if (point == null) + { + return; + } + + final double lat = point.getLatitude().getDouble(); + final double lon = point.getLongitude().getDouble(); + submitSearch(lat, lon); + + // Set status label according to error or "none found", leave blank if ok + if (_errorMessage == null && _trackListModel.isEmpty()) { + _errorMessage = I18nManager.getText("dialog.geocaching.nonefound"); + } + _statusLabel.setText(_errorMessage == null ? "" : _errorMessage); + } + + /** + * Submit the search for the given parameters + * @param inLat latitude + * @param inLon longitude + */ + private void submitSearch(double inLat, double inLon) + { + // The only parameters are lat and long from the current point + String urlString = "http://opencaching.de/search.php?searchto=searchbydistance&showresult=1" + + "&output=XML&sort=bydistance&lat=" + inLat + + "&lon=" + inLon + "&distance=" + MAX_DISTANCE + "&unit=km"; + // Parse the returned XML with a special handler + OpenCachingDeXmlHandler xmlHandler = new OpenCachingDeXmlHandler(); + InputStream inStream = null; + + try + { + URL url = new URL(urlString); + SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser(); + inStream = url.openStream(); + saxParser.parse(inStream, xmlHandler); + } + catch (Exception e) { + _errorMessage = e.getClass().getName() + " - " + e.getMessage(); + } + // Close stream and ignore errors + try { + inStream.close(); + } catch (Exception e) {} + // Add track list to model + ArrayList trackList = xmlHandler.getTrackList(); + _trackListModel.addTracks(trackList); + + // Show error message if any + if (_trackListModel.isEmpty()) + { + String error = xmlHandler.getErrorMessage(); + if (error != null && !error.equals("")) + { + _app.showErrorMessageNoLookup(getNameKey(), error); + _errorMessage = error; + } + } + } + + /** + * Load the selected point(s) + */ + protected void loadSelected() + { + // Find the rows selected in the table and get the corresponding coords + int numSelected = _trackTable.getSelectedRowCount(); + if (numSelected < 1) return; + int[] rowNums = _trackTable.getSelectedRows(); + for (int i=0; i= 0 && rowNum < _trackListModel.getRowCount()) + { + String lat = _trackListModel.getTrack(rowNum).getLatitude(); + String lon = _trackListModel.getTrack(rowNum).getLongitude(); + if (lat != null && lon != null) + { + DataPoint point = new DataPoint(new Latitude(lat), new Longitude(lon), null); + point.setFieldValue(Field.WAYPT_NAME, _trackListModel.getTrack(rowNum).getTrackName(), false); + _app.createPoint(point); + } + } + } + // Close the dialog + _cancelled = true; + _dialog.dispose(); + } +} diff --git a/tim/prune/function/SearchWikipediaNames.java b/tim/prune/function/SearchWikipediaNames.java index 5ab3950..20b23de 100644 --- a/tim/prune/function/SearchWikipediaNames.java +++ b/tim/prune/function/SearchWikipediaNames.java @@ -16,8 +16,8 @@ import tim.prune.data.DataPoint; import tim.prune.data.Field; import tim.prune.data.Latitude; import tim.prune.data.Longitude; -import tim.prune.function.gpsies.GenericDownloaderFunction; -import tim.prune.function.gpsies.GpsiesTrack; +import tim.prune.function.search.GenericDownloaderFunction; +import tim.prune.function.search.SearchResult; /** * Function to search Wikipedia for place names @@ -133,7 +133,7 @@ public class SearchWikipediaNames extends GenericDownloaderFunction inStream.close(); } catch (Exception e) {} // Add track list to model - ArrayList trackList = xmlHandler.getTrackList(); + ArrayList trackList = xmlHandler.getTrackList(); // TODO: Do a better job of sorting replies by relevance - use three different lists _trackListModel.addTracks(trackList); } @@ -203,11 +203,11 @@ public class SearchWikipediaNames extends GenericDownloaderFunction int rowNum = rowNums[i]; if (rowNum >= 0 && rowNum < _trackListModel.getRowCount()) { - String coords = _trackListModel.getTrack(rowNum).getDownloadLink(); - String[] latlon = coords.split(","); - if (latlon.length == 2) + String lat = _trackListModel.getTrack(rowNum).getLatitude(); + String lon = _trackListModel.getTrack(rowNum).getLongitude(); + if (lat != null && lon != null) { - DataPoint point = new DataPoint(new Latitude(latlon[0]), new Longitude(latlon[1]), null); + DataPoint point = new DataPoint(new Latitude(lat), new Longitude(lon), null); point.setFieldValue(Field.WAYPT_NAME, _trackListModel.getTrack(rowNum).getTrackName(), false); _app.createPoint(point); } diff --git a/tim/prune/function/SetLanguage.java b/tim/prune/function/SetLanguage.java index 27ec94e..832b521 100644 --- a/tim/prune/function/SetLanguage.java +++ b/tim/prune/function/SetLanguage.java @@ -41,15 +41,15 @@ public class SetLanguage extends GenericFunction private int _startIndex = 0; /** Names of languages for display in dropdown (not translated) */ - private static final String[] LANGUAGE_NAMES = {"\u010de\u0161tina", "deutsch", "english", "american english", - "espa\u00F1ol", "fran\u00E7ais", "italiano", "magyar", "nederlands", "polski", - "portugu\u00EAs", "\u0440\u0443\u0441\u0441\u043a\u0438\u0439 (russian)", "\u4e2d\u6587 (chinese)", "\u65E5\u672C\u8A9E (japanese)", - "\uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean)", "schwiizerd\u00FC\u00FCtsch", "t\u00FCrk\u00E7e", - "afrikaans", "rom\u00E2n\u0103", "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430 \u043c\u043e\u0432\u0430 (ukrainian)" + private static final String[] LANGUAGE_NAMES = {"afrikaans", "\u010de\u0161tina", "deutsch", "english", "american english", + "espa\u00F1ol", "fran\u00E7ais", "italiano", "magyar", "nederlands", "polski", "portugu\u00EAs", "rom\u00E2n\u0103", + "\u0440\u0443\u0441\u0441\u043a\u0438\u0439 (russian)", "\u4e2d\u6587 (chinese)", + "\u65E5\u672C\u8A9E (japanese)", "\uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean)", "schwiizerd\u00FC\u00FCtsch", + "t\u00FCrk\u00E7e", "\u0443\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430 \u043c\u043e\u0432\u0430 (ukrainian)" }; /** Associated language codes (must be in same order as names!) */ - private static final String[] LANGUAGE_CODES = {"cz", "de", "en", "en_us", "es", "fr", "it", "hu", - "nl", "pl", "pt", "ru", "zh", "ja", "ko", "de_ch", "tr", "af", "ro", "uk" + private static final String[] LANGUAGE_CODES = {"af", "cz", "de", "en", "en_us", "es", "fr", "it", "hu", + "nl", "pl", "pt", "ro", "ru", "zh", "ja", "ko", "de_ch", "tr", "uk" }; diff --git a/tim/prune/function/autoplay/AutoplayFunction.java b/tim/prune/function/autoplay/AutoplayFunction.java new file mode 100644 index 0000000..acb71ee --- /dev/null +++ b/tim/prune/function/autoplay/AutoplayFunction.java @@ -0,0 +1,334 @@ +package tim.prune.function.autoplay; + +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Iterator; +import java.util.TreeSet; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import tim.prune.App; +import tim.prune.GenericFunction; +import tim.prune.I18nManager; +import tim.prune.data.Field; +import tim.prune.data.Timestamp; +import tim.prune.data.Track; +import tim.prune.gui.GuiGridLayout; +import tim.prune.gui.IconManager; +import tim.prune.gui.WholeNumberField; + +/** + * Function to handle the autoplay of a track + */ +public class AutoplayFunction extends GenericFunction implements Runnable +{ + /** Dialog */ + private JDialog _dialog = null; + /** Entry field for number of seconds to autoplay for */ + private WholeNumberField _durationField = null; + /** Checkbox for using point timestamps */ + private JCheckBox _useTimestampsCheckbox = null; + /** Buttons for controlling autoplay */ + private JButton _rewindButton = null, _pauseButton = null, _playButton = null; + /** Flag for recalculating all the times */ + private boolean _needToRecalculate = true; + /** Point list */ + private PointList _pointList = null; + /** Flag to see if we're still running or not */ + private boolean _running = false; + /** Remember the time we started playing */ + private long _startTime = 0L; + + + /** + * Constructor + * @param inApp App object + */ + public AutoplayFunction(App inApp) { + super(inApp); + } + + @Override + public String getNameKey() { + return "function.autoplay"; + } + + /** + * Begin the function + */ + public void begin() + { + if (_dialog == null) + { + _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true); + _dialog.setLocationRelativeTo(_parentFrame); + _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + _dialog.getContentPane().add(makeDialogComponents()); + _dialog.pack(); + _dialog.setResizable(false); + _dialog.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + _running = false; + super.windowClosing(e); + } + }); + } + // Don't select any point + _app.getTrackInfo().selectPoint(-1); + // enable buttons + enableButtons(false, true); // can't pause, can play + // MAYBE: reset duration if it's too long + // Disable point checkbox if there aren't any times + final boolean hasTimes = _app.getTrackInfo().getTrack().hasData(Field.TIMESTAMP); + _useTimestampsCheckbox.setEnabled(hasTimes); + if (!hasTimes) + { + _useTimestampsCheckbox.setSelected(false); + } + + _needToRecalculate = true; + _dialog.setVisible(true); + } + + + /** + * Create dialog components + * @return Panel containing all gui elements in dialog + */ + private Component makeDialogComponents() + { + JPanel dialogPanel = new JPanel(); + dialogPanel.setLayout(new BoxLayout(dialogPanel, BoxLayout.Y_AXIS)); + // Duration panel + JPanel durationPanel = new JPanel(); + GuiGridLayout grid = new GuiGridLayout(durationPanel); + grid.add(new JLabel(I18nManager.getText("dialog.autoplay.duration") + " :")); + _durationField = new WholeNumberField(3); + _durationField.setValue(60); // default is one minute + _durationField.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + onParamsChanged(); + } + }); + grid.add(_durationField); + durationPanel.setAlignmentX(Component.CENTER_ALIGNMENT); + dialogPanel.add(durationPanel); + // Checkbox + _useTimestampsCheckbox = new JCheckBox(I18nManager.getText("dialog.autoplay.usetimestamps")); + _useTimestampsCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT); + dialogPanel.add(_useTimestampsCheckbox); + _useTimestampsCheckbox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + onParamsChanged(); + } + }); + // Button panel + JPanel buttonPanel = new JPanel(); + buttonPanel.setLayout(new FlowLayout(FlowLayout.CENTER)); + buttonPanel.add(_rewindButton = new JButton(IconManager.getImageIcon(IconManager.AUTOPLAY_REWIND))); + _rewindButton.setToolTipText(I18nManager.getText("dialog.autoplay.rewind")); + _rewindButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + onRewindPressed(); + } + }); + buttonPanel.add(_pauseButton = new JButton(IconManager.getImageIcon(IconManager.AUTOPLAY_PAUSE))); + _pauseButton.setToolTipText(I18nManager.getText("dialog.autoplay.pause")); + _pauseButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + onPausePressed(); + } + }); + buttonPanel.add(_playButton = new JButton(IconManager.getImageIcon(IconManager.AUTOPLAY_PLAY))); + _playButton.setToolTipText(I18nManager.getText("dialog.autoplay.play")); + _playButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + onPlayPressed(); + } + }); + buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT); + dialogPanel.add(buttonPanel); + return dialogPanel; + } + + /** + * React to a change to either the duration or the checkbox + */ + private void onParamsChanged() + { + onRewindPressed(); + enableButtons(false, _durationField.getValue() > 0); + _needToRecalculate = true; + } + + /** + * React to rewind button pressed - stop and go back to the first point + */ + private void onRewindPressed() + { + //System.out.println("Rewind! Stop thread if playing"); + _running = false; + if (_pointList != null) + { + _pointList.set(0); + _app.getTrackInfo().selectPoint(_pointList.getCurrentPointIndex()); + } + } + + /** + * React to pause button pressed - stop scrolling but maintain position + */ + private void onPausePressed() + { + //System.out.println("Pause! Stop thread if playing"); + _running = false; + enableButtons(false, true); + } + + /** + * React to play button being pressed - either start or resume + */ + private void onPlayPressed() + { + //System.out.println("Play!"); + if (_needToRecalculate) { + recalculateTimes(); + } + enableButtons(true, false); + if (_pointList.isAtStart() || _pointList.isFinished()) + { + _pointList.set(0); + _startTime = System.currentTimeMillis(); + } + else + { + // Get current millis from pointList, reset _startTime + _startTime = System.currentTimeMillis() - _pointList.getCurrentMilliseconds(); + } + new Thread(this).start(); + } + + /** + * Recalculate the times using the dialog settings + */ + private void recalculateTimes() + { + //System.out.println("Recalculate using params " + _durationField.getValue() + // + " and " + (_useTimestampsCheckbox.isSelected() ? "times" : "indexes")); + if (_useTimestampsCheckbox.isSelected()) { + _pointList = generatePointListUsingTimes(_app.getTrackInfo().getTrack(), _durationField.getValue()); + } + else { + _pointList = generatePointListUsingIndexes(_app.getTrackInfo().getTrack().getNumPoints(), _durationField.getValue()); + } + _needToRecalculate = false; + } + + /** + * Enable and disable the pause and play buttons + * @param inCanPause true to enable pause button + * @param inCanPlay true to enable play button + */ + private void enableButtons(boolean inCanPause, boolean inCanPlay) + { + _pauseButton.setEnabled(inCanPause); + _playButton.setEnabled(inCanPlay); + } + + /** + * Generate a points list based just on the point timestamps + * (points without timestamps will be ignored) + * @param inTrack track object + * @param inDuration number of seconds to play + * @return PointList object + */ + private static PointList generatePointListUsingTimes(Track inTrack, int inDuration) + { + // Make a Set of all the points with timestamps and sort them + TreeSet set = new TreeSet(); + int numPoints = inTrack.getNumPoints(); + for (int i=0; i it = set.iterator(); + while (it.hasNext()) + { + PointInfo info = it.next(); + if (previousTime != null) + { + if (info.getSegmentFlag()) { + trackMillis += 1000; // just add a second if it's a new segment + } + else { + trackMillis += (info.getTimestamp().getMillisecondsSince(previousTime)); + } + } + previousTime = info.getTimestamp(); + list.setPoint(trackMillis, info.getIndex()); + } + // Now normalize the list to the requested length + list.normalize(inDuration); + return list; + } + + + /** + * Generate a points list based just on indexes, ignoring timestamps + * @param inNumPoints number of points in track + * @param inDuration number of seconds to play + * @return PointList object + */ + private static PointList generatePointListUsingIndexes(int inNumPoints, int inDuration) + { + // simple case, just take all the points in the track + PointList list = new PointList(inNumPoints); + // Add each of the points in turn + for (int i=0; i +{ + /** Timestamp of the point, if any */ + private Timestamp _timestamp = null; + /** Point index in the track */ + private int _pointIndex = 0; + /** Segment flag of point */ + private boolean _segmentFlag = false; + + + /** + * Constructor + * @param inPoint point from track + * @param inIndex index of point in track + */ + public PointInfo(DataPoint inPoint, int inIndex) + { + if (inPoint.hasTimestamp()) + { + _timestamp = inPoint.getTimestamp(); + } + else if (inPoint.getPhoto() != null && inPoint.getPhoto().hasTimestamp()) + { + _timestamp = inPoint.getPhoto().getTimestamp(); + } + _pointIndex = inIndex; + _segmentFlag = inPoint.getSegmentStart(); + } + + /** @return timestamp */ + public Timestamp getTimestamp() { + return _timestamp; + } + + /** @return point index */ + public int getIndex() { + return _pointIndex; + } + + /** @return segment flag */ + public boolean getSegmentFlag() { + return _segmentFlag; + } + + /** + * Sort two objects by timestamp and if times equal then by point index + */ + public int compareTo(PointInfo inOther) + { + long timeDiff = 0; + final boolean thisHasTime = (_timestamp != null); + final boolean otherHasTime = (inOther._timestamp != null); + if (thisHasTime && otherHasTime) + { + timeDiff = _timestamp.getMillisecondsSince(inOther._timestamp); + } + else if (thisHasTime) + { + timeDiff = -1; // points without time to the end + } + else if (otherHasTime) + { + timeDiff = 1; + } + // If the times are equal (or both missing) then use the point index + if (timeDiff == 0) { + return _pointIndex - inOther._pointIndex; + } + // Otherwise, compare by time + return (timeDiff < 0 ? -1 : 1); + } + + @Override + public boolean equals(Object inOther) + { + if (inOther == null) return false; + try + { + PointInfo other = (PointInfo) inOther; + if (_pointIndex != other._pointIndex) return false; + final boolean thisHasTime = (_timestamp != null); + final boolean otherHasTime = (other._timestamp != null); + if (thisHasTime != otherHasTime) {return false;} + if (!thisHasTime && !otherHasTime) {return true;} + return _timestamp.isEqual(other._timestamp); + } + catch (ClassCastException cce) {} + return false; + } +} diff --git a/tim/prune/function/autoplay/PointList.java b/tim/prune/function/autoplay/PointList.java new file mode 100644 index 0000000..13ccf61 --- /dev/null +++ b/tim/prune/function/autoplay/PointList.java @@ -0,0 +1,115 @@ +package tim.prune.function.autoplay; + +/** + * Class to hold a list of points and hold a running position + */ +public class PointList +{ + /** Array of milliseconds for each point */ + private long[] _millis = null; + /** Array of indexes of corresponding points */ + private int[] _indexes = null; + /** Array index of current position */ + private int _currentItem = 0; + /** Max array index */ + private int _maxItem = 0; + + /** + * Constructor + * @param inNumPoints number of points + */ + public PointList(int inNumPoints) + { + _millis = new long[inNumPoints]; + _indexes = new int[inNumPoints]; + _currentItem = 0; + _maxItem = inNumPoints - 1; + } + + /** + * Add a point to the array + * @param inMillis milliseconds since start + * @param inIndex point index + */ + public void setPoint(long inMillis, int inIndex) + { + _millis[_currentItem] = inMillis; + _indexes[_currentItem] = inIndex; + _currentItem++; + } + + /** + * Set the position using the current milliseconds + * @param inMillis milliseconds since start + */ + public void set(long inMillis) + { + if (isFinished() || inMillis < _millis[_currentItem]) + { + // must be reset + _currentItem = 0; + } + while (_currentItem < _maxItem && _millis[_currentItem + 1] < inMillis) + { + _currentItem++; + } + } + + /** + * Normalize the list to cover the requested number of seconds duration + * @param inSeconds length of autoplay sequence in seconds + */ + public void normalize(int inSeconds) + { + if (_maxItem <= 0) + { + return; // nothing to normalize + } + long currentDuration = _millis[_maxItem] - _millis[0]; + if (currentDuration > 0L) + { + double multFactor = inSeconds * 1000.0 / currentDuration; + for (int i=0; i<=_maxItem; i++) + { + _millis[i] = (long) (_millis[i] * multFactor); + } + } + } + + /** @return the milliseconds of the current point */ + public long getCurrentMilliseconds() + { + if (isAtStart() || isFinished()) { + return 0L; + } + return _millis[_currentItem]; + } + + /** @return the index of the current point */ + public int getCurrentPointIndex() + { + return _indexes[_currentItem]; + } + + /** @return true if we're on the first point */ + public boolean isAtStart() { + return _currentItem == 0; + } + + /** @return true if we're on the last point */ + public boolean isFinished() { + return _currentItem >= _maxItem; + } + + /** + * @param inCurrentMillis current time in milliseconds since start + * @return number of milliseconds to wait until next point is due + */ + public long getMillisUntilNextPoint(long inCurrentMillis) + { + if (isFinished() || _millis[_currentItem+1] < _millis[_currentItem]) { + return 0; // no next point + } + return _millis[_currentItem+1] - inCurrentMillis; + } +} diff --git a/tim/prune/function/browser/BrowserLauncher.java b/tim/prune/function/browser/BrowserLauncher.java index 4ba4b8d..7c6fa58 100644 --- a/tim/prune/function/browser/BrowserLauncher.java +++ b/tim/prune/function/browser/BrowserLauncher.java @@ -86,6 +86,7 @@ public abstract class BrowserLauncher */ public static void launchBrowser(String inUrl) { + if (inUrl == null) {return;} // First choice is to try the Desktop library from java 6, if available try { Class d = Class.forName("java.awt.Desktop"); diff --git a/tim/prune/function/browser/UrlGenerator.java b/tim/prune/function/browser/UrlGenerator.java index 8d264be..a0100b1 100644 --- a/tim/prune/function/browser/UrlGenerator.java +++ b/tim/prune/function/browser/UrlGenerator.java @@ -22,38 +22,46 @@ public abstract class UrlGenerator if (FIVE_DP instanceof DecimalFormat) ((DecimalFormat) FIVE_DP).applyPattern("0.00000"); } - /** Constant for Google Maps */ - public static final int MAP_SOURCE_GOOGLE = 0; - /** Constant for Open Street Maps */ - public static final int MAP_SOURCE_OSM = 1; - /** Constant for Mapquest */ - public static final int MAP_SOURCE_MAPQUEST = 2; - /** Constant for Yahoo */ - public static final int MAP_SOURCE_YAHOO = 3; - /** Constant for Bing */ - public static final int MAP_SOURCE_BING = 4; + public enum WebService + { + MAP_SOURCE_GOOGLE, /* Google maps */ + MAP_SOURCE_OSM, /* OpenStreetMap */ + MAP_SOURCE_MAPQUEST, /* Mapquest */ + MAP_SOURCE_YAHOO, /* Yahoo */ + MAP_SOURCE_BING, /* Bing */ + MAP_SOURCE_PEAKFINDER, /* PeakFinder */ + MAP_SOURCE_GEOHACK, /* Geohack */ + MAP_SOURCE_PANORAMIO, /* Panoramio */ + MAP_SOURCE_OPENCACHINGCOM, /* Opencaching.com */ + } /** * Generate a URL for the given source and track info - * @param inSource source to use, either google or openstreetmap + * @param inSource source to use, from the enum in UrlGenerator * @param inTrackInfo track info * @return url for map */ - public static String generateUrl(int inSource, TrackInfo inTrackInfo) + public static String generateUrl(WebService inSource, TrackInfo inTrackInfo) { - if (inSource == MAP_SOURCE_GOOGLE) { - return generateGoogleUrl(inTrackInfo); - } - else if (inSource == MAP_SOURCE_MAPQUEST) { - return generateMapquestUrl(inTrackInfo); - } - else if (inSource == MAP_SOURCE_YAHOO) { - return generateYahooUrl(inTrackInfo); - } - else if (inSource == MAP_SOURCE_BING) { - return generateBingUrl(inTrackInfo); + switch (inSource) + { + case MAP_SOURCE_GOOGLE: + return generateGoogleUrl(inTrackInfo); + case MAP_SOURCE_MAPQUEST: + return generateMapquestUrl(inTrackInfo); + case MAP_SOURCE_YAHOO: + return generateYahooUrl(inTrackInfo); + case MAP_SOURCE_BING: + return generateBingUrl(inTrackInfo); + case MAP_SOURCE_PEAKFINDER: + case MAP_SOURCE_GEOHACK: + case MAP_SOURCE_PANORAMIO: + case MAP_SOURCE_OPENCACHINGCOM: + return generateUrlForPoint(inSource, inTrackInfo); + case MAP_SOURCE_OSM: + default: + return generateOpenStreetMapUrl(inTrackInfo); } - return generateOpenStreetMapUrl(inTrackInfo); } /** @@ -88,33 +96,6 @@ public abstract class UrlGenerator return url; } - /** - * Generate a url for Open Street Map - * @param inTrackInfo track information - * @return URL - */ - private static String generateOpenStreetMapUrl(TrackInfo inTrackInfo) - { - // Check if any data to display - if (inTrackInfo == null || inTrackInfo.getTrack() == null || inTrackInfo.getTrack().getNumPoints() < 1) - { - return null; - } - DoubleRange latRange = inTrackInfo.getTrack().getLatRange(); - DoubleRange lonRange = inTrackInfo.getTrack().getLonRange(); - // Build basic url using min and max lat and long - String url = "http://openstreetmap.org/?minlat=" + FIVE_DP.format(latRange.getMinimum()) - + "&maxlat=" + FIVE_DP.format(latRange.getMaximum()) - + "&minlon=" + FIVE_DP.format(lonRange.getMinimum()) + "&maxlon=" + FIVE_DP.format(lonRange.getMaximum()); - DataPoint currPoint = inTrackInfo.getCurrentPoint(); - // Add selected point, if any (no way to add point name?) - if (currPoint != null) { - url = url + "&mlat=" + FIVE_DP.format(currPoint.getLatitude().getDouble()) - + "&mlon=" + FIVE_DP.format(currPoint.getLongitude().getDouble()); - } - return url; - } - /** * Generate a url for Mapquest maps * @param inTrackInfo track information @@ -178,6 +159,117 @@ public abstract class UrlGenerator return url; } + /** + * Generate a url for Open Street Map + * @param inTrackInfo track information + * @return URL + */ + private static String generateOpenStreetMapUrl(TrackInfo inTrackInfo) + { + // Check if any data to display + if (inTrackInfo == null || inTrackInfo.getTrack() == null || inTrackInfo.getTrack().getNumPoints() < 1) + { + return null; + } + DoubleRange latRange = inTrackInfo.getTrack().getLatRange(); + DoubleRange lonRange = inTrackInfo.getTrack().getLonRange(); + // Build basic url using min and max lat and long + String url = "http://openstreetmap.org/?minlat=" + FIVE_DP.format(latRange.getMinimum()) + + "&maxlat=" + FIVE_DP.format(latRange.getMaximum()) + + "&minlon=" + FIVE_DP.format(lonRange.getMinimum()) + "&maxlon=" + FIVE_DP.format(lonRange.getMaximum()); + DataPoint currPoint = inTrackInfo.getCurrentPoint(); + // Add selected point, if any (no way to add point name?) + if (currPoint != null) { + url = url + "&mlat=" + FIVE_DP.format(currPoint.getLatitude().getDouble()) + + "&mlon=" + FIVE_DP.format(currPoint.getLongitude().getDouble()); + } + return url; + } + + /** + * Generate a URL which only needs the current point + * This is just a helper method to simplify the calls to the service-specific methods + * @param inSource service to call + * @param inTrackInfo track info + * @return URL if available, or null + */ + private static String generateUrlForPoint(WebService inService, TrackInfo inTrackInfo) + { + if (inTrackInfo == null || inTrackInfo.getTrack() == null || inTrackInfo.getTrack().getNumPoints() < 1) + { + return null; + } + // Need a current point + DataPoint currPoint = inTrackInfo.getCurrentPoint(); + if (currPoint == null) + { + return null; + } + switch (inService) + { + case MAP_SOURCE_PEAKFINDER: + return generatePeakfinderUrl(currPoint); + case MAP_SOURCE_GEOHACK: + return generateGeohackUrl(currPoint); + case MAP_SOURCE_PANORAMIO: + return generatePanoramioUrl(currPoint); + case MAP_SOURCE_OPENCACHINGCOM: + return generateOpencachingComUrl(currPoint); + default: + return null; + } + } + + + /** + * Generate a url for PeakFinder + * @param inPoint current point, not null + * @return URL + */ + private static String generatePeakfinderUrl(DataPoint inPoint) + { + return "http://peakfinder.org/?lat=" + FIVE_DP.format(inPoint.getLatitude().getDouble()) + + "&lng=" + FIVE_DP.format(inPoint.getLongitude().getDouble()); + } + + /** + * Generate a url for Geohack + * @param inPoint current point, not null + * @return URL + */ + private static String generateGeohackUrl(DataPoint inPoint) + { + return "https://tools.wmflabs.org/geohack/geohack.php?params=" + FIVE_DP.format(inPoint.getLatitude().getDouble()) + + "_N_" + FIVE_DP.format(inPoint.getLongitude().getDouble()) + "_E"; + // TODO: Could use absolute values and S, W but this seems to work + } + + /** + * Generate a url for Panoramio.com + * @param inPoint current point, not null + * @return URL + */ + private static String generatePanoramioUrl(DataPoint inPoint) + { + return "http://panoramio.com/map/#lt=" + FIVE_DP.format(inPoint.getLatitude().getDouble()) + + "&ln=" + FIVE_DP.format(inPoint.getLongitude().getDouble()) + "&z=1&k=0"; + } + + + /** + * Generate a url for OpenCaching.com + * @param inPoint current point, not null + * @return URL + */ + private static String generateOpencachingComUrl(DataPoint inPoint) + { + final String occLang = I18nManager.getText("webservice.opencachingcom.lang"); + final String url = "http://www.opencaching.com/" + occLang + + "/#find?&loc=" + FIVE_DP.format(inPoint.getLatitude().getDouble()) + + "," + FIVE_DP.format(inPoint.getLongitude().getDouble()); + return url; + } + /** * Get the median value from the given lat/long range diff --git a/tim/prune/function/browser/WebMapFunction.java b/tim/prune/function/browser/WebMapFunction.java new file mode 100644 index 0000000..1639c45 --- /dev/null +++ b/tim/prune/function/browser/WebMapFunction.java @@ -0,0 +1,46 @@ +package tim.prune.function.browser; + +import tim.prune.App; +import tim.prune.GenericFunction; + +/** + * Function to show a webservice for the current area or point + */ +public class WebMapFunction extends GenericFunction +{ + /** Service to call */ + private UrlGenerator.WebService _service; + /** Key for appearance in menu */ + private String _nameKey = null; + + /** + * Constructor + * @param inApp app object + * @param inService web service to call + * @param inNameKey name key for function + */ + public WebMapFunction(App inApp, UrlGenerator.WebService inService, + String inNameKey) + { + super(inApp); + _service = inService; + _nameKey = inNameKey; + } + + @Override + public String getNameKey() { + return _nameKey; + } + + @Override + /** + * Do the function call + */ + public void begin() + { + String url = UrlGenerator.generateUrl(_service, _app.getTrackInfo()); + if (url != null) { + BrowserLauncher.launchBrowser(url); + } + } +} diff --git a/tim/prune/function/cache/ManageCacheFunction.java b/tim/prune/function/cache/ManageCacheFunction.java index 59ef13a..5431e9e 100644 --- a/tim/prune/function/cache/ManageCacheFunction.java +++ b/tim/prune/function/cache/ManageCacheFunction.java @@ -273,6 +273,7 @@ public class ManageCacheFunction extends GenericFunction implements Runnable */ public void run() { + // TODO: Maybe this can be speeded up so that it just finds the tilesets first and then gets the details later // Check if directory has anything in it _model = new TileCacheModel(_cacheDir); _model.buildTileSets(); diff --git a/tim/prune/function/cache/RowInfo.java b/tim/prune/function/cache/RowInfo.java index 8c7ee23..809c572 100644 --- a/tim/prune/function/cache/RowInfo.java +++ b/tim/prune/function/cache/RowInfo.java @@ -10,7 +10,6 @@ public class RowInfo private int _minZoom = -1, _maxZoom = -1; private int _numTiles = 0; private long _totalSize = 0L; - private boolean _unexpected = false; /** @@ -84,20 +83,6 @@ public class RowInfo return _totalSize; } - /** - * Mark that an unexpected file or directory was found - * TODO: Is this needed? - */ - public void foundUnexpected() { - _unexpected = true; - } - - /** - * @return true if any unexpected files or directories were found - */ - public boolean wasUnexpected() { - return _unexpected; - } /** * Add the given RowInfo object to this one @@ -117,6 +102,5 @@ public class RowInfo addZoom(inOther._maxZoom); if (inOther._zoom > 0) addZoom(inOther._zoom); - _unexpected = _unexpected || inOther._unexpected; } } diff --git a/tim/prune/function/cache/TileSet.java b/tim/prune/function/cache/TileSet.java index ca2b81a..525696e 100644 --- a/tim/prune/function/cache/TileSet.java +++ b/tim/prune/function/cache/TileSet.java @@ -59,6 +59,35 @@ public class TileSet return true; } + /** + * Check if a filename is numeric up until the first dot + * This appears to be much faster than scanning for a . with indexOf, then + * chopping to make a new String, and then calling isNumeric to scan through again + * @param inName name of file + * @return true if it only contains characters 0-9 before the first dot + */ + public static boolean isNumericUntilDot(String inName) + { + if (inName == null || inName.equals("") || inName.charAt(0) == '.') { + return false; + } + try + { + char c = '.'; + int i = 0; + do + { + c = inName.charAt(i); + if (c == '.') return true; // found the dot, so stop + if (c < '0' || c > '9') return false; // not numeric + i++; + } while (c != '\0'); + } + catch (IndexOutOfBoundsException iobe) {} + // Didn't find a dot, so can't be a valid name + return false; + } + /** * Make a RowInfo object from the given directory * @param inDir directory for a single zoom level @@ -78,9 +107,7 @@ public class TileSet { if (f != null && f.exists() && f.isFile() && f.canRead()) { - final String filename = f.getName(); - int dotpos = filename.lastIndexOf('.'); - if (dotpos > 0 && isNumeric(filename.substring(0, dotpos))) { + if (isNumericUntilDot(f.getName())) { row.addTile(f.length()); } } diff --git a/tim/prune/function/compress/DeleteMarkedPointsFunction.java b/tim/prune/function/compress/DeleteMarkedPointsFunction.java new file mode 100644 index 0000000..a604907 --- /dev/null +++ b/tim/prune/function/compress/DeleteMarkedPointsFunction.java @@ -0,0 +1,56 @@ +package tim.prune.function.compress; + +import tim.prune.App; +import tim.prune.GenericFunction; +import tim.prune.I18nManager; +import tim.prune.undo.UndoDeleteMarked; + +/** + * Function to delete the marked points in the track + */ +public class DeleteMarkedPointsFunction extends GenericFunction +{ + private boolean _splitSegments = false; + private String _parentFunctionKey = null; + + /** Constructor */ + public DeleteMarkedPointsFunction(App inApp) { + super(inApp); + } + + @Override + public String getNameKey() { + return "function.deletemarked"; + } + + /** + * Get notification about parent function + * @param inKey parent function name key + * @param inSplitSegments true to split segment, false to not + */ + public void setParentFunction(String inKey, boolean inSplitSegments) + { + _parentFunctionKey = inKey; + _splitSegments = inSplitSegments; + } + + @Override + public void begin() + { + UndoDeleteMarked undo = new UndoDeleteMarked(_app.getTrackInfo().getTrack()); + // call track to do the actual delete// + int numPointsDeleted = _app.getTrackInfo().deleteMarkedPoints(_splitSegments); + // add to undo stack if successful + if (numPointsDeleted > 0) + { + undo.setNumPointsDeleted(numPointsDeleted); + _app.completeFunction(undo, "" + numPointsDeleted + " " + + (numPointsDeleted==1?I18nManager.getText("confirm.deletepoint.single"):I18nManager.getText("confirm.deletepoint.multi"))); + } + else + { + final String titleKey = (_parentFunctionKey == null ? getNameKey() : _parentFunctionKey); + _app.showErrorMessage(titleKey, "dialog.deletemarked.nonefound"); + } + } +} diff --git a/tim/prune/function/compress/MarkAndDeleteFunction.java b/tim/prune/function/compress/MarkAndDeleteFunction.java index 2189ecb..dddc897 100644 --- a/tim/prune/function/compress/MarkAndDeleteFunction.java +++ b/tim/prune/function/compress/MarkAndDeleteFunction.java @@ -3,6 +3,7 @@ package tim.prune.function.compress; import javax.swing.JOptionPane; import tim.prune.App; +import tim.prune.FunctionLibrary; import tim.prune.GenericFunction; import tim.prune.I18nManager; @@ -39,13 +40,23 @@ public abstract class MarkAndDeleteFunction extends GenericFunction I18nManager.getText(getNameKey()), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, null, buttonTexts, buttonTexts[1]); if (answer == JOptionPane.CANCEL_OPTION) {_automaticallyDelete = true;} // "always" is third option + + // Make sure function knows what to do, whether we'll call it now or later + FunctionLibrary.FUNCTION_DELETE_MARKED_POINTS.setParentFunction( + getNameKey(), getShouldSplitSegments()); if (_automaticallyDelete || answer == JOptionPane.YES_OPTION) { new Thread(new Runnable() { - public void run() { - _app.finishCompressTrack(); + public void run() + { + FunctionLibrary.FUNCTION_DELETE_MARKED_POINTS.begin(); } }).start(); } } + + /** by default, segments are not split at deleted points */ + protected boolean getShouldSplitSegments() { + return false; + } } diff --git a/tim/prune/function/compress/MarkLiftsFunction.java b/tim/prune/function/compress/MarkLiftsFunction.java new file mode 100644 index 0000000..5e39866 --- /dev/null +++ b/tim/prune/function/compress/MarkLiftsFunction.java @@ -0,0 +1,143 @@ +package tim.prune.function.compress; + +import tim.prune.App; +import tim.prune.UpdateMessageBroker; +import tim.prune.data.DataPoint; +import tim.prune.data.Distance; +import tim.prune.data.RangeStats; +import tim.prune.data.Track; +import tim.prune.data.UnitSetLibrary; + +/** + * Function to mark all the points going uphill on ski lifts + */ +public class MarkLiftsFunction extends MarkAndDeleteFunction +{ + /** + * Constructor + * @param inApp App object + */ + public MarkLiftsFunction(App inApp) + { + super(inApp); + } + + /** @return name key */ + public String getNameKey() { + return "function.marklifts"; + } + + /** this function _does_ require split at deleted points */ + protected boolean getShouldSplitSegments() { + return true; + } + + /** + * Begin the function using the set parameters + */ + public void begin() + { + // TODO: Might need to do this in a separate thread, it might take a while if the track is big + // Loop over all points in track + int numMarked = 0; + final Track track = _app.getTrackInfo().getTrack(); + final int numPoints = track.getNumPoints(); + boolean[] markFlags = new boolean[numPoints]; + int previousStartIndex = -1; + for (int i=0; i (i+10)) + { + // Found a 2 minute range to test with at least 12 points + if (looksLikeLiftRange(track, i, n)) + { + // Passes tests, so we want to mark all points between i and n + int startIndex = i; + // First check if we can merge with the previous marked range + if (previousStartIndex >= 0 + && (looksLikeLiftRange(track, previousStartIndex, i) + || looksLikeLiftRange(track, previousStartIndex, n))) + { + startIndex = previousStartIndex; // merge + } + for (int j=startIndex; j<=n; j++) + { + markFlags[j] = true; + } + // Remember start point for next one + previousStartIndex = startIndex; + // skip forward half the range, don't need to test the same points again + i = (i+n)/2; + } + } + } + } + + // Copy mark flags to points + for (int i=0; i 0) + { + optionallyDeleteMarkedPoints(numMarked); + } + else + { + // TODO: Show message that no lifts were found + } + } + + + /** + * Check whether the specified range looks like an uphill lift section or not + * Must go at most a little bit downhill, much more uphill than down, and straight + * (speed isn't checked yet, but maybe could be?) + * @param inTrack track + * @param inStartIndex start index of range + * @param inEndIndex end index of range + * @return true if it looks like a lift + */ + private boolean looksLikeLiftRange(Track inTrack, int inStartIndex, int inEndIndex) + { + RangeStats stats = new RangeStats(inTrack, inStartIndex, inEndIndex); + int descent = stats.getTotalAltitudeRange().getDescent(UnitSetLibrary.UNITS_METRES); + if (descent < 20) + { + int ascent = stats.getTotalAltitudeRange().getClimb(UnitSetLibrary.UNITS_METRES); + if (ascent > (descent * 10)) + { + // Now check distance and compare to distance between start and end + final DataPoint startPoint = inTrack.getPoint(inStartIndex); + final DataPoint endPoint = inTrack.getPoint(inEndIndex); + + final double trackDist = stats.getTotalDistance(); + final double endToEndDist = Distance.convertRadiansToDistance( + DataPoint.calculateRadiansBetween(startPoint, endPoint)); + if ((trackDist / endToEndDist) < 1.02) // Straight(ish) line + { + return true; + } + //else System.out.println("Not straight enough: " + (trackDist / endToEndDist)); + } + } + return false; + } +} diff --git a/tim/prune/function/gpsies/GetGpsiesFunction.java b/tim/prune/function/gpsies/GetGpsiesFunction.java index e60ed74..cdcc9a9 100644 --- a/tim/prune/function/gpsies/GetGpsiesFunction.java +++ b/tim/prune/function/gpsies/GetGpsiesFunction.java @@ -12,6 +12,8 @@ import javax.xml.parsers.SAXParserFactory; import tim.prune.App; import tim.prune.GpsPrune; import tim.prune.I18nManager; +import tim.prune.function.search.GenericDownloaderFunction; +import tim.prune.function.search.SearchResult; import tim.prune.load.xml.XmlFileLoader; import tim.prune.load.xml.ZipFileLoader; @@ -65,7 +67,7 @@ public class GetGpsiesFunction extends GenericDownloaderFunction double[] coords = _app.getViewport().getBounds(); int currPage = 1; - ArrayList trackList = null; + ArrayList trackList = null; URL url = null; String descMessage = ""; InputStream inStream = null; diff --git a/tim/prune/function/gpsies/GpsiesXmlHandler.java b/tim/prune/function/gpsies/GpsiesXmlHandler.java index 3d801be..f90bb03 100644 --- a/tim/prune/function/gpsies/GpsiesXmlHandler.java +++ b/tim/prune/function/gpsies/GpsiesXmlHandler.java @@ -6,14 +6,16 @@ import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; +import tim.prune.function.search.SearchResult; + /** * XML handler for dealing with XML returned from gpsies.com */ public class GpsiesXmlHandler extends DefaultHandler { private String _value = null; - private ArrayList _trackList = null; - private GpsiesTrack _track = null; + private ArrayList _trackList = null; + private SearchResult _track = null; /** @@ -23,10 +25,10 @@ public class GpsiesXmlHandler extends DefaultHandler Attributes inAttributes) throws SAXException { if (inTagName.equals("tracks")) { - _trackList = new ArrayList(); + _trackList = new ArrayList(); } else if (inTagName.equals("track")) { - _track = new GpsiesTrack(); + _track = new SearchResult(); } _value = null; super.startElement(inUri, inLocalName, inTagName, inAttributes); @@ -76,7 +78,7 @@ public class GpsiesXmlHandler extends DefaultHandler /** * @return the list of tracks */ - public ArrayList getTrackList() + public ArrayList getTrackList() { return _trackList; } diff --git a/tim/prune/function/gpsies/TrackListModel.java b/tim/prune/function/gpsies/TrackListModel.java index 274c0b8..298578c 100644 --- a/tim/prune/function/gpsies/TrackListModel.java +++ b/tim/prune/function/gpsies/TrackListModel.java @@ -8,6 +8,7 @@ import javax.swing.table.AbstractTableModel; import tim.prune.I18nManager; import tim.prune.config.Config; import tim.prune.data.Unit; +import tim.prune.function.search.SearchResult; /** * Model for list of tracks from gpsies.com @@ -15,7 +16,7 @@ import tim.prune.data.Unit; public class TrackListModel extends AbstractTableModel { /** List of tracks */ - private ArrayList _trackList = null; + private ArrayList _trackList = null; /** Column heading for track name */ private String _nameColLabel = null; /** Column heading for length */ @@ -80,7 +81,7 @@ public class TrackListModel extends AbstractTableModel */ public Object getValueAt(int inRowNum, int inColNum) { - GpsiesTrack track = _trackList.get(inRowNum); + SearchResult track = _trackList.get(inRowNum); if (inColNum == 0) {return track.getTrackName();} double lengthM = track.getLength(); // convert to current distance units @@ -94,9 +95,9 @@ public class TrackListModel extends AbstractTableModel * Add a list of tracks to this model * @param inList list of tracks to add */ - public void addTracks(ArrayList inList) + public void addTracks(ArrayList inList) { - if (_trackList == null) {_trackList = new ArrayList();} + if (_trackList == null) {_trackList = new ArrayList();} final int prevCount = _trackList.size(); if (inList != null && inList.size() > 0) { _trackList.addAll(inList); @@ -112,7 +113,7 @@ public class TrackListModel extends AbstractTableModel * @param inRowNum row number from 0 * @return track object for this row */ - public GpsiesTrack getTrack(int inRowNum) + public SearchResult getTrack(int inRowNum) { return _trackList.get(inRowNum); } diff --git a/tim/prune/function/gpsies/GenericDownloaderFunction.java b/tim/prune/function/search/GenericDownloaderFunction.java similarity index 98% rename from tim/prune/function/gpsies/GenericDownloaderFunction.java rename to tim/prune/function/search/GenericDownloaderFunction.java index 286ba1a..403a0ef 100644 --- a/tim/prune/function/gpsies/GenericDownloaderFunction.java +++ b/tim/prune/function/search/GenericDownloaderFunction.java @@ -1,4 +1,4 @@ -package tim.prune.function.gpsies; +package tim.prune.function.search; import java.awt.BorderLayout; import java.awt.Component; @@ -25,6 +25,7 @@ import tim.prune.App; import tim.prune.GenericFunction; import tim.prune.I18nManager; import tim.prune.function.browser.BrowserLauncher; +import tim.prune.function.gpsies.TrackListModel; /** * Function to load track information from any source, diff --git a/tim/prune/function/search/SearchMapillaryFunction.java b/tim/prune/function/search/SearchMapillaryFunction.java new file mode 100644 index 0000000..32c58bd --- /dev/null +++ b/tim/prune/function/search/SearchMapillaryFunction.java @@ -0,0 +1,231 @@ +package tim.prune.function.search; + +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; + +import tim.prune.App; +import tim.prune.I18nManager; +import tim.prune.data.DataPoint; +import tim.prune.data.Distance; +import tim.prune.data.Field; +import tim.prune.data.Latitude; +import tim.prune.data.Longitude; +import tim.prune.data.SourceInfo; +import tim.prune.data.UnitSetLibrary; +import tim.prune.load.MediaLinkInfo; + +/** + * Function to search mapillary for photos + */ +public class SearchMapillaryFunction extends GenericDownloaderFunction +{ + /** Maximum number of results to get */ + private static final int MAX_RESULTS = 20; + + + /** + * Constructor + * @param inApp app object + */ + public SearchMapillaryFunction(App inApp) + { + super(inApp); + } + + @Override + public String getNameKey() { + return "function.mapillary"; + } + + @Override + protected String getColumnKey(int inColNum) + { + if (inColNum == 0) return "dialog.wikipedia.column.name"; + return "dialog.wikipedia.column.distance"; + } + + /** + * Run method, for searching in a separate thread + */ + public void run() + { + _statusLabel.setText(I18nManager.getText("confirm.running")); + // Get coordinates from current point (if any) or from centre of screen + double lat = 0.0, lon = 0.0; + DataPoint currentPoint = _app.getTrackInfo().getCurrentPoint(); + if (currentPoint == null) + { + double[] coords = _app.getViewport().getBounds(); + lat = (coords[0] + coords[2]) / 2.0; + lon = (coords[1] + coords[3]) / 2.0; + } + else + { + lat = currentPoint.getLatitude().getDouble(); + lon = currentPoint.getLongitude().getDouble(); + } + + // Construct URL + final String urlString = "http://api.mapillary.com/v1/im/close?lat=" + + lat + "&lon=" + lon + "&distance=1000&limit=" + MAX_RESULTS; + //System.out.println(urlString); + InputStream inStream = null; + try + { + inStream = new URL(urlString).openStream(); + StringBuilder sb = new StringBuilder(); + int ch = 0; + while ((ch = inStream.read()) >= 0) + { + sb.append((char) ch); + } + //System.out.println("Got answer: '" + sb.toString() + "'"); + + ArrayList resultList = new ArrayList(); + for (String result : sb.toString().split("\\},\\{")) + { + //System.out.println("Result: '" + result + "'"); + SearchResult sr = new SearchResult(); + for (String prop : result.split(",")) + { + String key = getKey(prop); + if (key == null) {continue;} + if (key.equals("key")) + { + final String value = getValue(prop); + sr.setDownloadLink("http://images.mapillary.com/" + value + "/thumb-1024.jpg"); + sr.setWebUrl("http://www.mapillary.com/map/im/" + value); + sr.setTrackName(value); + } + else if (key.equals("lat")) { + sr.setLatitude(getValue(prop)); + } + else if (key.equals("lon")) { + sr.setLongitude(getValue(prop)); + } + } + + if (sr.getLatitude() != null && sr.getLongitude() != null && sr.getTrackName() != null) + { + // Calculate distance away from current point and set this in sr.setLength + DataPoint resultPoint = new DataPoint(new Latitude(sr.getLatitude()), new Longitude(sr.getLongitude()), null); + if (resultPoint.isValid() && currentPoint != null && currentPoint.isValid()) + { + double radianDist = DataPoint.calculateRadiansBetween(currentPoint, resultPoint); + double metresAway = Distance.convertRadiansToDistance(radianDist, UnitSetLibrary.UNITS_METRES); + sr.setLength(metresAway); + } + + // If there's a valid result, add it to the temporary list + if (sr.getTrackName() != null) { + resultList.add(sr); + } + } + } + // Add all the results to the table model in one go + if (!resultList.isEmpty()) { + _trackListModel.addTracks(resultList); + } + } + catch (Exception e) { + _errorMessage = e.getClass().getName() + " - " + e.getMessage(); + } + // Close stream and ignore errors + try { + inStream.close(); + } catch (Exception e) {} + + // Set status label according to error or "none found", leave blank if ok + if (_errorMessage == null && _trackListModel.isEmpty()) { + _errorMessage = I18nManager.getText("dialog.mapillary.nonefound"); + } + _statusLabel.setText(_errorMessage == null ? "" : _errorMessage); + } + + /** + * From a JSON key:value string, return just the key + * @param inString string to parse + * @return just the key without the surrounding quotes, or null if not found + */ + private static String getKey(String inString) + { + if (inString == null || inString.equals("")) {return null;} + final int colonPos = inString.indexOf(':'); + if (colonPos <= 0) {return null;} + int startPos = 0; + char c; + while ((c = inString.charAt(startPos)) == '[' + || c == '{' || c == '\"') + { + startPos++; + } + int endPos = colonPos; + while ((c = inString.charAt(endPos-1)) == '\"') + { + endPos--; + } + return inString.substring(startPos, endPos); + } + + /** + * From a JSON key:value string, return just the value + * @param inString string to parse + * @return just the value without the surrounding quotes + */ + private static String getValue(String inString) + { + final int colonPos = inString.indexOf(':'); + if (colonPos <= 0 || colonPos >= inString.length()) {return null;} + int startPos = colonPos+1; + char c; + while ((c = inString.charAt(startPos)) == '\"') + { + startPos++; + } + int endPos = inString.length()-1; + while ((c = inString.charAt(endPos-1)) == '\"' + || c == '}' || c == ']') + { + endPos--; + } + return inString.substring(startPos, endPos); + } + + @Override + protected void loadSelected() + { + // Find the row(s) selected in the table and get the corresponding track + int numSelected = _trackTable.getSelectedRowCount(); + if (numSelected < 1) return; + int[] rowNums = _trackTable.getSelectedRows(); + + String[][] pointData = new String[numSelected][]; + String[] linkArray = new String[numSelected]; + + // Loop over each of the selected points + for (int i=0; i= 0 && rowNum < _trackListModel.getRowCount()) + { + SearchResult result = _trackListModel.getTrack(rowNum); + //String url = result.getDownloadLink(); + pointData[i][0] = result.getLatitude(); + pointData[i][1] = result.getLongitude(); + pointData[i][2] = "1"; // all points have a new segment + linkArray[i] = result.getDownloadLink(); + } + } + // Prepare the data for the app + final Field[] fields = {Field.LATITUDE, Field.LONGITUDE, Field.NEW_SEGMENT}; + _app.autoAppendNextFile(); + _app.informDataLoaded(fields, pointData, null, new SourceInfo("mapillary", SourceInfo.FILE_TYPE.JSON), + null, new MediaLinkInfo(linkArray)); + + // Close the dialog + _cancelled = true; + _dialog.dispose(); + } +} diff --git a/tim/prune/function/gpsies/GpsiesTrack.java b/tim/prune/function/search/SearchResult.java similarity index 68% rename from tim/prune/function/gpsies/GpsiesTrack.java rename to tim/prune/function/search/SearchResult.java index da1339e..2a05a8c 100644 --- a/tim/prune/function/gpsies/GpsiesTrack.java +++ b/tim/prune/function/search/SearchResult.java @@ -1,9 +1,9 @@ -package tim.prune.function.gpsies; +package tim.prune.function.search; /** - * Class to hold a single track from Gpsies.com + * Class to hold a search result from wikipedia / gpsies / panoramio etc */ -public class GpsiesTrack +public class SearchResult { /** Track name or title */ private String _trackName = null; @@ -15,6 +15,8 @@ public class GpsiesTrack private double _trackLength = 0.0; /** Download link */ private String _downloadLink = null; + /** Coordinates of point */ + private String _latitude = null, _longitude = null; /** @@ -96,4 +98,32 @@ public class GpsiesTrack { return _downloadLink; } + + /** + * @param inLatitude latitude + */ + public void setLatitude(String inLatitude) { + _latitude = inLatitude; + } + + /** + * @return latitude + */ + public String getLatitude() { + return _latitude; + } + + /** + * @param inLongitude longitude + */ + public void setLongitude(String inLongitude) { + _longitude = inLongitude; + } + + /** + * @return longitude + */ + public String getLongitude() { + return _longitude; + } } diff --git a/tim/prune/function/srtm/LookupSrtmFunction.java b/tim/prune/function/srtm/LookupSrtmFunction.java index 2ed1454..011dff6 100644 --- a/tim/prune/function/srtm/LookupSrtmFunction.java +++ b/tim/prune/function/srtm/LookupSrtmFunction.java @@ -228,13 +228,18 @@ public class LookupSrtmFunction extends GenericFunction implements Runnable + (fouralts[2]==VOID_VAL?1:0) + (fouralts[3]==VOID_VAL?1:0); // if (numVoids > 0) System.out.println(numVoids + " voids found"); double altitude = 0.0; - switch (numVoids) { + switch (numVoids) + { case 0: altitude = bilinearInterpolate(fouralts, x, y); break; case 1: altitude = bilinearInterpolate(fixVoid(fouralts), x, y); break; case 2: case 3: altitude = averageNonVoid(fouralts); break; default: altitude = VOID_VAL; } + // Special case for terrain tracks, don't interpolate voids yet + if (!_normalTrack && numVoids > 0) { + altitude = VOID_VAL; + } if (altitude != VOID_VAL) { point.setFieldValue(Field.ALTITUDE, ""+altitude, false); diff --git a/tim/prune/gui/IconManager.java b/tim/prune/gui/IconManager.java index eff4714..fd0a888 100644 --- a/tim/prune/gui/IconManager.java +++ b/tim/prune/gui/IconManager.java @@ -25,9 +25,11 @@ public abstract class IconManager /** Icon for autopan button on main map display when selected */ public static final String AUTOPAN_BUTTON_ON = "autopan_on.gif"; /** Icon for points connected icon on main map display */ - public static final String POINTS_CONNECTED_BUTTON = "points_connected.gif"; + public static final String POINTS_CONNECTED_BUTTON = "points_connected.png"; /** Icon for points disconnected icon on main map display */ - public static final String POINTS_DISCONNECTED_BUTTON = "points_disconnected.gif"; + public static final String POINTS_DISCONNECTED_BUTTON = "points_disconnected.png"; + /** Icon for points hidden, just lines icon on main map display */ + public static final String POINTS_HIDDEN_BUTTON = "points_hidden.png"; /** Icon for edit mode button on main map display when not selected */ public static final String EDIT_MODE_BUTTON = "drag_points_icon.gif"; /** Icon for edit mode button on main map display when selected */ @@ -70,6 +72,12 @@ public abstract class IconManager public static final String PLAY_AUDIO = "play_audio.gif"; /** Icon for stopping the current audio clip */ public static final String STOP_AUDIO = "stop_audio.gif"; + /** Icon for autoplaying a track */ + public static final String AUTOPLAY_PLAY = "play.png"; + /** Icon for pausing autoplay of a track */ + public static final String AUTOPLAY_PAUSE = "pause.png"; + /** Icon for rewinding the autoplay of a track */ + public static final String AUTOPLAY_REWIND = "rewind.png"; /** Icon for a given entry being valid (green tick) */ public static final String ENTRY_VALID = "entry_valid.gif"; diff --git a/tim/prune/gui/MenuManager.java b/tim/prune/gui/MenuManager.java index 741425d..f664f4b 100644 --- a/tim/prune/gui/MenuManager.java +++ b/tim/prune/gui/MenuManager.java @@ -30,7 +30,10 @@ import tim.prune.data.Selection; import tim.prune.data.Track; import tim.prune.data.TrackInfo; import tim.prune.function.ChooseSingleParameter; +import tim.prune.function.SearchOpenCachingDeFunction; import tim.prune.function.browser.UrlGenerator; +import tim.prune.function.browser.WebMapFunction; +import tim.prune.function.search.SearchMapillaryFunction; /** * Class to manage the menu bar and tool bar, @@ -60,6 +63,7 @@ public class MenuManager implements DataSubscriber private JMenuItem _cropTrackItem = null; private JMenuItem _compressItem = null; private JMenuItem _markRectangleItem = null; + private JMenuItem _markUphillLiftsItem = null; private JMenuItem _deleteMarkedPointsItem = null; private JMenuItem _deleteByDateItem = null; private JMenuItem _interpolateItem = null; @@ -89,13 +93,20 @@ public class MenuManager implements DataSubscriber private JMenuItem _uploadGpsiesItem = null; private JMenuItem _lookupSrtmItem = null; private JMenuItem _downloadSrtmItem = null; - private JMenuItem _lookupWikipediaItem = null; + private JMenuItem _nearbyWikipediaItem = null; + private JMenuItem _showPeakfinderItem = null; + private JMenuItem _showGeohackItem = null; + private JMenuItem _showPanoramioItem = null; + private JMenuItem _showOpencachingComItem = null; + private JMenuItem _searchOpencachingDeItem = null; + private JMenuItem _searchMapillaryItem = null; private JMenuItem _downloadOsmItem = null; private JMenuItem _getWeatherItem = null; private JMenuItem _distanceItem = null; private JMenuItem _fullRangeDetailsItem = null; private JMenuItem _estimateTimeItem = null; private JMenuItem _learnEstimationParams = null; + private JMenuItem _autoplayTrack = null; private JMenuItem _saveExifItem = null; private JMenuItem _photoPopupItem = null; private JMenuItem _selectNoPhotoItem = null; @@ -113,6 +124,7 @@ public class MenuManager implements DataSubscriber private JMenuItem _correlateAudiosItem = null; private JMenuItem _selectNoAudioItem = null; private JCheckBoxMenuItem _onlineCheckbox = null; + private JCheckBoxMenuItem _antialiasCheckbox = null; private JCheckBoxMenuItem _autosaveSettingsCheckbox = null; // ActionListeners for reuse by menu and toolbar @@ -257,14 +269,43 @@ public class MenuManager implements DataSubscriber // Upload to gpsies _uploadGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_UPLOAD_GPSIES, false); onlineMenu.add(_uploadGpsiesItem); + onlineMenu.addSeparator(); - _lookupWikipediaItem = makeMenuItem(FunctionLibrary.FUNCTION_LOOKUP_WIKIPEDIA, false); - onlineMenu.add(_lookupWikipediaItem); + // browser submenu + _browserMapMenu = new JMenu(I18nManager.getText("menu.view.browser")); + _browserMapMenu.setEnabled(false); + JMenuItem googleMapsItem = makeMenuItem(new WebMapFunction(_app, UrlGenerator.WebService.MAP_SOURCE_GOOGLE, "menu.view.browser.google")); + _browserMapMenu.add(googleMapsItem); + JMenuItem openMapsItem = makeMenuItem(new WebMapFunction(_app, UrlGenerator.WebService.MAP_SOURCE_OSM, "menu.view.browser.openstreetmap")); + _browserMapMenu.add(openMapsItem); + JMenuItem mapquestMapsItem = makeMenuItem(new WebMapFunction(_app, UrlGenerator.WebService.MAP_SOURCE_MAPQUEST, "menu.view.browser.mapquest")); + _browserMapMenu.add(mapquestMapsItem); + JMenuItem yahooMapsItem = makeMenuItem(new WebMapFunction(_app, UrlGenerator.WebService.MAP_SOURCE_YAHOO, "menu.view.browser.yahoo")); + _browserMapMenu.add(yahooMapsItem); + JMenuItem bingMapsItem = makeMenuItem(new WebMapFunction(_app, UrlGenerator.WebService.MAP_SOURCE_BING, "menu.view.browser.bing")); + _browserMapMenu.add(bingMapsItem); + onlineMenu.add(_browserMapMenu); + // wikipedia + _nearbyWikipediaItem = makeMenuItem(FunctionLibrary.FUNCTION_NEARBY_WIKIPEDIA, false); + onlineMenu.add(_nearbyWikipediaItem); JMenuItem searchWikipediaNamesItem = makeMenuItem(FunctionLibrary.FUNCTION_SEARCH_WIKIPEDIA); onlineMenu.add(searchWikipediaNamesItem); + _showPeakfinderItem = makeMenuItem(new WebMapFunction(_app, UrlGenerator.WebService.MAP_SOURCE_PEAKFINDER, "webservice.peakfinder"), false); + onlineMenu.add(_showPeakfinderItem); + _showGeohackItem = makeMenuItem(new WebMapFunction(_app, UrlGenerator.WebService.MAP_SOURCE_GEOHACK, "webservice.geohack"), false); + onlineMenu.add(_showGeohackItem); + _showPanoramioItem = makeMenuItem(new WebMapFunction(_app, UrlGenerator.WebService.MAP_SOURCE_PANORAMIO, "webservice.panoramio"), false); + onlineMenu.add(_showPanoramioItem); + _showOpencachingComItem = makeMenuItem(new WebMapFunction(_app, UrlGenerator.WebService.MAP_SOURCE_OPENCACHINGCOM, "webservice.opencachingcom"), false); + onlineMenu.add(_showOpencachingComItem); + + onlineMenu.addSeparator(); + _searchOpencachingDeItem = makeMenuItem(new SearchOpenCachingDeFunction(_app), false); + onlineMenu.add(_searchOpencachingDeItem); + _searchMapillaryItem = makeMenuItem(new SearchMapillaryFunction(_app), false); + onlineMenu.add(_searchMapillaryItem); _downloadOsmItem = makeMenuItem(FunctionLibrary.FUNCTION_DOWNLOAD_OSM, false); onlineMenu.add(_downloadOsmItem); - onlineMenu.addSeparator(); _getWeatherItem = makeMenuItem(FunctionLibrary.FUNCTION_GET_WEATHER_FORECAST, false); onlineMenu.add(_getWeatherItem); menubar.add(onlineMenu); @@ -304,13 +345,9 @@ public class MenuManager implements DataSubscriber }); _markRectangleItem.setEnabled(false); trackMenu.add(_markRectangleItem); - _deleteMarkedPointsItem = new JMenuItem(I18nManager.getText("menu.track.deletemarked")); - _deleteMarkedPointsItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - _app.finishCompressTrack(); - } - }); - _deleteMarkedPointsItem.setEnabled(false); + _markUphillLiftsItem = makeMenuItem(FunctionLibrary.FUNCTION_MARK_LIFTS, false); + trackMenu.add(_markUphillLiftsItem); + _deleteMarkedPointsItem = makeMenuItem(FunctionLibrary.FUNCTION_DELETE_MARKED_POINTS, false); trackMenu.add(_deleteMarkedPointsItem); _deleteByDateItem = makeMenuItem(FunctionLibrary.FUNCTION_DELETE_BY_DATE, false); trackMenu.add(_deleteByDateItem); @@ -483,45 +520,6 @@ public class MenuManager implements DataSubscriber // 3d _show3dItem = makeMenuItem(FunctionLibrary.FUNCTION_3D, false); viewMenu.add(_show3dItem); - // browser submenu - _browserMapMenu = new JMenu(I18nManager.getText("menu.view.browser")); - _browserMapMenu.setEnabled(false); - JMenuItem googleMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.google")); - googleMapsItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - _app.showExternalMap(UrlGenerator.MAP_SOURCE_GOOGLE); - } - }); - _browserMapMenu.add(googleMapsItem); - JMenuItem openMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.openstreetmap")); - openMapsItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - _app.showExternalMap(UrlGenerator.MAP_SOURCE_OSM); - } - }); - _browserMapMenu.add(openMapsItem); - JMenuItem mapquestMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.mapquest")); - mapquestMapsItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - _app.showExternalMap(UrlGenerator.MAP_SOURCE_MAPQUEST); - } - }); - _browserMapMenu.add(mapquestMapsItem); - JMenuItem yahooMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.yahoo")); - yahooMapsItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - _app.showExternalMap(UrlGenerator.MAP_SOURCE_YAHOO); - } - }); - _browserMapMenu.add(yahooMapsItem); - JMenuItem bingMapsItem = new JMenuItem(I18nManager.getText("menu.view.browser.bing")); - bingMapsItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - _app.showExternalMap(UrlGenerator.MAP_SOURCE_BING); - } - }); - _browserMapMenu.add(bingMapsItem); - viewMenu.add(_browserMapMenu); // Charts _chartItem = makeMenuItem(FunctionLibrary.FUNCTION_CHARTS, false); viewMenu.add(_chartItem); @@ -535,6 +533,10 @@ public class MenuManager implements DataSubscriber // estimate time _estimateTimeItem = makeMenuItem(FunctionLibrary.FUNCTION_ESTIMATE_TIME, false); viewMenu.add(_estimateTimeItem); + viewMenu.addSeparator(); + // autoplay + _autoplayTrack = makeMenuItem(FunctionLibrary.FUNCTION_AUTOPLAY_TRACK, false); + viewMenu.add(_autoplayTrack); menubar.add(viewMenu); // Add photo menu @@ -640,6 +642,16 @@ public class MenuManager implements DataSubscriber settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_COLOURS)); // Set line width used for drawing settingsMenu.add(makeMenuItem(new ChooseSingleParameter(_app, FunctionLibrary.FUNCTION_SET_LINE_WIDTH))); + // Use antialias or not + _antialiasCheckbox = new JCheckBoxMenuItem(I18nManager.getText("menu.settings.antialias"), false); + _antialiasCheckbox.setSelected(Config.getConfigBoolean(Config.KEY_ANTIALIAS)); + _antialiasCheckbox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Config.setConfigBoolean(Config.KEY_ANTIALIAS, _antialiasCheckbox.isSelected()); + UpdateMessageBroker.informSubscribers(MAPSERVER_CHANGED); + } + }); + settingsMenu.add(_antialiasCheckbox); // Set language settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_LANGUAGE)); // Set altitude tolerance @@ -860,6 +872,7 @@ public class MenuManager implements DataSubscriber _exportImageItem.setEnabled(hasMultiplePoints); _compressItem.setEnabled(hasData); _markRectangleItem.setEnabled(hasData); + _markUphillLiftsItem.setEnabled(hasData && _track.hasAltitudeData()); _deleteMarkedPointsItem.setEnabled(hasData && _track.hasMarkedPoints()); _rearrangeWaypointsItem.setEnabled(hasData && _track.hasTrackPoints() && _track.hasWaypoints()); _splitSegmentsItem.setEnabled(hasData && _track.hasTrackPoints() && _track.getNumPoints() > 3); @@ -870,10 +883,11 @@ public class MenuManager implements DataSubscriber _chartItem.setEnabled(hasData); _browserMapMenu.setEnabled(hasData); _distanceItem.setEnabled(hasData); + _autoplayTrack.setEnabled(hasData && _track.getNumPoints() > 3); _getGpsiesItem.setEnabled(hasData); _uploadGpsiesItem.setEnabled(hasData && _track.hasTrackPoints()); _lookupSrtmItem.setEnabled(hasData); - _lookupWikipediaItem.setEnabled(hasData); + _nearbyWikipediaItem.setEnabled(hasData); _downloadOsmItem.setEnabled(hasData); _getWeatherItem.setEnabled(hasData); _findWaypointItem.setEnabled(hasData && _track.hasWaypoints()); @@ -900,6 +914,12 @@ public class MenuManager implements DataSubscriber _selectEndItem.setEnabled(hasPoint); _selectEndButton.setEnabled(hasPoint); _duplicatePointItem.setEnabled(hasPoint); + _showPeakfinderItem.setEnabled(hasPoint); + _showGeohackItem.setEnabled(hasPoint); + _showPanoramioItem.setEnabled(hasPoint); + _showOpencachingComItem.setEnabled(hasPoint); + _searchOpencachingDeItem.setEnabled(hasPoint); + _searchMapillaryItem.setEnabled(hasPoint); // is it a waypoint? _selectSegmentItem.setEnabled(hasPoint && !currPoint.isWaypoint()); // are there any photos? diff --git a/tim/prune/gui/TripleStateCheckBox.java b/tim/prune/gui/TripleStateCheckBox.java new file mode 100644 index 0000000..6bd6001 --- /dev/null +++ b/tim/prune/gui/TripleStateCheckBox.java @@ -0,0 +1,78 @@ +package tim.prune.gui; + +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import javax.swing.ImageIcon; +import javax.swing.JCheckBox; + +/** + * Class to represent a checkbox with three states, through which it cycles + * Instead of calling isChecked, need to use getCurrentState which will + * return 0, 1 or 2 + */ +public class TripleStateCheckBox extends JCheckBox implements ItemListener +{ + /** Array of icons to be used */ + private ImageIcon[] _icons = new ImageIcon[3]; + /** Current state 0, 1 or 2 */ + private int _currState = 0; + + /** Inner class to proxy the listening events */ + private class ProxyListener implements ItemListener + { + /** Listener onto which some of the events will be passed */ + private ItemListener _listener = null; + /** Constructor */ + ProxyListener(ItemListener inListener) {_listener = inListener;} + /** React to events, and only pass on the selected ones */ + public void itemStateChanged(ItemEvent arg0) { + if (arg0.getStateChange() == ItemEvent.SELECTED) { + _listener.itemStateChanged(arg0); + } + } + } + + /** Constructor */ + public TripleStateCheckBox() + { + addItemListener(this); + } + + /** Set the current state */ + public void setCurrentState(int inState) + { + _currState = inState % 3; + setIcon(_icons[_currState]); + setSelected(false); + setSelectedIcon(_icons[(_currState+1)%3]); + } + + /** @return current state 0, 1 or 2 */ + public int getCurrentState() + { + return _currState; + } + + /** + * Set the icon to use for the given index + * @param inIndex index 0, 1 or 2 + * @param inIcon icon to use for that state + */ + public void setIcon(int inIndex, ImageIcon inIcon) + { + _icons[inIndex % 3] = inIcon; + } + + @Override + /** Intercept listener adding by putting a proxy inbetween */ + public void addItemListener(ItemListener inListener) { + super.addItemListener(new ProxyListener(inListener)); + } + + /** React to a selection event by advancing the state */ + public void itemStateChanged(ItemEvent inEvent) + { + setCurrentState(_currState + 1); + } +} diff --git a/tim/prune/gui/UndoManager.java b/tim/prune/gui/UndoManager.java index 48307c1..b9d9f32 100644 --- a/tim/prune/gui/UndoManager.java +++ b/tim/prune/gui/UndoManager.java @@ -4,7 +4,6 @@ import java.awt.FlowLayout; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.Stack; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JDialog; @@ -19,16 +18,17 @@ import javax.swing.event.ListSelectionListener; import tim.prune.App; import tim.prune.I18nManager; -import tim.prune.undo.UndoOperation; +import tim.prune.undo.UndoStack; /** * Class to manage the selection of actions to undo */ public class UndoManager { - private App _app; - private JDialog _dialog; - private JList _actionList; + private App _app = null; + private JFrame _parentFrame = null; + private JDialog _dialog = null; + private JList _actionList = null; /** @@ -39,18 +39,26 @@ public class UndoManager public UndoManager(App inApp, JFrame inFrame) { _app = inApp; - _dialog = new JDialog(inFrame, I18nManager.getText("dialog.undo.title"), true); - _dialog.setLocationRelativeTo(inFrame); + _parentFrame = inFrame; + } + + /** + * Show the dialog to select which actions to undo + */ + public void show() + { + _dialog = new JDialog(_parentFrame, I18nManager.getText("dialog.undo.title"), true); + _dialog.setLocationRelativeTo(_parentFrame); JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout(3, 3)); mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - Stack undoStack = inApp.getUndoStack(); + UndoStack undoStack = _app.getUndoStack(); mainPanel.add(new JLabel(I18nManager.getText("dialog.undo.pretext")), BorderLayout.NORTH); String[] undoActions = new String[undoStack.size()]; for (int i=0; i(undoActions); _actionList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); diff --git a/tim/prune/gui/images/add_photo_icon.png b/tim/prune/gui/images/add_photo_icon.png old mode 100755 new mode 100644 diff --git a/tim/prune/gui/images/add_textfile_icon.png b/tim/prune/gui/images/add_textfile_icon.png old mode 100755 new mode 100644 diff --git a/tim/prune/gui/images/pause.png b/tim/prune/gui/images/pause.png new file mode 100644 index 0000000..b9f48da Binary files /dev/null and b/tim/prune/gui/images/pause.png differ diff --git a/tim/prune/gui/images/play.png b/tim/prune/gui/images/play.png new file mode 100644 index 0000000..38abef7 Binary files /dev/null and b/tim/prune/gui/images/play.png differ diff --git a/tim/prune/gui/images/points_connected.gif b/tim/prune/gui/images/points_connected.gif deleted file mode 100644 index e6091c1..0000000 Binary files a/tim/prune/gui/images/points_connected.gif and /dev/null differ diff --git a/tim/prune/gui/images/points_connected.png b/tim/prune/gui/images/points_connected.png new file mode 100644 index 0000000..1891af0 Binary files /dev/null and b/tim/prune/gui/images/points_connected.png differ diff --git a/tim/prune/gui/images/points_disconnected.gif b/tim/prune/gui/images/points_disconnected.gif deleted file mode 100644 index 1015169..0000000 Binary files a/tim/prune/gui/images/points_disconnected.gif and /dev/null differ diff --git a/tim/prune/gui/images/points_disconnected.png b/tim/prune/gui/images/points_disconnected.png new file mode 100644 index 0000000..37f2c0f Binary files /dev/null and b/tim/prune/gui/images/points_disconnected.png differ diff --git a/tim/prune/gui/images/points_hidden.png b/tim/prune/gui/images/points_hidden.png new file mode 100644 index 0000000..452015c Binary files /dev/null and b/tim/prune/gui/images/points_hidden.png differ diff --git a/tim/prune/gui/images/rewind.png b/tim/prune/gui/images/rewind.png new file mode 100644 index 0000000..bc0fdbd Binary files /dev/null and b/tim/prune/gui/images/rewind.png differ diff --git a/tim/prune/gui/map/DiskTileCacher.java b/tim/prune/gui/map/DiskTileCacher.java index 459b140..63dc684 100644 --- a/tim/prune/gui/map/DiskTileCacher.java +++ b/tim/prune/gui/map/DiskTileCacher.java @@ -40,7 +40,6 @@ public class DiskTileCacher implements Runnable _url = inUrl; _file = inFile; _observer = inObserver; - new Thread(this).start(); } /** @@ -98,7 +97,7 @@ public class DiskTileCacher implements Runnable // Start a new thread to load the image if necessary if ((dir.exists() || dir.mkdirs()) && dir.canWrite()) { - new DiskTileCacher(inUrl, tileFile, inObserver); + new Thread(new DiskTileCacher(inUrl, tileFile, inObserver)).start(); return true; } return false; // couldn't write the file diff --git a/tim/prune/gui/map/MapCanvas.java b/tim/prune/gui/map/MapCanvas.java index 7a6bce8..4221520 100644 --- a/tim/prune/gui/map/MapCanvas.java +++ b/tim/prune/gui/map/MapCanvas.java @@ -11,6 +11,7 @@ import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; +import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -59,6 +60,7 @@ import tim.prune.function.compress.MarkPointsInRectangleFunction; import tim.prune.function.edit.FieldEdit; import tim.prune.function.edit.FieldEditList; import tim.prune.gui.IconManager; +import tim.prune.gui.TripleStateCheckBox; import tim.prune.gui.colour.PointColourer; import tim.prune.tips.TipManager; @@ -97,7 +99,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe /** Checkbox for autopan */ private JCheckBox _autopanCheckBox = null; /** Checkbox for connecting track points */ - private JCheckBox _connectCheckBox = null; + private TripleStateCheckBox _connectCheckBox = null; /** Checkbox for enable edit mode */ private JCheckBox _editmodeCheckBox = null; /** Right-click popup menu */ @@ -241,8 +243,11 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe _autopanCheckBox.setFocusable(false); // stop button from stealing keyboard focus _topPanel.add(_autopanCheckBox); // Add checkbox button for connecting points or not - _connectCheckBox = new JCheckBox(IconManager.getImageIcon(IconManager.POINTS_DISCONNECTED_BUTTON), true); - _connectCheckBox.setSelectedIcon(IconManager.getImageIcon(IconManager.POINTS_CONNECTED_BUTTON)); + _connectCheckBox = new TripleStateCheckBox(); + _connectCheckBox.setIcon(0, IconManager.getImageIcon(IconManager.POINTS_CONNECTED_BUTTON)); + _connectCheckBox.setIcon(1, IconManager.getImageIcon(IconManager.POINTS_DISCONNECTED_BUTTON)); + _connectCheckBox.setIcon(2, IconManager.getImageIcon(IconManager.POINTS_HIDDEN_BUTTON)); + _connectCheckBox.setCurrentState(0); _connectCheckBox.setOpaque(false); _connectCheckBox.setToolTipText(I18nManager.getText("menu.map.connect")); _connectCheckBox.addItemListener(itemListener); @@ -509,8 +514,10 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe _mapImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB); } - // Clear map Graphics g = _mapImage.getGraphics(); + // Set antialiasing according to config + ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, + Config.getConfigBoolean(Config.KEY_ANTIALIAS) ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); // Clear to background g.setColor(Config.getColourScheme().getColour(ColourScheme.IDX_BACKGROUND)); g.fillRect(0, 0, getWidth(), getHeight()); @@ -678,7 +685,9 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe // draw track points inG.setColor(pointColour); int prevX = -1, prevY = -1; - boolean connectPoints = _connectCheckBox.isSelected(); + final int connectState = _connectCheckBox.getCurrentState(); + final boolean drawLines = (connectState % 2) == 0; // 0 or 2 + final boolean drawPoints = (connectState <= 1); // 0 or 1 boolean prevPointVisible = false, currPointVisible = false; boolean anyWaypoints = false; boolean isWaypoint = false; @@ -696,7 +705,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe anyWaypoints = anyWaypoints || isWaypoint; if (!isWaypoint) { - if (currPointVisible || prevPointVisible) + if ((currPointVisible || prevPointVisible) && drawPoints) { // For track points, work out which colour to use if (_track.getPoint(i).getDeleteFlag()) { @@ -721,7 +730,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe } // Connect track points if either of them are visible - if (connectPoints && !(prevX == -1 && prevY == -1) + if (drawLines && !(prevX == -1 && prevY == -1) && !_track.getPoint(i).getSegmentStart()) { inG.drawLine(prevX, prevY, px, py); diff --git a/tim/prune/gui/map/MapSource.java b/tim/prune/gui/map/MapSource.java index 88ab85a..b7a08fc 100644 --- a/tim/prune/gui/map/MapSource.java +++ b/tim/prune/gui/map/MapSource.java @@ -84,13 +84,19 @@ public abstract class MapSource { if (inUrl == null || inUrl.equals("")) {return null;} String urlstr = inUrl; + boolean urlOk = false; + // check prefix - try { - new URL(urlstr.replace('[', 'w').replace(']', 'w')); - // There's a warning that this URL object isn't used, but it's enough to know the parse - // was successful without an exception being thrown. + try + { + urlOk = new URL(urlstr.replace('[', 'w').replace(']', 'w')) != null; } catch (MalformedURLException e) + { + urlOk = false; + } + + if (!urlOk) { // fail if protocol specified if (urlstr.indexOf("://") >= 0) {return null;} @@ -102,7 +108,8 @@ public abstract class MapSource urlstr = urlstr + "/"; } // Validate current url, return null if not ok - try { + try + { URL url = new URL(urlstr.replace('[', 'w').replace(']', 'w')); // url host must contain a dot if (url.getHost().indexOf('.') < 0) {return null;} diff --git a/tim/prune/gui/map/MapSourceLibrary.java b/tim/prune/gui/map/MapSourceLibrary.java index b82fd4e..e324af1 100644 --- a/tim/prune/gui/map/MapSourceLibrary.java +++ b/tim/prune/gui/map/MapSourceLibrary.java @@ -43,8 +43,8 @@ public abstract class MapSourceLibrary _sourceList.add(new OsmMapSource("Reitkarte", "http://topo[234].wanderreitkarte.de/topo/")); _sourceList.add(new MffMapSource("Mapsforfree", "http://maps-for-free.com/layer/relief/", "jpg", "http://maps-for-free.com/layer/water/", "gif", 11)); - _sourceList.add(new OsmMapSource("Hikebikemap", "http://toolserver.org/tiles/hikebike/", - "http://toolserver.org/~cmarqu/hill/", 18)); + _sourceList.add(new OsmMapSource("Hikebikemap", "http://[abc].tiles.wmflabs.org/hikebike/", + "http://[abc].tiles.wmflabs.org/hillshading/", 18)); _sourceList.add(new OsmMapSource("Openseamap", "http://tile.openstreetmap.org/", "http://tiles.openseamap.org/seamark/", 18)); } diff --git a/tim/prune/gui/profile/ProfileChart.java b/tim/prune/gui/profile/ProfileChart.java index 0dcabcb..b2d0d0d 100644 --- a/tim/prune/gui/profile/ProfileChart.java +++ b/tim/prune/gui/profile/ProfileChart.java @@ -4,10 +4,13 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; + import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; @@ -86,6 +89,9 @@ public class ProfileChart extends GenericDisplay implements MouseListener public void paint(Graphics g) { super.paint(g); + // Set antialiasing depending on Config + ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, + Config.getConfigBoolean(Config.KEY_ANTIALIAS) ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); ColourScheme colourScheme = Config.getColourScheme(); paintBackground(g, colourScheme); if (_track != null && _track.getNumPoints() > 0) diff --git a/tim/prune/jpeg/ExternalExifLibrary.java b/tim/prune/jpeg/ExternalExifLibrary.java index 0d94f03..4d06a27 100644 --- a/tim/prune/jpeg/ExternalExifLibrary.java +++ b/tim/prune/jpeg/ExternalExifLibrary.java @@ -2,12 +2,14 @@ package tim.prune.jpeg; import java.io.File; +import com.drew.imaging.ImageMetadataReader; import com.drew.lang.Rational; import com.drew.metadata.Directory; import com.drew.metadata.Metadata; -import com.drew.metadata.MetadataException; -import com.drew.metadata.exif.ExifDirectory; +import com.drew.metadata.exif.ExifSubIFDDirectory; +import com.drew.metadata.exif.ExifIFD0Directory; import com.drew.metadata.exif.ExifReader; +import com.drew.metadata.exif.ExifThumbnailDirectory; import com.drew.metadata.exif.GpsDirectory; /** @@ -31,57 +33,52 @@ public class ExternalExifLibrary implements ExifLibrary // Read exif data from picture try { - Metadata metadata = new Metadata(); - new ExifReader(inFile).extract(metadata); + Metadata metadata = ImageMetadataReader.readMetadata(inFile); if (metadata.containsDirectory(GpsDirectory.class)) { Directory gpsdir = metadata.getDirectory(GpsDirectory.class); - if (gpsdir.containsTag(GpsDirectory.TAG_GPS_LATITUDE) - && gpsdir.containsTag(GpsDirectory.TAG_GPS_LONGITUDE) - && gpsdir.containsTag(GpsDirectory.TAG_GPS_LATITUDE_REF) - && gpsdir.containsTag(GpsDirectory.TAG_GPS_LONGITUDE_REF)) + if (gpsdir.containsTag(GpsDirectory.TAG_LATITUDE) + && gpsdir.containsTag(GpsDirectory.TAG_LONGITUDE) + && gpsdir.containsTag(GpsDirectory.TAG_LATITUDE_REF) + && gpsdir.containsTag(GpsDirectory.TAG_LONGITUDE_REF)) { - data.setLatitudeRef(gpsdir.getString(GpsDirectory.TAG_GPS_LATITUDE_REF)); - Rational[] latRats = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LATITUDE); + data.setLatitudeRef(gpsdir.getString(GpsDirectory.TAG_LATITUDE_REF)); + Rational[] latRats = gpsdir.getRationalArray(GpsDirectory.TAG_LATITUDE); double seconds = ExifGateway.convertToPositiveValue(latRats[2].getNumerator(), latRats[2].getDenominator()); data.setLatitude(new double[] {latRats[0].doubleValue(), latRats[1].doubleValue(), seconds}); - data.setLongitudeRef(gpsdir.getString(GpsDirectory.TAG_GPS_LONGITUDE_REF)); - Rational[] lonRats = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE); + data.setLongitudeRef(gpsdir.getString(GpsDirectory.TAG_LONGITUDE_REF)); + Rational[] lonRats = gpsdir.getRationalArray(GpsDirectory.TAG_LONGITUDE); seconds = ExifGateway.convertToPositiveValue(lonRats[2].getNumerator(), lonRats[2].getDenominator()); data.setLongitude(new double[] {lonRats[0].doubleValue(), lonRats[1].doubleValue(), seconds}); } // Altitude (if present) - if (gpsdir.containsTag(GpsDirectory.TAG_GPS_ALTITUDE) && gpsdir.containsTag(GpsDirectory.TAG_GPS_ALTITUDE_REF)) + if (gpsdir.containsTag(GpsDirectory.TAG_ALTITUDE) && gpsdir.containsTag(GpsDirectory.TAG_ALTITUDE_REF)) { - data.setAltitude(gpsdir.getRational(GpsDirectory.TAG_GPS_ALTITUDE).intValue()); - byte altRef = (byte) gpsdir.getInt(GpsDirectory.TAG_GPS_ALTITUDE_REF); + data.setAltitude(gpsdir.getRational(GpsDirectory.TAG_ALTITUDE).intValue()); + byte altRef = (byte) gpsdir.getInt(GpsDirectory.TAG_ALTITUDE_REF); data.setAltitudeRef(altRef); } - try + // Timestamp and datestamp (if present) + final int TAG_DATESTAMP = 0x001d; + if (gpsdir.containsTag(GpsDirectory.TAG_TIME_STAMP) && gpsdir.containsTag(TAG_DATESTAMP)) { - // Timestamp and datestamp (if present) - final int TAG_GPS_DATESTAMP = 0x001d; - if (gpsdir.containsTag(GpsDirectory.TAG_GPS_TIME_STAMP) && gpsdir.containsTag(TAG_GPS_DATESTAMP)) - { - Rational[] times = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_TIME_STAMP); - data.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(), - times[2].intValue()}); - Rational[] dates = gpsdir.getRationalArray(TAG_GPS_DATESTAMP); - if (dates != null) { - data.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()}); - } + Rational[] times = gpsdir.getRationalArray(GpsDirectory.TAG_TIME_STAMP); + data.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(), + times[2].intValue()}); + Rational[] dates = gpsdir.getRationalArray(TAG_DATESTAMP); + if (dates != null) { + data.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()}); } } - catch (MetadataException me) {} // ignore, use other tags instead // Image bearing (if present) - if (gpsdir.containsTag(GpsDirectory.TAG_GPS_IMG_DIRECTION) && gpsdir.containsTag(GpsDirectory.TAG_GPS_IMG_DIRECTION_REF)) + if (gpsdir.containsTag(GpsDirectory.TAG_IMG_DIRECTION) && gpsdir.containsTag(GpsDirectory.TAG_IMG_DIRECTION_REF)) { - Rational bearing = gpsdir.getRational(GpsDirectory.TAG_GPS_IMG_DIRECTION); + Rational bearing = gpsdir.getRational(GpsDirectory.TAG_IMG_DIRECTION); if (bearing != null) { data.setBearing(bearing.doubleValue()); } @@ -89,30 +86,39 @@ public class ExternalExifLibrary implements ExifLibrary } // Tags from Exif directory - if (metadata.containsDirectory(ExifDirectory.class)) + if (metadata.containsDirectory(ExifSubIFDDirectory.class)) { - Directory exifdir = metadata.getDirectory(ExifDirectory.class); + Directory exifdir = metadata.getDirectory(ExifSubIFDDirectory.class); // Take time and date from exif tags - if (exifdir.containsTag(ExifDirectory.TAG_DATETIME_ORIGINAL)) { - data.setOriginalTimestamp(exifdir.getString(ExifDirectory.TAG_DATETIME_ORIGINAL)); + if (exifdir.containsTag(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL)) { + data.setOriginalTimestamp(exifdir.getString(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL)); } // Also take "digitized" timestamp - if (exifdir.containsTag(ExifDirectory.TAG_DATETIME_DIGITIZED)) { - data.setDigitizedTimestamp(exifdir.getString(ExifDirectory.TAG_DATETIME_DIGITIZED)); + if (exifdir.containsTag(ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED)) { + data.setDigitizedTimestamp(exifdir.getString(ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED)); } + } + if (metadata.containsDirectory(ExifIFD0Directory.class)) + { + Directory exifdir = metadata.getDirectory(ExifIFD0Directory.class); // Photo rotation code - if (exifdir.containsTag(ExifDirectory.TAG_ORIENTATION)) { - data.setOrientationCode(exifdir.getInt(ExifDirectory.TAG_ORIENTATION)); + if (exifdir.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) { + data.setOrientationCode(exifdir.getInt(ExifIFD0Directory.TAG_ORIENTATION)); // NOTE: this presumably takes the _last_ orientation value found, not the first. } + } + + if (metadata.containsDirectory(ExifThumbnailDirectory.class)) + { + ExifThumbnailDirectory exifdir = metadata.getDirectory(ExifThumbnailDirectory.class); - // Thumbnail - if (exifdir.containsTag(ExifDirectory.TAG_THUMBNAIL_DATA)) + // TODO: Check this thumbnail stuff + if (exifdir.hasThumbnailData()) { - // Make a copy of the byte data rather than keeping a reference to extracted array - byte[] tdata = exifdir.getByteArray(ExifDirectory.TAG_THUMBNAIL_DATA); + // Make a copy of the byte data + byte[] tdata = exifdir.getThumbnailData(); byte[] thumb = new byte[tdata.length]; System.arraycopy(tdata, 0, thumb, 0, tdata.length); data.setThumbnailImage(thumb); diff --git a/tim/prune/lang/prune-texts_af.properties b/tim/prune/lang/prune-texts_af.properties index 35ef53f..ef735f7 100644 --- a/tim/prune/lang/prune-texts_af.properties +++ b/tim/prune/lang/prune-texts_af.properties @@ -12,7 +12,7 @@ menu.track=Baan menu.track.undo=Herroep menu.track.clearundo=Maak herroep lys skoon menu.track.markrectangle=Merk punte -menu.track.deletemarked=Vee gemerkde punte uit +function.deletemarked=Vee gemerkde punte uit menu.range=Reeks menu.range.all=Selekteer alles menu.range.none=Selekteer niks diff --git a/tim/prune/lang/prune-texts_cz.properties b/tim/prune/lang/prune-texts_cz.properties index 2ac7ca6..54093a8 100644 --- a/tim/prune/lang/prune-texts_cz.properties +++ b/tim/prune/lang/prune-texts_cz.properties @@ -12,7 +12,7 @@ menu.track=Stopa menu.track.undo=Undo menu.track.clearundo=Vypr\u00e1zdnit pam\u011b\u0165 undo menu.track.markrectangle=Ozna\u010dit body v obd\u00e9ln\u00edku -menu.track.deletemarked=Smazat ozna\u010den\u00e9 body +function.deletemarked=Smazat ozna\u010den\u00e9 body function.rearrangewaypoints=P\u0159euspo\u0159\u00e1dat z\u00e1jmov\u00e9 body menu.range=Rozmez\u00ed menu.range.all=Vybrat v\u0161e diff --git a/tim/prune/lang/prune-texts_da.properties b/tim/prune/lang/prune-texts_da.properties index 8bcf9ca..e1d29ae 100644 --- a/tim/prune/lang/prune-texts_da.properties +++ b/tim/prune/lang/prune-texts_da.properties @@ -9,7 +9,7 @@ menu.file.save=Gem som tekst menu.file.exit=Afslut menu.track.undo=Fortryd menu.track.clearundo=Nulstil fortrydelsesliste -menu.track.deletemarked=Slet markerede punkter +function.deletemarked=Slet markerede punkter function.rearrangewaypoints=Omorganis\u00e9r waypoints dialog.rearrange.tonearest=Hvert waypoint til n\u00e6rmeste nabo menu.range=Omr\u00e5de diff --git a/tim/prune/lang/prune-texts_de.properties b/tim/prune/lang/prune-texts_de.properties index a85515e..4169c91 100644 --- a/tim/prune/lang/prune-texts_de.properties +++ b/tim/prune/lang/prune-texts_de.properties @@ -12,7 +12,7 @@ menu.track=Track menu.track.undo=R\u00fcckg\u00e4ngig menu.track.clearundo=Liste der letzten \u00c4nderungen l\u00f6schen menu.track.markrectangle=Punkte im Viereck markieren -menu.track.deletemarked=Markierte Punkte l\u00f6schen +function.deletemarked=Markierte Punkte l\u00f6schen function.rearrangewaypoints=Wegpunkte neu anordnen menu.range=Bereich menu.range.all=Alles markieren @@ -39,6 +39,7 @@ menu.view.browser.yahoo=Yahoo Maps menu.view.browser.bing=Bing Maps menu.settings=Einstellungen menu.settings.onlinemode=Karten aus dem Internet laden +menu.settings.antialias=Kantengl\u00e4ttung an menu.settings.autosave=Einstellungen automatisch speichern menu.help=Hilfe # Popup menu for map @@ -86,6 +87,7 @@ function.exportsvg=SVG exportieren function.exportimage=Bild exportieren function.editwaypointname=Namen des Punkts bearbeiten function.compress=Track komprimieren +function.marklifts=Bergbahnen markieren function.deleterange=Bereich l\u00f6schen function.croptrack=Track zuschneiden function.interpolate=Punkte interpolieren @@ -102,6 +104,7 @@ function.distances=Entfernungen function.fullrangedetails=Zus\u00e4tzliche Bereichdetails function.estimatetime=Zeit absch\u00e4tzen function.learnestimationparams=Zeitparameter erlernen +function.autoplay=Track abspielen function.setmapbg=Karte Hintergrund setzen function.setpaths=Programmpfade setzen function.selectsegment=Aktuellen Abschnitt markieren @@ -112,7 +115,9 @@ function.uploadgpsies=Track zu GPSies.com hochladen function.lookupsrtm=H\u00f6hendaten von SRTM nachschlagen function.downloadsrtm=SRTM Dateien herunterladen function.getwikipedia=Wikipediaartikel in der N\u00e4he nachschlagen -function.searchwikipedianames=Wikipedia mit Name durchsuchen +function.searchwikipedianames=Wikipedia nach Namen durchsuchen +function.searchopencachingde=OpenCaching.de durchsuchen +function.mapillary=Mapillary nach Fotos durchsuchen function.downloadosm=OSM-Daten f\u00fcr dieses Gebiet herunterladen function.duplicatepoint=Punkt verdoppeln function.setcolours=Farben einstellen @@ -377,9 +382,11 @@ dialog.gpsies.activity.motorbiking=Motorradfahren dialog.gpsies.activity.snowshoe=Schneeschuhwandern dialog.gpsies.activity.sailing=Segeln dialog.gpsies.activity.skating=Inline-Skating +dialog.mapillary.nonefound=Keine Fotos gefunden dialog.wikipedia.column.name=Artikelname dialog.wikipedia.column.distance=Entfernung dialog.wikipedia.nonefound=Keine Punkte gefunden +dialog.geocaching.nonefound=Keine Punkte gefunden dialog.correlate.notimestamps=Die Punkte enthalten keine Zeitangaben, deshalb k\u00f6nnen die Fotos nicht zugeordnet werden. dialog.correlate.nouncorrelatedphotos=Alle Fotos sind schon zugeordnet.\nWollen Sie trotzdem fortfahren? dialog.correlate.nouncorrelatedaudios=Alle Audiodateien sind schon zugeordnet.\nWollen Sie trotzdem fortfahren? @@ -588,6 +595,11 @@ dialog.deletebydate.column.keep=Behalten dialog.deletebydate.column.delete=L\u00f6schen dialog.setaltitudetolerance.text.metres=Mindestabweichung (Meter) f\u00fcr H\u00f6henunterschiede dialog.setaltitudetolerance.text.feet=Mindestabweichung (Feet) f\u00fcr H\u00f6henunterschiede +dialog.autoplay.duration=Abspieldauer (Sek) +dialog.autoplay.usetimestamps=Zeitstempeln verwenden +dialog.autoplay.rewind=Zum Anfang +dialog.autoplay.pause=Pause +dialog.autoplay.play=Abspielen # 3d window dialog.3d.title=GpsPrune-3D-Ansicht @@ -753,6 +765,7 @@ fieldname.duration=Zeitdauer fieldname.speed=Geschwindigkeit fieldname.verticalspeed=Vertikale Geschwindigkeit fieldname.description=Beschreibung +fieldname.mediafilename=Foto- / Audioname # Measurement units units.original=Original @@ -790,6 +803,11 @@ logic.or=oder url.googlemaps=maps.google.de wikipedia.lang=de openweathermap.lang=de +webservice.peakfinder=Peakfinder.org \u00f6ffnen +webservice.geohack=Geohack-Seite \u00f6ffnen +webservice.panoramio=Panoramio Karte \u00f6ffnen +webservice.opencachingcom=Opencaching.com \u00f6ffnen +webservice.opencachingcom.lang=de # Cardinals for 3d plots cardinal.n=N diff --git a/tim/prune/lang/prune-texts_de_CH.properties b/tim/prune/lang/prune-texts_de_CH.properties index a0bad3e..d4e0e1e 100644 --- a/tim/prune/lang/prune-texts_de_CH.properties +++ b/tim/prune/lang/prune-texts_de_CH.properties @@ -12,7 +12,7 @@ menu.track=Track menu.track.undo=Undo menu.track.clearundo=Undo-Liste l\u00f6sche menu.track.markrectangle=P\u00fcnkte inem Viereck markiere -menu.track.deletemarked=Markierte P\u00fcnkte l\u00f6sche +function.deletemarked=Markierte P\u00fcnkte l\u00f6sche function.rearrangewaypoints=Waypoints reorganisiere menu.range=Beriich menu.range.all=Alles selektiere @@ -38,6 +38,7 @@ menu.view.showsidebars=Seiteleischten aazeige menu.view.browser=Karte inem Browser menu.settings=Iistellige menu.settings.onlinemode=Karten uusem Internet lade +menu.settings.antialias=Kantegl\u00e4ttig aa menu.settings.autosave=Iistellige automatisch speichere menu.help=Hilfe # Popup menu for map @@ -85,6 +86,7 @@ function.exportsvg=SVG exportier\u00e4 function.exportimage=Bild exportier\u00e4 function.editwaypointname=Waypoint Namen editiere function.compress=Track komprimier\u00e4 +function.marklifts=Bergb\u00e4hnli markiere function.deleterange=Beriich l\u00f6sche function.croptrack=Track zuschniide function.deletebydate=P\u00fcnkte na Datum l\u00f6sche @@ -100,6 +102,7 @@ function.distances=Entf\u00e4rnige function.fullrangedetails=Zues\u00e4tzlichi Beriichinfos function.estimatetime=Ziit absch\u00e4tze function.learnestimationparams=Ziitparameter erlerne +function.autoplay=Track abschpiel\u00e4 function.setmapbg=Karte Hintegrund setz\u00e4 function.selectsegment=Aktuelli Segm\u00e4nt selektiere function.splitsegments=In Tracksegm\u00e4nte schniide @@ -109,7 +112,9 @@ function.uploadgpsies=Date zum Gpsies uufalad\u00e4 function.lookupsrtm=H\u00f6hendate vonem SRTM hole function.downloadsrtm=SRTM Files abalade function.getwikipedia=Im Wikipedia in dr N\u00f6chi naaluege -function.searchwikipedianames=Wikipedia mit Name durasueche +function.searchwikipedianames=Wikipedia nachem Namen durasueche +function.searchopencachingde=OpenCaching.de durasueche +function.mapillary=Mapillary nach F\u00f6telis durasueche function.downloadosm=OSM-Date f\u00fcr dere Gebiet abalad\u00e4 function.duplicatepoint=Punkt verdoppl\u00e4 function.correlatephotos=F\u00f6telis korrelier\u00e4 @@ -275,13 +280,13 @@ dialog.confirmcutandmove.text=Diese Daten enthalte Ziitst\u00e4mpel Informatione dialog.interpolate.parameter.text=Aazahl P\u00fcnkte zum inn\u00e4tue zw\u00fcschet den selektierten P\u00fcnkten dialog.interpolate.betweenwaypoints=Zw\u00fcschet d Waypoints interpoliere? dialog.undo.title=Undo Operation(e) -dialog.undo.pretext=Selektiere die Operatione die r\u00fcckg\u00e4ngig gmacht s\u00f6llti werde. +dialog.undo.pretext=Welli Operatione s\u00f6llet r\u00fcckg\u00e4ngig gmacht werde? dialog.undo.none.title=Undo n\u00f6d m\u00f6glich dialog.undo.none.text=Keini Operatione k\u00f6nne r\u00fcckg\u00e4ngig gmacht werde. dialog.clearundo.title=Undo-Liste l\u00f6sch\u00e4 dialog.clearundo.text=Sind Sie sicher, Sie wend die Undo-Liste l\u00f6sche?\nAlle Undo Infos werdet verlore gah! dialog.pointedit.title=Punkt editier\u00e4 -dialog.pointedit.intro=W\u00e4hlet Sie j\u00e4den F\u00e4ld uus, um den Wert z'seh und z'\u00e4ndere +dialog.pointedit.intro=W\u00e4hlet Sie j\u00e4des F\u00e4ld uus, um den Wert z'seh und z'\u00e4ndere dialog.pointedit.table.field=F\u00e4ld dialog.pointedit.nofield=Kei F\u00e4ld uusgew\u00e4hlt dialog.pointedit.table.value=Wert @@ -362,7 +367,7 @@ dialog.gpsies.nonefound=Kei Tracks gfunde dialog.gpsies.username=Gpsies Username dialog.gpsies.password=Gpsies Passwort dialog.gpsies.keepprivate=Track privat halte -dialog.gpsies.confirmopenpage=Websiite f\u00fcrn uufageladenen Track \u00f6ffne? +dialog.gpsies.confirmopenpage=Websiite f\u00fcrn uufagladenen Track \u00f6ffne? dialog.gpsies.activities=Aktivit\u00e4ten dialog.gpsies.activity.trekking=Wandere dialog.gpsies.activity.walking=Z'Fuess gah @@ -372,9 +377,11 @@ dialog.gpsies.activity.motorbiking=Motorrad dialog.gpsies.activity.snowshoe=Schneeschuh dialog.gpsies.activity.sailing=Segle dialog.gpsies.activity.skating=Inline-Skate +dialog.mapillary.nonefound=Kei F\u00f6telis gfunde dialog.wikipedia.column.name=Artikelname dialog.wikipedia.column.distance=Entf\u00e4rnig dialog.wikipedia.nonefound=Kei Wiki-Iitr\u00e4ge gfunde +dialog.geocaching.nonefound=Kei Cäches gfunde dialog.correlate.notimestamps=Es h\u00e4t kei Ziitst\u00e4mpel inem Track inn\u00e4, so s'isch n\u00f6d m\u00f6glech die F\u00f6telis zu korrelier\u00e4. dialog.correlate.nouncorrelatedphotos=Alle F\u00f6telis sin scho korreliert.\nWend Sie trotzdem fortsetz\u00e4? dialog.correlate.nouncorrelatedaudios=Alle Audios sin scho korreliert.\nWend Sie trotzdem fortsetz\u00e4? @@ -433,7 +440,7 @@ dialog.deletemarked.nonefound=Kei P\u00fcnkte h\u00e4tte gel\u00f6scht werde k\u dialog.pastecoordinates.desc=G\u00e4bet Sie hier die Koordinaten inn\u00e4 dialog.pastecoordinates.coords=Koordinate dialog.pastecoordinates.nothingfound=Pr\u00fcefet Sie die Koordinate und versuechet nomal -dialog.help.help=Bitte lueg na\n http://gpsprune.activityworkshop.net/\nf\u00fcr wiitere Information und Benutzeraaleitige. +dialog.help.help=Lueget Sie na\n http://gpsprune.activityworkshop.net/\nf\u00fcr wiitere Information und Benutzeraaleitige. dialog.about.version=Version dialog.about.build=Build dialog.about.summarytext1=GpsPrune isch s Programm f\u00fcrs Lade, Darstelle und Editiere vo Date von GPS Ger\u00e4te. @@ -477,7 +484,7 @@ dialog.keys.intro=Aastatt d'Muus k\u00f6nnet Sie diese Tastekombinationen nutze dialog.keys.keylist=
Pfiil TasteKarte verschiebe
Strg + links, r\u00e4chts PfiilVorherigi oder n\u00f6chsti Punkt markiere
Strg + uuf, aba PfiilIi- oder Uusezoome
Strg + Bild uuf, abVorherigi oder n\u00f6chsti Segm\u00e4nt markiere
Strg + Pos1, \u00c4ndeErschti oder letschti Punkt markiere
EntfAktuelli Punkt l\u00f6sche
dialog.keys.normalmodifier=Strg dialog.keys.macmodifier=Kommando -dialog.saveconfig.desc=Die folgendi Iinstellige k\u00f6nne gspeicheret werde : +dialog.saveconfig.desc=Die folgendi Iistellige k\u00f6nne gspeicheret werde : dialog.saveconfig.prune.trackdirectory=Trackverzeichnis dialog.saveconfig.prune.photodirectory=F\u00f6teliverzeichnis dialog.saveconfig.prune.languagecode=Sprochecode (DE_ch) @@ -526,7 +533,7 @@ dialog.colourer.type.bygradient=Nach Gef\u00e4lle dialog.colourer.type.bydate=Nach Datum dialog.colourer.start=Aafangsfarb dialog.colourer.end=Zielfarb -dialog.colourer.maxcolours=Maximal Anzahl Farbe +dialog.colourer.maxcolours=Maximal Aazahl Farbe dialog.setlanguage.firstintro=Sie k\u00f6nnet entweder eini vo den iigebouti Sproche

oder ne Text-Datei uusw\u00e4hle. dialog.setlanguage.secondintro=Sie m\u00fcnt Ihri Iistellige speichere und dann

GpsPrune wieder neustarte um die Sproch z'\u00e4ndere. dialog.setlanguage.language=Sproch @@ -582,7 +589,12 @@ dialog.deletebydate.nodate=Ohni Ziitaagab dialog.deletebydate.column.keep=Behalte dialog.deletebydate.column.delete=L\u00f6sche dialog.setaltitudetolerance.text.metres=Mindeschtabweichig (Meter) f\u00fcr H\u00f6chiunterschied -dialog.setaltitudetolerance.text.feet=Mindeschtabweichig (Feet) f\u00fcr H\u00f6chinunterschied +dialog.setaltitudetolerance.text.feet=Mindeschtabweichig (Feet) f\u00fcr H\u00f6chiunterschied +dialog.autoplay.duration=Abspieldauer (Sek) +dialog.autoplay.usetimestamps=Ziitst\u00e4mple verw\u00e4nde +dialog.autoplay.rewind=Zum Aafang +dialog.autoplay.pause=Pause +dialog.autoplay.play=Abschpiele # 3d window dialog.3d.title=GpsPrune Dr\u00fc\u00fc-d Aasicht @@ -693,7 +705,7 @@ details.trackdetails=Details vom Track details.notrack=Kei Track glade worde details.track.points=P\u00fcnkte details.track.file=Datei -details.track.numfiles=Anzahl Dateie +details.track.numfiles=Aazahl Dateie details.pointdetails=Details vonem Punkt details.index.selected=Index details.index.of=vo @@ -748,6 +760,7 @@ fieldname.duration=Ziitl\u00e4ngi fieldname.speed=Gschwindikeit fieldname.verticalspeed=Uf/Ab Gschwindikeit fieldname.description=Bschriibig +fieldname.mediafilename=F\u00f6teli- / Audioname # Measurement units units.original=Original @@ -785,6 +798,11 @@ logic.or=oder url.googlemaps=maps.google.ch wikipedia.lang=als openweathermap.lang=de +webservice.peakfinder=Peakfinder.org \u00f6ffne +webservice.geohack=Geohack-Siite \u00f6ffne +webservice.panoramio=Panoramio Karte \u00f6ffne +webservice.opencachingcom=Opencaching.com \u00f6ffne +webservice.opencachingcom.lang=de # Cardinals for 3d plots cardinal.n=N diff --git a/tim/prune/lang/prune-texts_en.properties b/tim/prune/lang/prune-texts_en.properties index 447ce4d..785a62e 100644 --- a/tim/prune/lang/prune-texts_en.properties +++ b/tim/prune/lang/prune-texts_en.properties @@ -12,7 +12,7 @@ menu.track=Track menu.track.undo=Undo menu.track.clearundo=Clear undo list menu.track.markrectangle=Mark points in rectangle -menu.track.deletemarked=Delete marked points +function.deletemarked=Delete marked points menu.range=Range menu.range.all=Select all menu.range.none=Select none @@ -38,6 +38,7 @@ menu.view.browser.yahoo=Yahoo maps menu.view.browser.bing=Bing maps menu.settings=Settings menu.settings.onlinemode=Load maps from internet +menu.settings.antialias=Use antialiasing menu.settings.autosave=Autosave settings on exit menu.help=Help # Popup menu for map @@ -85,6 +86,7 @@ function.exportsvg=Export SVG function.exportimage=Export image function.editwaypointname=Edit waypoint name function.compress=Compress track +function.marklifts=Mark uphill lifts function.deleterange=Delete range function.croptrack=Crop track function.interpolate=Interpolate points @@ -102,6 +104,7 @@ function.distances=Distances function.fullrangedetails=Full range details function.estimatetime=Estimate time function.learnestimationparams=Learn time estimation parameters +function.autoplay=Autoplay track function.selectsegment=Select current segment function.splitsegments=Split track into segments function.sewsegments=Sew track segments together @@ -111,6 +114,8 @@ function.lookupsrtm=Get altitudes from SRTM function.downloadsrtm=Download SRTM tiles function.getwikipedia=Get nearby Wikipedia articles function.searchwikipedianames=Search Wikipedia by name +function.searchopencachingde=Search OpenCaching.de +function.mapillary=Search for photos in Mapillary function.downloadosm=Download OSM data for area function.duplicatepoint=Duplicate point function.connecttopoint=Connect to point @@ -377,9 +382,11 @@ dialog.gpsies.activity.motorbiking=Motorbiking dialog.gpsies.activity.snowshoe=Snowshoeing dialog.gpsies.activity.sailing=Sailing dialog.gpsies.activity.skating=Skating +dialog.mapillary.nonefound=No photos found dialog.wikipedia.column.name=Article name dialog.wikipedia.column.distance=Distance dialog.wikipedia.nonefound=No wikipedia entries found +dialog.geocaching.nonefound=No geocaches found dialog.correlate.notimestamps=There are no timestamps in the data points, so there is nothing to correlate with the photos. dialog.correlate.nouncorrelatedphotos=There are no uncorrelated photos.\nAre you sure you want to continue? dialog.correlate.nouncorrelatedaudios=There are no uncorrelated audios.\nAre you sure you want to continue? @@ -438,12 +445,12 @@ dialog.deletemarked.nonefound=No data points could be removed dialog.pastecoordinates.desc=Enter or paste the coordinates here dialog.pastecoordinates.coords=Coordinates dialog.pastecoordinates.nothingfound=Please check the coordinates and try again -dialog.help.help=Please see\n http://gpsprune.activityworkshop.net/\nfor more information and tips,\nincluding a new PDF user guide you can buy. +dialog.help.help=Please see\n http://gpsprune.activityworkshop.net/\nfor more information and tips,\nincluding a PDF user guide you can buy. dialog.about.version=Version dialog.about.build=Build dialog.about.summarytext1=GpsPrune is a program for loading, displaying and editing data from GPS receivers. dialog.about.summarytext2=It is released under the Gnu GPL for free, open, worldwide use and enhancement.
Copying, redistribution and modification are permitted and encouraged
according to the conditions in the included license.txt file. -dialog.about.summarytext3=Please see http://activityworkshop.net/ for more information and tips, including
a new PDF user guide you can buy. +dialog.about.summarytext3=Please see http://activityworkshop.net/ for more information and tips, including
a PDF user guide you can buy. dialog.about.languages=Available languages dialog.about.translatedby=English text by activityworkshop. dialog.about.systeminfo=System info @@ -588,6 +595,11 @@ dialog.deletebydate.column.keep=Keep dialog.deletebydate.column.delete=Delete dialog.setaltitudetolerance.text.metres=Limit (in metres) below which small climbs and descents will be ignored dialog.setaltitudetolerance.text.feet=Limit (in feet) below which small climbs and descents will be ignored +dialog.autoplay.duration=Duration (secs) +dialog.autoplay.usetimestamps=Use point timestamps +dialog.autoplay.rewind=Back to beginning +dialog.autoplay.pause=Pause +dialog.autoplay.play=Play # 3d window dialog.3d.title=GpsPrune Three-d view @@ -753,6 +765,7 @@ fieldname.duration=Duration fieldname.speed=Speed fieldname.verticalspeed=Vertical speed fieldname.description=Description +fieldname.mediafilename=Filename # Measurement units units.original=Original @@ -796,6 +809,11 @@ logic.or=or url.googlemaps=maps.google.co.uk wikipedia.lang=en openweathermap.lang=en +webservice.peakfinder=Open Peakfinder.org +webservice.geohack=Open Geohack page +webservice.panoramio=Open Panoramio map +webservice.opencachingcom=Open Opencaching.com +webservice.opencachingcom.lang=en # 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 5b920b8..a8be199 100644 --- a/tim/prune/lang/prune-texts_es.properties +++ b/tim/prune/lang/prune-texts_es.properties @@ -12,7 +12,7 @@ menu.track=Track menu.track.undo=Deshacer menu.track.clearundo=Despejar la lista de deshacer menu.track.markrectangle=Marcar puntos dentro de un rect\u00e1ngulo -menu.track.deletemarked=Eliminar puntos marcados +function.deletemarked=Eliminar puntos marcados menu.range=Rango menu.range.all=Seleccionar todo menu.range.none=No seleccionar nada @@ -38,6 +38,7 @@ menu.view.browser.yahoo=Mapas Yahoo menu.view.browser.bing=Mapas Bing menu.settings=Preferencias menu.settings.onlinemode=Cargar mapas de Internet +menu.settings.antialias=Usar antialiasing menu.settings.autosave=Auto Guardar menu.help=Ayuda @@ -114,7 +115,8 @@ function.lookupsrtm=Obtener altitudes de SRTM function.downloadsrtm=Descargar datos de SRTM function.getwikipedia=Obtener art\u00edculos de Wikipedia cercanos function.searchwikipedianames=Buscar en Wikipedia por nombre -function.searchopencachingde=Buscar OpenCaching.de +function.searchopencachingde=Buscar en OpenCaching.de +function.mapillary=Buscar en Mapillary function.downloadosm=Descargar datos OSM del \u00e1rea function.duplicatepoint=Duplicar punto function.setcolours=Establecer color @@ -377,6 +379,7 @@ dialog.gpsies.activity.motorbiking=En moto dialog.gpsies.activity.snowshoe=Raquetas de nieve dialog.gpsies.activity.sailing=Vela dialog.gpsies.activity.skating=Patinaje +dialog.mapillary.nonefound=No se encontraron fotos dialog.wikipedia.column.name=Nombre del art\u00edculo dialog.wikipedia.column.distance=Distancia dialog.wikipedia.nonefound=No se encontraron puntos @@ -583,13 +586,13 @@ dialog.weather.humidity=Humedad dialog.deletebydate.nodate=Sin marcas de tiempo dialog.deletebydate.column.keep=Mantener dialog.deletebydate.column.delete=Eliminar +dialog.autoplay.duration=Duraci\u00f3n (seg) ## 3d window dialog.3d.title=GpsPrune vista 3-D dialog.3d.altitudefactor=Factor de exageraci\u00f3n de altura ## Confirm messages -# These are displayed as confirmation in the status bar confirm.loadfile=Dato cargado de confirm.save.ok1=Guardado correctamente confirm.save.ok2=puntos al archivo @@ -678,7 +681,6 @@ filetype.png=Archivos PNG filetype.audio=Archivos MP3, OGG, WAV ## Display components -# These are all for the side panels showing point/range details display.nodata=Ning\u00fan dato cargado display.noaltitudes=Los datos del track no incluyen altitudes display.notimestamps=Los datos de recorrido no incluyen marcas de tiempo @@ -743,6 +745,7 @@ fieldname.duration=Duraci\u00f3n fieldname.speed=Velocidad fieldname.verticalspeed=Velocidad vertical fieldname.description=Descripci\u00f3n +fieldname.mediafilename=Archivo ## Measurement units units.original=Original @@ -786,6 +789,10 @@ logic.or=o url.googlemaps=maps.google.es wikipedia.lang=es openweathermap.lang=sp +webservice.peakfinder=Abrir Peakfinder.org +webservice.geohack=Abrir Geohack +webservice.panoramio=Abrir mapa Panoramio +webservice.opencachingcom=Abrir Opencaching.com webservice.opencachingcom.lang=es ## Cardinals for 3d plots @@ -795,7 +802,6 @@ cardinal.e=E cardinal.w=O ## Undo operations -# These will be displayed in the undo list after you've performed the operation, to tell you what you did undo.load=cargar datos undo.loadphotos=cargar fotos undo.loadaudios=cargar archivos de audio diff --git a/tim/prune/lang/prune-texts_fa.properties b/tim/prune/lang/prune-texts_fa.properties index a70545b..a7637b2 100644 --- a/tim/prune/lang/prune-texts_fa.properties +++ b/tim/prune/lang/prune-texts_fa.properties @@ -9,7 +9,7 @@ menu.file.exit=\u062e\u0631\u0648\u062c menu.track=\u0645\u0633\u064a\u0631 menu.track.undo=\u0628\u0627\u0637\u0644 \u06a9\u0631\u062f\u0646 \u06a9\u0627\u0631 \u0642\u0628\u0644\u064a menu.track.clearundo=\u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u0644\u064a\u0633\u062a \u06a9\u0627\u0631\u0647\u0627\u06cc \u0627\u0646\u062c\u0627\u0645 \u0634\u062f\u0647 -menu.track.deletemarked=\u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u0646\u0642\u0627\u0637 \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647 +function.deletemarked=\u067e\u0627\u06a9 \u06a9\u0631\u062f\u0646 \u0646\u0642\u0627\u0637 \u0627\u0646\u062a\u062e\u0627\u0628 \u0634\u062f\u0647 function.rearrangewaypoints=\u0628\u0627\u0632 \u0686\u064a\u0646\u06cc \u0646\u0642\u0627\u0637 \u0645\u0633\u064a\u0631 dialog.rearrange.tostart=\u0647\u0645\u0647 \u0646\u0642\u0627\u0637 \u0628\u0647 \u0627\u0628\u062a\u062f\u0627\u06cc \u0645\u0633\u064a\u0631 dialog.rearrange.toend=\u0647\u0645\u0647 \u0646\u0642\u0627\u0637 \u0628\u0647 \u0627\u0646\u062a\u0647\u0627\u06cc \u0645\u0633\u064a\u0631 diff --git a/tim/prune/lang/prune-texts_fr.properties b/tim/prune/lang/prune-texts_fr.properties index ad05294..5714803 100644 --- a/tim/prune/lang/prune-texts_fr.properties +++ b/tim/prune/lang/prune-texts_fr.properties @@ -12,7 +12,7 @@ menu.track=Trace menu.track.undo=Annuler menu.track.clearundo=Purger la liste d'annulation menu.track.markrectangle=S\u00e9lectionner les points dans un rectangle -menu.track.deletemarked=Supprimer les points marqu\u00e9s +function.deletemarked=Supprimer les points marqu\u00e9s function.rearrangewaypoints=R\u00e9arranger les points du navigation menu.range=\u00c9tendue menu.range.all=Tout s\u00e9lectionner @@ -39,6 +39,7 @@ menu.view.browser.yahoo=Cartes Yahoo menu.view.browser.bing=Cartes Bing menu.settings=Pr\u00e9f\u00e9rences menu.settings.onlinemode=Charger cartes depuis internet +menu.settings.antialias=Anticr\u00e9nelage menu.settings.autosave=Sauver automatiquement en quittant menu.help=Aide # Popup menu for map @@ -114,6 +115,8 @@ function.lookupsrtm=R\u00e9cup\u00e9rer les altitudes depuis SRTM function.downloadsrtm=T\u00e9l\u00e9charger les donn\u00e9es SRTM function.getwikipedia=Obtenir les articles de Wikip\u00e9dia \u00e0 proximit\u00e9 function.searchwikipedianames=Rechercher dans Wikip\u00e9dia par nom +function.searchopencachingde=Rechercher dans OpenCaching.de +function.mapillary=Rechercher dans Mapillary function.downloadosm=T\u00e9l\u00e9charger les donn\u00e9es OSM de la zone function.duplicatepoint=Dupliquer le point function.setcolours=Choisir les couleurs @@ -338,6 +341,8 @@ dialog.estimatetime.results.actualtime=Dur\u00e9e en fait dialog.estimatetime.error.noaltitudes=L'\u00e9tendue s\u00e9lectionn\u00e9e de contient pas d'altitudes dialog.learnestimationparams.averageerror=Erreur en moyenne dialog.learnestimationparams.combinedresults=R\u00e9sultats combin\u00e9es +dialog.learnestimationparams.weight.current=actuel +dialog.learnestimationparams.weight.calculated=calcul\u00e9 dialog.setmapbg.intro=S\u00e9lectionnez une source de cartes, ou ajoutez-en une nouvelle dialog.addmapsource.title=Ajouter une nouvelle source de cartes dialog.addmapsource.sourcename=Nom de la source @@ -507,6 +512,14 @@ dialog.colourchooser.green=Vert dialog.colourchooser.blue=Bleu dialog.colourer.type=Crit\u00e8re de coloriste dialog.colourer.type.none=Aucun +dialog.colourer.type.byfile=Selon fichier +dialog.colourer.type.bysegment=Selon segment +dialog.colourer.type.byaltitude=Selon altitude +dialog.colourer.type.byspeed=Selon vitesse +dialog.colourer.type.byvertspeed=Selon vitesse verticale +dialog.colourer.type.bygradient=Selon la pente +dialog.colourer.type.bydate=Selon la date +dialog.colourer.maxcolours=Nombre de couleurs maximum dialog.setlanguage.firstintro=Vous pouvez s\u00e9lectionner l'une des langues disponibles,

ou bien un fichier de langue \u00e0 utiliser. dialog.setlanguage.secondintro=Vous devez sauvegarder vos param\u00e8tres puis

red\u00e9marrer GpsPrune pour changer de langue. dialog.setlanguage.language=Langue @@ -559,6 +572,9 @@ dialog.weather.creditnotice=Ces donn\u00e9es sont fournies par openweathermap.or dialog.deletebydate.nodate=Sans horodatage dialog.deletebydate.column.keep=Garder dialog.deletebydate.column.delete=Supprimer +dialog.autoplay.duration=Dur\u00e9e (sec) +dialog.autoplay.pause=Pause +dialog.autoplay.play=Jouer # 3d window dialog.3d.title=Vue 3D de GpsPrune @@ -722,6 +738,7 @@ fieldname.duration=Dur\u00e9e fieldname.speed=Vitesse fieldname.verticalspeed=Vitesse verticale fieldname.description=Description +fieldname.mediafilename=Nom de fichier # Measurement units units.original=Original @@ -765,6 +782,10 @@ logic.or=ou url.googlemaps=maps.google.fr wikipedia.lang=fr openweathermap.lang=fr +webservice.peakfinder=Ouvrir Peakfinder.org +webservice.geohack=Ouvrir la page Geohack +webservice.panoramio=Ouvrir la carte Panoramio +webservice.opencachingcom=Ouvrir Opencaching.com webservice.opencachingcom.lang=fr # Cardinals for 3d plots diff --git a/tim/prune/lang/prune-texts_hu.properties b/tim/prune/lang/prune-texts_hu.properties index 74ba9e4..c083f63 100644 --- a/tim/prune/lang/prune-texts_hu.properties +++ b/tim/prune/lang/prune-texts_hu.properties @@ -12,7 +12,7 @@ menu.track=Nyomvonal menu.track.undo=Visszavon\u00e1s menu.track.clearundo=Visszavon\u00e1si lista t\u00f6rl\u00e9se menu.track.markrectangle=N\u00e9gyzeten bel\u00fcli pontok megjel\u00f6l\u00e9se -menu.track.deletemarked=Jel\u00f6lt pontok t\u00f6rl\u00e9se +function.deletemarked=Jel\u00f6lt pontok t\u00f6rl\u00e9se menu.range=Tartom\u00e1ny menu.range.all=Mindet kijel\u00f6l menu.range.none=Kijel\u00f6l\u00e9s megsz\u00fcntet\u00e9se @@ -38,6 +38,7 @@ menu.view.browser.yahoo=Yahoo! Maps menu.view.browser.bing=Bing Maps menu.settings=Be\u00e1ll\u00edt\u00e1sok menu.settings.onlinemode=T\u00e9rk\u00e9pek bet\u00f6lt\u00e9se internetr\u0151l +menu.settings.antialias=\u00c9lsim\u00edt\u00e1s haszn\u00e1lata menu.settings.autosave=Be\u00e1ll\u00edt\u00e1sok automatikus ment\u00e9se kil\u00e9p\u00e9skor menu.help=S\u00fag\u00f3 @@ -86,6 +87,7 @@ function.exportsvg=Export\u00e1l\u00e1s SVG-be function.exportimage=Export\u00e1l\u00e1s k\u00e9pbe function.editwaypointname=\u00datpont nev\u00e9nek szerkeszt\u00e9se function.compress=Nyomvonal t\u00f6m\u00f6r\u00edt\u00e9se +function.marklifts=S\u00edliftek megjel\u00f6l\u00e9se function.deleterange=Tartom\u00e1ny t\u00f6rl\u00e9se function.croptrack=Nyomvonal k\u00f6rbev\u00e1g\u00e1sa function.interpolate=Pontok interpol\u00e1l\u00e1sa @@ -103,6 +105,7 @@ function.distances=T\u00e1vols\u00e1gok function.fullrangedetails=Teljes tartom\u00e1ny r\u00e9szletei function.estimatetime=Becs\u00fclt id\u0151 function.learnestimationparams=Id\u0151becsl\u00e9s tanul\u00e1s\u00e1nak param\u00e9terei +function.autoplay=Nyomvonal lej\u00e1tsz\u00e1sa function.setmapbg=H\u00e1tt\u00e9rk\u00e9p be\u00e1ll\u00edt\u00e1sa function.setpaths=Program\u00fatvonalak be\u00e1ll\u00edt\u00e1sa function.selectsegment=Aktu\u00e1lis szakasz kiv\u00e1laszt\u00e1sa @@ -115,6 +118,7 @@ function.downloadsrtm=SRTM csemp\u00e9k let\u00f6lt\u00e9se function.getwikipedia=K\u00f6zeli Wikip\u00e9dia sz\u00f3cikkek let\u00f6lt\u00e9se function.searchwikipedianames=Keres\u00e9s a Wikip\u00e9di\u00e1ban n\u00e9v szerint function.searchopencachingde=Keres\u00e9s az OpenCaching.de-n +function.mapillary=F\u00e9nyk\u00e9pek keres\u00e9se Mapillary-n function.downloadosm=OSM adatok let\u00f6lt\u00e9se a ter\u00fcletr\u0151l function.duplicatepoint=Pont kett\u0151z\u00e9se function.setcolours=Sz\u00ednek be\u00e1ll\u00edt\u00e1sa @@ -379,6 +383,7 @@ dialog.gpsies.activity.motorbiking=Motorker\u00e9kp\u00e1roz\u00e1s dialog.gpsies.activity.snowshoe=H\u00f3talpas s\u00e9ta dialog.gpsies.activity.sailing=Vitorl\u00e1z\u00e1s dialog.gpsies.activity.skating=Korcsoly\u00e1z\u00e1s +dialog.mapillary.nonefound=Nem tal\u00e1lhat\u00f3k f\u00e9nyk\u00e9pek dialog.wikipedia.column.name=Sz\u00f3cikk neve dialog.wikipedia.column.distance=T\u00e1vols\u00e1g dialog.wikipedia.nonefound=Nem tal\u00e1lhat\u00f3 Wikip\u00e9dia sz\u00f3cikk @@ -447,7 +452,7 @@ dialog.about.summarytext1=A GpsPrune egy program GPS vev\u0151kr\u0151l sz\u00e1 dialog.about.summarytext2=Gnu GPL licenc alatt ker\u00fclt kiad\u00e1sra a szabad, ny\u00edlt, vil\u00e1gm\u00e9ret\u0171 haszn\u00e1lathoz \u00e9s fejleszt\u00e9shez.
M\u00e1sol\u00e1sa, terjeszt\u00e9se \u00e9s m\u00f3dos\u00edt\u00e1sa megengedett \u00e9s \u00f6szt\u00f6nz\u00f6tt
a mell\u00e9kelt license.txt f\u00e1jlban r\u00f6gz\u00edtett felt\u00e9telek szerint dialog.about.summarytext3=Tov\u00e1bbi inform\u00e1ci\u00f3k\u00e9rt \u00e9s kezel\u00e9si \u00fatmutat\u00f3\u00e9rt l\u00e1sd a http://activityworkshop.net/ webhelyet. dialog.about.languages=El\u00e9rhet\u0151 nyelvek -dialog.about.translatedby=Magyar sz\u00f6veg: Ball\u00f3 Gy\u00f6rgy, B\u00e1thory P\u00e9ter, Peter Gervai +dialog.about.translatedby=Magyar sz\u00f6veg: Ball\u00f3 Gy\u00f6rgy \u00e9s B\u00e1thory P\u00e9ter dialog.about.systeminfo=Rendszerinform\u00e1ci\u00f3 dialog.about.systeminfo.os=Oper\u00e1ci\u00f3s rendszer dialog.about.systeminfo.java=Java futtat\u00f3k\u00f6rnyezet @@ -590,6 +595,11 @@ dialog.deletebydate.column.keep=Megtart dialog.deletebydate.column.delete=T\u00f6r\u00f6l dialog.setaltitudetolerance.text.metres=Az a hat\u00e1r (m\u00e9terben) ami alatt a kis s\u00fcllyed\u00e9seket \u00e9s emelked\u00e9seket figyelmen k\u00edv\u00fcl hagyjuk dialog.setaltitudetolerance.text.feet=Az a hat\u00e1r (l\u00e1bban) ami alatt a kis s\u00fcllyed\u00e9seket \u00e9s emelked\u00e9seket figyelmen k\u00edv\u00fcl hagyjuk +dialog.autoplay.duration=Id\u0151tartam (mp) +dialog.autoplay.usetimestamps=Nyompontok id\u0151b\u00e9lyege alapj\u00e1n +dialog.autoplay.rewind=Vissza az elej\u00e9re +dialog.autoplay.pause=Sz\u00fcnet +dialog.autoplay.play=Lej\u00e1tsz\u00e1s # 3d window dialog.3d.title=GpsPrune 3D n\u00e9zet @@ -755,6 +765,7 @@ fieldname.duration=Id\u0151tartam fieldname.speed=Sebess\u00e9g fieldname.verticalspeed=F\u00fcgg\u0151leges sebess\u00e9g fieldname.description=Le\u00edr\u00e1s +fieldname.mediafilename=F\u00e1jln\u00e9v # Measurement units units.original=Eredeti diff --git a/tim/prune/lang/prune-texts_it.properties b/tim/prune/lang/prune-texts_it.properties index 06eb029..69a9c83 100644 --- a/tim/prune/lang/prune-texts_it.properties +++ b/tim/prune/lang/prune-texts_it.properties @@ -12,7 +12,7 @@ menu.track=Traccia menu.track.undo=Annulla menu.track.clearundo=Cancella lista annulla menu.track.markrectangle=Segnare i punti nel rettangolo -menu.track.deletemarked=Cancella punti marcati +function.deletemarked=Cancella punti marcati function.rearrangewaypoints=Riorganizza waypoint menu.range=Serie menu.range.all=Seleziona tutto @@ -35,10 +35,11 @@ menu.view.browser=Mappa sul browser menu.view.browser.google=Google maps menu.view.browser.openstreetmap=Openstreetmap menu.view.browser.mapquest=Mapquest -menu.view.browser.yahoo=mappe Yahoo -menu.view.browser.bing=mappe Bing +menu.view.browser.yahoo=Mappe Yahoo +menu.view.browser.bing=Mappe Bing menu.settings=Preferenze menu.settings.onlinemode=Carica mappa da internet +menu.settings.antialias=Usa antialiasing menu.settings.autosave=Salva settaggi con chiusura del programma menu.help=Aiuto # Popup menu for map @@ -114,6 +115,7 @@ function.downloadsrtm=Scarica file da SRTM function.getwikipedia=Ottieni informazioni da Wikipedia function.searchwikipedianames=Cerca il nome in Wikipedia function.searchopencachingde=Cerca OpenCaching.de +function.mapillary=Cerca Mapillary.com function.downloadosm=Scarica dati OSM dell'area function.duplicatepoint=Duplica punto corrente in coda function.setcolours=Scegli colori @@ -754,6 +756,7 @@ fieldname.duration=Durata fieldname.speed=Velocit\u00e0 fieldname.verticalspeed=Velocit\u00e0 verticale fieldname.description=Descrizione +fieldname.mediafilename=File # Measurement units units.original=Originale @@ -797,6 +800,10 @@ logic.or=o url.googlemaps=maps.google.it wikipedia.lang=it openweathermap.lang=it +webservice.peakfinder=Apri Peakfinder.org +webservice.geohack=Apri la pagina Geohack +webservice.panoramio=Apri la mappa Panoramio +webservice.opencachingcom=Apri Opencaching.com webservice.opencachingcom.lang=it # Cardinals for 3d plots diff --git a/tim/prune/lang/prune-texts_ja.properties b/tim/prune/lang/prune-texts_ja.properties index 371eec5..087e8f7 100644 --- a/tim/prune/lang/prune-texts_ja.properties +++ b/tim/prune/lang/prune-texts_ja.properties @@ -11,7 +11,7 @@ menu.track=\u30c8\u30e9\u30c3\u30af(T) menu.track.undo=\u30a2\u30f3\u30c9\u30a5 menu.track.clearundo=\u30a2\u30f3\u30c9\u30a5\u30ea\u30b9\u30c8\u3092\u7a7a\u306b\u3059\u308b menu.track.markrectangle=\u56db\u89d2\u306e\u4e2d\u306b\u5370\u3092\u3064\u3051\u308b -menu.track.deletemarked=\u5370\u306e\u4ed8\u3044\u305f\u70b9\u3092\u524a\u9664 +function.deletemarked=\u5370\u306e\u4ed8\u3044\u305f\u70b9\u3092\u524a\u9664 function.rearrangewaypoints=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u4e26\u3079\u66ff\u3048 menu.range=\u7bc4\u56f2(R) menu.range.all=\u5168\u3066\u9078\u629e diff --git a/tim/prune/lang/prune-texts_ko.properties b/tim/prune/lang/prune-texts_ko.properties index 69722c9..e1f1945 100644 --- a/tim/prune/lang/prune-texts_ko.properties +++ b/tim/prune/lang/prune-texts_ko.properties @@ -9,7 +9,7 @@ menu.file.exit=\uc885\ub8cc menu.track=\ud2b8\ub799 menu.track.undo=\uc2e4\ud589\ucde8\uc18c menu.track.clearundo=\uc2e4\ud589\ucde8\uc18c \ubaa9\ub85d \uc0ad\uc81c -menu.track.deletemarked=\ud45c\uc2dc\ub41c \uc9c0\uc810 \uc9c0\uc6b0\uae30 +function.deletemarked=\ud45c\uc2dc\ub41c \uc9c0\uc810 \uc9c0\uc6b0\uae30 function.rearrangewaypoints=\uacbd\uc720\uc9c0 \uc7ac\uc815\ub82c menu.range=\uc5f0\uacb0\uc120 menu.range.all=\ubaa8\ub450 \uc120\ud0dd diff --git a/tim/prune/lang/prune-texts_nl.properties b/tim/prune/lang/prune-texts_nl.properties index a9431c6..548f9b6 100644 --- a/tim/prune/lang/prune-texts_nl.properties +++ b/tim/prune/lang/prune-texts_nl.properties @@ -12,7 +12,7 @@ menu.track=Route menu.track.undo=Ongedaan maken menu.track.clearundo=Ongedaan-maken lijst wissen menu.track.markrectangle=Makeer alle punten in een vierkant -menu.track.deletemarked=Verwijderen gemarkeerde punten +function.deletemarked=Verwijderen gemarkeerde punten menu.range=Reeks menu.range.all=Selecteer alles menu.range.none=Selecteer geen @@ -38,6 +38,7 @@ menu.view.browser.yahoo=Yahoo maps menu.view.browser.bing=Bing maps menu.settings=Instellingen menu.settings.onlinemode=Kaarten van internet ophalen +menu.settings.antialias=Anti-kartelvorming menu.settings.autosave=Automatisch opslaan bij afsluiten menu.help=Help # Popup menu for map @@ -113,6 +114,7 @@ function.lookupsrtm=Hoogtes van SRTM ophalen function.downloadsrtm=Downloaden SRTM tegels function.getwikipedia=Wikipedia artikelen uit de buurt ophalen function.searchwikipedianames=Wikipedia zoeken op naam +function.searchopencachingde=OpenCaching.de zoeken function.downloadosm=Downloaden OSM data voor gebied function.duplicatepoint=Dupliceer punt function.setcolours=Instellen kleuren @@ -377,9 +379,11 @@ dialog.gpsies.activity.motorbiking=Motorrijden dialog.gpsies.activity.snowshoe=Sneeuwschoen-lopen dialog.gpsies.activity.sailing=Zeilen dialog.gpsies.activity.skating=Skating +dialog.mapillary.nonefound=Geen foto's gevonden dialog.wikipedia.column.name=Artikelnaam dialog.wikipedia.column.distance=Afstand dialog.wikipedia.nonefound=Geen punten gevonden +dialog.geocaching.nonefound=Geen punten gevonden dialog.correlate.notimestamps=Er zit geen tijdinformatie in de punten, dus kunnen ze niet aan foto's gekoppeld worden. dialog.correlate.nouncorrelatedphotos=Er zijn geen ongekoppelde foto's.\nWeet u zeker dat u wilt doorgaan? dialog.correlate.nouncorrelatedaudios=Er zijn geen ongekoppelde geluidsbestanden.\nWeet u zeker dat u wilt doorgaan? @@ -588,6 +592,7 @@ dialog.deletebydate.column.keep=Behouden dialog.deletebydate.column.delete=Verwijderen dialog.setaltitudetolerance.text.metres=Grens (in meters) waaronder kleine klimmen en afdalingen worden genegeerd dialog.setaltitudetolerance.text.feet=Grens (in feet) waaronder kleine klimmen en afdalingen worden genegeerd +dialog.autoplay.duration=Duur (sec) # 3d window dialog.3d.title=GpsPrune in 3D @@ -753,6 +758,7 @@ fieldname.duration=Duur fieldname.speed=Snelheid fieldname.verticalspeed=Verticale snelheid fieldname.description=Omschrijving +fieldname.mediafilename=Bestandsnaam # Measurement units units.original=Oorspronkelijke @@ -796,6 +802,10 @@ logic.or=of url.googlemaps=maps.google.nl wikipedia.lang=nl openweathermap.lang=nl +webservice.peakfinder=Open Peakfinder.org +webservice.geohack=Open Geohack webpagina +webservice.panoramio=Open Panoramio map +webservice.opencachingcom=Open Opencaching.com webservice.opencachingcom.lang=nl # Cardinals for 3d plots diff --git a/tim/prune/lang/prune-texts_pl.properties b/tim/prune/lang/prune-texts_pl.properties index acf3fe0..a2302fe 100644 --- a/tim/prune/lang/prune-texts_pl.properties +++ b/tim/prune/lang/prune-texts_pl.properties @@ -12,7 +12,7 @@ menu.track=\u015acie\u017cka menu.track.undo=Cofnij menu.track.clearundo=Wyczy\u015b\u0107 list\u0119 zmian menu.track.markrectangle=Zaznaczenie prostok\u0105tne -menu.track.deletemarked=Usu\u0144 zaznaczone punkty +function.deletemarked=Usu\u0144 zaznaczone punkty menu.range=Zakres menu.range.all=Zaznacz wszystko menu.range.none=Usu\u0144 zaznaczenie @@ -588,6 +588,7 @@ dialog.deletebydate.column.keep=Zostaw dialog.deletebydate.column.delete=Usu\u0144 dialog.setaltitudetolerance.text.metres=Limit (w metrach) poni\u017cej kt\u00f3rego, ma\u0142e spadki wzniosy b\u0119d\u0105 ignorowane dialog.setaltitudetolerance.text.feet=Limit (w stopach) poni\u017cej kt\u00f3rego, ma\u0142e spadki wzniosy b\u0119d\u0105 ignorowane +dialog.autoplay.duration=Czas trwania (sek) # 3d window dialog.3d.title=GpsPrune widok tr\u00f3jwymiarowy @@ -753,6 +754,7 @@ fieldname.duration=Czas trwania fieldname.speed=Pr\u0119dko\u015b\u0107 fieldname.verticalspeed=Pr\u0119dko\u015b\u0107 pionowa fieldname.description=Opis +fieldname.mediafilename=Nazwa pliku # Measurement units units.original=Oryginalny diff --git a/tim/prune/lang/prune-texts_pt.properties b/tim/prune/lang/prune-texts_pt.properties index 6319688..8737cd3 100644 --- a/tim/prune/lang/prune-texts_pt.properties +++ b/tim/prune/lang/prune-texts_pt.properties @@ -12,7 +12,7 @@ menu.track=Rota menu.track.undo=Desfazer menu.track.clearundo=Limpar lista de desfazer menu.track.markrectangle=Marcar pontos no ret\u00e2ngulo -menu.track.deletemarked=Remover pontos marcados +function.deletemarked=Remover pontos marcados function.rearrangewaypoints=Rearrumar pontos menu.range=Intervalo menu.range.all=Selecionar tudo @@ -113,6 +113,8 @@ function.lookupsrtm=Obter altitudes a partir do SRTM function.downloadsrtm=Baixar arquivos SRTM function.getwikipedia=Obter artigos da Wikip\u00e9dia das redondezas function.searchwikipedianames=Procurar na Wikip\u00e9dia por nome +function.searchopencachingde=Procurar na OpenCaching.de +function.mapillary=Procurar na Mapillary.com function.downloadosm=Baixar dados OSM para a \u00e1rea function.duplicatepoint=Duplicar ponto function.setcolours=Definir cores @@ -393,7 +395,7 @@ dialog.correlate.options.offset.minutes=minutos e dialog.correlate.options.offset.seconds=segundos dialog.correlate.options.photolater=Foto mais recente que o ponto dialog.correlate.options.pointlaterphoto=Ponto mais recente que a foto -dialog.correlate.options.audiolater=\u00e1udio mais recente que o ponto +dialog.correlate.options.audiolater=\u00c1udio mais recente que o ponto dialog.correlate.options.pointlateraudio=Ponto mais recente que a \u00e1udio dialog.correlate.options.limitspanel=Limites de correla\u00e7\u00e3o dialog.correlate.options.notimelimit=Nenhum limite de tempo @@ -565,6 +567,13 @@ dialog.weather.wind=Vento dialog.weather.temp=Temp dialog.weather.humidity=Umidade dialog.weather.creditnotice=Estes dados foram disponibilizados por openweathermap.org. A p\u00e1gina Web possui mais detalhes. +dialog.deletebydate.column.keep=Guardar +dialog.deletebydate.column.delete=Remover +dialog.autoplay.duration=Dura\u00e7\u00e3o (seg) +dialog.autoplay.usetimestamps=Usar data-hora +dialog.autoplay.rewind=Rebobinar +dialog.autoplay.pause=Suspender +dialog.autoplay.play=Tocar # 3d window dialog.3d.title=Vista 3D do GpsPrune @@ -719,6 +728,7 @@ fieldname.longitude=Longitude fieldname.altitude=Altura fieldname.timestamp=Tempo fieldname.time=Tempo +fieldname.date=Data fieldname.waypointname=Nome fieldname.waypointtype=Tipo fieldname.newsegment=Segmento @@ -729,6 +739,7 @@ fieldname.duration=Dura\u00e7\u00e3o fieldname.speed=Velocidade fieldname.verticalspeed=Velocidade vertical fieldname.description=Descri\u00e7\u00e3o +fieldname.mediafilename=Arquivo # Measurement units units.original=Original @@ -772,6 +783,11 @@ logic.or=ou url.googlemaps=maps.google.com.br wikipedia.lang=pt openweathermap.lang=pt +webservice.peakfinder=Abrir Peakfinder.org +webservice.geohack=Abrir p\u00e1gina Geohack +webservice.panoramio=Abrir mapa do Panoramio +webservice.opencachingcom=Abrir Opencaching.com +webservice.opencachingcom.lang=pt # Cardinals for 3d plots cardinal.n=N diff --git a/tim/prune/lang/prune-texts_ro.properties b/tim/prune/lang/prune-texts_ro.properties index e311430..0a1f020 100644 --- a/tim/prune/lang/prune-texts_ro.properties +++ b/tim/prune/lang/prune-texts_ro.properties @@ -1,46 +1,51 @@ # Text entries for the GpsPrune application -# Romanian entries as extra +# Romanian entries thanks to Rothermographer, Oana and Cristian # Menu entries menu.file=Fi\u015fier menu.file.addphotos=Adaug\u0103 foto menu.file.recentfiles=Fi\u015fiere recente -menu.file.save=Salvare +menu.file.save=Salveaz\u0103 ca fi\u0219ier text menu.file.exit=Ie\u015fire menu.online=Internet menu.track=Traseu menu.track.undo=Anulare -menu.track.clearundo=\u015etergere lista de anulari -menu.track.deletemarked=\u015etergere puncte marcate +menu.track.clearundo=\u015eterge lista de anul\u0103ri +menu.track.markrectangle=Selecteaz\u0103 puncte din p\u0103trat +function.deletemarked=\u015eterge punctele marcate menu.range=Interval -menu.range.all=Selectare toate +menu.range.all=Selecteaz\u0103 toate punctele menu.range.none=Nu selecta niciun punct -menu.range.start=Seteaza inceputul selectiei -menu.range.end=Seteaza sfarsitul selectiei -menu.range.average=Mediere selec\u0163ie -menu.range.reverse=Inversare selec\u0163ie -menu.range.mergetracksegments=Unire segmente traseu -menu.range.cutandmove=Taiere si mutare selec\u0163ie +menu.range.start=Seteaz\u0103 inceputul intervalului +menu.range.end=Seteaz\u0103 sfarsitul intervalului +menu.range.average=Mediaz\u0103 selec\u0163ia +menu.range.reverse=Inverseaz\u0103 intervalul +menu.range.mergetracksegments=Une\u0219te segmentele traseului +menu.range.cutandmove=Taie \u0219i mut\u0103 intervalul menu.point=Punct -menu.point.editpoint=Editare punct -menu.point.deletepoint=\u015etergere punct +menu.point.editpoint=Editeaz\u0103 punct +menu.point.deletepoint=\u015eterge punct menu.photo=Foto -menu.photo.saveexif=Salveaza la Exif +menu.photo.saveexif=Salveaz\u0103 \u00een Exif menu.audio=Audio menu.view=Vizualizare -menu.view.browser=Harta in browser -menu.view.browser.google=Harti Google +menu.view.showsidebars=Afi\u0219eaz\u0103 panourile laterale +menu.view.browser=Harta \u00een browser +menu.view.browser.google=Harta Google menu.view.browser.openstreetmap=Openstreetmap menu.view.browser.mapquest=Mapquest -menu.view.browser.yahoo=Harti Yahoo -menu.view.browser.bing=Harti Bing +menu.view.browser.yahoo=Harta Yahoo +menu.view.browser.bing=Harta Bing menu.settings=Set\u0103ri menu.settings.onlinemode=\u00cencarc\u0103 h\u0103r\u021bi +menu.settings.antialias=Folose\u0219te antialiasing +menu.settings.autosave=Salveaz\u0103 set\u0103rile automat la ie\u0219ire menu.help=Ajutor + # Popup menu for map menu.map.zoomin=Apropie -menu.map.zoomout=Departeaza -menu.map.zoomfull=Departeaza la maxim +menu.map.zoomout=Dep\u0103rteaz\u0103 +menu.map.zoomfull=Dep\u0103rteaz\u0103 la maxim menu.map.newpoint=Creaz\u0103 punct menu.map.drawpoints=Creaz\u0103 serie de puncte menu.map.connect=Traseaz\u0103 linii \u00eentre puncte @@ -71,87 +76,116 @@ shortcut.menu.range.all=T shortcut.menu.help.help=A # Functions -function.open=Deschidere fi\u015fier -function.importwithgpsbabel=Importare fi\u015fier cu GPSBabel +function.open=Deschide fi\u015fier +function.importwithgpsbabel=Import\u0103 fi\u015fier cu GPSBabel function.loadfromgps=\u00cencarc\u0103 date de la GPS function.sendtogps=Trimite date spre GPS -function.exportkml=Export\u0103 \u00eentr-un fi\u015fier KML -function.exportgpx=Export\u0103 \u00eentr-un fi\u015fier GPX -function.exportpov=Export\u0103 \u00eentr-un fi\u015fier POV -function.exportsvg=Export\u0103 \u00eentr-un fi\u015fier SVG +function.exportkml=Export\u0103 \u00een fi\u015fier KML +function.exportgpx=Export\u0103 \u00een fi\u015fier GPX +function.exportpov=Export\u0103 \u00een fi\u015fier POV +function.exportsvg=Export\u0103 \u00een fi\u015fier SVG function.exportimage=Export\u0103 imagine -function.editwaypointname=Editare nume waypoint -function.compress=Comprima traseu -function.deleterange=\u015etergere gama -function.interpolate=Interpolare +function.editwaypointname=Editeaz\u0103 nume waypoint +function.compress=Comprim\u0103 traseu +function.marklifts=Marcheaz\u0103 urc\u0103rile pe instala\u021bii +function.deleterange=\u015eterge intervalul +function.croptrack=Decupeaz\u0103 traseul +function.interpolate=Interpoleaz\u0103 +function.deletebydate=\u0218terge puncte pe criterii de timp function.addtimeoffset=Adaug\u0103 decalaj timp function.addaltitudeoffset=Adaug\u0103 decalaj altitudine -function.rearrangewaypoints=Rearanjare waypoint -function.findwaypoint=Gasire waypoint +function.rearrangewaypoints=Rearanjeaz\u0103 waypoint +function.convertnamestotimes=Converte\u0219te numele waypoint-urilor \u00een timpi +function.deletefieldvalues=\u0218terge valorile c\u00e2mpurilor +function.findwaypoint=G\u0103se\u0219te waypoint +function.pastecoordinates=Introdu coordonate noi function.charts=Grafice -function.show3d=Vizualizare arborescenta +function.show3d=Vizualizare 3D function.distances=Distan\u0163e -function.fullrangedetails=Informa\u0163ie complet -function.getgpsies=\u00cencarc\u0103 trassee Gpsies -function.uploadgpsies=Trimite date spre Gpsies -function.downloadsrtm=\u00cencarc\u0103 date SRTM +function.fullrangedetails=Informa\u0163ie complet\u0103 function.estimatetime=Estimare durat\u0103 -function.setmapbg=Seteaza harta -function.selectsegment=Selectare segment curent -function.setcolours=Selectare culorile -function.setlanguage=Selectare limba -function.connecttopoint=Conecteaza la punct -function.disconnectfrompoint=Deconecteaza de la punct -function.removephoto=Elimina foto -function.correlatephotos=Corelare fotografii -function.rearrangephotos=Rearanjare fotografii -function.rotatephotoleft=Roti foto la st\u00e2nga -function.rotatephotoright=Roti foto la dreapta +function.learnestimationparams=\u00cenva\u021b\u0103 parametri de estimare timpi +function.autoplay=Parcurge traseu +function.setmapbg=Seteaz\u0103 fundalul h\u0103r\u021bii +function.setpaths=Seteaz\u0103 calea c\u0103tre aplica\u021bii +function.selectsegment=Selecteaz\u0103 segment curent +function.splitsegments=Divizeaz\u0103 traseul \u00een segmente +function.sewsegments=Combin\u0103 segmentele traseului +function.getgpsies=\u00cencarc\u0103 trasee Gpsies +function.uploadgpsies=Trimite date spre Gpsies +function.lookupsrtm=Descarc\u0103 date SRTM \u00een cache +function.downloadsrtm=Descarc\u0103 date SRTM +function.getwikipedia=Caut\u0103 articole Wikipedia din proximitate +function.searchwikipedianames=Caut\u0103 Wikipedia dup\u0103 nume +function.searchopencachingde=Caut\u0103 OpenCaching.de +function.mapillary=Caut\u0103 fotografii \u00een Mapillary +function.downloadosm=Descarc\u0103 date OSM pentru zona traseului +function.duplicatepoint=Duplic\u0103 punctul +function.setcolours=Seteaz\u0103 culori +function.setlinewidth=Seteaz\u0103 grosime linie +function.setlanguage=Seteaz\u0103 limb\u0103 +function.connecttopoint=Conecteaz\u0103 la punct +function.disconnectfrompoint=Deconecteaz\u0103 de la punct +function.removephoto=Elimin\u0103 foto +function.correlatephotos=Coreleaz\u0103 fotografii +function.rearrangephotos=Rearanjeaz\u0103 fotografii +function.rotatephotoleft=Rote\u0219te foto la st\u00e2nga +function.rotatephotoright=Rote\u0219te foto la dreapta function.photopopup=Arat\u0103 foto +function.ignoreexifthumb=Ignor\u0103 icoana EXIF function.loadaudio=Adaug\u0103 audio -function.removeaudio=Elimina audio -function.playaudio=Redare audio +function.removeaudio=Elimin\u0103 audio +function.correlateaudios=Coreleaz\u0103 clipuri audio +function.playaudio=Red\u0103 clip audio +function.stopaudio=Opre\u0219te clip audio function.help=Ajutor -function.showkeys=Arat\u0103 tastele scurt\u0103turi +function.showkeys=Arat\u0103 scurt\u0103turi function.about=Despre GpsPrune -function.checkversion=Verific\u0103 pentru o versiune noua +function.checkversion=Verific\u0103 versiune noua function.saveconfig=Salvare set\u0103ri function.diskcache=Salvare harti +function.managetilecache=Administreaz\u0103 imaginile salvate function.getweatherforecast=Prognoz\u0103 meteo +function.setaltitudetolerance=Alege toleran\u021ba varia\u021biei altitudinii # Dialogs dialog.exit.confirm.title=Ie\u015fire din programul GpsPrune -dialog.exit.confirm.text=Datele dumneavoastra nu sunt salvate.\nSunte\u0163i sigur ca\u0103 dori\u0163i s\u0103 ie\u015fiti? -dialog.openappend.title=Adauga la datele existente -dialog.openappend.text=Adauga la datele deja incarcate? +dialog.exit.confirm.text=Datele dumneavoastra nu sunt salvate.\nSunte\u0163i sigur c\u0103 dori\u0163i s\u0103 ie\u015fiti? +dialog.openappend.title=Adaug\u0103 la datele existente +dialog.openappend.text=Adaug\u0103 la datele deja incarcate? dialog.deletepoint.title=\u015eterge Punct dialog.deletepoint.deletephoto=\u015eterg fotografiile atasate acestui punct? dialog.deletephoto.title=\u015eterge foto dialog.deletephoto.deletepoint=\u015eterg punct atasat acestei fotografii? dialog.deleteaudio.deletepoint=\u015eterg punct atasat acestei audio? -dialog.openoptions.title=Optiuni deschidere -dialog.load.table.field=Cimp +dialog.openoptions.title=Op\u021biuni deschidere +dialog.openoptions.filesnippet=Extras din fi\u0219ier +dialog.load.table.field=C\u00e2mp dialog.load.table.datatype=Tip data dialog.load.table.description=Descriere -dialog.delimiter.label=Delimitator cimp -dialog.delimiter.comma=Virgula , +dialog.delimiter.label=Delimitator c\u00e2mp +dialog.delimiter.comma=Virgul\u0103 , dialog.delimiter.tab=Tab -dialog.delimiter.space=Spatiu -dialog.delimiter.semicolon=Punct si virgula : -dialog.delimiter.other=Alte -dialog.openoptions.deliminfo.records=inregistrari, cu -dialog.openoptions.deliminfo.fields=cimpuri -dialog.openoptions.deliminfo.norecords=Nu sunt inregistrari -dialog.openoptions.altitudeunits=Unit\u0103\u0163i de altitudini -dialog.openoptions.speedunits=Unit\u0103\u0163i de viteza -dialog.openoptions.vertspeedunits=Unit\u0103\u0163i de viteza vertical\u0103 +dialog.delimiter.space=Spa\u021biu +dialog.delimiter.semicolon=Punct \u0219i virgul\u0103 ; +dialog.delimiter.other=Altele +dialog.openoptions.deliminfo.records=\u00eenregistr\u0103ri, cu +dialog.openoptions.deliminfo.fields=c\u00e2mpuri +dialog.openoptions.deliminfo.norecords=Nu sunt \u00eenregistr\u0103ri +dialog.openoptions.altitudeunits=Unit\u0103\u0163i de altitudine +dialog.openoptions.speedunits=Unit\u0103\u0163i de vitez\u0103 +dialog.openoptions.vertspeedunits=Unit\u0103\u0163i de vitez\u0103 vertical\u0103 +dialog.openoptions.vspeed.positiveup=Vitezele pozitive \u00een sus +dialog.openoptions.vspeed.positivedown=Vitezele pozitive \u00een jos +dialog.open.contentsdoubled=Acest fi\u0219ier con\u021bine dou\u0103 copii ale aceluia\u0219i punct,\nonce ca waypoint-uri \u0219i ca puncte de traseu. +dialog.selecttracks.intro=Alege\u021bi traseul(traseele) pentru \u00eenc\u0103rcare. dialog.selecttracks.noname=F\u0103r\u0103 nume -dialog.jpegload.subdirectories=Include subdirectori -dialog.jpegload.loadjpegswithoutcoords=Include fotografii fara coordonate +dialog.jpegload.subdirectories=Include subdirectoarele +dialog.jpegload.loadjpegswithoutcoords=Include fotografii f\u0103r\u0103 coordonate dialog.jpegload.loadjpegsoutsidearea=Include fotografii din afara zonei curente dialog.jpegload.progress.title=\u00cenc\u0103rcare fotografii -dialog.jpegload.progress=Va rog sa asteptati, caut fotografiile -dialog.gpsload.nogpsbabel=Nu gasesc programul gpsbabel. Continui ? +dialog.jpegload.progress=Va rog s\u0103 a\u0219tepta\u021bi, caut fotografiile +dialog.gpsload.nogpsbabel=Nu g\u0103sesc programul gpsbabel. Continui? dialog.gpsload.device=Nume dispozitiv dialog.gpsload.format=Format dialog.gpsload.getwaypoints=\u00cencarc\u0103 waypoints @@ -165,128 +199,264 @@ dialog.addfilter.title=Adaug\u0103 filtru dialog.gpsbabel.filter.discard=Arunc\u0103 dialog.gpsbabel.filter.simplify=Simplific\u0103 dialog.gpsbabel.filter.distance=Distan\u0163\u0103 -dialog.gpsbabel.filter.interpolate=Interpolare +dialog.gpsbabel.filter.interpolate=Interpoleaz\u0103 dialog.gpsbabel.filter.discard.intro=Arunc\u0103 puncte dac\u0103 dialog.gpsbabel.filter.discard.hdop=Hdop > dialog.gpsbabel.filter.discard.vdop=Vdop > dialog.gpsbabel.filter.discard.numsats=Num\u0103r de sateli\u0163i < +dialog.gpsbabel.filter.discard.nofix=Punctul nu are fix GPS +dialog.gpsbabel.filter.discard.unknownfix=Punctul are fix GPS necunoscut +dialog.gpsbabel.filter.simplify.intro=\u0218terge punctele dac\u0103 dialog.gpsbabel.filter.simplify.maxpoints=Num\u0103r de puncte < +dialog.gpsbabel.filter.simplify.maxerror=sau erori de distan\u021b\u0103 < +dialog.gpsbabel.filter.simplify.crosstrack=\u00een lungul traseului dialog.gpsbabel.filter.simplify.length=diferen\u0163\u0103 de lungime +dialog.gpsbabel.filter.simplify.relative=relativ la HDOP +dialog.gpsbabel.filter.distance.intro=\u0218terge punctele dac\u0103 sunt aproape de puncte anterioare dialog.gpsbabel.filter.distance.distance=Dac\u0103 distan\u0163\u0103 < dialog.gpsbabel.filter.distance.time=\u0219i diferen\u0163\u0103 de timp < -dialog.gpsbabel.filter.interpolate.distance=Dac\u0103 distan\u0163\u0103 > -dialog.gpsbabel.filter.interpolate.time=sau diferen\u0163\u0103 de timp > +dialog.gpsbabel.filter.interpolate.intro=Adaug\u0103 puncte \u00eentre punctele existente +dialog.gpsbabel.filter.interpolate.distance=Dac\u0103 distan\u0163a > +dialog.gpsbabel.filter.interpolate.time=sau diferen\u0163a de timp > dialog.saveoptions.title=Salvare fi\u015fier -dialog.save.table.field=Cimp -dialog.save.table.hasdata=Date +dialog.save.fieldstosave=C\u00e2mpuri ce urmeaz\u0103 a fi salvate +dialog.save.table.field=C\u00e2mp +dialog.save.table.hasdata=Con\u021bine date dialog.save.table.save=Salvare +dialog.save.headerrow=Salveaza cap tabel dialog.save.coordinateunits=Format coordonate -dialog.save.altitudeunits=Unit\u0103\u0163i de altitudini +dialog.save.altitudeunits=Unit\u0103\u0163i de altitudine dialog.save.timestampformat=Format de timp dialog.save.overwrite.title=Fi\u015fierul exist\u0103 dialog.save.overwrite.text=Fi\u015fierul exist\u0103. \u00cel suprascriu? +dialog.save.notypesselected=Niciun tip de punct nu a fost selectat dialog.exportkml.text=Titlu -dialog.exportkml.imagesize=Dimensiune imaginii +dialog.exportkml.altitude=Altitudini absolute (pentru avia\u021bie) +dialog.exportkml.kmz=Comprim\u0103 pentru a produce fi\u0219ier KMZ +dialog.exportkml.exportimages=Export\u0103 icoane pentru imagini \u00een KMZ +dialog.exportkml.imagesize=Dimensiune icoane imagini \u00een KMZ dialog.exportkml.trackcolour=Culoarea liniei +dialog.exportkml.standardkml=KML standard +dialog.exportkml.extendedkml=KML extins cu date cronologice dialog.exportgpx.name=Nume dialog.exportgpx.desc=Descriere +dialog.exportgpx.includetimestamps=Include date cronologice +dialog.exportgpx.copysource=Copiaz\u0103 sursa xml dialog.exportgpx.encoding=Codare dialog.exportgpx.encoding.system=Sistem dialog.exportgpx.encoding.utf8=UTF-8 +dialog.exportpov.text=Introduce\u021bi parametrii pentru export POV dialog.exportpov.font=Fontul dialog.exportpov.camerax=Vedere X dialog.exportpov.cameray=Vedere Y dialog.exportpov.cameraz=Vedere Z dialog.exportpov.modelstyle=Stilul +dialog.exportpov.ballsandsticks=Bile \u0219i be\u021be +dialog.exportpov.tubesandwalls=Tuburi \u0219i pere\u021bi +dialog.3d.warningtracksize=Acest traseu are un num\u0103r mare de puncte pe care Java3D ar putea s\u0103 nu fie capabil s\u0103-l afi\u0219eze. Sigur dori\u021bi s\u0103 continua\u021bi? dialog.3d.useterrain=Arat\u0103 teren -dialog.3d.terraingridsize=Dimensiune a grilei -dialog.exportpov.baseimage=Imagine cartografice -dialog.baseimage.title=Imagine cartografice +dialog.3d.terraingridsize=Dimensiunea grilei +dialog.exportpov.baseimage=Imagine cartografic\u0103 +dialog.exportpov.cannotmakebaseimage=Imaginea cartografic\u0103 nu poate fi scris\u0103 +dialog.baseimage.title=Imagine cartografic\u0103 +dialog.baseimage.useimage=Folose\u0219te imaginea +dialog.baseimage.mapsource=Sursa h\u0103r\u021bii dialog.baseimage.zoom=Nivel de zoom dialog.baseimage.incomplete=Imagine incomplet\u0103 -dialog.baseimage.tiles=Tigla +dialog.baseimage.tiles=\u021aigle +dialog.baseimage.size=Dimensiunea imaginii +dialog.exportsvg.text=Alege\u021bi parametrii pentru export SVG dialog.exportsvg.phi=Azimut \u03d5 dialog.exportsvg.theta=\u00cenclina\u0163ie \u03b8 +dialog.exportsvg.gradients=Folose\u0219te gradien\u021bi pentru umbrire +dialog.exportimage.noimagepossible=Imaginile hart\u0103 trebuie sa fie salvate \u00een cache pe disc pentru a putea fi folosite la export. +dialog.exportimage.drawtrack=Deseneaz\u0103 traseu pe hart\u0103 +dialog.exportimage.drawtrackpoints=Deseneaz\u0103 punctele traseului +dialog.exportimage.textscalepercent=Factor de scalare a textului (%) +dialog.pointtype.desc=Salveaz\u0103 urm\u0103toarele tipuri de puncte: dialog.pointtype.track=Puncte de traseu -dialog.pointtype.waypoint=Waypoints +dialog.pointtype.waypoint=Waypoint-uri dialog.pointtype.photo=Puncte foto dialog.pointtype.audio=Puncte audio -dialog.pointtype.selection=Doar interval -dialog.undo.title=Anulare -dialog.pointedit.title=Editare punct -dialog.pointedit.intro=V\u0103 rog selecta\u0163i r\u00e2ndul care va fi editat -dialog.pointedit.table.field=Cimp +dialog.pointtype.selection=Doar intervalul selectat +dialog.confirmreversetrack.title=Confirm\u0103 inversarea +dialog.confirmreversetrack.text=Acest traseu con\u021bine informa\u021bii cronologice a c\u0103ror ordine va fi incorect\u0103 dup\u0103 inversare.\nSigur dori\u021bi s\u0103 inversa\u021bi selec\u021bia? +dialog.confirmcutandmove.title=Confirm\u0103 t\u0103irea \u0219i mutarea +dialog.confirmcutandmove.text=Acest traseu con\u021bine informa\u021bii cronologice a c\u0103ror ordine va fi incorect\u0103 dup\u0103 mutare.\n Sigur dori\u021bi mutarea sec\u021biunii? +dialog.interpolate.parameter.text=Num\u0103rul de puncte de inserat \u00eentre fiecare pereche de puncte +dialog.interpolate.betweenwaypoints=Interpolez \u00eentre waypoint-uri? +dialog.undo.title=Anuleaz\u0103 +dialog.undo.pretext=Selecta\u021bi opera\u021biile ce vor fi anulate +dialog.undo.none.title=Nu se poate anula +dialog.undo.none.text=Nu exist\u0103 opera\u021bii pentru anulare! +dialog.clearundo.title=\u0218terge lista de anul\u0103ri +dialog.clearundo.text=Sigur vre\u021bi s\u0103 \u0219terge\u021bi lista de anul\u0103ri?\nToat\u0103 \u00eenforma\u021bia de anulare va fi pierdut\u0103! +dialog.pointedit.title=Editeaz\u0103 punct +dialog.pointedit.intro=Selecta\u0163i r\u00e2ndul care va fi editat +dialog.pointedit.table.field=C\u00e2mp +dialog.pointedit.nofield=Niciun c\u00e2mp selectat dialog.pointedit.table.value=Valoare dialog.pointnameedit.name=Nume de waypoint dialog.pointnameedit.uppercase=Litere MARI dialog.pointnameedit.lowercase=Litere mici +dialog.pointnameedit.titlecase=Prima Liter\u0103 Mare +dialog.addtimeoffset.add=Adaug\u0103 timp +dialog.addtimeoffset.subtract=Scade timp dialog.addtimeoffset.days=Zile dialog.addtimeoffset.hours=Ore dialog.addtimeoffset.minutes=Minute +dialog.addtimeoffset.notimestamps=Nu poate fi ad\u0103ugat un decalaj de timp pentru c\u0103 selec\u021bia nu con\u021bine date cronologice +dialog.findwaypoint.intro=Introduce\u021bi o parte a numelui waypoint-ului dialog.findwaypoint.search=C\u0103utare +dialog.saveexif.title=Salveaz\u0103 Exif +dialog.saveexif.intro=Selecteaz\u0103 fotografiile ce urmeaz\u0103 a fi salvate folosind bifele +dialog.saveexif.nothingtosave=Coordonatele sunte neschimbate, nu e nimic de salvat +dialog.saveexif.noexiftool=Aplica\u021bia exiftool nu a fost g\u0103sit\u0103. Continui? dialog.saveexif.table.photoname=Nume -dialog.saveexif.title=Salvare Exif dialog.saveexif.table.status=Stare -dialog.saveexif.table.save=Salveaza +dialog.saveexif.table.save=Salveaz\u0103 dialog.saveexif.photostatus.connected=Conectat dialog.saveexif.photostatus.disconnected=Deconectat dialog.saveexif.photostatus.modified=Modificat dialog.saveexif.overwrite=Suprascrie fi\u015fiere +dialog.saveexif.force=Ignor\u0103 erorile minore dialog.charts.xaxis=Axa X dialog.charts.yaxis=Axa Y dialog.charts.output=Rezultat +dialog.charts.screen=Rezultatul pe ecran +dialog.charts.svg=Rezultatul \u00een fi\u0219ier SVG dialog.charts.svgwidth=L\u0103\u021bime SVG dialog.charts.svgheight=\u00cen\u0103l\u021bime SVG -dialog.distances.column.from=De punct +dialog.charts.needaltitudeortimes=Traseul trebuie s\u0103 con\u021bina altitudini sau date cronologice pentru a crea grafice +dialog.charts.gnuplotnotfound=Aplica\u021bia gnuplot nu a fost g\u0103sit\u0103 la calea dat\u0103 +dialog.distances.intro=Distan\u021be \u00een linie dreapt\u0103 \u00eentre puncte +dialog.distances.column.from=De la punct dialog.distances.column.to=Spre punct dialog.distances.currentpoint=Punct curent +dialog.distances.toofewpoints=Aceast\u0103 func\u021bie are nevoie de waypoint-uri pentru a calcula distan\u021ba dintre ele +dialog.fullrangedetails.intro=Detalii pentru invervalul selectat +dialog.fullrangedetails.coltotal=Cu tot cu pauze +dialog.fullrangedetails.colsegments=F\u0103r\u0103 pauze dialog.estimatetime.details=Detalii -dialog.estimatetime.parameters=Parametrii +dialog.estimatetime.gentle=Domol +dialog.estimatetime.steep=Abrupt +dialog.estimatetime.climb=Urcare +dialog.estimatetime.descent=Cobor\u00e2re +dialog.estimatetime.parameters=Parametri dialog.estimatetime.parameters.timefor=Durata pentru dialog.estimatetime.results=Rezultate dialog.estimatetime.results.estimatedtime=Durata estimat\u0103 dialog.estimatetime.results.actualtime=Durata (measured) -dialog.learnestimationparams.averageerror=Eroare estimat -dialog.learnestimationparams.combinedresults=Rezultate combinat +dialog.estimatetime.error.nodistance=Estim\u0103rile de timp necesit\u0103 puncte de traseu conectate, pentru a putea fi calculat\u0103 distan\u021ba +dialog.estimatetime.error.noaltitudes=Selec\u021bia nu include informa\u021bii de altitudine +dialog.learnestimationparams.intro=Ace\u0219tia sunt parametrii calcula\u021bi pentru acest traseu +dialog.learnestimationparams.combine=Ace\u0219ti parametri pot fi combina\u021bi cu valorile curente +dialog.learnestimationparams.averageerror=Eroare estimat\u0103 +dialog.learnestimationparams.combinedresults=Rezultate combinate +dialog.learnestimationparams.weight.100pccurrent=P\u0103streaz\u0103 valorile curente dialog.learnestimationparams.weight.current=curente dialog.learnestimationparams.weight.calculated=calculate +dialog.learnestimationparams.weight.50pc=Media dintre valorile curente \u0219i cele calculate +dialog.learnestimationparams.weight.100pccalculated=Folose\u0219te valorile calculate +dialog.setmapbg.intro=Alege\u021bi una din sursele h\u0103r\u021bii sau ad\u0103uga\u021bi una nou\u0103 +dialog.addmapsource.title=Adaug\u0103 surs\u0103 noua de hart\u0103 dialog.addmapsource.sourcename=Nume +dialog.addmapsource.layer1url=URL pentru primul strat +dialog.addmapsource.layer2url=URL pentru cel de-al doilea strat (op\u021bional) +dialog.addmapsource.maxzoom=Nivelul de apropiere maxim dialog.addmapsource.noname=F\u0103r\u0103 nume dialog.gpsies.column.name=Nume dialog.gpsies.column.length=Lungime dialog.gpsies.description=Descriere dialog.gpsies.nodescription=F\u0103r\u0103 descriere -dialog.gpsies.nonefound=Nu a fost g\u0103sit +dialog.gpsies.nonefound=Nu a fost g\u0103sit niciun traseu dialog.gpsies.username=Gpsies username dialog.gpsies.password=Gpsies parol\u0103 dialog.gpsies.keepprivate=Traseu privat +dialog.gpsies.confirmopenpage=Deschid pagin\u0103 web pentru traseul \u00eenc\u0103rcat? dialog.gpsies.activities=Activit\u0103\u0163i +dialog.gpsies.activity.trekking=Mers pe munte +dialog.gpsies.activity.walking=Mers pe jos +dialog.gpsies.activity.jogging=Alergare +dialog.gpsies.activity.biking=Biciclet\u0103 +dialog.gpsies.activity.motorbiking=Motociclet\u0103 +dialog.gpsies.activity.snowshoe=Mers cu rachete de z\u0103pad\u0103 +dialog.gpsies.activity.sailing=Navigare +dialog.gpsies.activity.skating=Role +dialog.mapillary.nonefound=Nicio fotografie nu a fost g\u0103sit\u0103 dialog.wikipedia.column.name=Nume dialog.wikipedia.column.distance=Distan\u0163\u0103 dialog.wikipedia.nonefound=Nu a fost g\u0103sit -dialog.correlate.select.photoname=Nume -dialog.correlate.select.timediff=Diferenta de timp +dialog.geocaching.nonefound=Nu a fost g\u0103sit +dialog.correlate.notimestamps=Corelarea cu fotografiile nu se poate realiza pentru c\u0103 \u00een puncte nu exist\u0103 informa\u021bie cronologic\u0103 +dialog.correlate.nouncorrelatedphotos=Nu exist\u0103 fotografii necorelate. Continui? +dialog.correlate.nouncorrelatedaudios=Nu exist\u0103 clipuri audio necorelate. Continui? +dialog.correlate.photoselect.intro=Alege\u021bi una din fotografiile corelate ca referin\u021b\u0103 pentru decalajul de timp +dialog.correlate.select.photoname=Nume foto +dialog.correlate.select.timediff=Diferen\u021ba de timp +dialog.correlate.select.photolater=Foto mai t\u00e2rziu +dialog.correlate.options.intro=Alege\u021bi op\u021biunile pentru corelare automat\u0103 +dialog.correlate.options.offsetpanel=Decalaj de timp +dialog.correlate.options.offset=Decalaj dialog.correlate.options.offset.hours=ore, -dialog.correlate.options.offset.minutes=minute, +dialog.correlate.options.offset.minutes=minute \u0219i dialog.correlate.options.offset.seconds=secunde +dialog.correlate.options.photolater=Foto dup\u0103 punct +dialog.correlate.options.pointlaterphoto=Punct dup\u0103 foto +dialog.correlate.options.audiolater=Audio dup\u0103 punct +dialog.correlate.options.pointlateraudio=Punct dup\u0103 audio +dialog.correlate.options.limitspanel=Limite corelare +dialog.correlate.options.notimelimit=F\u0103r\u0103 limit\u0103 de timp +dialog.correlate.options.timelimit=Limit\u0103 de timp +dialog.correlate.options.nodistancelimit=F\u0103r\u0103 limit\u0103 de distan\u021b\u0103 +dialog.correlate.options.distancelimit=Limit\u0103 de distan\u021b\u0103 dialog.correlate.options.correlate=Corelare -dialog.correlate.timestamp.beginning=\u00cenceptutul +dialog.correlate.alloutsiderange=Toate elementele sunt \u00een afara intervalului de timp din traseu, deci nu pot fi corelate.\n \u00cencerca\u021bi schimbarea decalajului de timp sau corela\u021bi manual cel pu\u021bin un element. +dialog.correlate.filetimes=Informa\u021bia cronologic\u0103 din fi\u0219ier arat\u0103: +dialog.correlate.filetimes2=a clipului audio +dialog.correlate.correltimes=Pentru corelare folose\u0219te: +dialog.correlate.timestamp.beginning=\u00cenceputul dialog.correlate.timestamp.middle=Mijlocul dialog.correlate.timestamp.end=Sf\u00e2r\u015fitul -dialog.correlate.select.audioname=Nume +dialog.correlate.audioselect.intro=Alege\u021bi unul din clipurile audio corelate ca referin\u021b\u0103 pentru decalajul de timp +dialog.correlate.select.audioname=Nume clip +dialog.correlate.select.audiolater=Audio mai t\u00e2rziu +dialog.rearrangewaypoints.desc=Alege\u021bi destina\u021bia \u0219i ordinea de sortare a waypoint-urilor +dialog.rearrangephotos.desc=Alege\u021bi destina\u021bia \u0219i ordinea de sortare a punctelor foto dialog.rearrange.tostart=Toate la inceputul fi\u015fierului -dialog.rearrange.toend=Toate la sfarsitul fi\u015fierului +dialog.rearrange.toend=Toate la sf\u00e2r\u0219itul fi\u015fierului dialog.rearrange.tonearest=Fiecare la punctul cel mai apropiat al traseului dialog.rearrange.nosort=Nu sunt sortate -dialog.rearrange.sortbyfilename=Sorta dup\u0103 nume de fi\u015fier -dialog.rearrange.sortbyname=Sorta dup\u0103 nume -dialog.rearrange.sortbytime=Sorta dup\u0103 timp +dialog.rearrange.sortbyfilename=Sortez\u0103 dup\u0103 nume de fi\u015fier +dialog.rearrange.sortbyname=Sorteaz\u0103 dup\u0103 nume +dialog.rearrange.sortbytime=Sorteaz\u0103 dup\u0103 timp +dialog.compress.closepoints.title=\u0218tergere puncte apropiate +dialog.compress.closepoints.paramdesc=Anvergur\u0103 +dialog.compress.wackypoints.title=\u0218tergere puncte aberante +dialog.compress.wackypoints.paramdesc=Factor de distan\u021b\u0103 +dialog.compress.singletons.title=\u0218tergere puncte singulare +dialog.compress.singletons.paramdesc=Factor de distan\u021b\u0103 +dialog.compress.duplicates.title=\u0218tergerea duplicatelor +dialog.compress.douglaspeucker.title=Compresie Douglas-Peucker +dialog.compress.douglaspeucker.paramdesc=Anvergur\u0103 +dialog.compress.summarylabel=Puncte ce vor fi \u0219terse +dialog.compress.confirm=Au fost marcate %d puncte. \u0218terg aceste puncte? +dialog.compress.confirmnone=niciun punct nu a fost marcat +dialog.deletemarked.nonefound=Niciun punct nu a putut fi \u0219ters +dialog.pastecoordinates.desc=Scrie\u021bi sau copia\u021bi aici coordonatele dialog.pastecoordinates.coords=Coordonate +dialog.pastecoordinates.nothingfound=V\u0103 rug\u0103m verifica\u021bi coordonatele \u0219i \u00eencerca\u021bi din nou. +dialog.help.help=V\u0103 rug\u0103m vizita\u021bi \n http://gpsprune.activityworkshop.net/\npentru mai multe informa\u021bii, inclusiv un nou manual PDF care poate fi cump\u0103rat. dialog.about.version=Versiunea -dialog.about.build=Construi -dialog.about.languages=Limbi -dialog.about.systeminfo=Informa\u0163ii a sistemului +dialog.about.build=Versiunea minor\u0103 +dialog.about.summarytext1=GpsPrune e o aplica\u021bie pentru \u00eenc\u0103rcarea, afi\u0219area \u0219i editarea datelor salvate de receptoarele GPS. +dialog.about.summarytext2=Este distribuit\u0103 sub licen\u021b\u0103 Gnu GPL pentru a permite utilizarea gratuit\u0103 \u00een lumea \u00eentreag\u0103
\u0219i pentru a permite oricui dore\u0219te \u00eembun\u0103t\u0103\u021biea aplica\u021biei.
Copierea, redistribuirea \u0219i modificarea sunt permise \u0219i \u00eencurajate
\u00een conformitate cu condi\u021biile descrise \u00een fi\u0219ierul license.txt care este inclus \u00een aplica\u021bie. +dialog.about.summarytext3=V\u0103 rug\u0103m vizita\u021bi http://activityworkshop.net/ pentru mai multe informa\u021bii \u0219i indicii, inclusiv
un nou manual \u00een format PDF care poate fi cump\u0103rat. +dialog.about.languages=Traduceri +dialog.about.translatedby=Textele romanesti sunt de Rothermographer, Oana \u0219i Cristian +dialog.about.systeminfo=Informa\u0163ii sistem dialog.about.systeminfo.os=Sistem de operare +dialog.about.systeminfo.java=Java Runtime dialog.about.systeminfo.java3d=Java3d instalat dialog.about.systeminfo.povray=Povray instalat dialog.about.systeminfo.exiftool=Exiftool instalat @@ -299,33 +469,112 @@ dialog.about.systeminfo.exiflib.external=Extern dialog.about.systeminfo.exiflib.external.failed=Extern (absent) dialog.about.yes=Da dialog.about.no=Nu +dialog.about.credits=Mul\u021bumiri +dialog.about.credits.code=Codul GpsPune a fost scris de +dialog.about.credits.exifcode=Codul Exif de +dialog.about.credits.icons=Unele icoane au fost luate de la +dialog.about.credits.translators=Traduc\u0103tori +dialog.about.credits.translations=La traduceri au ajutat +dialog.about.credits.devtools=Unelte de dezvoltare +dialog.about.credits.othertools=Alte unelte +dialog.about.credits.thanks=Mul\u021bumiri dialog.about.readme=Cite\u015fte-m\u0103 -dialog.checkversion.releasedate1=Aceasta versiune noua a fost lansapa pe +dialog.checkversion.error=Num\u0103rul versiunii nu a putut fi verificat.\nVerifica\u021bi conexiunea Internet. +dialog.checkversion.uptodate=Folosi\u021bi cea mai recent\u0103 versiune a GpsPrune. +dialog.checkversion.newversion1=A ap\u0103rut o nou\u0103 versiune GpsPrune. Cea mai nou\u0103 versiune este +dialog.checkversion.newversion2=. +dialog.checkversion.releasedate1=Aceast\u0103 versiune nou\u0103 a fost lansat\u0103 la dialog.checkversion.releasedate2=. +dialog.checkversion.download=Pentru a desc\u0103rca noua versiune merge\u021bi la http://gpsprune.activityworkshop.net/download.html. +dialog.keys.intro=Pute\u021bi folosi urm\u0103toarele scurt\u0103turi \u00een locul mouse-ului +dialog.keys.keylist=
Taste s\u0103ge\u021biMut\u0103 harta st\u00e2nga, dreapta, sus, jos
Ctrl + s\u0103geat\u0103 st\u00e2nga, dreaptaSelecteaz\u0103 punctul anterior sau urm\u0103tor
Ctrl + s\u0103geat\u0103 sus, josAproprie sau \u00eendep\u0103rteaz\u0103
Ctrl + PgUp, PgDownSelecteaz\u0103 segmentul anterior sau urm\u0103tor
Ctrl + Home, EndSelecteaz\u0103 primul, ultimul punct
Del\u0218terge punctul curent
+dialog.keys.normalmodifier=Ctrl +dialog.keys.macmodifier=Command +dialog.saveconfig.desc=Urm\u0103toarele set\u0103ri pot fi salvate \u00eentr-un fi\u0219ier de configur\u0103ri : +dialog.saveconfig.prune.trackdirectory=Director trasee +dialog.saveconfig.prune.photodirectory=Director foto dialog.saveconfig.prune.languagecode=Limb\u0103 (RO) dialog.saveconfig.prune.languagefile=Fi\u015fier de limba dialog.saveconfig.prune.gpsdevice=Dispozitiv GPS dialog.saveconfig.prune.gpsformat=Format GPS -dialog.setcolours.background=Fund +dialog.saveconfig.prune.povrayfont=Font Povray +dialog.saveconfig.prune.gnuplotpath=Calea c\u0103tre gnuplot +dialog.saveconfig.prune.gpsbabelpath=Calea c\u0103tre gpsbabel +dialog.saveconfig.prune.exiftoolpath=Calea c\u0103tre exiftool +dialog.saveconfig.prune.mapsource=Surs\u0103 hart\u0103 selectat\u0103 +dialog.saveconfig.prune.mapsourcelist=Surse hart\u0103 +dialog.saveconfig.prune.diskcache=Cache hart\u0103 +dialog.saveconfig.prune.kmzimagewidth=Dimensiuni imagini \u00een KMZ +dialog.saveconfig.prune.colourscheme=Schem\u0103 de culoare +dialog.saveconfig.prune.linewidth=Grosime linie +dialog.saveconfig.prune.kmltrackcolour=Culoar track KML +dialog.saveconfig.prune.autosavesettings=Set\u0103ri salv\u0103ri automate +dialog.setpaths.intro=Dac\u0103 dori\u021bi pute\u021bi alege calea c\u0103tre aplica\u021bii externe +dialog.setpaths.found=Cale g\u0103sit\u0103? +dialog.addaltitude.noaltitudes=Intervalul nu con\u021bine altitudini +dialog.addaltitude.desc=Decalaj altitudine +dialog.lookupsrtm.overwritezeros=Suprascriu altitudinile cu valoare zero? +dialog.setcolours.intro=Face\u021bi click pe un petec de culoare pentru a schimba culoarea +dialog.setcolours.background=Fundal +dialog.setcolours.borders=Margini dialog.setcolours.lines=Linii dialog.setcolours.primary=Primar dialog.setcolours.secondary=Secundar dialog.setcolours.point=Puncte dialog.setcolours.selection=Selec\u0163ie dialog.setcolours.text=Text -dialog.colourchooser.title=Selectare culoare +dialog.colourchooser.title=Alege\u021bi culoare dialog.colourchooser.red=Ro\u0219u dialog.colourchooser.green=Verde dialog.colourchooser.blue=Albastru +dialog.colourer.intro=Un algoritm de colorare poate da punctelor culori diferite +dialog.colourer.type=Tip algoritm colorare dialog.colourer.type.none=Nimic +dialog.colourer.type.byfile=Dup\u0103 fi\u0219ier +dialog.colourer.type.bysegment=Dup\u0103 segment +dialog.colourer.type.byaltitude=Dup\u0103 altitudine +dialog.colourer.type.byspeed=Dup\u0103 vitez\u0103 +dialog.colourer.type.byvertspeed=Dup\u0103 viteza vertical\u0103 +dialog.colourer.type.bygradient=Dup\u0103 gradient +dialog.colourer.type.bydate=Dup\u0103 dat\u0103 +dialog.colourer.start=Culoare de \u00eenceput +dialog.colourer.end=Culoare de sf\u00e2r\u0219it +dialog.colourer.maxcolours=Num\u0103rul maxim de culori +dialog.setlanguage.firstintro=Pute\u021bi folosi una din limbile incluse,

sau pute\u021bi alege un fi\u0219ier text pe care s\u0103-l folosi\u021bi. +dialog.setlanguage.secondintro=Trebuie s\u0103 salva\u021bi set\u0103rile \u0219i s\u0103

restarta\u021bi GpsPrune pentru a schimba limba dialog.setlanguage.language=Limb\u0103 dialog.setlanguage.languagefile=Fi\u015fier de limba -dialog.diskcache.table.tiles=Tigla -dialog.searchwikipedianames.search=C\u0103utare : +dialog.setlanguage.endmessage=Salva\u021bi set\u0103rile \u0219i restarta\u021bi GpsPrune\npentru ca schimbarea de limb\u0103 s\u0103 aib\u0103 efect. +dialog.setlanguage.endmessagewithautosave=Restarta\u021bi GpsPrune pentru ca schimbare limbii s\u0103 aib\u0103 efect. +dialog.diskcache.save=Salveaz\u0103 imaginile h\u0103r\u021bii pe disc +dialog.diskcache.dir=Director cache +dialog.diskcache.createdir=Creaz\u0103 director +dialog.diskcache.nocreate=Directorul cache nu a putut fi creat +dialog.diskcache.cannotwrite=\u021aiglele h\u0103r\u021bii nu pot fi salvate \u00een directorul selectat +dialog.diskcache.table.path=Cale +dialog.diskcache.table.usedby=Folosit de +dialog.diskcache.table.zoom=Nivel apropiere +dialog.diskcache.table.tiles=\u021aigle +dialog.diskcache.table.megabytes=Megabytes +dialog.diskcache.tileset=Set \u021bigle (tile-uri) +dialog.diskcache.tileset.multiple=multiple +dialog.diskcache.deleteold=\u015eterge imaginile vechi +dialog.diskcache.maximumage=V\u00e2rsta maxim\u0103 (zile) +dialog.diskcache.deleteall=\u015eterge toate imaginile +dialog.diskcache.deleted=Au fost \u0219terse %d fi\u0219iere din cache +dialog.deletefieldvalues.intro=Alege\u021bi c\u00e2mpurile ce urmeaz\u0103 a fi \u0219terse din intervalul curent +dialog.deletefieldvalues.nofields=Nu poate fi \u0219ters nici un c\u00e2mp pentru intervalul dat +dialog.setlinewidth.text=Introduce\u021bi grosimea liniilor ce vor fi desenate pentru trasee (1-3) +dialog.downloadosm.desc=Confirma\u021bi desc\u0103rcarea datelor brute OSM pentru zona specificat\u0103: +dialog.searchwikipedianames.search=Caut\u0103: dialog.weather.location=Loca\u0163ie +dialog.weather.update=Prognoz\u0103 actualizat\u0103 dialog.weather.sunrise=R\u0103s\u0103rit dialog.weather.sunset=Apus de soare +dialog.weather.temperatureunits=Temperaturi dialog.weather.currentforecast=Vremea curent\u0103 +dialog.weather.dailyforecast=Prognoz\u0103 zilnic\u0103 +dialog.weather.3hourlyforecast=Prognoz\u0103 la fiecare 3 ore dialog.weather.day.now=Vremea curent\u0103 dialog.weather.day.today=Ast\u0103zi dialog.weather.day.tomorrow=M\u00e2ine @@ -336,49 +585,109 @@ dialog.weather.day.thursday=Joi dialog.weather.day.friday=Vineri dialog.weather.day.saturday=S\u00e2mb\u0103t\u0103 dialog.weather.day.sunday=Duminic\u0103 +dialog.weather.wind=V\u00e2nt +dialog.weather.temp=Temp +dialog.weather.humidity=Umiditate +dialog.weather.creditnotice=Acest set de date este oferit de openweathermap.org. Site-ul lor de web are mai multe detalii. +dialog.deletebydate.onlyonedate=Toate punctele au fost \u00eenregistrate la aceea\u0219i dat\u0103. +dialog.deletebydate.intro=Pentru fiecare dat\u0103 din traseu pute\u021bi alege s\u0103 \u0219terge\u021bi sau s\u0103 p\u0103stra\u021bi punctele +dialog.deletebydate.nodate=F\u0103r\u0103 info cronologic +dialog.deletebydate.column.keep=P\u0103streaz\u0103 +dialog.deletebydate.column.delete=\u015eterge +dialog.setaltitudetolerance.text.metres=Limita (\u00een metri) sub care micile urc\u0103ri \u0219i cobor\u00e2ri vor fi ignorate +dialog.setaltitudetolerance.text.feet=Limita (\u00een picioare) sub care micile urc\u0103ri \u0219i cobor\u00e2ri vor fi ignorate +dialog.autoplay.duration=Durat\u0103 (sec) +dialog.autoplay.usetimestamps=Folose\u0219te puncte cronologice +dialog.autoplay.rewind=\u00cenapoi la \u00eenceput +dialog.autoplay.pause=Pauz\u0103 +dialog.autoplay.play=Redare + +# 3d window +dialog.3d.title=Vedere GpsPrune Three-d +dialog.3d.altitudefactor=Factorul de exagerare a altitudinii # Confirm messages -confirm.loadfile=Date incarcate din fi\u015fier +confirm.loadfile=Date \u00eenc\u0103rcate din fi\u015fier confirm.save.ok1=Salvat cu succes confirm.save.ok2=puncte \u00een +confirm.deletepoint.single=punct a fost \u0219ters +confirm.deletepoint.multi=puncte au fost \u0219terse +confirm.point.edit=puncte editate +confirm.mergetracksegments=Segmente traseului au fost unite +confirm.reverserange=Intervalul a fost inversat +confirm.addtimeoffset=Decalajele de timp au fost ad\u0103ugate +confirm.addaltitudeoffset=Decalajele de altitudine au fost ad\u0103ugate +confirm.rearrangewaypoints=Waypoint-urile au fost rearanjate +confirm.rearrangephotos=Fotografiile au fost rearanjate +confirm.splitsegments=Au fost f\u0103cute %d diviz\u0103ri de segmente +confirm.sewsegments=Au fost combinate %d segmente +confirm.cutandmove=Selec\u021bia a fost mutat\u0103 +confirm.interpolate=Punctele au fost ad\u0103ugate +confirm.convertnamestotimes=Numele waypoint-urile au fost convertite +confirm.saveexif.ok=Au fost salvate %d fi\u0219iere foto +confirm.undo.single=opera\u021bia a fost anulat\u0103 +confirm.undo.multi=opera\u021biile au fost anulate +confirm.jpegload.single=foto a fost ad\u0103ugat\u0103 +confirm.jpegload.multi=fotografiile au fost ad\u0103ugate confirm.media.connect=foto/audio conectat confirm.photo.disconnect=foto deconectat confirm.audio.disconnect=audio deconectat confirm.media.removed=\u0219ters +confirm.correlatephotos.single=foto a fost corelat\u0103 +confirm.correlatephotos.multi=fotografiile au fost corelate +confirm.createpoint=punct creat +confirm.rotatephoto=foto rotit\u0103 confirm.running=Executare ... +confirm.lookupsrtm=Au fost g\u0103site %d valori de altitudine confirm.downloadsrtm=S-au desc\u0103rcat %d fi\u015fiere confirm.downloadsrtm.1=S-au desc\u0103rcat %d fi\u015fier +confirm.downloadsrtm.none=Niciun fi\u0219ier nu a fost desc\u0103rcat, ele erau deja prezente \u00een cache +confirm.deletefieldvalues=Valorile c\u00e2mpurilor au fost \u0219terse +confirm.audioload=Fi\u0219iere audio au fost ad\u0103ugate +confirm.correlateaudios.single=clipul audio a fost corelat +confirm.correlateaudios.multi=clipurile audio au fost corelate -# Tips +# Tips, shown just once when appropriate tip.title=Indiciu +tip.useamapcache=Prin configurarea unui cache pe disc (Set\u0103ri -> Salvare h\u0103r\u021bi)\npute\u021bi \u00eembun\u0103t\u0103\u021bi viteza de afi\u0219are \u0219i reduce traficul de re\u021bea +tip.learntimeparams=Rezultatele vor fi mai corecte dac\u0103 folosi\u021bi\nTraseu -> \u00cenva\u021b\u0103 parametri pentru estim\u0103ri de timp\npe traseele deja \u00eenregistrate. +tip.downloadsrtm=Pute\u021bi \u00eembun\u0103t\u0103\u021bi viteza prin folosirea\nInternet -> Descarc\u0103 date SRTM +tip.usesrtmfor3d=Acest traseu nu are valori de altitudine.\nPute\u021bi folosi func\u021biile SRTM pentru a aproxima altitudinile \u00een vederea 3D. +tip.manuallycorrelateone=Decalajul de timp poate fi calculat dac\u0103 cel pu\u021bin un element e conectat. # Buttons button.ok=OK -button.back=Inapoi +button.back=\u00cenapoi button.next=Urmator button.finish=Terminat button.cancel=Renun\u0163\u0103 button.overwrite=Suprascrie -button.moveup=Muta in sus -button.movedown=Muta in jos -button.edit=Editare -button.exit=Iesire -button.close=Inchide -button.continue=Continua +button.moveup=Mut\u0103 \u00een sus +button.movedown=Mut\u0103 \u00een jos +button.edit=Editeaz\u0103 +button.exit=Ie\u0219ire +button.close=\u00cenchide +button.continue=Continu\u0103 button.yes=Da button.no=Nu button.yestoall=Da pentru tot button.notoall=Nu pentru tot +button.always=\u00centotdeauna button.select=Selectare -button.selectall=Selecteaza tot -button.selectnone=Deselecteaza tot -button.load=Descarca +button.selectall=Selecteaz\u0103 tot +button.selectnone=Deselecteaz\u0103 tot +button.preview=Previzualizare +button.load=Descarc\u0103 button.upload=Trimite -button.guessfields=Ghici cimpuri -button.check=Verifica -button.delete=\u015etergere -button.manage=Administra -button.combine=Combina +button.guessfields=Ghice\u0219te c\u00e2mpuri +button.showwebpage=Deschide pagina web +button.check=Verific\u0103 +button.resettodefaults=Revino la valorile standard +button.browse=Browse... +button.addnew=Adaug\u0103 +button.delete=\u015eterge +button.manage=Administreaz\u0103 +button.combine=Combin\u0103 # File types filetype.txt=Fi\u015fiere text @@ -393,23 +702,32 @@ filetype.png=Fi\u015fiere PNG filetype.audio=Fi\u015fiere MP3, OGG, WAV # Display components +display.nodata=Nu exist\u0103 date \u00eenc\u0103rcate +display.noaltitudes=Traseul nu include altitudini +display.notimestamps=Datele traseului nu includ date cronologice +display.novalues=Datele traseului nu includ valori pentru acest c\u00e2mp details.trackdetails=Detalii traseul +details.notrack=Niciun traseu \u00eenc\u0103rcat details.track.points=Puncte -details.pointdetails=Detalii punctul +details.track.file=Fi\u0219ier +details.track.numfiles=Num\u0103rul de fi\u015fiere +details.pointdetails=Detalii punct details.index.selected=Punct -details.index.of=de -details.photofile=Fi\u015fier -details.rangedetails=Detalii intervalul -details.range.selected=Selectat +details.index.of=din +details.nopointselection=Niciun punct selectat +details.photofile=Fi\u015fier foto +details.norangeselection=Niciun interval selectat +details.rangedetails=Detalii interval +details.range.selected=Selectat de la details.range.to=la -details.altitude.to=la +details.altitude.to=p\u00e2n\u0103 la details.range.climb=Urcare details.range.descent=Cobor\u00e2re details.coordformat=Format coordonate -details.distanceunits=Unit\u0103\u0163i de distan\u0163e +details.distanceunits=Unitate de distan\u021b\u0103 display.range.time.secs=s display.range.time.mins=m -display.range.time.hours=o +display.range.time.hours=h display.range.time.days=z details.range.avespeed=Viteza medie details.range.maxspeed=Viteza maxim\u0103 @@ -417,14 +735,19 @@ details.range.numsegments=Num\u0103r de segmente details.range.pace=Ritm details.range.gradient=Gradient details.lists.waypoints=Waypoints -details.lists.photos=Foto-uri +details.lists.photos=Fotografii details.lists.audio=Audio details.photodetails=Detalii foto +details.nophoto=Nicio foto selectat\u0103 details.photo.loading=\u00cenc\u0103rcare details.photo.bearing=Direc\u0163ie details.media.connected=Conectat +details.media.fullpath=Cale complet\u0103 details.audiodetails=Detalii audio +details.noaudio=Niciun clip audio selectat details.audio.file=Fi\u015fier +details.audio.playing=Redare audio... +map.overzoom=Nu exist\u0103 h\u0103r\u021bi la acest nivel de apropiere # Field names fieldname.latitude=Latitudine @@ -436,30 +759,37 @@ fieldname.date=Data fieldname.waypointname=Nume fieldname.waypointtype=Tip fieldname.newsegment=Segment -fieldname.prefix=Cimp +fieldname.custom=Personalizat +fieldname.prefix=C\u00e2mp fieldname.distance=Distan\u0163\u0103 fieldname.duration=Durat\u0103 fieldname.speed=Vitez\u0103 fieldname.verticalspeed=Vitez\u0103 vertical\u0103 fieldname.description=Descriere +fieldname.mediafilename=Fi\u0219ier # Measurement units +units.original=Ini\u021bial units.default=Implicit units.metres=Metri units.metres.short=m +units.feet=Picioare +units.feet.short=ft units.kilometres=Kilometri units.kilometres.short=km units.kilometresperhour=km pe or\u0103 -units.kilometresperhour.short=km/o -units.miles=Mil\u0103 +units.kilometresperhour.short=km/h +units.miles=Mile units.miles.short=mi -units.milesperhour=mil\u0103 pe or\u0103 -units.milesperhour.short=mpo -units.nauticalmiles=Mil\u0103 marin\u0103 -units.nauticalmiles.short=mm +units.milesperhour=mile pe or\u0103 +units.milesperhour.short=mph +units.nauticalmiles=Mile marine +units.nauticalmiles.short=N.m. units.nauticalmilesperhour.short=kn -units.metrespersec=metri pe secund +units.metrespersec=metri pe secund\u0103 units.metrespersec.short=m/s +units.feetpersec=picioare pe secund\u0103 +units.feetpersec.short=ft/s units.hours=ore units.minutes=minute units.seconds=secunde @@ -476,9 +806,15 @@ units.degreesfahrenheit.short=\u00b0F logic.and=\u0219i logic.or=sau -# External urls +# External urls and services +url.googlemaps=maps.google.com wikipedia.lang=ro openweathermap.lang=ro +webservice.peakfinder=Deschide Peakfinder.org +webservice.geohack=Deschide pagina Geohack +webservice.panoramio=Deschide harta Panoramio +webservice.opencachingcom=Deschide Opencaching.com +webservice.opencachingcom.lang=en # Cardinals for 3d plots cardinal.n=N @@ -487,24 +823,80 @@ cardinal.e=E cardinal.w=V # Undo operations -undo.load=\u00cencarc\u0103 date -undo.loadphotos=\u00cencarc\u0103 fotografii -undo.loadaudios=\u00cencarc\u0103 audio -undo.editpoint=Editare punct -undo.deletepoint=\u015eterge punct -undo.removephoto=Elimina foto -undo.removeaudio=Elimina audio -undo.deleterange=\u015eterge interval -undo.deletemarked=\u015eterge puncte -undo.connect=conecteaza -undo.disconnect=deconecteaza -undo.rotatephoto=roti foto +undo.load=\u00eencarc\u0103 date +undo.loadphotos=\u00eencarc\u0103 fotografii +undo.loadaudios=\u00eencarc\u0103 audio +undo.editpoint=editare punct +undo.deletepoint=\u0219terge punct +undo.removephoto=elimina foto +undo.removeaudio=elimin\u0103 audio +undo.deleterange=\u0219tergere interval +undo.croptrack=decupare traseu +undo.deletemarked=\u0219tergere puncte +undo.insert=adaugare puncte +undo.reverse=inversarea selec\u021biei +undo.mergetracksegments=unirea segmentelor traseului +undo.splitsegments=desp\u0103r\u021birea segmentelor traseului +undo.sewsegments=combinarea segmentelor traseului +undo.addtimeoffset=ad\u0103ugarea decalajului de timp +undo.addaltitudeoffset=ad\u0103ugarea decalajului de altitudine +undo.rearrangewaypoints=rearanjarea waypoint-urilor +undo.cutandmove=mutarea sec\u021biunii +undo.connect=conectarea +undo.disconnect=deconectarea +undo.correlatephotos=corelarea fotografiilor +undo.rearrangephotos=rearanjarea fotografiilor +undo.createpoint=ad\u0103ugarea punctului +undo.rotatephoto=rotirea fotografiei +undo.convertnamestotimes=conversia numelor \u00een timpi +undo.lookupsrtm=calcularea altitudinilor din SRTM +undo.deletefieldvalues=\u0219tergerea valorilor c\u00e2mpurilor +undo.correlateaudios=corelarea clipurilor audio # Error messages -error.saveexif.cannotoverwrite1=Fi\u0219ier -error.jpegload.nofilesfound=Nu au fost g\u0103site fi\u0219iere -error.jpegload.nojpegsfound=Nu au fost g\u0103site fi\u0219iere jpeg -error.jpegload.nogpsfound=Nu a fost g\u0103sit informa\u021Bii GPS -error.audioload.nofilesfound=Nu au fost g\u0103site fi\u0219iere audio +error.save.dialogtitle=Eroare la salvarea datelor +error.save.nodata=Nu exist\u0103 nimic de salvat +error.save.failed=Salvarea datelor \u00een fi\u0219ier a e\u0219uat +error.saveexif.filenotfound=Cautarea foto a e\u0219uat +error.saveexif.cannotoverwrite1=Fi\u0219ierul foto +error.saveexif.cannotoverwrite2=este read only \u0219i nu poate fi suprascris. Salvez o copie? +error.saveexif.failed=Salvarea a %d imagini a e\u0219uat +error.saveexif.forced=%d imagini au necesitat salvare for\u021bat\u0103 +error.load.dialogtitle=Eroare la \u00eencarcarea datelor +error.load.noread=Fi\u0219ierul nu poate fi citit +error.load.nopoints=\u00cen fi\u0219ier nu au fost g\u0103site coordonate geografice +error.load.unknownxml=Formatul XML nu poate fi recunoscut +error.load.noxmlinzip=\u00cen interiorul fi\u0219ierului ZIP sau KMZ nu a fost g\u0103sit con\u021binut XML +error.load.othererror=Eroare la citirea fi\u0219ierului: +error.jpegload.dialogtitle=Eroare la \u00eenc\u0103rcarea fotografiilor +error.jpegload.nofilesfound=Nu a fost g\u0103sit niciun fi\u0219ier +error.jpegload.nojpegsfound=Nu a fost g\u0103sit niciun fi\u0219ier jpeg +error.jpegload.nogpsfound=\u00cen EXIF-ul fi\u0219ierelor JPEG nu a fost g\u0103sit\u0103 informa\u021bie GPS +error.jpegload.exifreadfailed=Citirea informa\u021biei EXIF a e\u0219uat. Informa\u021bia EXIF nu poate fi citit\u0103 far\u0103 o bibliotec\u0103 extern\u0103 sau intern\u0103. +error.audioload.nofilesfound=Nu a fost g\u0103sit niciun clip audio. +error.gpsload.unknown=Eroare cu cauz\u0103 necunoscut\u0103 +error.undofailed.title=Anularea a e\u0219uat +error.undofailed.text=\u00cencercarea de anulare a e\u0219uat +error.function.noop.title=Func\u021bia nu a avut niciun efect +error.rearrange.noop=Rearanjarea punctelor nu a avut niciun efect error.function.notavailable.title=Func\u021bie indisponibil\u0103 -error.readme.notfound=Fi\u015Fierul "cite\u015Fte-m\u0103" nu a fost g\u0103sit +error.function.nojava3d=Aceast\u0103 func\u021bie necesit\u0103 biblioteca Java3d +error.3d=Eroare la afi\u0219area 3d +error.readme.notfound=Fi\u0219erul "Cite\u015fte-m\u0103" nu a fost g\u0103sit +error.osmimage.dialogtitle=Eroarea la \u00eenc\u0103rcarea imaginilor h\u0103r\u021bii +error.osmimage.failed=\u00cenc\u0103rcarea imaginilor h\u0103r\u021bii a e\u0219uat. Verifica\u021bi conexiunea la internet. +error.language.wrongfile=Fi\u0219ierul selectat nu pare a fi un fi\u0219ier de limb\u0103 pentru GpsPrune +error.convertnamestotimes.nonames=Niciun nume de waypoint nu a fost g\u0103sit sau nu au putut fi convertite +error.lookupsrtm.nonefound=Pentru aceste puncte nu exist\u0103 valori de altitudine +error.lookupsrtm.nonerequired=Toate punctele au deja altitudine, nu e nimic de calculat +error.gpsies.uploadnotok=Server-ul gpsies a \u00eentors mesajul +error.gpsies.uploadfailed=Upload-ul a e\u0219uat cu eroarea +error.showphoto.failed=\u00cenc\u0103rcarea foto a e\u0219uat +error.playaudiofailed=\u00cencercarea de a reda clipul audio a e\u0219uat +error.cache.notthere=Directorul tile cache nu a fost g\u0103sit +error.cache.empty=Directorul tile cache e gol +error.cache.cannotdelete=Tile-urile (imaginile hart\u0103) nu au putut fi \u0219terse +error.learnestimationparams.failed=Nu pot fi \u00eenv\u0103\u021ba\u021bi parametrii din acest traseu.\n\u00cencerca\u021bi s\u0103 \u00eenc\u0103rca\u021bi mai multe trasee. +error.tracksplit.nosplit=Traseul nu a putut fi spart +error.downloadsrtm.nocache=Fi\u0219ierele nu au putut fi salvate.\nV\u0103 rug\u0103m verifica\u021bi setarea cache-ului. +error.sewsegments.nothingdone=Segmentele nu au putut fi combinate.\n\u00cen traseu sunt acum %d segmente. diff --git a/tim/prune/lang/prune-texts_ru.properties b/tim/prune/lang/prune-texts_ru.properties index ec30638..ea96aa8 100644 --- a/tim/prune/lang/prune-texts_ru.properties +++ b/tim/prune/lang/prune-texts_ru.properties @@ -12,7 +12,7 @@ menu.track=\u0422\u0440\u0435\u043a menu.track.undo=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c menu.track.clearundo=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 menu.track.markrectangle=\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0438 \u0432 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0435 -menu.track.deletemarked=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u043d\u044b\u0435 \u0442\u043e\u0447\u043a\u0438 +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 @@ -108,7 +108,7 @@ function.sewsegments=\u0421\u043a\u043b\u0435\u0438\u0442\u044c \u0441\u0435\u04 function.getgpsies=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0442\u0440\u0435\u043a\u0438 function.uploadgpsies=\u0412\u044b\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0442\u0440\u0435\u043a \u043d\u0430 gpsies.com function.lookupsrtm=\u0412\u044b\u0441\u043e\u0442\u044b \u0432 SRTM -function.downloadsrtm=\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c STRM +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.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 @@ -694,6 +694,7 @@ fieldname.duration=\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u0435\ fieldname.speed=\u0421\u043a\u043e\u0440\u043e\u0441\u0442\u044c fieldname.verticalspeed=\u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c fieldname.description=\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 +fieldname.mediafilename=\u0424\u0430\u0439\u043b # Measurement units units.original=\u041e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 @@ -737,6 +738,7 @@ logic.or=\u0438\u043b\u0438 url.googlemaps=maps.google.ru wikipedia.lang=ru openweathermap.lang=ru +webservice.opencachingcom.lang=ru # Cardinals for 3d plots cardinal.n=\u0421\u0435\u0432\u0435\u0440 diff --git a/tim/prune/lang/prune-texts_sv.properties b/tim/prune/lang/prune-texts_sv.properties index ecde4b7..59a84af 100644 --- a/tim/prune/lang/prune-texts_sv.properties +++ b/tim/prune/lang/prune-texts_sv.properties @@ -11,7 +11,7 @@ menu.track=Sp\u00e5r menu.track.undo=\u00c5ngra menu.track.clearundo=Rensa \u00e5ngra-historik menu.track.markrectangle=Markera punkter i rektangel -menu.track.deletemarked=Radera markerade punkter +function.deletemarked=Radera markerade punkter function.rearrangewaypoints=Ordna waypoints dialog.rearrange.tostart=Alla till b\u00f6rjan av fil dialog.rearrange.toend=Alla till slut av fil diff --git a/tim/prune/lang/prune-texts_tr.properties b/tim/prune/lang/prune-texts_tr.properties index d236ff3..68eca80 100644 --- a/tim/prune/lang/prune-texts_tr.properties +++ b/tim/prune/lang/prune-texts_tr.properties @@ -12,7 +12,7 @@ menu.track.clearundo=Geri alma listesi s\u0131f\u0131rla menu.point.editpoint=Nokta d\u00fczenle menu.point.deletepoint=Noktay\u0131 sil function.deleterange=S\u0131ray\u0131 sil -menu.track.deletemarked=Se\u00e7ili noktalar\u0131 sil +function.deletemarked=Se\u00e7ili noktalar\u0131 sil function.interpolate=\u0130nterpolasyon menu.range.average=Se\u00e7me ortala menu.range.reverse=S\u0131ra tersine \u00e7evir diff --git a/tim/prune/lang/prune-texts_uk.properties b/tim/prune/lang/prune-texts_uk.properties index 3b47eea..380e564 100644 --- a/tim/prune/lang/prune-texts_uk.properties +++ b/tim/prune/lang/prune-texts_uk.properties @@ -11,7 +11,7 @@ menu.track=\u0422\u0440\u0435\u043a menu.track.undo=\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 menu.track.clearundo=\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u043c\u0456\u043d menu.track.markrectangle=\u041f\u043e\u0437\u043d\u0430\u0447\u0438\u0442\u0438 \u0442\u043e\u0447\u043a\u0438 \u0443 \u043f\u0440\u044f\u043c\u043e\u043a\u0443\u0442\u043d\u0438\u043a\u0443 -menu.track.deletemarked=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043f\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0456 \u0442\u043e\u0447\u043a\u0438 +function.deletemarked=\u0412\u0438\u043b\u0443\u0447\u0438\u0442\u0438 \u043f\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0456 \u0442\u043e\u0447\u043a\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 dialog.rearrange.tostart=\u0423\u0441\u0435 \u043d\u0430 \u043f\u043e\u0447\u0430\u0442\u043e\u043a \u0444\u0430\u0439\u043b\u0443 dialog.rearrange.toend=\u0423\u0441\u0435 \u043d\u0430 \u043a\u0456\u043d\u0435\u0446\u044c \u0444\u0430\u0439\u043b\u0443 diff --git a/tim/prune/lang/prune-texts_zh.properties b/tim/prune/lang/prune-texts_zh.properties index 40319fa..a2344e4 100644 --- a/tim/prune/lang/prune-texts_zh.properties +++ b/tim/prune/lang/prune-texts_zh.properties @@ -12,7 +12,7 @@ menu.track=\u8f68\u8ff9 menu.track.undo=\u64a4\u9500 menu.track.clearundo=\u6e05\u9664\u64a4\u9500\u6e05\u5355 menu.track.markrectangle=\u6807\u8bb0\u9009\u53d6\u533a\u57df\u5185\u7684\u70b9 -menu.track.deletemarked=\u5220\u9664\u5df2\u6807\u8bb0\u8f68\u8ff9\u70b9 +function.deletemarked=\u5220\u9664\u5df2\u6807\u8bb0\u8f68\u8ff9\u70b9 menu.range=\u822a\u6bb5 menu.range.all=\u5168\u9009 menu.range.none=\u64a4\u9500\u9009\u62e9 diff --git a/tim/prune/load/FileLoader.java b/tim/prune/load/FileLoader.java index 8669e18..cf60f9e 100644 --- a/tim/prune/load/FileLoader.java +++ b/tim/prune/load/FileLoader.java @@ -63,6 +63,7 @@ public class FileLoader _fileChooser.addChoosableFileFilter(new GenericFileFilter("filetype.kml", new String[] {"kml"})); _fileChooser.addChoosableFileFilter(new GenericFileFilter("filetype.kmz", new String[] {"kmz"})); _fileChooser.setAcceptAllFileFilterUsed(true); + _fileChooser.setFileFilter(_fileChooser.getAcceptAllFileFilter()); // For some reason seems necessary // start from directory in config if already set (by load jpegs) String configDir = Config.getConfigString(Config.KEY_TRACK_DIR); if (configDir == null) {configDir = Config.getConfigString(Config.KEY_PHOTO_DIR);} diff --git a/tim/prune/load/xml/GpxHandler.java b/tim/prune/load/xml/GpxHandler.java index 4208014..225a667 100644 --- a/tim/prune/load/xml/GpxHandler.java +++ b/tim/prune/load/xml/GpxHandler.java @@ -70,7 +70,7 @@ public class GpxHandler extends XmlHandler else if (tag.equals("type")) { _currentTag = _type; } - else if (tag.equals("description")) { + else if (tag.equals("description") || tag.equals("desc")) { _currentTag = _description; } else if (tag.equals("link")) { diff --git a/tim/prune/load/xml/KmlHandler.java b/tim/prune/load/xml/KmlHandler.java index 2ddd1cd..e8f2c6a 100644 --- a/tim/prune/load/xml/KmlHandler.java +++ b/tim/prune/load/xml/KmlHandler.java @@ -13,9 +13,10 @@ import tim.prune.data.Field; public class KmlHandler extends XmlHandler { private boolean _insideCoordinates = false; + private boolean _insideGxTrack = false; private String _value = null; private String _name = null, _desc = null; - private String _imgLink = null; + private String _timestamp = null, _imgLink = null; private StringBuffer _coordinates = null; private ArrayList _coordinateList = null; private ArrayList _pointList = new ArrayList(); @@ -34,13 +35,21 @@ public class KmlHandler extends XmlHandler { String tagName = localName; if (tagName == null || tagName.equals("")) {tagName = qName;} - if (tagName.equalsIgnoreCase("Placemark")) { + tagName = tagName.toLowerCase(); + + if (tagName.equals("placemark")) + { _coordinateList = new ArrayList(); } - else if (tagName.equalsIgnoreCase("coordinates")) { + else if (tagName.equals("coordinates")) + { _insideCoordinates = true; _coordinates = null; } + else if (tagName.equals("gx:track")) + { + _insideGxTrack = true; + } _value = null; super.startElement(uri, localName, qName, attributes); } @@ -55,28 +64,44 @@ public class KmlHandler extends XmlHandler { String tagName = localName; if (tagName == null || tagName.equals("")) {tagName = qName;} - if (tagName.equalsIgnoreCase("Placemark")) + tagName = tagName.toLowerCase(); + + if (tagName.equals("placemark")) { processPlacemark(); - _name = _desc = _imgLink = null; + _name = _desc = _imgLink = _timestamp = null; } - else if (tagName.equalsIgnoreCase("coordinates")) { + else if (tagName.equals("coordinates")) + { _insideCoordinates = false; if (_coordinates != null) _coordinateList.add(_coordinates.toString().trim()); } - else if (tagName.equalsIgnoreCase("name")) _name = _value; - else if (tagName.equalsIgnoreCase("description")) { + else if (tagName.equals("name")) + { + _name = _value; + } + else if (tagName.equals("description")) + { _desc = _value; _imgLink = getImgLink(_desc); } - else if (tagName.equalsIgnoreCase("when")) { - _whenList.add(_value); + else if (tagName.equals("when")) + { + if (!_insideGxTrack) + _timestamp = _value; + else + _whenList.add(_value); } - else if (tagName.equalsIgnoreCase("gx:coord")) { - _whereList.add(_value); + else if (tagName.equals("gx:coord")) + { + if (_insideGxTrack) { + _whereList.add(_value); + } } - else if (tagName.equalsIgnoreCase("gx:Track")) { + else if (tagName.equals("gx:track")) + { processGxTrack(); + _insideGxTrack = false; } super.endElement(uri, localName, qName); } @@ -123,7 +148,7 @@ public class KmlHandler extends XmlHandler { // Add single point to list final String name = (isSingleSelection ? _name : null); - _pointList.add(makeStringArray(coords, name, _desc)); + _pointList.add(makeStringArray(coords, name, _desc, _timestamp)); _linkList.add(_imgLink); } else if (numPoints > 1) @@ -134,7 +159,7 @@ public class KmlHandler extends XmlHandler { if (coordArray[p] != null && coordArray[p].trim().length()>3) { - String[] pointArray = makeStringArray(coordArray[p], null, null); + String[] pointArray = makeStringArray(coordArray[p], null, null, null); if (firstPoint) {pointArray[5] = "1";} // start of segment flag firstPoint = false; _pointList.add(pointArray); @@ -150,14 +175,17 @@ public class KmlHandler extends XmlHandler */ private void processGxTrack() { - if (_whenList.size() > 0 && _whenList.size() == _whereList.size()) + if (!_whereList.isEmpty()) { + // If the whens don't match, then throw them all away + if (_whenList.size() != _whereList.size()) {System.out.println("clearing!"); _whenList.clear();} + // Add each of the unnamed track points to list boolean firstPoint = true; final int numPoints = _whenList.size(); for (int p=0; p < numPoints; p++) { - String when = _whenList.get(p); + String when = (_whenList.isEmpty() ? null : _whenList.get(p)); String where = _whereList.get(p); if (where != null) { @@ -210,10 +238,11 @@ public class KmlHandler extends XmlHandler * @param inCoordinates coordinate string in Kml format * @param inName name of waypoint, or null if track point * @param inDesc description of waypoint, if any + * @param inDesc timestamp of waypoint, if any * @return String array for point */ private static String[] makeStringArray(String inCoordinates, - String inName, String inDesc) + String inName, String inDesc, String inTimestamp) { String[] result = new String[7]; String[] values = inCoordinates.split(","); @@ -223,6 +252,7 @@ public class KmlHandler extends XmlHandler } result[3] = inName; result[4] = inDesc; + result[6] = inTimestamp; return result; } diff --git a/tim/prune/load/xml/XmlHandler.java b/tim/prune/load/xml/XmlHandler.java index b604fde..fa51ebf 100644 --- a/tim/prune/load/xml/XmlHandler.java +++ b/tim/prune/load/xml/XmlHandler.java @@ -22,7 +22,7 @@ public abstract class XmlHandler extends DefaultHandler public abstract Field[] getFieldArray(); /** - * Can be overriden (eg by gpx handler) to provide a track name list + * Can be overridden (eg by gpx handler) to provide a track name list * @return track name list object if any, or null */ public TrackNameList getTrackNameList() { @@ -30,7 +30,7 @@ public abstract class XmlHandler extends DefaultHandler } /** - * Can be overriden (eg by gpx handler) to provide an array of links to media + * Can be overridden (eg by gpx handler) to provide an array of links to media * @return array of Strings if any, or null */ public String[] getLinkArray() { diff --git a/tim/prune/readme.txt b/tim/prune/readme.txt index eae9fe3..8c92694 100644 --- a/tim/prune/readme.txt +++ b/tim/prune/readme.txt @@ -1,8 +1,8 @@ -GpsPrune version 17.2 -===================== +GpsPrune version 18 +=================== GpsPrune is an application for viewing, editing and managing coordinate data from GPS systems, -including format conversion, charting and photo correlation. +including format conversion, charting, 3d visualisation, audio and photo correlation, and online resource lookup. Full details can be found at http://gpsprune.activityworkshop.net/ GpsPrune is copyright 2006-2015 activityworkshop.net and distributed under the terms of the Gnu GPL version 2. @@ -17,7 +17,7 @@ Running ======= To run GpsPrune from the jar file, simply call it from a command prompt or shell: - java -jar gpsprune_17.2.jar + java -jar gpsprune_18.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,21 +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_17.2.jar --lang=DE + java -jar gpsprune_18.jar --lang=DE -New with version 17.2 -===================== -The following fixes were added since version 17.1: - - Speed up the cache management dialog - - Translation improvements - -New with version 17.1 -===================== -The following fixes were added since version 17: - - Fix the decimal precision of coordinates calculated by interpolation and averaging - - Fix the selection adjustment when midpoints within the selection are dragged - - Minor translation improvements +New with version 18 +=================== +The following features were added since version 17: + - New search options using opencaching.de and mapillary + - New web options using peakfinder, geohack and panoramio + - Autoplay function for automatically scrolling through the track + - Marking uphill lift sections of skiing / snowboarding tracks + - Configurable anti-aliasing for map view and profile view + - Allow showing just the lines between track points but not the track points New with version 17 =================== @@ -50,7 +47,7 @@ The following features were added since version 16: - Select the current segment - Adding an altitude tolerance to the climb and descent calculations - Sorting waypoints by name or by timestamp - + New with version 16 =================== The following features were added since version 15: @@ -244,7 +241,7 @@ Further information and updates =============================== To obtain the source code (if it wasn't included in your jar file), or for further information, -please visit the website: http://activityworkshop.net/ +please visit the website: http://gpsprune.activityworkshop.net/ You will find there user guides, screenshots and demo videos illustrating the major features. As GpsPrune is further developed, subsequent versions of the program will also be made freely diff --git a/tim/prune/save/BaseImageConfigDialog.java b/tim/prune/save/BaseImageConfigDialog.java index 0265569..8e7e9ae 100644 --- a/tim/prune/save/BaseImageConfigDialog.java +++ b/tim/prune/save/BaseImageConfigDialog.java @@ -471,7 +471,7 @@ public class BaseImageConfigDialog implements Runnable { _previewPanel.setImage(groutedImage); final int numTilesRemaining = groutedImage.getNumTilesTotal() - groutedImage.getNumTilesUsed(); - final boolean offerDownload = numTilesRemaining > 0 && numTilesRemaining < 50; + final boolean offerDownload = numTilesRemaining > 0 && numTilesRemaining < 50 && Config.getConfigBoolean(Config.KEY_ONLINE_MODE); // Set values of labels _downloadTilesButton.setVisible(offerDownload); _downloadTilesButton.setEnabled(offerDownload); @@ -502,6 +502,7 @@ public class BaseImageConfigDialog implements Runnable try { zoomLevel = Integer.parseInt(_zoomDropdown.getSelectedItem().toString()); } + catch (NullPointerException npe) {} catch (Exception e) { System.err.println("Exception: " + e.getClass().getName() + " : " + e.getMessage()); } diff --git a/tim/prune/save/FileSaver.java b/tim/prune/save/FileSaver.java index ecf61d3..1e199d9 100644 --- a/tim/prune/save/FileSaver.java +++ b/tim/prune/save/FileSaver.java @@ -102,17 +102,25 @@ public class FileSaver _dialog.getContentPane().add(makeDialogComponents()); _dialog.pack(); } + // Has the track got media? + final boolean hasMedia = _app.getTrackInfo().getPhotoList().hasCorrelatedPhotos() + || _app.getTrackInfo().getAudioList().hasCorrelatedAudios(); // Check field list Track track = _app.getTrackInfo().getTrack(); FieldList fieldList = track.getFieldList(); int numFields = fieldList.getNumFields(); - _model = new FieldSelectionTableModel(numFields); + _model = new FieldSelectionTableModel(numFields + (hasMedia ? 1 : 0)); for (int i=0; i", "", inPoint.getWaypointName()); - source = replaceGpxTags(source, "", "", + if (source != null) + { + source = source.replaceAll("", "").replaceAll("", ""); + } + source = replaceGpxTags(source, "", "", XmlUtils.fixCdata(inPoint.getFieldValue(Field.DESCRIPTION))); } // photo / audio links @@ -696,9 +700,9 @@ public class GpxExporter extends GenericFunction implements Runnable String desc = XmlUtils.fixCdata(inPoint.getFieldValue(Field.DESCRIPTION)); if (desc != null && !desc.equals("")) { - inWriter.write("\t\t"); + inWriter.write("\t\t"); inWriter.write(desc); - inWriter.write("\n"); + inWriter.write("\n"); } // Media links, if any if (inPhoto && inPoint.getPhoto() != null) diff --git a/tim/prune/threedee/TerrainHelper.java b/tim/prune/threedee/TerrainHelper.java index 16e63ed..ffe9db8 100644 --- a/tim/prune/threedee/TerrainHelper.java +++ b/tim/prune/threedee/TerrainHelper.java @@ -371,6 +371,7 @@ public class TerrainHelper // System.out.println("Averaging values " + alt1.getMetricValue() + " and " + alt2.getMetricValue()); int newAltitude = (int) ((alt1.getMetricValue() + alt2.getMetricValue()) / 2.0); corner.setFieldValue(Field.ALTITUDE, "" + newAltitude, false); + // TODO: Check forcing metres? Is there a nicer way? } } } @@ -394,14 +395,19 @@ public class TerrainHelper if (prevIndexWithAlt >= 0 && prevIndexWithAlt < (i-1)) { final int gapLen = i - prevIndexWithAlt; - final double alt1 = inTerrainTrack.getPoint(prevIndexWithAlt).getAltitude().getMetricValue(); - final double alt2 = inTerrainTrack.getPoint(i).getAltitude().getMetricValue(); + final int cellIndex1 = inCornerIndex + prevIndexWithAlt * inInc; + final double alt1 = inTerrainTrack.getPoint(cellIndex1).getAltitude().getMetricValue(); + final int cellIndex2 = inCornerIndex + i * inInc; + final double alt2 = inTerrainTrack.getPoint(cellIndex2).getAltitude().getMetricValue(); + //System.out.println("Altitude along edge goes from " + alt1 + " (at " + prevIndexWithAlt + ") to " + + // alt2 + " (at " + i + ")"); for (int j = 1; j < gapLen; j++) { - // System.out.println("Fill in " + (prevIndexWithAlt + j) + " using " + prevIndexWithAlt + " and " + i); final double alt = alt1 + (alt2-alt1) * j / gapLen; + //System.out.println("Fill in " + (prevIndexWithAlt + j) + "(" + (inCornerIndex + (prevIndexWithAlt + j) * inInc) + ") with alt " + (int) alt); final DataPoint p = inTerrainTrack.getPoint(inCornerIndex + (prevIndexWithAlt + j) * inInc); p.setFieldValue(Field.ALTITUDE, "" + (int) alt, false); + // TODO: Check forcing metres? } } prevIndexWithAlt = i; @@ -415,7 +421,7 @@ public class TerrainHelper */ private void fixBiggerHoles(Track inTerrainTrack) { - double[] altitudes = new double[inTerrainTrack.getNumPoints()]; + TerrainPatch patch = new TerrainPatch(_gridSize); for (int i=0; i<_gridSize; i++) { int prevHoriz = -1, prevVert = -1; @@ -425,18 +431,13 @@ public class TerrainHelper { if (prevHoriz > -1 && prevHoriz != (j-1)) { -// System.out.println("Found a gap for y=" + i +" between x=" + prevHoriz + " and " + j + " (" + (j-prevHoriz-1) + ")"); + //System.out.println("Found a gap for y=" + i +" between x=" + prevHoriz + " and " + j + " (" + (j-prevHoriz-1) + ")"); double startVal = inTerrainTrack.getPoint(i * _gridSize + prevHoriz).getAltitude().getMetricValue(); double endVal = inTerrainTrack.getPoint(i * _gridSize + j).getAltitude().getMetricValue(); for (int k=prevHoriz + 1; k< j; k++) { double val = startVal + (k-prevHoriz) * (endVal-startVal) / (j-prevHoriz); - if (altitudes[i * _gridSize + k] > 0.0) { - altitudes[i * _gridSize + k] = (altitudes[i * _gridSize + k] + val) / 2.0; - } - else { - altitudes[i * _gridSize + k] = val; - } + patch.addAltitude(i * _gridSize + k, val, k-prevHoriz, j-prevHoriz); } } prevHoriz = j; @@ -445,32 +446,31 @@ public class TerrainHelper { if (prevVert > -1 && prevVert != (j-1)) { -// System.out.println("Found a gap for x=" + i +" between y=" + prevVert + " and " + j + " (" + (j-prevVert-1) + ")"); + //System.out.println("Found a gap for x=" + i +" between y=" + prevVert + " and " + j + " (" + (j-prevVert-1) + ")"); double startVal = inTerrainTrack.getPoint(prevVert * _gridSize + i).getAltitude().getMetricValue(); double endVal = inTerrainTrack.getPoint(j * _gridSize + i).getAltitude().getMetricValue(); for (int k=prevVert + 1; k< j; k++) { double val = startVal + (k-prevVert) * (endVal-startVal) / (j-prevVert); - if (altitudes[k * _gridSize + i] > 0.0) { - altitudes[k * _gridSize + i] = (altitudes[k * _gridSize + i] + val) / 2.0; - } - else { - altitudes[k * _gridSize + i] = val; - } + patch.addAltitude(k * _gridSize + i, val, k-prevVert, j-prevVert); } } prevVert = j; } } } - // Now the doubles have been set and/or averaged, we can set the values in the points + // Smooth the patch to reduce the blocky effect from the voids + patch.smooth(); + + // Now the doubles have been set and averaged, we can set the values in the points for (int i=0; i 0.0) + if (!p.hasAltitude()) { - p.setFieldValue(Field.ALTITUDE, "" + altitudes[i], false); - p.getAltitude().reset(new Altitude((int) altitudes[i], UnitSetLibrary.UNITS_METRES)); + final double altitude = patch.getAltitude(i); + p.setFieldValue(Field.ALTITUDE, "" + altitude, false); + p.getAltitude().reset(new Altitude((int) altitude, UnitSetLibrary.UNITS_METRES)); } } } diff --git a/tim/prune/threedee/TerrainPatch.java b/tim/prune/threedee/TerrainPatch.java new file mode 100644 index 0000000..10f0b6e --- /dev/null +++ b/tim/prune/threedee/TerrainPatch.java @@ -0,0 +1,116 @@ +package tim.prune.threedee; + +public class TerrainPatch +{ + private int _gridSize = 0; + private double[] _altitudes = null; + private int[] _tempDists = null; + + /** + * Constructor + * @param inGridSize size of grid edge + */ + public TerrainPatch(int inGridSize) + { + _gridSize = inGridSize; + int numNodes = inGridSize * inGridSize; + _altitudes = new double[numNodes]; + _tempDists = new int[numNodes]; + } + + /** + * Add an altitude interpolation to the mix + * @param inPointIndex point index to array + * @param inValue altitude value in metres + * @param inGapIndex index of point within gap, from 1 to gapLength-1 + * @param inGapLength length of gap, minimum 2 + */ + public void addAltitude(int inPointIndex, double inValue, int inGapIndex, int inGapLength) + { + final int dist = Math.min(inGapIndex, inGapLength-inGapIndex); + if (_tempDists[inPointIndex] == 0) + { + if (_altitudes[inPointIndex] > 0.0) System.err.println("Altitude shouldn't be 0 if dist is 0!"); + // first point + _altitudes[inPointIndex] = inValue; + _tempDists[inPointIndex] = dist; + } + else + { + // second point + final double firstValue = _altitudes[inPointIndex]; + final int firstDist = _tempDists[inPointIndex]; + final double firstWeight = dist * 1.0 / (dist + firstDist); + final double secondWeight= firstDist * 1.0 / (dist + firstDist); + _altitudes[inPointIndex] = firstWeight * firstValue + secondWeight * inValue; + _tempDists[inPointIndex] = 0; + } + } + + /** + * Smooth the patch to reduce blockiness + */ + public void smooth() + { + double[] altCopy = new double[_altitudes.length]; + for (int i=0; i<_gridSize; i++) + { + for (int j=0; j<_gridSize; j++) + { + if (hasAltitude(i, j) && hasAltitude(i-1, j) && hasAltitude(i+1, j) + && hasAltitude(i, j+1) && hasAltitude(i-1, j+1) && hasAltitude(i+1, j+1) + && hasAltitude(i, j-1) && hasAltitude(i-1, j-1) && hasAltitude(i+1, j-1)) + { + // got a 3x3 square, can do a blur + double alt = (getAltitude(i, j) + getAltitude(i-1, j) + getAltitude(i+1, j) + + getAltitude(i, j+1) + getAltitude(i-1, j+1) + getAltitude(i+1, j+1) + + getAltitude(i, j-1) + getAltitude(i-1, j-1) + getAltitude(i+1, j-1)) / 9.0; + altCopy[i * _gridSize + j] = alt; + } + } + } + // Copy results back + for (int k=0; k 0.0) + { + _altitudes[k] = altCopy[k]; + } + } + } + + /** + * @param inI first index + * @param inJ second index + * @return true if there is an altitude in the patch in this position + */ + private boolean hasAltitude(int inI, int inJ) + { + return inI >= 0 && inI < _gridSize && inJ >= 0 && inJ < _gridSize + && _altitudes[inI * _gridSize + inJ] > 0.0; + } + + /** + * @param inI first index + * @param inJ second index + * @return true if there is an altitude in the patch in this position + */ + private double getAltitude(int inI, int inJ) + { + if (inI >= 0 && inI < _gridSize && inJ >= 0 && inJ < _gridSize) + { + return _altitudes[inI * _gridSize + inJ]; + } + return 0.0; + } + + /** + * @param inPointIndex point index + * @return altitude value + */ + public double getAltitude(int inPointIndex) + { + if (_tempDists[inPointIndex] != 0) System.err.println("Dists should be 0 if we're retrieving!"); + return _altitudes[inPointIndex]; + } +} diff --git a/tim/prune/undo/UndoStack.java b/tim/prune/undo/UndoStack.java index bca92b1..d3e85e0 100644 --- a/tim/prune/undo/UndoStack.java +++ b/tim/prune/undo/UndoStack.java @@ -3,22 +3,60 @@ package tim.prune.undo; import java.util.Stack; /** - * Stack of undo operations - * which also remembers how many times it's been cleared + * Class to hold an undo operation together with a counter */ -public class UndoStack extends Stack +class UndoOpWithState { - private int _numTimesDeleted = 0; - - /** @return number of times this stack has been deleted */ - public int getNumTimesDeleted() { - return _numTimesDeleted; + public UndoOperation _undoOperation = null; + public int _undoCounter = 0; + /** Constructor */ + public UndoOpWithState(UndoOperation inOp, int inCounter) + { + _undoOperation = inOp; + _undoCounter = inCounter; } +} + +/** + * Stack of undo operations + * which also remembers how many undos have been performed + */ +public class UndoStack extends Stack +{ + /** Number of undos (and clears) already performed */ + private int _numUndos = 0; @Override public void clear() { - _numTimesDeleted++; + _numUndos++; super.clear(); } + + /** Add an undo operation to the stack */ + public synchronized boolean add(UndoOperation inOp) + { + return super.add(new UndoOpWithState(inOp, _numUndos)); + } + + /** Pop the latest operation from the stack */ + public synchronized UndoOperation popOperation() + { + _numUndos++; + return super.pop()._undoOperation; + } + + /** Get the operation at the given index */ + public UndoOperation getOperationAt(int inIndex) + { + return super.elementAt(inIndex)._undoOperation; + } + + /** @return number of undos */ + public int getNumUndos() + { + if (isEmpty()) {return 0;} + // Get the number of undos stored by the last operation on the stack + return peek()._undoCounter; + } }