[Git][debian-gis-team/gpsprune][upstream] New upstream version 23.2

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Mon Oct 2 04:37:38 BST 2023



Bas Couwenberg pushed to branch upstream at Debian GIS Project / gpsprune


Commits:
91c24efc by Bas Couwenberg at 2023-10-02T05:32:32+02:00
New upstream version 23.2
- - - - -


15 changed files:

- build.sh
- tim/prune/GpsPrune.java
- tim/prune/data/Timestamp.java
- tim/prune/data/TimestampLocal.java
- tim/prune/data/TimestampUtc.java
- tim/prune/gui/map/MapSourceLibrary.java
- tim/prune/lang/prune-texts_en.properties
- tim/prune/lang/prune-texts_es.properties
- tim/prune/lang/prune-texts_pl.properties
- tim/prune/lang/prune-texts_pt.properties
- tim/prune/load/FileTypeLoader.java
- tim/prune/load/MediaHelper.java
- tim/prune/readme.txt
- tim/prune/save/GpxWriter.java
- tim/prune/save/KmlExporter.java


Changes:

=====================================
build.sh
=====================================
@@ -1,6 +1,6 @@
 # Build script
 # Version number
-PRUNENAME=gpsprune_23.1
+PRUNENAME=gpsprune_23.2
 # remove compile directory
 rm -rf compile
 # remove dist directory


