import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.Set;
-import java.util.Stack;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
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;
/**
* @return the undo stack
*/
- public Stack<UndoOperation> getUndoStack()
+ public UndoStack getUndoStack()
{
return _undoStack;
}
// 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"));
}
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
}
- /**
- * 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
*/
}
else
{
- new UndoManager(this, _frame);
+ new UndoManager(this, _frame).show();
}
}
{
for (int i=0; i<inNumUndos; i++)
{
- _undoStack.pop().performUndo(_trackInfo);
+ _undoStack.popOperation().performUndo(_trackInfo);
}
String message = "" + inNumUndos + " "
+ (inNumUndos==1?I18nManager.getText("confirm.undo.single"):I18nManager.getText("confirm.undo.multi"));
/**
* @return the current data status, used for later comparison
*/
- public DataStatus getCurrentDataStatus() {
- return new DataStatus(_undoStack.size(), _undoStack.getNumTimesDeleted());
- }
-
- /**
- * Show a map url in an external browser
- * @param inSourceIndex index of map source to use
- */
- public void showExternalMap(int inSourceIndex)
+ public DataStatus getCurrentDataStatus()
{
- BrowserLauncher.launchBrowser(UrlGenerator.generateUrl(inSourceIndex, _trackInfo));
+ return new DataStatus(_undoStack.size(), _undoStack.getNumUndos());
}
+
/**
* Display a standard error message
* @param inTitleKey key to lookup for window title
public class DataStatus
{
private int _undoSize = 0;
- private int _deleteCount = 0;
+ private int _numUndos = 0;
/**
* Constructor
* @param inUndoSize current size of undo stack
- * @param inDeleteCount number of times undo stack has been deleted
+ * @param inNumUndos number of operations undone
*/
- public DataStatus(int inUndoSize, int inDeleteCount)
+ public DataStatus(int inUndoSize, int inNumUndos)
{
_undoSize = inUndoSize;
- _deleteCount = inDeleteCount;
+ _numUndos = inNumUndos;
}
/**
public boolean hasDataChanged(DataStatus inPreviousStatus)
{
return _undoSize != inPreviousStatus._undoSize
- || _deleteCount != inPreviousStatus._deleteCount;
+ || _numUndos != inPreviousStatus._numUndos;
}
}
import tim.prune.correlate.AudioCorrelator;
import tim.prune.correlate.PhotoCorrelator;
import tim.prune.function.*;
+import tim.prune.function.autoplay.AutoplayFunction;
import tim.prune.function.charts.Charter;
import tim.prune.function.compress.CompressTrackFunction;
+import tim.prune.function.compress.DeleteMarkedPointsFunction;
+import tim.prune.function.compress.MarkLiftsFunction;
import tim.prune.function.compress.MarkPointsInRectangleFunction;
import tim.prune.function.deletebydate.DeleteByDateFunction;
import tim.prune.function.distance.DistanceFunction;
public static GenericFunction FUNCTION_SEW_SEGMENTS = null;
public static GenericFunction FUNCTION_REARRANGE_PHOTOS = null;
public static GenericFunction FUNCTION_COMPRESS = null;
+ public static GenericFunction FUNCTION_MARK_LIFTS = null;
+ public static DeleteMarkedPointsFunction FUNCTION_DELETE_MARKED_POINTS = null;
public static GenericFunction FUNCTION_DELETE_RANGE = null;
public static GenericFunction FUNCTION_CROP_TRACK = null;
public static GenericFunction FUNCTION_MARK_IN_RECTANGLE = null;
public static SingleNumericParameterFunction FUNCTION_INTERPOLATE = null;
public static GenericFunction FUNCTION_LOOKUP_SRTM = null;
public static GenericFunction FUNCTION_DOWNLOAD_SRTM = null;
- public static GenericFunction FUNCTION_LOOKUP_WIKIPEDIA = null;
+ public static GenericFunction FUNCTION_NEARBY_WIKIPEDIA = null;
public static GenericFunction FUNCTION_SEARCH_WIKIPEDIA = null;
public static GenericFunction FUNCTION_DOWNLOAD_OSM = null;
public static GenericFunction FUNCTION_ADD_TIME_OFFSET = null;
public static GenericFunction FUNCTION_3D = null;
public static GenericFunction FUNCTION_DISTANCES = null;
public static GenericFunction FUNCTION_FULL_RANGE_DETAILS = null;
+ public static GenericFunction FUNCTION_AUTOPLAY_TRACK = null;
public static GenericFunction FUNCTION_ESTIMATE_TIME = null;
public static GenericFunction FUNCTION_LEARN_ESTIMATION_PARAMS = null;
public static GenericFunction FUNCTION_GET_GPSIES = null;
FUNCTION_SEW_SEGMENTS = new SewTrackSegmentsFunction(inApp);
FUNCTION_REARRANGE_PHOTOS = new RearrangePhotosFunction(inApp);
FUNCTION_COMPRESS = new CompressTrackFunction(inApp);
+ FUNCTION_MARK_LIFTS = new MarkLiftsFunction(inApp);
+ FUNCTION_DELETE_MARKED_POINTS = new DeleteMarkedPointsFunction(inApp);
FUNCTION_DELETE_RANGE = new DeleteSelectedRangeFunction(inApp);
FUNCTION_CROP_TRACK = new CropToSelection(inApp);
FUNCTION_MARK_IN_RECTANGLE = new MarkPointsInRectangleFunction(inApp);
FUNCTION_INTERPOLATE = new InterpolateFunction(inApp);
FUNCTION_LOOKUP_SRTM = new LookupSrtmFunction(inApp);
FUNCTION_DOWNLOAD_SRTM = new DownloadSrtmFunction(inApp);
- FUNCTION_LOOKUP_WIKIPEDIA = new GetWikipediaFunction(inApp);
+ FUNCTION_NEARBY_WIKIPEDIA = new GetWikipediaFunction(inApp);
FUNCTION_SEARCH_WIKIPEDIA = new SearchWikipediaNames(inApp);
FUNCTION_DOWNLOAD_OSM = new DownloadOsmFunction(inApp);
FUNCTION_ADD_TIME_OFFSET = new AddTimeOffset(inApp);
FUNCTION_3D = new ShowThreeDFunction(inApp);
FUNCTION_DISTANCES = new DistanceFunction(inApp);
FUNCTION_FULL_RANGE_DETAILS = new FullRangeDetails(inApp);
+ FUNCTION_AUTOPLAY_TRACK = new AutoplayFunction(inApp);
FUNCTION_ESTIMATE_TIME = new EstimateTime(inApp);
FUNCTION_LEARN_ESTIMATION_PARAMS = new LearnParameters(inApp);
FUNCTION_GET_GPSIES = new GetGpsiesFunction(inApp);
public class GpsPrune
{
/** Version number of application, used in about screen and for version check */
- public static final String VERSION_NUMBER = "17.2";
+ public static final String VERSION_NUMBER = "18";
/** Build number, just used for about screen */
- public static final String BUILD_NUMBER = "320b";
+ public static final String BUILD_NUMBER = "334";
/** Static reference to App object */
private static App APP = null;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.Enumeration;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Properties;
*/
public abstract class I18nManager
{
- private static final String BUNDLE_NAME = "tim.prune.lang.prune-texts";
- private static final Locale BACKUP_LOCALE = new Locale("en", "GB");
-
- private static ResourceBundle EnglishTexts = null;
- private static ResourceBundle LocalTexts = null;
+ /** Properties object into which all the texts are copied */
+ private static Properties LocalTexts = null;
/** External properties file for developer testing */
private static Properties ExternalPropsFile = null;
*/
public static void init(Locale inLocale)
{
+ final String BUNDLE_NAME = "tim.prune.lang.prune-texts";
+ final Locale BACKUP_LOCALE = new Locale("en", "GB");
+
+ LocalTexts = new Properties();
// Load English texts first to use as defaults
- EnglishTexts = ResourceBundle.getBundle(BUNDLE_NAME, BACKUP_LOCALE);
+ loadFromBundle(ResourceBundle.getBundle(BUNDLE_NAME, BACKUP_LOCALE));
// Get bundle for selected locale, if any
try
{
if (inLocale != null)
{
- LocalTexts = ResourceBundle.getBundle(BUNDLE_NAME, inLocale);
+ loadFromBundle(ResourceBundle.getBundle(BUNDLE_NAME, inLocale));
}
else
{
// locale is null so just use the system default
- LocalTexts = ResourceBundle.getBundle(BUNDLE_NAME, Locale.getDefault());
+ loadFromBundle(ResourceBundle.getBundle(BUNDLE_NAME, Locale.getDefault()));
}
}
catch (MissingResourceException mre) { // ignore error, default to english
}
}
+ /**
+ * Copy all the translations from the given bundle and store in the Properties object
+ * overwriting the existing translations if necessary
+ * @param inBundle bundle object loaded from file
+ */
+ private static void loadFromBundle(ResourceBundle inBundle)
+ {
+ Enumeration<String> e = inBundle.getKeys();
+ while (e.hasMoreElements())
+ {
+ String key = e.nextElement();
+ LocalTexts.setProperty(key, inBundle.getString(key));
+ }
+ }
/**
* Add a language file
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;
}
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 */
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
*/
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));
}
/**
-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
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 = {
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;
FIXED_FORMAT5,
FIXED_FORMAT6,
FIXED_FORMAT7,
+ FIXED_FORMAT8,
GENERAL_STRING
}
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
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) {
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)
/**
* 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;
}
}
*/
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));
}
/**
* 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();
}
descBuffer.append("<p>").append(I18nManager.getText("dialog.about.summarytext3")).append("</p>");
descBuffer.append("<p>").append(I18nManager.getText("dialog.about.languages")).append(" : ")
.append("\u010de\u0161tina, deutsch, english, espa\u00F1ol, fran\u00E7ais, italiano, magyar,<br>" +
- " nederlands, polski, portugu\u00EAs, \u0440\u0443\u0441\u0441\u043a\u0438\u0439 (russian), \u4e2d\u6587 (chinese), \u65E5\u672C\u8A9E (japanese),<br>" +
- " \uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean), schwiizerd\u00FC\u00FCtsch, t\u00FCrk\u00E7e, afrikaans, rom\u00E2n\u0103, ukrainian</p>");
+ " nederlands, polski, portugu\u00EAs, rom\u00E2n\u0103, \u0440\u0443\u0441\u0441\u043a\u0438\u0439 (russian), \u4e2d\u6587 (chinese),<br>" +
+ " \u65E5\u672C\u8A9E (japanese), \uD55C\uAD6D\uC5B4/\uC870\uC120\uB9D0 (korean), schwiizerd\u00FC\u00FCtsch, t\u00FCrk\u00E7e, afrikaans, ukrainian</p>");
descBuffer.append("<p>").append(I18nManager.getText("dialog.about.translatedby")).append("</p>");
JEditorPane descPane = new JEditorPane("text/html", descBuffer.toString());
descPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
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") + " : "),
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
inStream.close();
} catch (Exception e) {}
// Add track list to model
- ArrayList<GpsiesTrack> trackList = xmlHandler.getTrackList();
+ ArrayList<SearchResult> trackList = xmlHandler.getTrackList();
_trackListModel.addTracks(trackList);
// Show error message if any
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);
}
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<GpsiesTrack> _trackList = null;
- private GpsiesTrack _track = null;
- private String _lat = null, _lon = null;
+ private ArrayList<SearchResult> _trackList = null;
+ private SearchResult _track = null;
private String _errorMessage = null;
Attributes inAttributes) throws SAXException
{
if (inTagName.equals("geonames")) {
- _trackList = new ArrayList<GpsiesTrack>();
+ _trackList = new ArrayList<SearchResult>();
}
else if (inTagName.equals("entry")) {
- _track = new GpsiesTrack();
- _lat = null;
- _lon = null;
+ _track = new SearchResult();
}
else if (inTagName.equals("status")) {
_errorMessage = inAttributes.getValue("message");
{
if (inTagName.equals("entry")) {
// end of the entry
- _track.setDownloadLink(_lat + "," + _lon);
_trackList.add(_track);
}
else if (inTagName.equals("title")) {
_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 {
/**
* @return the list of tracks
*/
- public ArrayList<GpsiesTrack> getTrackList()
+ public ArrayList<SearchResult> getTrackList()
{
return _trackList;
}
--- /dev/null
+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<SearchResult> _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<SearchResult>();
+ }
+ 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<SearchResult> getTrackList()
+ {
+ return _trackList;
+ }
+
+ /**
+ * @return error message, if any
+ */
+ public String getErrorMessage() {
+ return _errorMessage;
+ }
+}
System.arraycopy(nonPhotos, 0, neworder, 0, numNonPhotos);
System.arraycopy(photos, 0, neworder, numNonPhotos, numPhotos);
}
-
+
// Give track the new point order
pointsChanged = track.replaceContents(neworder);
}
--- /dev/null
+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<SearchResult> 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<numSelected; i++)
+ {
+ int rowNum = rowNums[i];
+ if (rowNum >= 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();
+ }
+}
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
inStream.close();
} catch (Exception e) {}
// Add track list to model
- ArrayList<GpsiesTrack> trackList = xmlHandler.getTrackList();
+ ArrayList<SearchResult> trackList = xmlHandler.getTrackList();
// TODO: Do a better job of sorting replies by relevance - use three different lists
_trackListModel.addTracks(trackList);
}
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);
}
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"
};
--- /dev/null
+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<PointInfo> set = new TreeSet<PointInfo>();
+ int numPoints = inTrack.getNumPoints();
+ for (int i=0; i<numPoints; i++)
+ {
+ PointInfo info = new PointInfo(inTrack.getPoint(i), i);
+ if (info.getTimestamp() != null) {
+ set.add(info);
+ }
+ }
+ // For each point, keep track of the time since the previous time
+ Timestamp previousTime = null;
+ long trackMillis = 0L;
+ // Copy info to point list
+ numPoints = set.size();
+ PointList list = new PointList(numPoints);
+ Iterator<PointInfo> 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<inNumPoints; i++)
+ {
+ list.setPoint(i, i);
+ }
+ list.normalize(inDuration);
+ return list;
+ }
+
+ /**
+ * Run method, for scrolling in separate thread
+ */
+ public void run()
+ {
+ _running = true;
+ _app.getTrackInfo().selectPoint(_pointList.getCurrentPointIndex());
+ while (_running && !_pointList.isFinished())
+ {
+ _pointList.set(System.currentTimeMillis() - _startTime);
+ final int pointIndex = _pointList.getCurrentPointIndex();
+ //System.out.println("Set point index to " + pointIndex);
+ _app.getTrackInfo().selectPoint(pointIndex);
+ long waitInterval = _pointList.getMillisUntilNextPoint(System.currentTimeMillis() - _startTime);
+ if (waitInterval < 20) {waitInterval = 20;}
+ try {Thread.sleep(waitInterval);}
+ catch (InterruptedException ie) {}
+ }
+ _running = false;
+ enableButtons(false, true);
+ }
+}
--- /dev/null
+package tim.prune.function.autoplay;
+
+import tim.prune.data.DataPoint;
+import tim.prune.data.Timestamp;
+
+/**
+ * Holds the information about a single point required for the sorting
+ */
+public class PointInfo implements Comparable<PointInfo>
+{
+ /** 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;
+ }
+}
--- /dev/null
+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;
+ }
+}
*/
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");
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);
}
/**
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
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
--- /dev/null
+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);
+ }
+ }
+}
*/
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();
private int _minZoom = -1, _maxZoom = -1;
private int _numTiles = 0;
private long _totalSize = 0L;
- private boolean _unexpected = false;
/**
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
addZoom(inOther._maxZoom);
if (inOther._zoom > 0)
addZoom(inOther._zoom);
- _unexpected = _unexpected || inOther._unexpected;
}
}
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
{
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());
}
}
--- /dev/null
+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");
+ }
+ }
+}
import javax.swing.JOptionPane;
import tim.prune.App;
+import tim.prune.FunctionLibrary;
import tim.prune.GenericFunction;
import tim.prune.I18nManager;
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;
+ }
}
--- /dev/null
+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<numPoints; i++)
+ {
+ DataPoint currPoint = track.getPoint(i);
+ if (currPoint != null && !currPoint.isWaypoint() && currPoint.hasAltitude() && currPoint.hasTimestamp())
+ {
+ int n = i+1;
+ DataPoint endPoint = track.getPoint(n);
+ while (endPoint != null && endPoint.hasAltitude() && endPoint.hasTimestamp() &&
+ !endPoint.isWaypoint() && endPoint.getTimestamp().getSecondsSince(currPoint.getTimestamp()) < 120)
+ {
+ n++;
+ endPoint = track.getPoint(n);
+ }
+ if (endPoint != null && endPoint.hasAltitude() && endPoint.hasTimestamp() && !endPoint.isWaypoint()
+ && n > (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<numPoints; i++)
+ {
+ DataPoint point = track.getPoint(i);
+ if (!point.isWaypoint()) point.setMarkedForDeletion(markFlags[i]);
+ if (markFlags[i]) numMarked++;
+ }
+ // Inform subscribers to update display
+ UpdateMessageBroker.informSubscribers();
+ // Confirm message showing how many marked
+ if (numMarked > 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;
+ }
+}
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;
double[] coords = _app.getViewport().getBounds();
int currPage = 1;
- ArrayList<GpsiesTrack> trackList = null;
+ ArrayList<SearchResult> trackList = null;
URL url = null;
String descMessage = "";
InputStream inStream = null;
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<GpsiesTrack> _trackList = null;
- private GpsiesTrack _track = null;
+ private ArrayList<SearchResult> _trackList = null;
+ private SearchResult _track = null;
/**
Attributes inAttributes) throws SAXException
{
if (inTagName.equals("tracks")) {
- _trackList = new ArrayList<GpsiesTrack>();
+ _trackList = new ArrayList<SearchResult>();
}
else if (inTagName.equals("track")) {
- _track = new GpsiesTrack();
+ _track = new SearchResult();
}
_value = null;
super.startElement(inUri, inLocalName, inTagName, inAttributes);
/**
* @return the list of tracks
*/
- public ArrayList<GpsiesTrack> getTrackList()
+ public ArrayList<SearchResult> getTrackList()
{
return _trackList;
}
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
public class TrackListModel extends AbstractTableModel
{
/** List of tracks */
- private ArrayList<GpsiesTrack> _trackList = null;
+ private ArrayList<SearchResult> _trackList = null;
/** Column heading for track name */
private String _nameColLabel = null;
/** Column heading for length */
*/
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
* Add a list of tracks to this model
* @param inList list of tracks to add
*/
- public void addTracks(ArrayList<GpsiesTrack> inList)
+ public void addTracks(ArrayList<SearchResult> inList)
{
- if (_trackList == null) {_trackList = new ArrayList<GpsiesTrack>();}
+ if (_trackList == null) {_trackList = new ArrayList<SearchResult>();}
final int prevCount = _trackList.size();
if (inList != null && inList.size() > 0) {
_trackList.addAll(inList);
* @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);
}
-package tim.prune.function.gpsies;
+package tim.prune.function.search;
import java.awt.BorderLayout;
import java.awt.Component;
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,
--- /dev/null
+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<SearchResult> resultList = new ArrayList<SearchResult>();
+ 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<numSelected; i++)
+ {
+ pointData[i] = new String[3]; // lat, long, segment
+ int rowNum = rowNums[i];
+ if (rowNum >= 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();
+ }
+}
-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;
private double _trackLength = 0.0;
/** Download link */
private String _downloadLink = null;
+ /** Coordinates of point */
+ private String _latitude = null, _longitude = null;
/**
{
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;
+ }
}
+ (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);
/** 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 */
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";
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,
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;
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;
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
// 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);
});
_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);
// 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);
// 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
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
_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);
_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());
_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?
--- /dev/null
+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);
+ }
+}
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;
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<String> _actionList;
+ private App _app = null;
+ private JFrame _parentFrame = null;
+ private JDialog _dialog = null;
+ private JList<String> _actionList = null;
/**
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<UndoOperation> 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<undoStack.size(); i++)
{
- undoActions[i] = undoStack.elementAt(undoStack.size()-1-i).getDescription();
+ undoActions[i] = undoStack.getOperationAt(undoStack.size()-1-i).getDescription();
}
_actionList = new JList<String>(undoActions);
_actionList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
_url = inUrl;
_file = inFile;
_observer = inObserver;
- new Thread(this).start();
}
/**
// 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
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;
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;
/** 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 */
_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);
_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());
// 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;
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()) {
}
// 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);
{
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;}
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;}
_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));
}
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;
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)
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;
/**
// 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());
}
}
// 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);
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
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
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
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
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
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
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
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
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?
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
fieldname.speed=Geschwindigkeit
fieldname.verticalspeed=Vertikale Geschwindigkeit
fieldname.description=Beschreibung
+fieldname.mediafilename=Foto- / Audioname
# Measurement units
units.original=Original
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
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
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
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
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
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
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
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
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?
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.
dialog.keys.keylist=<table><tr><td>Pfiil Taste</td><td>Karte verschiebe</td></tr><tr><td>Strg + links, r\u00e4chts Pfiil</td><td>Vorherigi oder n\u00f6chsti Punkt markiere</td></tr><tr><td>Strg + uuf, aba Pfiil</td><td>Ii- oder Uusezoome</td></tr><tr><td>Strg + Bild uuf, ab</td><td>Vorherigi oder n\u00f6chsti Segm\u00e4nt markiere</td></tr><tr><td>Strg + Pos1, \u00c4nde</td><td>Erschti oder letschti Punkt markiere</td></tr><tr><td>Entf</td><td>Aktuelli Punkt l\u00f6sche</td></tr></table>
dialog.keys.normalmodifier=Strg
dialog.keys.macmodifier=Kommando
-dialog.saveconfig.desc=Die folgendi 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)
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<p>oder ne Text-Datei uusw\u00e4hle.
dialog.setlanguage.secondintro=Sie m\u00fcnt Ihri Iistellige speichere und dann<p>GpsPrune wieder neustarte um die Sproch z'\u00e4ndere.
dialog.setlanguage.language=Sproch
dialog.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
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
fieldname.speed=Gschwindikeit
fieldname.verticalspeed=Uf/Ab Gschwindikeit
fieldname.description=Bschriibig
+fieldname.mediafilename=F\u00f6teli- / Audioname
# Measurement units
units.original=Original
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
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
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
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
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
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
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?
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.<br>Copying, redistribution and modification are permitted and encouraged<br>according to the conditions in the included <code>license.txt</code> file.
-dialog.about.summarytext3=Please see <code style="font-weight:bold">http://activityworkshop.net/</code> for more information and tips, including<br>a new PDF user guide you can buy.
+dialog.about.summarytext3=Please see <code style="font-weight:bold">http://activityworkshop.net/</code> for more information and tips, including<br>a PDF user guide you can buy.
dialog.about.languages=Available languages
dialog.about.translatedby=English text by activityworkshop.
dialog.about.systeminfo=System info
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
fieldname.speed=Speed
fieldname.verticalspeed=Vertical speed
fieldname.description=Description
+fieldname.mediafilename=Filename
# Measurement units
units.original=Original
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
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
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
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
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
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
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
fieldname.speed=Velocidad
fieldname.verticalspeed=Velocidad vertical
fieldname.description=Descripci\u00f3n
+fieldname.mediafilename=Archivo
## Measurement units
units.original=Original
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
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
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
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
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
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
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
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,<p> ou bien un fichier de langue \u00e0 utiliser.
dialog.setlanguage.secondintro=Vous devez sauvegarder vos param\u00e8tres puis<p>red\u00e9marrer GpsPrune pour changer de langue.
dialog.setlanguage.language=Langue
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
fieldname.speed=Vitesse
fieldname.verticalspeed=Vitesse verticale
fieldname.description=Description
+fieldname.mediafilename=Nom de fichier
# Measurement units
units.original=Original
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
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
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
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
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
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
dialog.gpsies.activity.snowshoe=H\u00f3talpas s\u00e9ta
dialog.gpsies.activity.sailing=Vitorl\u00e1z\u00e1s
dialog.gpsies.activity.skating=Korcsoly\u00e1z\u00e1s
+dialog.mapillary.nonefound=Nem tal\u00e1lhat\u00f3k f\u00e9nyk\u00e9pek
dialog.wikipedia.column.name=Sz\u00f3cikk neve
dialog.wikipedia.column.distance=T\u00e1vols\u00e1g
dialog.wikipedia.nonefound=Nem tal\u00e1lhat\u00f3 Wikip\u00e9dia sz\u00f3cikk
dialog.about.summarytext2=Gnu GPL licenc alatt ker\u00fclt kiad\u00e1sra a szabad, ny\u00edlt, vil\u00e1gm\u00e9ret\u0171 haszn\u00e1lathoz \u00e9s fejleszt\u00e9shez.<br>M\u00e1sol\u00e1sa, terjeszt\u00e9se \u00e9s m\u00f3dos\u00edt\u00e1sa megengedett \u00e9s \u00f6szt\u00f6nz\u00f6tt<br>a mell\u00e9kelt <code>license.txt</code> 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 <code style="font-weight:bold">http://activityworkshop.net/</code> 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
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
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
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
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
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
fieldname.speed=Velocit\u00e0
fieldname.verticalspeed=Velocit\u00e0 verticale
fieldname.description=Descrizione
+fieldname.mediafilename=File
# Measurement units
units.original=Originale
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
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
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
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
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
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
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?
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
fieldname.speed=Snelheid
fieldname.verticalspeed=Verticale snelheid
fieldname.description=Omschrijving
+fieldname.mediafilename=Bestandsnaam
# Measurement units
units.original=Oorspronkelijke
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
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
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
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
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
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
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
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
fieldname.altitude=Altura
fieldname.timestamp=Tempo
fieldname.time=Tempo
+fieldname.date=Data
fieldname.waypointname=Nome
fieldname.waypointtype=Tipo
fieldname.newsegment=Segmento
fieldname.speed=Velocidade
fieldname.verticalspeed=Velocidade vertical
fieldname.description=Descri\u00e7\u00e3o
+fieldname.mediafilename=Arquivo
# Measurement units
units.original=Original
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
# 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
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
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<br>\u0219i pentru a permite oricui dore\u0219te \u00eembun\u0103t\u0103\u021biea aplica\u021biei.<br>Copierea, redistribuirea \u0219i modificarea sunt permise \u0219i \u00eencurajate<br>\u00een conformitate cu condi\u021biile descrise \u00een fi\u0219ierul <code>license.txt</code> care este inclus \u00een aplica\u021bie.
+dialog.about.summarytext3=V\u0103 rug\u0103m vizita\u021bi <code style="font-weight:bold">http://activityworkshop.net/</code> pentru mai multe informa\u021bii \u0219i indicii, inclusiv<br>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
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=<table><tr><td>Taste s\u0103ge\u021bi</td><td>Mut\u0103 harta st\u00e2nga, dreapta, sus, jos</td></tr><tr><td>Ctrl + s\u0103geat\u0103 st\u00e2nga, dreapta</td><td>Selecteaz\u0103 punctul anterior sau urm\u0103tor</td></tr><tr><td>Ctrl + s\u0103geat\u0103 sus, jos</td><td>Aproprie sau \u00eendep\u0103rteaz\u0103</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Selecteaz\u0103 segmentul anterior sau urm\u0103tor</td></tr><tr><td>Ctrl + Home, End</td><td>Selecteaz\u0103 primul, ultimul punct</td></tr><tr><td>Del</td><td>\u0218terge punctul curent</td></tr></table>
+dialog.keys.normalmodifier=Ctrl
+dialog.keys.macmodifier=Command
+dialog.saveconfig.desc=Urm\u0103toarele set\u0103ri pot fi salvate \u00eentr-un fi\u0219ier de configur\u0103ri :
+dialog.saveconfig.prune.trackdirectory=Director trasee
+dialog.saveconfig.prune.photodirectory=Director foto
dialog.saveconfig.prune.languagecode=Limb\u0103 (RO)
dialog.saveconfig.prune.languagefile=Fi\u015fier de limba
dialog.saveconfig.prune.gpsdevice=Dispozitiv GPS
dialog.saveconfig.prune.gpsformat=Format GPS
-dialog.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,<p>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<p>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
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
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
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
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
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
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.
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
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
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
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
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
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
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
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
_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);}
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")) {
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<String> _coordinateList = null;
private ArrayList<String[]> _pointList = new ArrayList<String[]>();
{
String tagName = localName;
if (tagName == null || tagName.equals("")) {tagName = qName;}
- if (tagName.equalsIgnoreCase("Placemark")) {
+ tagName = tagName.toLowerCase();
+
+ if (tagName.equals("placemark"))
+ {
_coordinateList = new ArrayList<String>();
}
- 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);
}
{
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);
}
{
// 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)
{
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);
*/
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)
{
* @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(",");
}
result[3] = inName;
result[4] = inDesc;
+ result[6] = inTimestamp;
return result;
}
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() {
}
/**
- * 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() {
-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.
=======
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
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
===================
- 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:
===============================
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
{
_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);
try {
zoomLevel = Integer.parseInt(_zoomDropdown.getSelectedItem().toString());
}
+ catch (NullPointerException npe) {}
catch (Exception e) {
System.err.println("Exception: " + e.getClass().getName() + " : " + e.getMessage());
}
_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<numFields; i++)
{
Field field = fieldList.getField(i);
FieldInfo info = new FieldInfo(field, track.hasData(field));
_model.addFieldInfo(info, i);
}
+ // Add a field for photos / audio if any present
+ if (hasMedia)
+ {
+ _model.addFieldInfo(new FieldInfo(Field.MEDIA_FILENAME, true), numFields);
+ }
// Initialise dialog and show it
initDialog(_model, inDefaultDelimiter);
_dialog.setVisible(true);
inBuffer.append(inPoint.getTimestamp().getText(inTimestampFormat));
}
}
+ else if (inField == Field.MEDIA_FILENAME)
+ {
+ if (inPoint.hasMedia())
+ {
+ inBuffer.append(inPoint.getMediaName());
+ }
+ }
else
{
String value = inPoint.getFieldValue(inField);
if (inPoint.isWaypoint())
{
source = replaceGpxTags(source, "<name>", "</name>", inPoint.getWaypointName());
- source = replaceGpxTags(source, "<description>", "</description>",
+ if (source != null)
+ {
+ source = source.replaceAll("<description>", "<desc>").replaceAll("</description>", "</desc>");
+ }
+ source = replaceGpxTags(source, "<desc>", "</desc>",
XmlUtils.fixCdata(inPoint.getFieldValue(Field.DESCRIPTION)));
}
// photo / audio links
String desc = XmlUtils.fixCdata(inPoint.getFieldValue(Field.DESCRIPTION));
if (desc != null && !desc.equals(""))
{
- inWriter.write("\t\t<description>");
+ inWriter.write("\t\t<desc>");
inWriter.write(desc);
- inWriter.write("</description>\n");
+ inWriter.write("</desc>\n");
}
// Media links, if any
if (inPhoto && inPoint.getPhoto() != null)
// 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?
}
}
}
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;
*/
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;
{
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;
{
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<inTerrainTrack.getNumPoints(); i++)
{
DataPoint p = inTerrainTrack.getPoint(i);
- if (!p.hasAltitude() && altitudes[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));
}
}
}
--- /dev/null
+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<altCopy.length; k++)
+ {
+ if (altCopy[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];
+ }
+}
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<UndoOperation>
+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<UndoOpWithState>
+{
+ /** 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;
+ }
}