/* GNU General Public License CacheWolf is a software for PocketPC, Win and Linux that enables paperless caching. It supports the sites geocaching.com and opencaching.de Copyright (C) 2006 CacheWolf development team See http://www.cachewolf.de/ for more information. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package CacheWolf.exp; import com.stevesoft.ewe_pat.Regex; import com.stevesoft.ewe_pat.Transformer; import CacheWolf.MainForm; import CacheWolf.MainTab; import CacheWolf.Preferences; import CacheWolf.controls.ExecutePanel; import CacheWolf.controls.InfoBox; import CacheWolf.database.Attribute; import CacheWolf.database.CWPoint; import CacheWolf.database.CacheHolder; import CacheWolf.database.CacheHolderDetail; import CacheWolf.database.CacheImages; import CacheWolf.database.CacheSize; import CacheWolf.database.CacheTerrDiff; import CacheWolf.database.CacheType; import CacheWolf.database.Log; import CacheWolf.database.LogList; import CacheWolf.database.Travelbug; import CacheWolf.navi.TransformCoordinates; import CacheWolf.utils.Common; import CacheWolf.utils.DateFormat; import CacheWolf.utils.FileBugfix; import CacheWolf.utils.MyLocale; import CacheWolf.utils.SafeXML; import CacheWolf.utils.URLUTF8Encoder; import ewe.filechooser.FileChooser; import ewe.filechooser.FileChooserBase; import ewe.fx.Sound; import ewe.io.BufferedWriter; import ewe.io.File; import ewe.io.FileBase; import ewe.io.FileOutputStream; import ewe.io.FileWriter; import ewe.io.IOException; import ewe.io.InputStream; import ewe.io.PrintWriter; import ewe.io.StreamReader; import ewe.sys.Date; import ewe.sys.Handle; import ewe.sys.Process; import ewe.sys.Time; import ewe.sys.Vm; import ewe.ui.Control; import ewe.ui.ControlConstants; import ewe.ui.ControlEvent; import ewe.ui.DataChangeEvent; import ewe.ui.Event; import ewe.ui.Form; import ewe.ui.FormBase; import ewe.ui.ProgressBarForm; import ewe.ui.mButton; import ewe.ui.mCheckBox; import ewe.ui.mChoice; import ewe.ui.mInput; import ewe.ui.mLabel; import ewe.util.Enumeration; import ewe.util.Hashtable; import ewe.util.Iterator; import ewe.util.zip.ZipEntry; import ewe.util.zip.ZipException; import ewe.util.zip.ZipFile; /** * GPX exporter that should better handle the various tasks that can be accomplished with GPX */ public class GpxExportNg { final static String newLine = "\r\n"; final static String WPNAMESTYLE = "wpNameStyle"; final static String GPXVERSION = "GPXVersion"; final static String PQVERSION = "PQVersion"; final static String WITHGARMINEXTENSIONS = "withGarminExtensions"; final static String WITHGSAKEXTENSIONS = "withGSAKExtensions"; final static String SPLITSIZE = "splitSize"; final static String EXPORTADDIWITHINVALIDCOORDS = "exportAddiWithInvalidCoords"; final static String USECUSTOMICONS = "useCustomIcons"; final static String SENDTOGARMIN = "sendToGarmin"; final static String EXPORTLOGASPLAINTEXT = "exportLogsAsPlainText"; final static String ATTRIB2LOG = "attrib2Log"; final static String MAXNUMBEROFLOGSTOEXPORT = "maxNumberOfLogsToExport"; final static String PREFIX = "prefix"; /** write single GPX file */ final static int OUTPUT_SINGLE = 0; /** write several gpx files (and bmp-files) corresponding to definition in garminmap.xml */ final static int OUTPUT_SEVERAL = 1; /** write a gpi file (and bmp-files). Garmin-"database"-selection as defined by garminmap.xml */ final static int OUTPUT_GPI = 2; /** export is without groundspeak extensions */ final static int NOGSEXTENSION = 0; /** export is like groundspeak pocket query (PQ) */ final static int STYLE_PQEXTENSIONS = 1; /** export follows gc.com MyFinds format */ final static int STYLE_MYFINDS = 2; /** export uses only waypoint id */ final static int WPNAME_ID_CLASSIC = 0; /** export uses waypointid + type, terrain, difficulty, size */ final static int WPNAME_ID_SMART = 1; /** export uses cache names (will be made unique by gpsbabel) */ final static int WPNAME_NAME_SMART = 2; /** name used as key when storing preferences */ final static String exporterName = "GpxExportNG"; /** string representation of true */ final static String TRUE = "True"; /** string representation of false */ final static String FALSE = "False"; /** object used to determine custom symbols and POI categories */ private GarminMap garminMap; /** number of errors / warnings during export */ private int exportErrors = 0; /** */ private String finderid; private String xmlnsgpx; private String xmlnsgsak; private String xmlnspq; private String xmlnsgpxx; final static String GPXLOG = "\t\t\t\t<groundspeak:log id=\"@@LOGID@@\">" + newLine// + ("\t\t\t\t\t<groundspeak:date>@@LOGDATE@@T19:00:00Z</groundspeak:date>") + newLine// + ("\t\t\t\t\t<groundspeak:type>@@LOGTYPE@@</groundspeak:type>") + newLine// + ("\t\t\t\t\t<groundspeak:finder id=\"@@LOGFINDERID@@\">@@LOGFINDER@@</groundspeak:finder>") + newLine// + ("\t\t\t\t\t<groundspeak:text encoded=\"@@LOGENCODE@@\">@@LOGTEXT@@</groundspeak:text>") + newLine// + ("\t\t\t\t</groundspeak:log>") + newLine;// final static String GPXTB = "\t\t\t\t<groundspeak:travelbug id=\"@@TBID@@\" ref=\"@@TBREF@@\">" + newLine// + ("\t\t\t\t\t<groundspeak:name>@@TBNAME@@</groundspeak:name>") + newLine// + ("\t\t\t\t</groundspeak:travelbug>") + newLine;// // FIXME: don't use this until GPX import can strip this off as well final static String GPXADDIINMAIN = "@@ADDIID@@ - @@ADDISHORT@@@@ADDIDELIM@@"// + ("@@ADDILAT@@ @@ADDILON@@@@ADDIDELIM@@")// + ("@@ADDILONG@@@@ADDIDELIM@@");// private static boolean attrib2Log; private static int maxLogs; private int exportStyle; private int outputStyle; private static boolean hasBitmaps; private static boolean hasGpsbabel; private static String bitmapFileName; private Transformer handleLinebreaks; private Transformer removeHTMLTags; private Transformer removeNumericEntities; public GpxExportNg() { garminMap = new GarminMap(); bitmapFileName = FileBase.getProgramDirectory() + "/exporticons/GarminPOI.zip"; // own version if (!(hasBitmaps = new File(bitmapFileName).exists())) { // cw default version bitmapFileName = FileBase.getProgramDirectory() + "/exporticons/exporticons/GarminPOI.zip"; hasBitmaps = new File(bitmapFileName).exists(); } hasGpsbabel = Preferences.itself().gpsbabel != null; finderid = Preferences.itself().gcMemberId; if (finderid.equals("")) Preferences.itself().log("GPX Export: warning gcmemberid not set, check pref.xml", null); handleLinebreaks = new Transformer(true); handleLinebreaks.add(new Regex("\r", "")); handleLinebreaks.add(new Regex("\n", " ")); handleLinebreaks.add(new Regex("<br>", "\n")); handleLinebreaks.add(new Regex("<p>", "\n")); handleLinebreaks.add(new Regex("<hr>", "\n")); handleLinebreaks.add(new Regex("<br />", "\n")); removeHTMLTags = new Transformer(true); removeHTMLTags.add(new Regex("<(.*?)>", "")); removeNumericEntities = new Transformer(true); removeNumericEntities.add(new Regex("&#([xX]?)([a-fA-F0-9]*?);", "")); } private GpxExportNgForm exportOptions; private StringBuffer theLogs = new StringBuffer(); private CacheHolder ch; public void doit() { exportOptions = new GpxExportNgForm(garminMap.exists, hasBitmaps, hasGpsbabel); if (exportOptions.execute() == FormBase.IDCANCEL) { return; } this.exportStyle = this.exportOptions.getGroundspeakExtension(); this.outputStyle = this.exportOptions.getOutputStyle(); if (exportStyle == STYLE_PQEXTENSIONS) { maxLogs = exportOptions.getMaxLogs(); attrib2Log = exportOptions.getAttrib2Log(); } if (this.outputStyle == OUTPUT_SEVERAL || this.outputStyle == OUTPUT_GPI) { outputToDir(); } else { outputToGPXFile(); } if (exportErrors > 0) { new InfoBox(MyLocale.getMsg(5500, "Error"), exportErrors + " errors during export. Check log for details.").wait(FormBase.OKB); } } private void outputToDir() { final Hashtable fileHandles = new Hashtable(); final String outDir = exportOptions.getGpxOutputTo(); final String tempDir; final String baseDir = FileBase.getProgramDirectory(); final String prefix = exportOptions.getPrefix(); ZipFile poiZip = null; if (!garminMap.exists) { Preferences.itself().log("GPX Export: unable to load garminmap.xml", null); new InfoBox(MyLocale.getMsg(5500, "Error"), "unable to load garminmap.xml").wait(FormBase.OKB); return; } new File(outDir).mkdir(); if (outputStyle == OUTPUT_GPI) { // hier werden erstmal die gpx erzeugt tempDir = baseDir + FileBase.separator + "GPXExporterNG.tmp"; new File(tempDir).mkdir(); // only clean up output directory if user has chosen non empty prefix, // since otherwise all present POI would be deleted if (prefix.length() > 0) { String tmp[] = new FileBugfix(outDir).list(prefix + "*.gpi", ewe.io.FileBase.LIST_FILES_ONLY); for (int i = 0; i < tmp.length; i++) { File tmpFile = new File(outDir + FileBase.separator + tmp[i]); tmpFile.delete(); } } } else { // OUTPUT_SEPARATE die gpx werden gleich ins finale Verzeichnis geschrieben tempDir = outDir; String tmp[] = new FileBugfix(tempDir).list(prefix + "*.gpx", ewe.io.FileBase.LIST_FILES_ONLY); for (int i = 0; i < tmp.length; i++) { File tmpFile = new File(tempDir + FileBase.separator + tmp[i]); tmpFile.delete(); } tmp = new FileBugfix(tempDir).list(prefix + "*.bmp", ewe.io.FileBase.LIST_FILES_ONLY); for (int i = 0; i < tmp.length; i++) { File tmpFile = new File(tempDir + FileBase.separator + tmp[i]); tmpFile.delete(); } } ProgressBarForm pbf = new ProgressBarForm(); int poiCounter = 0; try { Handle h = new Handle(); int expCount = 0; int totalCount = MainForm.profile.cacheDB.countVisible(); pbf.showMainTask = false; pbf.setTask(h, "Exporting ..."); pbf.exec(); for (int i = 0; i < MainForm.profile.cacheDB.size(); i++) { ch = MainForm.profile.cacheDB.get(i); if (!ch.isVisible()) { continue; } else if (ch.isIncomplete()) { Preferences.itself().log("skipping export of incomplete waypoint " + ch.getCode(), null); } else { String poiId = garminMap.getPoiId(ch); if (null == poiId) { Preferences.itself().log("GPX Export: unmatched POI ID for " + ch.getCode() + " of type " + ch.getType(), null); exportErrors++; } else { PrintWriter writer; if (fileHandles.containsKey(poiId)) { writer = (PrintWriter) fileHandles.get(poiId); } else { writer = new PrintWriter(new BufferedWriter(new FileWriter(new File(tempDir + FileBase.separator + prefix + poiId + ".gpx")))); fileHandles.put(poiId, writer); writer.print(formatHeader()); } String strOut = formatCache(); if (!strOut.equals("")) { writer.print(strOut); } } } expCount++; h.progress = (float) expCount / (float) totalCount; h.changed(); } try { poiZip = new ZipFile(bitmapFileName); } catch (IOException e) { Preferences.itself().log("GPX Export: warning GarminPOI.zip not found", e, true); exportErrors++; } if (outputStyle == OUTPUT_GPI) { pbf.exit(0); pbf.setTask(h, "Transfer"); pbf.exec(); } Enumeration keys = fileHandles.keys(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); PrintWriter writer = (PrintWriter) fileHandles.get(key); writer.print("</gpx>" + newLine); writer.close(); if (outputStyle == OUTPUT_GPI) { poiCounter++; h.progress = (float) poiCounter / (float) fileHandles.size(); h.changed(); } if (poiZip != null) { if (!copyPoiIcon(tempDir, key, prefix, poiZip)) { exportErrors++; continue; } if (outputStyle == OUTPUT_GPI) { String[] cmdStack = new String[9]; cmdStack[0] = Preferences.itself().gpsbabel; cmdStack[1] = "-i"; cmdStack[2] = "gpx"; cmdStack[3] = "-f"; cmdStack[4] = tempDir + FileBase.separator + prefix + key + ".gpx"; cmdStack[5] = "-o"; cmdStack[6] = "garmin_gpi,sleep=1,category=" + prefix + key + ",bitmap=" + tempDir + FileBase.separator + prefix + key + ".bmp"; cmdStack[7] = "-F"; cmdStack[8] = outDir + FileBase.separator + prefix + key + ".gpi"; Process babelProcess = null; babelProcess = startProcess(cmdStack); StreamReader errorStream = new StreamReader(babelProcess.getErrorStream()); babelProcess.waitFor(); String errorMsg = errorStream.readALine(); if (errorMsg != null) { Preferences.itself().log("GPX Export: " + errorMsg, null); exportErrors++; } errorStream.close(); } } } // tempor�res Verzeichnis l�schen (wird bei gpi nicht mehr gebraucht) if (outputStyle == OUTPUT_GPI) { File tmpdir = new File(tempDir); String tmp[] = new FileBugfix(tempDir).list(prefix + "*.*", ewe.io.FileBase.LIST_FILES_ONLY); for (int i = 0; i < tmp.length; i++) { File tmpFile = new File(tempDir + FileBase.separator + tmp[i]); tmpFile.delete(); } tmpdir.delete(); } pbf.exit(0); } catch (Exception e) { Preferences.itself().log("GPX Export: unknown cause for ", e, true); exportErrors++; pbf.exit(0); } } private void outputToGPXFile() { if (exportOptions.getUseCustomIcons()) { if (!garminMap.exists) { Preferences.itself().log("unable to load garminmap.xml", null); } } final File file; boolean sendToGarmin = exportOptions.getSendToGarmin(); if (sendToGarmin) { file = new File(""); file.createTempFile("gpxexport", null, null); } else { file = new File(exportOptions.getGpxOutputTo()); } Vm.showWait(true); InfoBox infB = new InfoBox("Info", "Exporting", InfoBox.PROGRESS_WITH_WARNINGS); try { PrintWriter outp = new PrintWriter(new BufferedWriter(new FileWriter(file))); int expCount = 0; int totalCount = MainForm.profile.cacheDB.countVisible(); infB.exec(); infB.addWarning(file.getFileExt()); outp.print(formatHeader()); Preferences.itself().log("start: " + new Time().getTime()); Time startZeit = new Time(); int oldProzent = 0; for (int i = 0; i < MainForm.profile.cacheDB.size(); i++) { ch = MainForm.profile.cacheDB.get(i); if (!ch.isVisible()) { continue; } else if (ch.isIncomplete()) { exportErrors++; infB.addWarning("Skipping export of incomplete waypoint " + ch.getCode()); Preferences.itself().log("GPX Export: skipping export of incomplete waypoint " + ch.getCode(), null); } else { int splitSize = exportOptions.getSplitSize(); if (splitSize > 0) { if (expCount % splitSize == 0) { if (expCount > 0) { // schliesse Ausgabedatei outp.print("</gpx>" + newLine); outp.close(); // mache neue Ausgabedatei String newFileName = Common.getPathAndFilename(file.getAbsolutePath()) + (expCount / splitSize) + Common.getExtension(file.getFileExt()); File newFile = new File(newFileName); outp = new PrintWriter(new BufferedWriter(new FileWriter(newFile))); outp.print(formatHeader()); infB.addWarning(newFile.getFileExt()); } } } String strOut = formatCache(); if (!strOut.equals("")) { outp.print(strOut); expCount++; } } Time endZeit = new Time(); long benoetigteZeit = (endZeit.getTime() - startZeit.getTime()) / 1000; // sec if (benoetigteZeit > 1) { startZeit = endZeit; infB.setInfo("Exporting " + expCount + " ( " + totalCount + " )"); infB.redisplay(); } int prozent = ((expCount * 100) / totalCount); if (prozent != oldProzent) { oldProzent = prozent; MainTab.itself.tablePanel.updateStatusBar(" " + prozent + "% "); } if (infB.isClosed()) { break; } } Preferences.itself().log("stop: " + new Time().getTime()); MainTab.itself.tablePanel.updateStatusBar("done:" + expCount); outp.print("</gpx>" + newLine); outp.close(); } catch (Exception ex) { exportErrors++; Preferences.itself().log("GPX Export: unable to write output to " + file.toString(), ex, true); new InfoBox(MyLocale.getMsg(5500, "Error"), "unable to write output to " + file.toString()).wait(FormBase.OKB); return; } finally { infB.close(0); Vm.showWait(false); } if (sendToGarmin) { try { String[] cmdStack = new String[9]; cmdStack[0] = Preferences.itself().gpsbabel; cmdStack[1] = "-i"; cmdStack[2] = "gpx"; cmdStack[3] = "-f"; cmdStack[4] = file.getCreationName(); cmdStack[5] = "-o"; cmdStack[6] = "garmin"; cmdStack[7] = "-F"; cmdStack[8] = Preferences.itself().garminConn + (":"); Process babelProcess = null; babelProcess = startProcess(cmdStack); StreamReader errorStream = new StreamReader(babelProcess.getErrorStream()); babelProcess.waitFor(); String errorMsg = errorStream.readALine(); if (errorMsg != null) { Preferences.itself().log("GPX Export: " + errorMsg, null); exportErrors++; } errorStream.close(); } catch (Exception ex) { Preferences.itself().log("GPX Export error :", ex, true); } file.delete(); } } private String formatCache() { // no addis or custom in MyFindsPq - and of course only finds if (exportStyle == STYLE_MYFINDS) { if ((!ch.isFound() || ch.isCustomWpt() || ch.isAddiWpt())) return ""; } if (!ch.getWpt().isValid()) { if (!ch.isAddiWpt()) { Preferences.itself().log("[GPX Export:formatCache] " + ch.getCode() + " has invalid coords."); return ""; } if (!exportOptions.getExportAddiWithInvalidCoords()) { return ""; } } StringBuffer ret = new StringBuffer(); ch.getDetails(); try { ret.append(formatCompact()); if (exportOptions.getGPXVersion() == 1) ret.append(" <extensions>" + newLine); if (exportStyle == STYLE_PQEXTENSIONS || exportStyle == STYLE_MYFINDS) { ret.append(formatPqExtensions()); } if (exportOptions.getWithGarminExtensions()) { ret.append(formatGarminExtensions()); } if (exportOptions.getWithGSAKExtensions()) { ret.append(formatGSAKExtensions()); } if (exportOptions.getGPXVersion() == 1) ret.append(" </extensions>" + newLine); ret.append(" </wpt>").append(newLine); } catch (IllegalArgumentException e) { exportErrors++; ch.checkIncomplete(); // ch.setIncomplete(true); Preferences.itself().log("GPX Export: " + ch.getCode() + " check incomplete ", e, true); return ""; } catch (Exception e) { exportErrors++; Preferences.itself().log("GPX Export: " + ch.getCode() + " caused ", e, true); return ""; } return ret.toString(); } private String formatCompact() { StringBuffer ret = new StringBuffer(); CWPoint chWpt = ch.getWpt(); if (chWpt.isValid()) ret.append(" <wpt lat=\"" + chWpt.getLatDeg(TransformCoordinates.DD) + "\" lon=\"" + chWpt.getLonDeg(TransformCoordinates.DD) + "\">").append(newLine); else ret.append(" <wpt lat=\"" + "0" + "\" lon=\"" + "0" + "\">").append(newLine); if (exportStyle == STYLE_PQEXTENSIONS || exportStyle == STYLE_MYFINDS) { if (ch.isAddiWpt()) { try { ret.append(" <time>" + ch.mainCache.getHidden() + "T07:00:00Z</time>").append(newLine); } catch (Exception e) { Preferences.itself().log(ch.getCode() + " has no parent", null); exportErrors++; ret.append(" <time>1970-01-01T19:00:00Z</time>").append(newLine); } } else if (ch.isCustomWpt()) { ret.append(" <time>1970-01-01T19:00:00Z</time>").append(newLine); } else { ret.append(" <time>" + ch.getHidden() + "T19:00:00Z</time>").append(newLine); } } if (exportOptions.getWpNameStyle() == WPNAME_ID_SMART) { if (ch.isAddiWpt()) { ret.append(" <name>").append(SafeXML.cleanGPX(ch.mainCache.getCode())).append(" ").append(ch.getCode().substring(0, 2)).append("</name>").append(newLine); } else if (ch.isCustomWpt()) { ret.append(" <name>").append(SafeXML.cleanGPX(ch.getCode())).append("</name>").append(newLine); } else { ret.append(" <name>").append(SafeXML.cleanGPX(ch.getCode()))// .append(" ")// .append(CacheType.getExportShortId(ch.getType()))// .append(String.valueOf(ch.getDifficulty()))// .append(String.valueOf(ch.getTerrain()))// .append(CacheSize.getExportShortId(ch.getSize()))// .append(String.valueOf(ch.getNoFindLogs()))// .append("</name>").append(newLine); } } else { // WPNAME_ID_CLASSIC ret.append(" <name>").append(SafeXML.cleanGPX(ch.getCode())).append("</name>").append(newLine); } // no <cmt> for custom if (!ch.isCustomWpt()) { if (ch.isCacheWpt()) { if (exportStyle == NOGSEXTENSION) { // no <cmt> in PQs / ?Myfinds (used for POI) ret.append(" <cmt>").append(SafeXML.cleanGPX(ch.getName())); ret.append("\n" + SafeXML.cleanGPX(Common.rot13(removeHTMLTags.replaceAll(handleLinebreaks.replaceAll(ch.getDetails().Hints))))); ret.append("</cmt>").append(newLine); } } else { // is ADDI ret.append(" <cmt>"); // ev zus maincachedetails Hints ret.append(SafeXML.cleanGPX(ch.getDetails().LongDescription)); ret.append("</cmt>").append(newLine); } } if (ch.isAddiWpt() || ch.isCustomWpt()) { ret.append(" <desc>").append(SafeXML.cleanGPX(ch.getName())).append("</desc>").append(newLine); } else { ret.append(" <desc>").append(SafeXML.cleanGPX(ch.getName()))// .append(" by ")// .append(SafeXML.cleanGPX(ch.getOwner()))// .append(", ")// .append(CacheType.type2GSTypeTag(ch.getType()))// .append(" (")// .append(CacheTerrDiff.shortDT(ch.getDifficulty()))// .append("/")// .append(CacheTerrDiff.shortDT(ch.getTerrain()))// .append(")")// .append("</desc>").append(newLine); } if (exportStyle == STYLE_PQEXTENSIONS || exportStyle == STYLE_MYFINDS) { if (ch.isCacheWpt()) { if (!ch.isCustomWpt()) { ret.append(" <url>").append(ch.getDetails().URL).append("</url>").append(newLine); ret.append(" <urlname>").append(SafeXML.cleanGPX(ch.getName())).append("</urlname>").append(newLine); } } } if (exportOptions.getGPXVersion() == 1) { // link - tag CacheImages images = ch.getDetails().images.getDisplayImages(ch.getCode()); if (ch.isCacheWpt()) { if (!ch.isCustomWpt()) { for (int i = 0; i < images.size(); i++) { String filename = images.get(i).getFilename(); String url = MainForm.profile.dataDir + filename; // POILoader can only work with JPG-Files if (!filename.endsWith(".jpg")) continue; // check if the file is not deleted if (!(new File(url)).exists()) continue; String comment = images.get(i).getTitle(); ret.append("<link ").append("href=\"" + URLUTF8Encoder.encode(url, false) + "\">").append(newLine); ret.append("<text>" + SafeXML.cleanGPX(comment) + "</text>").append(newLine); ret.append("</link>").append(newLine); } } } } if (exportOptions.getUseCustomIcons()) { ret.append(" <sym>").append(garminMap.getIcon(ch)).append("</sym>").append(newLine); } else { if (ch.isAddiWpt()) { ret.append(" <sym>").append(CacheType.type2SymTag(ch.getType())).append("</sym>").append(newLine); } else if (ch.isCustomWpt()) { ret.append(" <sym>Custom</sym>").append(newLine); } else if (ch.isFound()) { ret.append(" <sym>Geocache Found</sym>").append(newLine); } else { ret.append(" <sym>Geocache</sym>").append(newLine); } } if (exportStyle == STYLE_PQEXTENSIONS || exportStyle == STYLE_MYFINDS) { ret.append(" <type>").append(CacheType.type2TypeTag(ch.getType())).append("</type>").append(newLine); } return ret.toString(); } /** * format gc.com extended cache information as found in a PQ * * @return formatted cache information for cache waypoints or emty string for all other waypoints (additional / custom) */ private String formatPqExtensions() { // no details for addis or custom waypoints // if (ch.isCustomWpt() || ch.isAddiWpt()) if (ch.isAddiWpt()) return ""; StringBuffer ret = new StringBuffer(); ret.append(" <groundspeak:cache id=\"").append(ch.getCacheID())// .append("\" available=\"").append(ch.isAvailable() ? TRUE : FALSE)// .append("\" archived=\"").append(ch.isArchived() ? TRUE : FALSE)// .append("\" xmlns:groundspeak=\"" + xmlnspq + "\">").append(newLine)// .append(" <groundspeak:name>").append(SafeXML.cleanGPX(ch.getName())).append("</groundspeak:name>").append(newLine)// .append(" <groundspeak:placed_by>").append(SafeXML.cleanGPX(ch.getOwner())).append("</groundspeak:placed_by>").append(newLine)// .append(" <groundspeak:owner id=\"").append("31415").append("\">").append(SafeXML.cleanGPX(ch.getOwner())).append("</groundspeak:owner>").append(newLine)// .append(" <groundspeak:type>").append(CacheType.type2GSTypeTag(ch.getType())).append("</groundspeak:type>").append(newLine)// .append(" <groundspeak:container>").append(CacheSize.cw2ExportString(ch.getSize())).append("</groundspeak:container>").append(newLine)// .append(" <groundspeak:attributes>").append(newLine)// .append(formatAttributes())// ab pq Version 1/0/1 .append(" </groundspeak:attributes>").append(newLine)// .append(" <groundspeak:difficulty>").append(CacheTerrDiff.shortDT(ch.getDifficulty())).append("</groundspeak:difficulty>").append(newLine)// .append(" <groundspeak:terrain>").append(CacheTerrDiff.shortDT(ch.getTerrain())).append("</groundspeak:terrain>").append(newLine)// .append(" <groundspeak:country>").append(SafeXML.cleanGPX(ch.getDetails().getCountry())).append("</groundspeak:country>").append(newLine)// .append(" <groundspeak:state>").append(SafeXML.cleanGPX(ch.getDetails().getState())).append("</groundspeak:state>").append(newLine)// .append(" <groundspeak:short_description html=\"").append(ch.isHTML() ? TRUE : FALSE).append("\"></groundspeak:short_description>").append(newLine)// .append(" <groundspeak:long_description html=\"").append(ch.isHTML() ? TRUE : FALSE).append("\">").append(SafeXML.cleanGPX(formatLongDescription())).append("</groundspeak:long_description>").append(newLine)// .append(" <groundspeak:encoded_hints>").append(SafeXML.cleanGPX(Common.rot13(ch.getDetails().Hints))).append("</groundspeak:encoded_hints>").append(newLine)// .append(" <groundspeak:logs>").append(newLine)// .append(formatLogs())// .append(" </groundspeak:logs>").append(newLine)// .append(" <groundspeak:travelbugs>").append(newLine)// .append(formatTbs())// .append(" </groundspeak:travelbugs>").append(newLine)// .append(" </groundspeak:cache>").append(newLine);// return ret.toString(); } private String formatGSAKExtensions() { if (ch.isAddiWpt()) return ""; StringBuffer ret_____ = new StringBuffer(); ret_____.append(" <gsak:wptExtension xmlns:gsak=\"" + xmlnsgsak + "\">").append(newLine); // if (ch.hasNote()) // eigentlich nur die von GC, aber ret_____.append(" <gsak:GcNote>").append(SafeXML.cleanGPX(ch.getDetails().getGCNotes())).append("</gsak:GcNote>").append(newLine); // if (ch.isSolved()) { // wir kennen die OriginalKoordinaten nicht, aber es gibt wohl nichts f�r nur corrected coordinates ret_____.append(" <gsak:LatBeforeCorrect>").append(ch.getWpt().getLatDeg(TransformCoordinates.DD)).append("</gsak:LatBeforeCorrect>").append(newLine) // .append(" <gsak:LonBeforeCorrect>").append(ch.getWpt().getLonDeg(TransformCoordinates.DD)).append("</gsak:LonBeforeCorrect>").append(newLine); // } if (Preferences.itself().useGCFavoriteValue) ret_____.append(" <gsak:FavPoints>").append("" + ch.getNumRecommended()).append("</gsak:FavPoints>").append(newLine); // ret_____.append(" <gsak:IsPremium>").append(SafeXML.strxmlencode(ch.isPremiumCache())).append("</gsak:IsPremium>").append(newLine); // // ret_____.append(" <gsak:CacheImages>").append("").append("</gsak:CacheImages>").append(newLine) // replace "" by format spoilers ret_____.append(" </gsak:wptExtension>").append(newLine);// return ret_____.toString(); } private String formatGarminExtensions() { StringBuffer ret_____ = new StringBuffer(); ret_____.append(" <gpxx:WaypointExtension xmlns:gpxx=\"" + xmlnsgpxx + "\">").append(newLine); // ret_____.append(" <gpxx:DisplayMode>").append("SymbolAndName").append("</gpxx:DisplayMode>").append(newLine); // ret_____.append(" </gpxx:WaypointExtension>").append(newLine);// return ret_____.toString(); } /* private String formatCacheboxExtensions() { if (ch.isAddiWpt()) return ""; StringBuffer ret_____ = new StringBuffer(); //cachebox-extension // /note // /solver // /clue = bei Wegpunkten Beschreibung // /Parent = bei Wegpunkten - GCxxxx return ret_____.toString(); } */ private String formatTbs() { StringBuffer ret = new StringBuffer(); Travelbug Tb; for (int i = 0; i < ch.getDetails().Travelbugs.size(); i++) { Tb = ch.getDetails().Travelbugs.getTB(i); ret.append(" <groundspeak:travelbug id=\"").// append(Integer.toString(i)).// append("\" ref=\"TB\">").// // append(newLine).// // append(" <groundspeak:name>").// append("<groundspeak:name>").// append(SafeXML.cleanGPX(Tb.getName())).// append("</groundspeak:name>").// // append(newLine).// // append(" </groundspeak:travelbug>\r\n");// append("</groundspeak:travelbug>\r\n");// } return ret.toString(); } /** * */ private String formatAttributes() { StringBuffer ret = new StringBuffer(); Attribute attrib; for (int i = 0; i < ch.getDetails().attributes.count(); i++) { // <groundspeak:attribute id="X" inc="Y">text f�r X</groundspeak:attribute> attrib = ch.getDetails().attributes.getAttribute(i); if (attrib.getGCId().length() > 0) { ret.append(" <groundspeak:attribute id=\"").// append(attrib.getGCId()).// append("\" inc=\"").// append(attrib.getInc()).// append("\">").// append(attrib.getGCText()).// append("</groundspeak:attribute>").// append(newLine);// } } return ret.toString(); } private String formatLogs() { theLogs.setLength(0); if (exportStyle == STYLE_MYFINDS) { if (ch.isFound()) { CacheHolderDetail chD = ch.getDetails(); // perhaps there is no Ownlog yet if (chD.getOwnLog() == null) { Preferences.itself().log(chD.getParent().getCode() + " missing own Log", null); return ""; } else { addLog(chD.getOwnLog()); } } } else { // it is PQ LogList logs = ch.getDetails().CacheLogs; int exportlogs; if (maxLogs < logs.size()) { if (maxLogs == -1) exportlogs = logs.size(); else exportlogs = maxLogs; } else { exportlogs = logs.size(); } final String cacheID = ch.getCacheID(); // with a special log addLog(createAttrLog(exportlogs)); // don't export the "dummy" lastLog (possibly accidently no Log.MAXLOGICON set, so check if empty) if (exportlogs > 0) { Log lastLog = logs.getLog(exportlogs - 1); if (lastLog.getIcon().equals(Log.MAXLOGICON)) exportlogs = exportlogs - 1; else if (lastLog.getIcon().length() == 0) exportlogs = exportlogs - 1; } int anzOwnLogs = 0; // CW doesn't save the LogID (upto version ~1.3.3394). // So we generate one by ch.GetCacheID() + Integer.toString(i) for (int i = 0; i < exportlogs; i++) { Log theLog = logs.getLog(i); String logID = theLog.getLogID(); if (logID.length() == 0) { theLog.setLogID(cacheID + Integer.toString(i)); } addLog(theLog); if (theLog.isOwnLog()) { anzOwnLogs = anzOwnLogs + 1; if (anzOwnLogs > 1) { Preferences.itself().log("doppelter eigener Fund" + ch.getCode(), null); } } } } return theLogs.toString(); } private Log createAttrLog(int exportlogs) { StringBuffer logText = new StringBuffer(); if (attrib2Log) { for (int i = 0; i < ch.getDetails().attributes.count(); i++) { Attribute attrib = ch.getDetails().attributes.getAttribute(i); logText.append(attrib.getInc() == 1 ? "Yes: " : "No: ").append(attrib.getMsg()).append("<br />").append(newLine); } } if (ch.isSolved()) { logText.append(MyLocale.getMsg(362, "solved")); } if (ch.hasNote()) { logText.append(SafeXML.cleanGPX(ch.getDetails().getCacheNotes())).append("<br />").append(newLine); } /* if (!ch.getLastSync().equals("")) logText.append(MyLocale.getMsg(1051, "Last sync date") + ": " + DateFormat.formatLastSyncDate(ch.getLastSync(), "")).append(newLine); */ if (logText.length() > 0) { Log log = new Log(ch.getCacheID() + Integer.toString(exportlogs), "-2", "icon_note.gif", DateFormat.yyyyMMddHHmmss2gpxLogdate(ch.getLastSync()), "CacheWolf", logText.toString()); return log; } else return null; } private void addLog(Log log) { if (log == null) return; String logMessage = log.getMessage(); if (exportOptions.getExportLogsAsPlainText()) { logMessage = removeHTMLTags.replaceAll(handleLinebreaks.replaceAll(logMessage)); } logMessage = removeNumericEntities.replaceAll(logMessage); Transformer replacePlaceholder = new Transformer(true); replacePlaceholder.add(new Regex("@@LOGID@@", log.getLogID())); replacePlaceholder.add(new Regex("@@LOGDATE@@", log.getDate())); replacePlaceholder.add(new Regex("@@LOGTYPE@@", log.icon2GPXType())); replacePlaceholder.add(new Regex("@@LOGFINDERID@@", log.getFinderID())); replacePlaceholder.add(new Regex("@@LOGFINDER@@", SafeXML.cleanGPX(log.getLogger()))); replacePlaceholder.add(new Regex("@@LOGENCODE@@", "")); replacePlaceholder.add(new Regex("@@LOGTEXT@@", SafeXML.cleanGPX(logMessage))); theLogs.append(replacePlaceholder.replaceAll(GPXLOG)); } private String formatHeader() { // GPX //http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd String gpx = ""; String xmlnsGPXVersion; String gpxVersion; switch (exportOptions.getGPXVersion()) { case 0: gpxVersion = "1.0"; xmlnsGPXVersion = "1/0"; //ohne das <extensions> tag break; default: gpxVersion = "1.1"; xmlnsGPXVersion = "1/1"; //mit <extensions> tag } xmlnsgpx = "http://www.topografix.com/GPX/" + xmlnsGPXVersion; gpx = xmlnsgpx + " " + xmlnsgpx + "/gpx.xsd"; // PQ Groundspeak /* * groundspeak PQ Extensions * 1.0 Basic Definition of PQ Extensions * 1.0.1 Extensions * added the inc for <groundspeak:attributes>: attributes like 'dog-friendly' or 'handicapped access' will be listed. ID corresponds to an enum in the Geocaching.com database * <groundspeak:attribute id="1" inc="1">Dogs allowed</groundspeak:attribute> * 1.1 Extensions * Owner : Added GUID for transition to database redesign. Both GUID and ID are now optional Owner ID corresponds to an account on Geocaching.com. * Added <groundspeak:lastUpdated>: "xs:dateTime" is the last time the cache has been edited by the user * Added <groundspeak:exported>: ="xs:dateTime" for the benefit of splitting out caches --> */ String pq = ""; String pqVersion; /* switch (exportOptions.getPQVersion()) { case 0: pqVersion = "1/0"; break; case 2: pqVersion = "1/1"; break; default: pqVersion = "1/0/1"; } */ pqVersion = "1/0/1"; xmlnspq = "http://www.groundspeak.com/cache/" + pqVersion; if (this.exportOptions.getGroundspeakExtension() != NOGSEXTENSION) { pq = xmlnspq + " " + xmlnspq + "/cache.xsd"; } // GSAK String gsak = ""; String gsakVersion = "6"; xmlnsgsak = "http://www.gsak.net/xmlv1/" + gsakVersion; if (this.exportOptions.getWithGSAKExtensions()) { gsak = xmlnsgsak + " " + xmlnsgsak + "/gsak.xsd"; } // Garmin gpxx // http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd String gpxx = ""; String gpxxVersion = "3"; xmlnsgpxx = "http://www.garmin.com/xmlschemas/GpxExtensions/v" + gpxxVersion; if (this.exportOptions.getWithGarminExtensions()) { gpxx = xmlnsgpxx + " " + "http://www.garmin.com/xmlschemas/GpxExtensionsv" + gpxxVersion + ".xsd"; //GpxExtensionsv3.xsd } Transformer trans = new Transformer(true); if (exportStyle == STYLE_MYFINDS) { trans.add(new Regex("@@NAME@@", "My Finds Pocket Query")); } else { trans.add(new Regex("@@NAME@@", "Waypoints for Cache Listings, Generated by CacheWolf")); } trans.add(new Regex("@@CREATEDATE@@", new Date().setToCurrentTime().setFormat("yyyy-MM-dd").toString())); trans.add(new Regex("@@xmlnsGPXVersion@@", xmlnsGPXVersion)); trans.add(new Regex("@@GPXVERSION@@", gpxVersion)); trans.add(new Regex("@@GPX@@", gpx)); trans.add(new Regex("@@PQEXTENSION@@", pq)); trans.add(new Regex("@@GSAKEXTENSION@@", gsak)); trans.add(new Regex("@@GPXXEXTENSION@@", gpxx)); // we need to fake desc to make clients like GSAK accept additional waypoints together with caches final String GPXHEADER = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + newLine// + "<gpx"// + " xmlns=\"http://www.topografix.com/GPX/@@xmlnsGPXVersion@@\""// + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""// + " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""// + " version=\"@@GPXVERSION@@\""// + " creator=\"CacheWolf\""// + " xsi:schemaLocation=\""// + "@@GPX@@"// + " @@PQEXTENSION@@" // + " @@GSAKEXTENSION@@" // + " @@GPXXEXTENSION@@" // + "\""// + ">"// + newLine// + formatMetaData(); return trans.replaceFirst(GPXHEADER); } private String formatMetaData() { if (exportOptions.getGPXVersion() == 0) { return "<name>@@NAME@@</name>" + newLine// + "<desc>This is an individual cache generated from Geocaching.com</desc>" + newLine// + "<author>Various users from geocaching.com and/or opencaching.de</author>" + newLine// + "<email>contact@cachewolf.de</email>" + newLine// + "<url>http://www.cachewolf.de/</url>" + newLine// + "<urlname>CacheWolf - Paperless Geocaching</urlname>" + newLine// + "<time>@@CREATEDATE@@T07:00:00Z</time>" + newLine// + "<keywords>cache, geocache, waypoints</keywords>" + newLine;// // FIXME: extend MainForm.profile to add <bounds minlat=\"50.91695\" minlon=\"6.876383\" maxlat=\"50.935183\" maxlon=\"6.918817\" /> // is it worth a second loop? // MainForm.profile.getSourroundingArea(false); // +("<bounds minlat=\"50.91695\" minlon=\"6.876383\" maxlat=\"50.935183\" maxlon=\"6.918817\" />") } else { return "<metadata>" + newLine // + "<desc>This is an individual cache generated from Geocaching.com</desc>" + newLine// + "<author>" + newLine // + "<name>" + "Various users from geocaching.com and/or opencaching.de" + "</name>" + newLine // + "<email domain=\"cachewolf.de\" id=\"contact\"/>" + newLine // + "<link href=\"http://www.cachewolf.de/\">" + newLine // + "<text>CacheWolf - Paperless Geocaching</text>" + newLine // + "</link>" + newLine // + "</author>" + newLine// + "<time>@@CREATEDATE@@T07:00:00Z</time>" + newLine// + "<keywords>cache, geocache, waypoints</keywords>" + newLine// + "</metadata>" + newLine; // } } /** * format a long description as found in the gc.com GPX files * * @return formatted output */ private String formatLongDescription() { if (ch.isAddiWpt() || ch.isCustomWpt()) { return ch.getDetails().LongDescription; } else { StringBuffer ret = new StringBuffer(); String delim = ""; ret.append(ch.getDetails().LongDescription); if (ch.isHTML()) { delim = "<br />"; } else { delim = newLine; } // FIXME: format is not quite right yet // FIXME: cut Addis off in GPXimporter otherwise people who use GPX to feed CacheWolf have them doubled if (ch.addiWpts.size() > 0 && exportStyle != STYLE_MYFINDS) { if (ch.isHTML()) { ret.append(newLine).append(newLine).append("<p>Additional Waypoints</p>"); } else { ret.append(newLine).append(newLine).append("Additional Waypoints").append(newLine); } Iterator iter = ch.addiWpts.iterator(); while (iter.hasNext()) { CacheHolder addi = (CacheHolder) iter.next(); Transformer trans = new Transformer(true); trans.add(new Regex("@@ADDIID@@", addi.getCode())); trans.add(new Regex("@@ADDISHORT@@", addi.getName())); trans.add(new Regex("@@ADDIDELIM@@", delim)); trans.add(new Regex("@@ADDILAT@@", formatAddiLatLon(addi.getWpt()))); trans.add(new Regex("@@ADDILON@@", "")); trans.add(new Regex("@@ADDILONG@@", addi.getDetails().LongDescription)); ret.append(trans.replaceAll(GPXADDIINMAIN)); } ret.append(delim).append(newLine); } return ret.toString(); } } /** * create a position information suitable for a gc.com PQlike export * * @param pos * position * @return if position is valid return the cachewolf formatted position, otherwise return teh string used in PQs */ private String formatAddiLatLon(CWPoint pos) { if (pos.isValid()) { return pos.toString(); } else { return "N/S __ � __ . ___ W/E ___ � __ . ___"; } } /** * copy the bitmap identified by <code>prefix</code> and <code>type</code> from <code>poiZip</code> to <code>outdir</code> * * @param outdir * @param type * @param prefix * @param poiZip * @return true on success, false otherwise */ boolean copyPoiIcon(String outdir, String type, String prefix, ZipFile poiZip) { ZipEntry icon; byte[] buff; int len; try { icon = poiZip.getEntry(type + ".bmp"); if (icon == null) return false; // icon not found in archive buff = new byte[icon.getSize()]; InputStream fis = poiZip.getInputStream(icon); FileOutputStream fos = new FileOutputStream(outdir + (FileBase.separator) + prefix + type + ".bmp"); while (0 < (len = fis.read(buff))) fos.write(buff, 0, len); fos.flush(); fos.close(); fis.close(); } catch (ZipException e) { Preferences.itself().log("failed to copy icon " + type + ".bmp", e, true); return false; } catch (IOException e) { Preferences.itself().log("failed to copy icon " + type + ".bmp", e, true); return false; } return true; } /** * Execute the command defined by cmd * * @param cmd * command and options to execute. if command or options include a space quatation marks are added. this will not wirk with the java version on unix systems * @return a handle to the process on success or null otherwise */ Process startProcess(String[] cmd) { String command = ""; if (cmd.length == 0) { exportErrors++; Preferences.itself().log("GPX Export: empty gpsbabel command", null); return null; } for (int i = 0; i < cmd.length; i++) { if (cmd[i].indexOf(" ") > -1) { cmd[i] = "\"" + cmd[i] + "\""; } command = command + cmd[i] + " "; } try { return Vm.exec(command); } catch (IOException e) { Preferences.itself().log("error excuting " + command, e, true); exportErrors++; return null; } } /** * dialog to set the GPX exporter options */ private class GpxExportNgForm extends Form { private mLabel lblGPXVersion, lblWithGSAKExtensions, lblWithGarminExtensions, lblWpNameStyle, lblAddiWithInvalidCoords, lblSplitSize, lblUseCustomIcons, lblSendToGarmin, lblMaxLogs, lblExportLogsAsPlainText, lblAttrib2Log, lblPrefix; private int gpxStyle, outputStyle, gpxVersion; private mCheckBox cbWithGSAKExtensions, cbWithGarminExtensions, cbUseCustomIcons, cbSendToGarmin, cbAddiWithInvalidCoords, cbAttrib2Log, cbExportLogsAsPlainText; private mInput ibMaxLogs, ibSplitSize, ibPrefix, ibFilename; private mChoice chStyle, chOutput, chGPXVersion, chWpNameStyle; private mButton btnFilename; private final ExecutePanel executePanel; private boolean hasIcons; private boolean hasGarminMap; private boolean isGpsBabelInstalled; private Hashtable exportValues; /** * set up the form / dialog */ private GpxExportNgForm(boolean _hasGarminMap, boolean _hasIcons, boolean _hasGpsbabel) { this.setTitle("GPX Export"); this.resizable = false; gpxStyle = MainForm.profile.getProfilesLastUsedGpxStyle(); hasIcons = _hasIcons; hasGarminMap = _hasGarminMap; isGpsBabelInstalled = _hasGpsbabel; lblGPXVersion = new mLabel(MyLocale.getMsg(2022, "GPX Version")); addNext(lblGPXVersion); chGPXVersion = new mChoice(); chGPXVersion.dontSearchForKeys = true; chGPXVersion.addItem("1.0"); // index 0 chGPXVersion.addItem("1.1"); // index 1 chGPXVersion.select(gpxVersion); addLast(chGPXVersion); addNext(new mLabel(MyLocale.getMsg(2013, "With Groundspeak Extensions"))); chStyle = new mChoice(); chStyle.dontSearchForKeys = true; // if you change the order of strings make sure to fix the event handler as well chStyle.addItem(MyLocale.getMsg(2004, "No")); // index 0 chStyle.addItem(MyLocale.getMsg(2005, "PQ like")); // index 1 chStyle.addItem(MyLocale.getMsg(2006, "MyFinds")); // index 2 chStyle.select(gpxStyle); addLast(chStyle); addNext(lblWithGarminExtensions = new mLabel(MyLocale.getMsg(2025, "With Garmin Extensions"))); cbWithGarminExtensions = new mCheckBox(" "); addLast(cbWithGarminExtensions); addNext(lblWithGSAKExtensions = new mLabel(MyLocale.getMsg(2023, "With GSAK Extensions"))); cbWithGSAKExtensions = new mCheckBox(" "); addLast(cbWithGSAKExtensions); addNext(lblWpNameStyle = new mLabel(MyLocale.getMsg(2014, "WP Names"))); chWpNameStyle = new mChoice(); chWpNameStyle.dontSearchForKeys = true; // if you change the order of strings make sure to fix the event handler as well chWpNameStyle.addItem(MyLocale.getMsg(2002, "keep")); // index 0 chWpNameStyle.addItem(MyLocale.getMsg(2003, "add details")); // index 1 // chIds.addItem(MyLocale.getMsg(31415,"Smart Names")); // index 2 addLast(chWpNameStyle); addNext(lblAddiWithInvalidCoords = new mLabel(MyLocale.getMsg(2020, "Export Addis without coordinates?"))); cbAddiWithInvalidCoords = new mCheckBox(" "); addLast(cbAddiWithInvalidCoords); addNext(lblUseCustomIcons = new mLabel(MyLocale.getMsg(2012, "Custom Icons"))); cbUseCustomIcons = new mCheckBox(" "); addLast(cbUseCustomIcons); addNext(lblSendToGarmin = new mLabel(MyLocale.getMsg(2011, "send to Garmin"))); cbSendToGarmin = new mCheckBox(" "); addLast(cbSendToGarmin); addNext(lblExportLogsAsPlainText = new mLabel(MyLocale.getMsg(2010, "HTML - Tags aus Logs entfernen"))); cbExportLogsAsPlainText = new mCheckBox(" "); addLast(cbExportLogsAsPlainText); addNext(lblAttrib2Log = new mLabel(MyLocale.getMsg(2017, "Attrib.->Log"))); cbAttrib2Log = new mCheckBox(" "); addLast(cbAttrib2Log); addNext(lblMaxLogs = new mLabel(MyLocale.getMsg(2018, "Max Logs"))); ibMaxLogs = new mInput(""); addLast(ibMaxLogs); addNext(new mLabel(MyLocale.getMsg(2024, "Output Style"))); chOutput = new mChoice(); chOutput.dontSearchForKeys = true; // if you change the order of strings make sure to fix the event handler as well chOutput.addItem(MyLocale.getMsg(2007, "Single GPX")); // index 0 chOutput.addItem(MyLocale.getMsg(2008, "Separate GPX")); // index 1 outputStyle = MainForm.profile.getProfilesLastUsedOutputStyle(); if (_hasGpsbabel) chOutput.addItem(MyLocale.getMsg(2009, "POI")); // index 2 else { if (outputStyle == 2) outputStyle = 0; } chOutput.select(outputStyle); addLast(chOutput); addNext(lblSplitSize = new mLabel(MyLocale.getMsg(2019, "SplitSize"))); ibSplitSize = new mInput(""); addLast(ibSplitSize); addNext(lblPrefix = new mLabel(MyLocale.getMsg(2016, "Prefix"))); ibPrefix = new mInput(""); addLast(ibPrefix); addNext(btnFilename = new mButton(MyLocale.getMsg(2021, "Ausgabedatei") + " ... ")); ibFilename = new mInput(""); addLast(ibFilename); disable(new mLabel(""), ibFilename); executePanel = new ExecutePanel(this); checkStyle(); } private void checkStyle() { this.gpxStyle = this.chStyle.selectedIndex; this.outputStyle = this.chOutput.selectedIndex; exportValues = Preferences.itself().getGpxExportPreferences(Preferences.itself().gpxStyles[gpxStyle]); setFromPreferences(); if (gpxStyle == STYLE_MYFINDS) { disable(lblGPXVersion, chGPXVersion); chWpNameStyle.select(0); disable(lblWpNameStyle, chWpNameStyle); disable(lblWithGarminExtensions, cbWithGarminExtensions); disable(lblWithGSAKExtensions, cbWithGSAKExtensions); disable(lblAddiWithInvalidCoords, cbAddiWithInvalidCoords); cbAddiWithInvalidCoords.setState(false); disable(lblUseCustomIcons, cbUseCustomIcons); cbUseCustomIcons.setState(false); disable(lblSendToGarmin, cbSendToGarmin); cbSendToGarmin.setState(false); enable(lblExportLogsAsPlainText, cbExportLogsAsPlainText); disable(lblMaxLogs, ibMaxLogs); disable(lblAttrib2Log, cbAttrib2Log); cbAttrib2Log.setState(false); disable(lblSplitSize, ibSplitSize); disable(lblPrefix, ibPrefix); outputStyle = OUTPUT_SINGLE; } else if (gpxStyle == STYLE_PQEXTENSIONS) { enable(lblGPXVersion, chGPXVersion); enable(lblWpNameStyle, chWpNameStyle); enable(lblWithGarminExtensions, cbWithGarminExtensions); enable(lblWithGSAKExtensions, cbWithGSAKExtensions); enable(lblAddiWithInvalidCoords, cbAddiWithInvalidCoords); enable(lblSplitSize, ibSplitSize); if (hasGarminMap) enable(lblUseCustomIcons, cbUseCustomIcons); else { disable(lblUseCustomIcons, cbUseCustomIcons); cbUseCustomIcons.setState(false); } if (isGpsBabelInstalled) enable(lblSendToGarmin, cbSendToGarmin); else { disable(lblSendToGarmin, cbSendToGarmin); cbSendToGarmin.setState(false); } enable(lblExportLogsAsPlainText, cbExportLogsAsPlainText); enable(lblMaxLogs, ibMaxLogs); enable(lblAttrib2Log, cbAttrib2Log); disable(lblPrefix, ibPrefix); } else { // without Groundspeak extension enable(lblGPXVersion, chGPXVersion); enable(lblWpNameStyle, chWpNameStyle); enable(lblWithGarminExtensions, cbWithGarminExtensions); enable(lblWithGSAKExtensions, cbWithGSAKExtensions); disable(lblAddiWithInvalidCoords, cbAddiWithInvalidCoords); cbAddiWithInvalidCoords.setState(false); disable(lblSplitSize, ibSplitSize); if (hasGarminMap) enable(lblUseCustomIcons, cbUseCustomIcons); else { disable(lblUseCustomIcons, cbUseCustomIcons); cbUseCustomIcons.setState(false); } disable(lblExportLogsAsPlainText, cbExportLogsAsPlainText); cbExportLogsAsPlainText.setState(false); disable(lblMaxLogs, ibMaxLogs); disable(lblAttrib2Log, cbAttrib2Log); } if (outputStyle == OUTPUT_SINGLE) { enable(lblSplitSize, ibSplitSize); if (isGpsBabelInstalled) enable(lblSendToGarmin, cbSendToGarmin); else { disable(lblSendToGarmin, cbSendToGarmin); cbSendToGarmin.setState(false); } disable(lblPrefix, ibPrefix); } else if (outputStyle == OUTPUT_SEVERAL) { disable(lblSplitSize, ibSplitSize); disable(lblSendToGarmin, cbSendToGarmin); cbSendToGarmin.setState(false); if (hasIcons) enable(lblUseCustomIcons, cbUseCustomIcons); else { disable(lblUseCustomIcons, cbUseCustomIcons); cbUseCustomIcons.setState(false); } enable(lblPrefix, ibPrefix); } else if (outputStyle == OUTPUT_GPI) { disable(lblSplitSize, ibSplitSize); disable(lblUseCustomIcons, cbUseCustomIcons); cbUseCustomIcons.setState(false); disable(lblSendToGarmin, cbSendToGarmin); cbSendToGarmin.setState(false); enable(lblPrefix, ibPrefix); } } private void disable(mLabel l, Control c) { if (l.change(ControlConstants.Disabled, 0)) l.repaint(); if (c.change(ControlConstants.Disabled, 0)) c.repaint(); } private void enable(mLabel l, Control c) { if (l.change(0, ControlConstants.Disabled)) l.repaint(); if (c.change(0, ControlConstants.Disabled)) c.repaint(); } private void setFromPreferences() { chWpNameStyle.select(Common.parseInt(getExportValue(WPNAMESTYLE))); chGPXVersion.select(Common.parseInt(getExportValue(GPXVERSION))); cbWithGarminExtensions.setState(Boolean.valueOf(getExportValue(WITHGARMINEXTENSIONS)).booleanValue()); cbWithGSAKExtensions.setState(Boolean.valueOf(getExportValue(WITHGSAKEXTENSIONS)).booleanValue()); int splitSize = Common.parseInt(getExportValue(SPLITSIZE)); ibSplitSize.setText((splitSize < 1) ? "" : String.valueOf(splitSize)); cbAddiWithInvalidCoords.setState(Boolean.valueOf(getExportValue(EXPORTADDIWITHINVALIDCOORDS)).booleanValue()); cbUseCustomIcons.setState(Boolean.valueOf(getExportValue(USECUSTOMICONS)).booleanValue()); cbSendToGarmin.setState(Boolean.valueOf(getExportValue(SENDTOGARMIN)).booleanValue()); cbExportLogsAsPlainText.setState(Boolean.valueOf(getExportValue(EXPORTLOGASPLAINTEXT)).booleanValue()); cbAttrib2Log.setState(Boolean.valueOf(getExportValue(ATTRIB2LOG)).booleanValue()); String strMaxNumberOfLogsToExport = getExportValue(MAXNUMBEROFLOGSTOEXPORT); int maxNumberOfLogsToExport = (strMaxNumberOfLogsToExport.length() == 0) ? 5 : Common.parseInt(strMaxNumberOfLogsToExport); ibMaxLogs.setText((maxNumberOfLogsToExport == -1) ? "" : String.valueOf(maxNumberOfLogsToExport)); ibPrefix.setText(getExportValue(PREFIX)); if (ibPrefix.getText().length() == 0) ibPrefix.setText("GC-"); //default ibFilename.setText(MainForm.profile.getGpxOutputTo()); } private String getExportValue(String item) { if (exportValues == null) return ""; String ret = (String) exportValues.get(item); if (ret == null) { return ""; } else { return ret; } } public int getGroundspeakExtension() { return chStyle.selectedIndex; } public int getOutputStyle() { return chOutput.selectedIndex; } public boolean getSendToGarmin() { return cbSendToGarmin.getState(); } public String getPrefix() { return ibPrefix.text; } public int getWpNameStyle() { return chWpNameStyle.selectedIndex; } public int getGPXVersion() { return chGPXVersion.selectedIndex; } public boolean getWithGarminExtensions() { return this.cbWithGarminExtensions.getState(); } public boolean getWithGSAKExtensions() { return this.cbWithGSAKExtensions.getState(); } public boolean getUseCustomIcons() { return cbUseCustomIcons.getState(); } public boolean getExportLogsAsPlainText() { return cbExportLogsAsPlainText.getState(); } public boolean getExportAddiWithInvalidCoords() { return cbAddiWithInvalidCoords.getState(); } public int getMaxLogs() { if (ibMaxLogs.getText().length() == 0) { ibMaxLogs.setText("-1"); return -1; } else return Common.parseInt(ibMaxLogs.getText()); } public int getSplitSize() { if (ibSplitSize.getText().length() == 0) return -1; else return Common.parseInt(ibSplitSize.getText()); } public boolean getAttrib2Log() { return cbAttrib2Log.getState(); } public String getGpxOutputTo() { return ibFilename.getText(); } /** * react to GUI events and toogle access to the checkboxes according to radio button settings pass everything else to <code>super()</code> */ public void onEvent(Event ev) { if (ev instanceof DataChangeEvent && ev.type == DataChangeEvent.DATA_CHANGED) { if (ev.target == chStyle && chStyle.selectedIndex != gpxStyle) { checkStyle(); } if (ev.target == chOutput && chOutput.selectedIndex != outputStyle) { checkStyle(); } } else if (ev instanceof ControlEvent && ev.type == ControlEvent.PRESSED) { if (ev.target == executePanel.applyButton) { boolean mayclose = true; if (gpxStyle == GpxExportNg.STYLE_PQEXTENSIONS) { int logs = getMaxLogs(); if (logs < -1) { mayclose = false; ibMaxLogs.selectAll(); ibMaxLogs.takeFocus(0); Sound.beep(); } } String tmp = ibFilename.getText(); File f = new File(tmp); if (outputStyle == OUTPUT_SINGLE) { if (!f.isFile()) { tmp = this.getOutputTo(FileChooser.SAVE | FileChooser.QUICK_SELECT); if (tmp.length() <= 0) { mayclose = false; btnFilename.takeFocus(0); } } } else { if (!f.isDirectory()) { tmp = this.getOutputTo(FileChooser.DIRECTORY_SELECT); if (tmp.length() <= 0) { mayclose = false; btnFilename.takeFocus(0); } } } ibFilename.setText(tmp); if (mayclose) { MainForm.profile.setLastUsedGpxStyle(gpxStyle); MainForm.profile.setLastUsedOutputStyle(outputStyle); MainForm.profile.setGpxOutputTo(ibFilename.getText()); setPreferences(); close(1); } } else if (ev.target == executePanel.cancelButton) { close(-1); } else if (ev.target == this.btnFilename) { String tmp; switch (outputStyle) { case OUTPUT_SEVERAL: case OUTPUT_GPI: tmp = this.getOutputTo(FileChooser.DIRECTORY_SELECT); break; default: tmp = this.getOutputTo(FileChooser.SAVE | FileChooser.QUICK_SELECT); } if (tmp.length() > 0) this.ibFilename.setText(tmp); } } super.onEvent(ev); } private void setPreferences() { exportValues.put(GPXVERSION, "" + chGPXVersion.selectedIndex); exportValues.put(WITHGARMINEXTENSIONS, SafeXML.strxmlencode(cbWithGarminExtensions.getState())); exportValues.put(WITHGSAKEXTENSIONS, SafeXML.strxmlencode(cbWithGSAKExtensions.getState())); switch (outputStyle) { case OUTPUT_SINGLE: exportValues.put(SENDTOGARMIN, SafeXML.strxmlencode(cbSendToGarmin.getState())); break; case OUTPUT_SEVERAL: exportValues.put(PREFIX, ibPrefix.text); break; case OUTPUT_GPI: exportValues.put(PREFIX, ibPrefix.text); break; } switch (gpxStyle) { case NOGSEXTENSION: exportValues.put(WPNAMESTYLE, "" + chWpNameStyle.selectedIndex); exportValues.put(USECUSTOMICONS, SafeXML.strxmlencode(cbUseCustomIcons.getState())); case STYLE_PQEXTENSIONS: exportValues.put(SPLITSIZE, ibSplitSize.text); exportValues.put(ATTRIB2LOG, SafeXML.strxmlencode(cbAttrib2Log.getState())); exportValues.put(EXPORTADDIWITHINVALIDCOORDS, SafeXML.strxmlencode(cbAddiWithInvalidCoords.getState())); exportValues.put(USECUSTOMICONS, SafeXML.strxmlencode(cbUseCustomIcons.getState())); exportValues.put(EXPORTLOGASPLAINTEXT, SafeXML.strxmlencode(cbExportLogsAsPlainText.getState())); exportValues.put(MAXNUMBEROFLOGSTOEXPORT, ibMaxLogs.text); break; case STYLE_MYFINDS: exportValues.put(EXPORTLOGASPLAINTEXT, SafeXML.strxmlencode(cbExportLogsAsPlainText.getState())); break; } } private String getOutputTo(int what) { FileChooser fc; fc = new FileChooser(what, ibFilename.getText()); if (what == FileChooserBase.DIRECTORY_SELECT) { fc.setTitle(MyLocale.getMsg(616, "Verzeichnis ausw�hlen")); } else { fc.setTitle(MyLocale.getMsg(2021, "Ausgabedatei")); fc.addMask("*.gpx"); } if (fc.execute() == FormBase.IDCANCEL) return ""; return fc.getChosenFile().getFullPath(); } } }