=====================================
tim/prune/GpsPrune.java
=====================================
@@ -37,9 +37,9 @@ import tim.prune.gui.profile.ProfileChart;
 public class GpsPrune
 {
 	/** Version number of application, used in about screen and for version check */
-	public static final String VERSION_NUMBER = "23.1";
+	public static final String VERSION_NUMBER = "23.2";
 	/** Build number, just used for about screen */
-	public static final String BUILD_NUMBER = "406";
+	public static final String BUILD_NUMBER = "408";
 	/** Static reference to App object */
 	private static App APP = null;
 


=====================================
tim/prune/data/Timestamp.java
=====================================
@@ -66,32 +66,28 @@ public abstract class Timestamp
 	/**
 	 * @return true if this timestamp is after the other one
 	 */
-	public boolean isAfter(Timestamp inOther)
-	{
-		return getMillisecondsSince(inOther) > 0;
+	public boolean isAfter(Timestamp inOther) {
+		return getMillisecondsSince(inOther) > 0L;
 	}
 
 	/**
 	 * @return true if this timestamp is before the other one
 	 */
-	public boolean isBefore(Timestamp inOther)
-	{
-		return getMillisecondsSince(inOther) < 0;
+	public boolean isBefore(Timestamp inOther) {
+		return getMillisecondsSince(inOther) < 0L;
 	}
 
 	/**
 	 * @return true if this timestamp is equal to the other one
 	 */
-	public boolean isEqual(Timestamp inOther)
-	{
-		return getMillisecondsSince(inOther) == 0;
+	public boolean isEqual(Timestamp inOther) {
+		return getMillisecondsSince(inOther) == 0L;
 	}
 
 	/**
 	 * @return the number of seconds since the other timestamp
 	 */
-	public long getSecondsSince(Timestamp inOther)
-	{
+	public long getSecondsSince(Timestamp inOther) {
 		return getMillisecondsSince(inOther) / 1000L;
 	}
 
@@ -100,16 +96,14 @@ public abstract class Timestamp
 	 * @param inOther other, earlier Timestamp
 	 * @return number of milliseconds since other timestamp
 	 */
-	public long getMillisecondsSince(Timestamp inOther)
-	{
+	public long getMillisecondsSince(Timestamp inOther) {
 		return getMilliseconds(null) - inOther.getMilliseconds(null);
 	}
 
 	/**
 	 * @return the number of seconds since the other timestamp using the given timezone
 	 */
-	public long getSecondsSince(Timestamp inOther, TimeZone inTimezone)
-	{
+	public long getSecondsSince(Timestamp inOther, TimeZone inTimezone) {
 		return (getMilliseconds(inTimezone) - inOther.getMilliseconds(inTimezone)) / 1000L;
 	}
 


=====================================
tim/prune/data/TimestampLocal.java
=====================================
@@ -14,8 +14,8 @@ import java.util.TimeZone;
 public class TimestampLocal extends Timestamp
 {
 	private final boolean _valid;
-	private int _year=0, _month=0, _day=0;
-	private int _hour=0, _minute=0, _second=0;
+	private final int _year, _month, _day;
+	private final int _hour, _minute, _second;
 
 
 	/**
@@ -35,15 +35,12 @@ public class TimestampLocal extends Timestamp
 			&& inHour >= 0 && inHour < 24
 			&& inMinute >= 0 && inMinute < 60
 			&& inSecond >= 0 && inSecond < 60;
-		if (_valid)
-		{
-			_year = inYear;
-			_month = inMonth;
-			_day = inDay;
-			_hour = inHour;
-			_minute = inMinute;
-			_second = inSecond;
-		}
+		_year = _valid ? inYear : 0;
+		_month = _valid ? inMonth : 0;
+		_day = _valid ? inDay : 0;
+		_hour = _valid ? inHour : 0;
+		_minute = _valid ? inMinute : 0;
+		_second = _valid ? inSecond : 0;
 	}
 
 


=====================================
tim/prune/data/TimestampUtc.java
=====================================
@@ -18,14 +18,14 @@ import java.util.regex.Pattern;
 public class TimestampUtc extends Timestamp
 {
 	private final boolean _valid;
-	private long _milliseconds = 0L;
-	private String _text = null;
+	private final long _milliseconds;
+	private final String _text;
 
 	private static final DateFormat ISO_8601_FORMAT_NOZ = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
 	private static DateFormat[] ALL_DATE_FORMATS = null;
 	private static Calendar CALENDAR = null;
 	private static final Pattern ISO8601_FRACTIONAL_PATTERN
-		= Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:[\\.,](\\d{1,3}))?(Z|[\\+-]\\d{2}(?::?\\d{2})?)?");
+		= Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(?:[.,](\\d{1,3}))?(Z|[+-]\\d{2}(?::?\\d{2})?)?");
 		//                    year     month     day T  hour    minute    sec             millisec   Z or +/-  hours  :   minutes
 	private static final Pattern GENERAL_TIMESTAMP_PATTERN
 		= Pattern.compile("(\\d{4})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})\\D(\\d{2})");
@@ -98,48 +98,51 @@ public class TimestampUtc extends Timestamp
 	 */
 	public TimestampUtc(String inString)
 	{
-		_text = null;
+		String text = null;
+		long millis = 0L;
 		if (inString != null && !inString.equals(""))
 		{
 			// Try each of the parse types in turn
 			for (ParseType type : ALL_PARSE_TYPES)
 			{
-				if (parseString(inString, type))
+				Long parsedMillis = parseString(inString, type);
+				if (parsedMillis != null)
 				{
 					ALL_PARSE_TYPES[0] = type;
-					_valid = true;
-					_text = inString;
-					return;
+					text = inString;
+					millis = parsedMillis;
+					break;
 				}
 			}
 		}
-		_valid = false;
+		_text = text;
+		_milliseconds = millis;
+		_valid = (_text != null);
 	}
 
 	/**
 	 * Try to parse the given string in the specified way
 	 * @param inString String to parse
 	 * @param inType parse type to use
-	 * @return true if successful
+	 * @return milliseconds if parse was successful, otherwise false
 	 */
-	private boolean parseString(String inString, ParseType inType)
+	private static Long parseString(String inString, ParseType inType)
 	{
 		if (inString == null || inString.equals("")) {
-			return false;
+			return null;
 		}
 		switch (inType)
 		{
-			case NONE: return false;
+			case NONE:
+				return null;
 			case LONG:
 				// Try to parse into a long
 				try
 				{
 					long rawValue = Long.parseLong(inString.trim());
-					_milliseconds = getMilliseconds(rawValue);
-					return true;
+					return getMilliseconds(rawValue);
 				}
-				catch (NumberFormatException nfe)
-				{}
+				catch (NumberFormatException ignored) {}
 				break;
 
 			case ISO8601_FRACTIONAL:
@@ -147,7 +150,7 @@ public class TimestampUtc extends Timestamp
 				if (fmatcher.matches())
 				{
 					try {
-						_milliseconds = getMilliseconds(Integer.parseInt(fmatcher.group(1)), // year
+						return getMilliseconds(Integer.parseInt(fmatcher.group(1)), // year
 							Integer.parseInt(fmatcher.group(2)), // month
 							Integer.parseInt(fmatcher.group(3)), // day
 							Integer.parseInt(fmatcher.group(4)), // hour
@@ -155,9 +158,8 @@ public class TimestampUtc extends Timestamp
 							Integer.parseInt(fmatcher.group(6)), // second
 							fmatcher.group(7),                   // fractional seconds
 							fmatcher.group(8));                  // timezone, if any
-						return true;
 					}
-					catch (NumberFormatException nfe) {}
+					catch (NumberFormatException ignored) {}
 				}
 				break;
 
@@ -178,21 +180,20 @@ public class TimestampUtc extends Timestamp
 					if (matcher.matches())
 					{
 						try {
-							_milliseconds = getMilliseconds(Integer.parseInt(matcher.group(1)),
+							return getMilliseconds(Integer.parseInt(matcher.group(1)),
 								Integer.parseInt(matcher.group(2)),
 								Integer.parseInt(matcher.group(3)),
 								Integer.parseInt(matcher.group(4)),
 								Integer.parseInt(matcher.group(5)),
 								Integer.parseInt(matcher.group(6)),
 								null, null); // no fractions of a second and no timezone
-							return true;
 						}
-						catch (NumberFormatException nfe2) {} // parse shouldn't fail if matcher matched
+						catch (NumberFormatException ignored) {} // parse shouldn't fail if matcher matched
 					}
 				}
-				return false;
+				break;
 		}
-		return false;
+		return null;
 	}
 
 
@@ -200,20 +201,18 @@ public class TimestampUtc extends Timestamp
 	 * Try to parse the given string with the given date format
 	 * @param inString String to parse
 	 * @param inDateFormat Date format to use
-	 * @return true if successful
+	 * @return milliseconds if successful
 	 */
-	private boolean parseString(String inString, DateFormat inDateFormat)
+	private static Long parseString(String inString, DateFormat inDateFormat)
 	{
 		ParsePosition pPos = new ParsePosition(0);
 		Date date = inDateFormat.parse(inString, pPos);
 		if (date != null && inString.length() == pPos.getIndex()) // require use of _all_ the string, not just the beginning
 		{
 			CALENDAR.setTime(date);
-			_milliseconds = CALENDAR.getTimeInMillis();
-			return true;
+			return CALENDAR.getTimeInMillis();
 		}
-
-		return false;
+		return null;
 	}
 
 
@@ -224,6 +223,7 @@ public class TimestampUtc extends Timestamp
 	public TimestampUtc(long inMillis)
 	{
 		_milliseconds = inMillis;
+		_text = null;
 		_valid = true;
 	}
 


=====================================
tim/prune/gui/map/MapSourceLibrary.java
=====================================
@@ -38,8 +38,8 @@ public abstract class MapSourceLibrary
 	 */
 	private static void addFixedSources()
 	{
-		_sourceList.add(new OsmMapSource("Mapnik", "https://[abc].tile.openstreetmap.org/"));
-		_sourceList.add(new OsmMapSource("Cycling Trails", "https://[abc].tile.openstreetmap.org/", "png",
+		_sourceList.add(new OsmMapSource("Mapnik", "https://tile.openstreetmap.org/"));
+		_sourceList.add(new OsmMapSource("Cycling Trails", "https://tile.openstreetmap.org/", "png",
 			"https://tile.waymarkedtrails.org/cycling/", "png", 18));
 		_sourceList.add(new OsmMapSource("Reitkarte", "http://topo[234].wanderreitkarte.de/topo/"));
 		_sourceList.add(new OsmMapSource("Mapsforfree", "https://maps-for-free.com/layer/relief/z{z}/row{y}/{z}_{x}-{y}.jpg", "jpg",


=====================================
tim/prune/lang/prune-texts_en.properties
=====================================
@@ -676,7 +676,7 @@ confirm.audiosloaded.single=1 audio file added
 confirm.audiosloaded=%d audio files added
 confirm.correlateaudios.single=audio was correlated
 confirm.correlateaudios.multi=%d audios were correlated
-confirm.applytimestamps=Timestamps applied to selection
+confirm.applytimestamps=Timestamps were applied to selection
 
 # Tips, shown just once when appropriate
 tip.title=Tip


=====================================
tim/prune/lang/prune-texts_es.properties
=====================================
@@ -310,7 +310,8 @@ dialog.pointnameedit.name=Nombre de waypoint
 dialog.pointnameedit.uppercase=May\u00fasculas
 dialog.pointnameedit.lowercase=min\u00fasculas
 dialog.pointnameedit.titlecase=Mezcla
-dialog.truncatecoords.numdigits=N\u00famero de d\u00edgitos decimales
+dialog.truncatecoords.intro=Seleccione el formato de las coordenadas y el n\u00famero de cifras decimales
+dialog.truncatecoords.numdigits=N\u00famero de cifras decimales
 dialog.truncatecoords.preview=Previsi\u00f3n
 dialog.addtimeoffset.add=A\u00f1adir tiempo
 dialog.addtimeoffset.subtract=Sustraer tiempo
@@ -615,6 +616,8 @@ dialog.projectpoint.bearing=Azimut (grados desde el Norte)
 dialog.projectcircle.desc=Insertar el radio del c\u00edrculo
 dialog.configuresrtm.threesecond=Datos de baja resoluci\u00f3n (3 segundos)
 dialog.configuresrtm.onesecond=Datos de alta resoluci\u00f3n (1 segundo)
+dialog.configuresrtm.userid=Nombre de usuario para NASA Earthdata
+dialog.configuresrtm.password=Contrase\u00f1a para NASA Earthdata
 
 # 3d window
 dialog.3d.title=GpsPrune vista 3-D
@@ -661,6 +664,7 @@ confirm.audiosloaded.single=A\u00f1adido archivo de audio
 confirm.audiosloaded=A\u00f1adidos %d archivos de audio
 confirm.correlateaudios.single=El audio fue correlacionado
 confirm.correlateaudios.multi=%d audios fueron correlacionados
+confirm.applytimestamps=Se han asignado marcas de tiempo a los puntos
 
 # Tips, shown just once when appropriate
 tip.title=Sugerencia


=====================================
tim/prune/lang/prune-texts_pl.properties
=====================================
@@ -25,6 +25,10 @@ menu.range.cutandmove=Wytnij i przesu\u0144 zaznaczenie
 menu.point=Punkt
 menu.point.editpoint=Edytuj punkt
 menu.point.deletepoint=Usu\u0144 punkt
+menu.point.goto=I\u015B\u0107 do
+menu.point.goto.highest=Najwy\u017Cszego punktu
+menu.point.goto.lowest=Najni\u017Cszego point
+menu.point.goto.fastest=Najszybszego point
 menu.photo=Zdj\u0119cie
 menu.photo.saveexif=Zapisz Exif
 menu.audio=Audio
@@ -530,6 +534,9 @@ dialog.displaysettings.wpicon.plectrum=Plektron
 dialog.displaysettings.wpicon.ring=Pier\u015Bcie\u0144
 dialog.displaysettings.linewidth=Wprowad\u017a grubo\u015b\u0107 linii do rysowania \u015bcie\u017cek
 dialog.displaysettings.antialias=U\u017Cyj antyaliasingu
+dialog.displaysettings.wpicon.ring=Pier\u015Bcie\u0144
+dialog.displaysettings.wpicon.pin=Ko\u0142ek tablicy
+dialog.displaysettings.wpicon.flag=Flaga
 dialog.displaysettings.size.small=Ma\u0142e
 dialog.displaysettings.size.medium=\u015arednie
 dialog.displaysettings.size.large=Du\u017ce
@@ -859,7 +866,6 @@ error.readme.notfound=Nie znaleziono pliku Readme
 error.osmimage.dialogtitle=B\u0142\u0105d przy \u0142adowaniu obraz\u00f3w map
 error.osmimage.failed=B\u0142\u0105d przy \u0142adowaniu obraz\u00f3w map. Sprawd\u017a po\u0142\u0105czenie z internetem.
 error.language.wrongfile=Wybrany plik nie jest plikiem z t\u0142umaczeniem dla GpsPrune
-
 error.lookupsrtm.nonefound=Nie znaleziono danych o wysoko\u015bci.
 error.lookupsrtm.nonerequired=Wszystkie pola maj\u0105 informacj\u0119 o wysoko\u015bci, nie ma czego szuka\u0107
 error.showphoto.failed=Nie powiod\u0142o si\u0119 za\u0142adowanie zdj\u0119cia


=====================================
tim/prune/lang/prune-texts_pt.properties
=====================================
@@ -800,9 +800,9 @@ cardinal.w=O
 
 # Undo operations
 undo.loadfile=Carregar dados %s
-undo.loadphoto=Carregar foto
+undo.loadphoto=Carregar foto %s
 undo.loadphotos=Carregar %d fotos
-undo.loadaudio=Carregar arquivo de \u00e1udio
+undo.loadaudio=Carregar arquivo de \u00e1udio '%s'
 undo.loadaudios=Carregar %d arquivos de \u00e1udio
 undo.editpoint=Editar ponto
 undo.editpoint.withname=Editar ponto '%s'


=====================================
tim/prune/load/FileTypeLoader.java
=====================================
@@ -151,7 +151,7 @@ public class FileTypeLoader
 
 	/**
 	 * Load the data from the xml handler
-	 * @param inHandler xml handler which read the data from GPSBabel
+	 * @param inHandler xml handler which read the data
 	 * @param inSourceInfo info about file (or not)
 	 * @param inAutoAppend true to auto-append
 	 * @param inMediaLinks media links, if any


=====================================
tim/prune/load/MediaHelper.java
=====================================
@@ -51,8 +51,11 @@ public abstract class MediaHelper
 	{
 		if (inPath == null || inPath.length() < 5) return null;
 		byte[] data = null;
-		// See if file is in the zip file
-		if (inZipFile != null && inZipFile.exists() && inZipFile.canRead())
+		// See if file is inside a zip file
+		boolean isZip = inZipFile != null && inZipFile.exists() && inZipFile.canRead()
+			&& !inZipFile.getName().toLowerCase().endsWith(".gpx")
+			&& !inZipFile.getName().toLowerCase().endsWith(".kml");
+		if (isZip)
 		{
 			try (ZipFile zf = new ZipFile(inZipFile))
 			{
@@ -64,12 +67,12 @@ public abstract class MediaHelper
 			catch (IOException ioe) {
 				System.err.println("Got ioe from zip file: " + ioe.getMessage());
 			}
-		}
 
-		if (data != null)
-		{
-			final String filename = new File(inPath).getName();
-			return createMediaObject(data, filename, null);
+			if (data != null)
+			{
+				final String filename = new File(inPath).getName();
+				return createMediaObject(data, filename, null);
+			}
 		}
 
 		// If we haven't got a result by now, try to load plain file


=====================================
tim/prune/readme.txt
=====================================
@@ -1,4 +1,4 @@
-GpsPrune version 23.1
+GpsPrune version 23.2
 =====================
 
 GpsPrune is an application for viewing, editing and managing coordinate data from GPS systems,
@@ -17,7 +17,7 @@ Running
 =======
 
 To run GpsPrune from the jar file, simply call it from a command prompt or shell:
-   java -jar gpsprune_23.1.jar
+   java -jar gpsprune_23.2.jar
 
 If the jar file is saved in a different directory, you will need to include the path.
 Depending on your system settings, you may be able to click or double-click on the jar file
@@ -25,9 +25,15 @@ in a file manager window to execute it.  A shortcut, menu item, alias, desktop i
 or other link can of course be made should you wish.
 
 To specify a language other than the default, use an additional parameter, eg:
-   java -jar gpsprune_23.1.jar --lang=DE
+   java -jar gpsprune_23.2.jar --lang=DE
 
 
+New with version 23.2
+=====================
+The following fixes were made since version 23.1:
+  - Bugfix for exporting timestamps of waypoints to gpx and kml/kmz
+  - Update to openstreetmap tile URLs (Issue #86)
+
 New with version 23.1
 =====================
 The following fixes were made since version 23:


=====================================
tim/prune/save/GpxWriter.java
=====================================
@@ -253,11 +253,15 @@ public class GpxWriter
 			inWriter.write("</ele>\n");
 		}
 		// timestamp if available (some waypoints have timestamps, some not)
-		if (inPoint.hasTimestamp() && _settings.getExportTimestamps())
+		if (_settings.getExportTimestamps())
 		{
-			inWriter.write("\t\t<time>");
-			inWriter.write(getPointTimestamp(inPoint).getText(Timestamp.Format.ISO8601, null));
-			inWriter.write("</time>\n");
+			Timestamp waypointTimestamp = getPointTimestamp(inPoint);
+			if (waypointTimestamp != null && waypointTimestamp.isValid())
+			{
+				inWriter.write("\t\t<time>");
+				inWriter.write(getPointTimestamp(inPoint).getText(Timestamp.Format.ISO8601, null));
+				inWriter.write("</time>\n");
+			}
 		}
 		// write waypoint name after elevation and time
 		inWriter.write("\t\t<name>");


=====================================
tim/prune/save/KmlExporter.java
=====================================
@@ -455,7 +455,8 @@ public class KmlExporter extends GenericFunction implements Runnable
 		boolean writeAudios = _pointTypeSelector.getAudiopointsSelected();
 		boolean justSelection = _pointTypeSelector.getJustSelection();
 		// Define xml header (depending on whether extensions are used or not)
-		if (useGxExtensions()) {
+		final boolean useGxExtensions = useGxExtensions();
+		if (useGxExtensions) {
 			inWriter.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<kml xmlns=\"http://earth.google.com/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\">\n");
 		}
 		else {
@@ -478,61 +479,62 @@ public class KmlExporter extends GenericFunction implements Runnable
 			selEnd = _trackInfo.getSelection().getEnd();
 		}
 
-		boolean absoluteAltitudes = _altitudesCheckbox.isSelected();
-		int i = 0;
-		DataPoint point = null;
+		final boolean absoluteAltitudes = _altitudesCheckbox.isSelected();
+		final int numPoints = _track.getNumPoints();
 		boolean hasTrackpoints = false;
 		boolean writtenPhotoHeader = false, writtenAudioHeader = false;
-		final int numPoints = _track.getNumPoints();
 		int numSaved = 0;
 		int photoNum = 0;
 		// Loop over waypoints
-		for (i=0; i<numPoints; i++)
+		for (int i=0; i<numPoints; i++)
 		{
-			point = _track.getPoint(i);
-			boolean writeCurrentPoint = !justSelection || (i>=selStart && i<=selEnd);
-			// Make a blob for each waypoint
-			if (point.isWaypoint())
+			if (justSelection && (i < selStart || i > selEnd)) {
+				continue;
+			}
+			DataPoint point = _track.getPoint(i);
+			if (!point.hasMedia())
 			{
-				if (writeWaypoints && writeCurrentPoint)
+				// Make a blob for each waypoint
+				if (point.isWaypoint())
 				{
-					exportWaypoint(point, inWriter, absoluteAltitudes);
-					numSaved++;
+					if (writeWaypoints)
+					{
+						exportWaypoint(point, inWriter, useGxExtensions, absoluteAltitudes);
+						numSaved++;
+					}
+				}
+				else {
+					hasTrackpoints = true;
 				}
-			}
-			else if (!point.hasMedia())
-			{
-				hasTrackpoints = true;
 			}
 			// Make a blob with description for each photo
 			// Photos have already been written so picture sizes already known
-			if (point.getPhoto() != null && point.getPhoto().isValid() && writePhotos && writeCurrentPoint)
+			if (point.getPhoto() != null && point.getPhoto().isValid() && writePhotos)
 			{
 				if (!writtenPhotoHeader)
 				{
-					inWriter.write("<Style id=\"camera_icon\"><IconStyle><Icon><href>http://maps.google.com/mapfiles/kml/pal4/icon46.png</href></Icon></IconStyle></Style>");
+					inWriter.write("\t<Style id=\"camera_icon\"><IconStyle><Icon><href>https://maps.google.com/mapfiles/kml/pal4/icon46.png</href></Icon></IconStyle></Style>\n");
 					writtenPhotoHeader = true;
 				}
 				photoNum++;
-				exportPhotoPoint(point, inWriter, inExportImages, i, photoNum, absoluteAltitudes);
+				exportPhotoPoint(point, inWriter, inExportImages, i, photoNum, useGxExtensions, absoluteAltitudes);
 				numSaved++;
 			}
 			// Make a blob with description for each audio clip
-			if (point.getAudio() != null && writeAudios && writeCurrentPoint)
+			if (point.getAudio() != null && writeAudios)
 			{
 				if (!writtenAudioHeader)
 				{
-					inWriter.write("<Style id=\"audio_icon\"><IconStyle><color>ff00ffff</color><Icon><href>http://maps.google.com/mapfiles/kml/shapes/star.png</href></Icon></IconStyle></Style>");
+					inWriter.write("\t<Style id=\"audio_icon\"><IconStyle><color>ff00ffff</color><Icon><href>https://maps.google.com/mapfiles/kml/shapes/star.png</href></Icon></IconStyle></Style>\n");
 					writtenAudioHeader = true;
 				}
-				exportAudioPoint(point, inWriter, absoluteAltitudes);
+				exportAudioPoint(point, inWriter, useGxExtensions, absoluteAltitudes);
 				numSaved++;
 			}
 		}
 		// Make a line for the track, if there is one
 		if (hasTrackpoints && writeTrack)
 		{
-			boolean useGxExtensions = _gxExtensionsRadio.isSelected();
 			if (useGxExtensions)
 			{
 				// Write track using the Google Extensions to KML including gx:Track
@@ -543,7 +545,7 @@ public class KmlExporter extends GenericFunction implements Runnable
 				numSaved += writeStandardTrack(inWriter, absoluteAltitudes, selStart, selEnd);
 			}
 		}
-		inWriter.write("</Folder>\n</kml>\n");
+		inWriter.write("\n</Folder>\n</kml>\n");
 		return numSaved;
 	}
 
@@ -563,7 +565,7 @@ public class KmlExporter extends GenericFunction implements Runnable
 		int numSaved = 0;
 		// Set up strings for start and end of track segment
 		String trackStart = "\t<Placemark>\n\t\t<name>track</name>\n\t\t<Style>\n\t\t\t<LineStyle>\n"
-			+ "\t\t\t\t<color>cc" + reverse(ColourUtils.makeHexCode(_colourPatch.getBackground())) + "</color>\n"
+			+ "\t\t\t\t<color>cc" + reverseRGB(ColourUtils.makeHexCode(_colourPatch.getBackground())) + "</color>\n"
 			+ "\t\t\t\t<width>4</width>\n\t\t\t</LineStyle>\n"
 			+ "\t\t</Style>\n\t\t<LineString>\n";
 		if (inAbsoluteAltitudes) {
@@ -623,7 +625,7 @@ public class KmlExporter extends GenericFunction implements Runnable
 		int numSaved = 0;
 		// Set up strings for start and end of track segment
 		String trackStart = "\t<Placemark>\n\t\t<name>track</name>\n\t\t<Style>\n\t\t\t<LineStyle>\n"
-			+ "\t\t\t\t<color>cc" + reverse(ColourUtils.makeHexCode(_colourPatch.getBackground())) + "</color>\n"
+			+ "\t\t\t\t<color>cc" + reverseRGB(ColourUtils.makeHexCode(_colourPatch.getBackground())) + "</color>\n"
 			+ "\t\t\t\t<width>4</width>\n\t\t\t</LineStyle>\n"
 			+ "\t\t</Style>\n\t\t<gx:Track>\n";
 		if (inAbsoluteAltitudes) {
@@ -700,8 +702,11 @@ public class KmlExporter extends GenericFunction implements Runnable
 	 * @param inCode colour code rrggbb
 	 * @return kml code bbggrr
 	 */
-	private static String reverse(String inCode)
+	private static String reverseRGB(String inCode)
 	{
+		if (inCode == null || inCode.length() != 6) {
+			return inCode;
+		}
 		return inCode.substring(4, 6) + inCode.substring(2, 4) + inCode.substring(0, 2);
 	}
 
@@ -709,13 +714,14 @@ public class KmlExporter extends GenericFunction implements Runnable
 	 * Export the specified waypoint into the file
 	 * @param inPoint waypoint to export
 	 * @param inWriter writer object
+	 * @param inWithTimestamp true to include timestamp of waypoint
 	 * @param inAbsoluteAltitude true for absolute altitude
 	 * @throws IOException on write failure
 	 */
-	private void exportWaypoint(DataPoint inPoint, Writer inWriter, boolean inAbsoluteAltitude) throws IOException
+	private void exportWaypoint(DataPoint inPoint, Writer inWriter, boolean inWithTimestamp, boolean inAbsoluteAltitude) throws IOException
 	{
 		String name = inPoint.getWaypointName().trim();
-		exportNamedPoint(inPoint, inWriter, name, inPoint.getFieldValue(Field.DESCRIPTION), null, inAbsoluteAltitude);
+		exportNamedPoint(inPoint, inWriter, name, inPoint.getFieldValue(Field.DESCRIPTION), null, inWithTimestamp, inAbsoluteAltitude);
 	}
 
 
@@ -723,17 +729,19 @@ public class KmlExporter extends GenericFunction implements Runnable
 	 * Export the specified audio point into the file
 	 * @param inPoint audio point to export
 	 * @param inWriter writer object
+	 * @param inWithTimestamp true to include point/audio timestamp
 	 * @param inAbsoluteAltitude true for absolute altitude
 	 * @throws IOException on write failure
 	 */
-	private void exportAudioPoint(DataPoint inPoint, Writer inWriter, boolean inAbsoluteAltitude) throws IOException
+	private void exportAudioPoint(DataPoint inPoint, Writer inWriter, boolean inWithTimestamp, boolean inAbsoluteAltitude)
+		throws IOException
 	{
 		String name = inPoint.getAudio().getName();
 		String desc = null;
 		if (inPoint.getAudio().getFile() != null) {
 			desc = inPoint.getAudio().getFile().getAbsolutePath();
 		}
-		exportNamedPoint(inPoint, inWriter, name, desc, "audio_icon", inAbsoluteAltitude);
+		exportNamedPoint(inPoint, inWriter, name, desc, "audio_icon", inWithTimestamp, inAbsoluteAltitude);
 	}
 
 
@@ -744,14 +752,18 @@ public class KmlExporter extends GenericFunction implements Runnable
 	 * @param inImageLink flag to set whether to export image links or not
 	 * @param inPointNumber number of point for accessing dimensions
 	 * @param inImageNumber number of image for filename
+	 * @param inWithTimestamp true to include point/photo timestamp
 	 * @param inAbsoluteAltitude true for absolute altitudes
 	 * @throws IOException on write failure
 	 */
 	private void exportPhotoPoint(DataPoint inPoint, Writer inWriter, boolean inImageLink,
-		int inPointNumber, int inImageNumber, boolean inAbsoluteAltitude)
+		int inPointNumber, int inImageNumber, boolean inWithTimestamp, boolean inAbsoluteAltitude)
 	throws IOException
 	{
 		String name = inPoint.getPhoto().getName();
+		if (inPoint.isWaypoint()) {
+			name = inPoint.getWaypointName();
+		}
 		String desc = null;
 		if (inImageLink)
 		{
@@ -764,7 +776,7 @@ public class KmlExporter extends GenericFunction implements Runnable
 				+ wrapInTableRow(getPointCaption(inPoint)) + "</table>]]>";
 		}
 		// Export point
-		exportNamedPoint(inPoint, inWriter, name, desc, "camera_icon", inAbsoluteAltitude);
+		exportNamedPoint(inPoint, inWriter, name, desc, "camera_icon", inWithTimestamp, inAbsoluteAltitude);
 	}
 
 	/**
@@ -774,11 +786,12 @@ public class KmlExporter extends GenericFunction implements Runnable
 	 * @param inName name of point
 	 * @param inDesc description of point, or null
 	 * @param inStyle style of point, or null
+	 * @param inWithTimestamp true to include timestamp
 	 * @param inAbsoluteAltitude true for absolute altitudes
 	 * @throws IOException on write failure
 	 */
 	private void exportNamedPoint(DataPoint inPoint, Writer inWriter, String inName,
-		String inDesc, String inStyle, boolean inAbsoluteAltitude)
+		String inDesc, String inStyle, boolean inWithTimestamp, boolean inAbsoluteAltitude)
 	throws IOException
 	{
 		inWriter.write("\t<Placemark>\n\t\t<name>");
@@ -793,10 +806,20 @@ public class KmlExporter extends GenericFunction implements Runnable
 		}
 		if (inStyle != null)
 		{
-			inWriter.write("<styleUrl>#");
+			inWriter.write("\t\t<styleUrl>#");
 			inWriter.write(inStyle);
 			inWriter.write("</styleUrl>\n");
 		}
+		if (inWithTimestamp)
+		{
+			Timestamp pointTimestamp = getPointTimestamp(inPoint);
+			if (pointTimestamp != null && pointTimestamp.isValid())
+			{
+				inWriter.write("\t\t<Timestamp>\n\t\t\t<when>");
+				inWriter.write(pointTimestamp.getText(Timestamp.Format.ISO8601, null));
+				inWriter.write("</when>\n\t\t</Timestamp>\n");
+			}
+		}
 		inWriter.write("\t\t<Point>\n");
 		if (inAbsoluteAltitude && inPoint.hasAltitude()) {
 			inWriter.write("\t\t\t<altitudeMode>absolute</altitudeMode>\n");
@@ -967,4 +990,29 @@ public class KmlExporter extends GenericFunction implements Runnable
 		}
 		return "<tr><td>" + fieldString + "</td></tr>";
 	}
+
+	/**
+	 * Get the timestamp from the point or its media
+	 * @param inPoint point object
+	 * @return Timestamp object if available, or null
+	 */
+	private static Timestamp getPointTimestamp(DataPoint inPoint)
+	{
+		if (inPoint.hasTimestamp()) {
+			return inPoint.getTimestamp();
+		}
+		if (inPoint.getPhoto() != null)
+		{
+			if (inPoint.getPhoto().hasTimestamp()) {
+				return inPoint.getPhoto().getTimestamp();
+			}
+		}
+		if (inPoint.getAudio() != null)
+		{
+			if (inPoint.getAudio().hasTimestamp()) {
+				return inPoint.getAudio().getTimestamp();
+			}
+		}
+		return null;
+	}
 }



View it on GitLab: https://salsa.debian.org/debian-gis-team/gpsprune/-/commit/91c24efca178f9f3b9816dad2f9b67a107d7a68f

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/gpsprune/-/commit/91c24efca178f9f3b9816dad2f9b67a107d7a68f
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20231002/309db540/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list