]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/load/GpsLoader.java
Version 11, August 2010
[GpsPrune.git] / tim / prune / load / GpsLoader.java
index b803844ea142a0857d997cf8570182779e407032..2196e0c3ff29695a13ac72f8abdf3e8bf528dcea 100644 (file)
@@ -6,79 +6,88 @@ import java.awt.FlowLayout;
 import java.awt.GridLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.InputStreamReader;
+import java.util.ArrayList;
 
 import javax.swing.BorderFactory;
 import javax.swing.BoxLayout;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JDialog;
-import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JProgressBar;
 import javax.swing.JTextField;
 import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 
 import tim.prune.App;
-import tim.prune.Config;
 import tim.prune.ExternalTools;
+import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
+import tim.prune.config.Config;
 import tim.prune.data.Altitude;
+import tim.prune.data.SourceInfo;
 import tim.prune.load.xml.XmlFileLoader;
 import tim.prune.load.xml.XmlHandler;
+import tim.prune.save.GpxExporter;
 
 /**
  * Class to manage the loading of GPS data using GpsBabel
  */
-public class GpsLoader implements Runnable
+public class GpsLoader extends GenericFunction implements Runnable
 {
-       private App _app = null;
-       private JFrame _parentFrame = null;
        private boolean _gpsBabelChecked = false;
        private JDialog _dialog = null;
        private JTextField _deviceField = null, _formatField = null;
        private JCheckBox _waypointCheckbox = null, _trackCheckbox = null;
+       private JCheckBox _saveCheckbox = null;
        private JButton _okButton = null;
-       private JProgressBar _waypointProgressBar = null, _trackProgressBar = null;
+       private JProgressBar _progressBar = null;
+       private File _saveFile = null;
        private boolean _cancelled = false;
 
 
        /**
         * Constructor
         * @param inApp Application object to inform of data load
-        * @param inParentFrame parent frame to reference for dialogs
         */
-       public GpsLoader(App inApp, JFrame inParentFrame)
+       public GpsLoader(App inApp)
        {
-               _app = inApp;
-               _parentFrame = inParentFrame;
+               super(inApp);
        }
 
+       /** Get the name key */
+       public String getNameKey() {
+               return "function.loadfromgps";
+       }
 
        /**
         * Open the GUI to select options and start the load
         */
-       public void openDialog()
+       public void begin()
        {
                // Check if gpsbabel looks like it's installed
-               if (_gpsBabelChecked || ExternalTools.isGpsbabelInstalled()
+               if (_gpsBabelChecked || ExternalTools.isToolInstalled(ExternalTools.TOOL_GPSBABEL)
                        || JOptionPane.showConfirmDialog(_dialog,
                                I18nManager.getText("dialog.gpsload.nogpsbabel"),
-                               I18nManager.getText("dialog.gpsload.title"),
+                               I18nManager.getText(getNameKey()),
                                JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION)
                {
                        _gpsBabelChecked = true;
                        // Make dialog window
                        if (_dialog == null)
                        {
-                               _dialog = new JDialog(_parentFrame, I18nManager.getText("dialog.gpsload.title"), true);
+                               _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
                                _dialog.setLocationRelativeTo(_parentFrame);
                                _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
                                _dialog.getContentPane().add(makeDialogComponents());
@@ -86,8 +95,8 @@ public class GpsLoader implements Runnable
                        }
                        // Initialise progress bars, buttons
                        enableOkButton();
-                       setupProgressBars(true);
-                       _dialog.show();
+                       setupProgressBar(true);
+                       _dialog.setVisible(true);
                }
        }
 
@@ -109,12 +118,21 @@ public class GpsLoader implements Runnable
                JLabel deviceLabel = new JLabel(I18nManager.getText("dialog.gpsload.device"));
                deviceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
                gridPanel.add(deviceLabel);
-               _deviceField = new JTextField(Config.getGpsDevice(), 12);
+               _deviceField = new JTextField(Config.getConfigString(Config.KEY_GPS_DEVICE), 12);
+               _deviceField.addKeyListener(new KeyAdapter() {
+                       public void keyReleased(KeyEvent e)
+                       {
+                               // close dialog if escape pressed
+                               if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                                       _dialog.dispose();
+                               }
+                       }
+               });
                gridPanel.add(_deviceField);
                JLabel formatLabel = new JLabel(I18nManager.getText("dialog.gpsload.format"));
                formatLabel.setHorizontalAlignment(SwingConstants.RIGHT);
                gridPanel.add(formatLabel);
-               _formatField = new JTextField(Config.getGpsFormat(), 12);
+               _formatField = new JTextField(Config.getConfigString(Config.KEY_GPS_FORMAT), 12);
                gridPanel.add(_formatField);
                gridPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
                gridPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 20));
@@ -135,11 +153,14 @@ public class GpsLoader implements Runnable
                _trackCheckbox.addChangeListener(checkboxListener);
                _trackCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
                mainPanel.add(_trackCheckbox);
-               // progress bars (initially invisible)
-               _waypointProgressBar = new JProgressBar(0, 10);
-               mainPanel.add(_waypointProgressBar);
-               _trackProgressBar = new JProgressBar(0, 10);
-               mainPanel.add(_trackProgressBar);
+               // Checkbox for immediately saving to file
+               _saveCheckbox = new JCheckBox(I18nManager.getText("dialog.gpsload.save"));
+               _saveCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
+               mainPanel.add(_saveCheckbox);
+
+               // progress bar (initially invisible)
+               _progressBar = new JProgressBar(0, 10);
+               mainPanel.add(_progressBar);
                outerPanel.add(mainPanel, BorderLayout.NORTH);
 
                // Lower panel with ok and cancel buttons
@@ -172,16 +193,13 @@ public class GpsLoader implements Runnable
        /**
         * @param inStart true if the dialog is restarting
         */
-       private void setupProgressBars(boolean inStart)
+       private void setupProgressBar(boolean inStart)
        {
                // set visibility
-               _waypointProgressBar.setVisible(!inStart && _waypointCheckbox.isSelected());
-               _trackProgressBar.setVisible(!inStart && _trackCheckbox.isSelected());
+               _progressBar.setVisible(!inStart);
                // set indeterminate flags, initial value
-               _waypointProgressBar.setIndeterminate(false);
-               _waypointProgressBar.setValue(0);
-               _trackProgressBar.setIndeterminate(false);
-               _trackProgressBar.setValue(0);
+               _progressBar.setIndeterminate(false);
+               _progressBar.setValue(0);
        }
 
 
@@ -200,45 +218,22 @@ public class GpsLoader implements Runnable
        public void run()
        {
                _okButton.setEnabled(false);
-               setupProgressBars(false);
-               if (_waypointCheckbox.isSelected())
+               setupProgressBar(false);
+               if (_waypointCheckbox.isSelected() || _trackCheckbox.isSelected())
                {
-                       _waypointProgressBar.setIndeterminate(true);
-                       _trackProgressBar.setIndeterminate(false);
+                       _progressBar.setIndeterminate(true);
+                       _saveFile = null;
                        try
                        {
-                               callGpsBabel(true);
+                               callGpsBabel();
                        }
                        catch (Exception e)
                        {
-                               JOptionPane.showMessageDialog(_dialog, e.getMessage(),
-                                       I18nManager.getText("dialog.gpsload.title"), JOptionPane.ERROR_MESSAGE);
+                               _app.showErrorMessageNoLookup(getNameKey(), e.getMessage());
                                _cancelled = true;
                        }
                }
-               // Exit if cancelled or failed
-               if (_cancelled) {
-                       setupProgressBars(true);
-                       enableOkButton();
-                       return;
-               }
-               if (_trackCheckbox.isSelected())
-               {
-                       _waypointProgressBar.setIndeterminate(false);
-                       _waypointProgressBar.setValue(10);
-                       _trackProgressBar.setIndeterminate(true);
-                       try
-                       {
-                               callGpsBabel(false);
-                       }
-                       catch (Exception e)
-                       {
-                               JOptionPane.showMessageDialog(_dialog, e.getMessage(),
-                                       I18nManager.getText("dialog.gpsload.title"), JOptionPane.ERROR_MESSAGE);
-                               _cancelled = true;
-                       }
-               }
-               setupProgressBars(true);
+               setupProgressBar(true);
                enableOkButton();
 
                // Close dialog
@@ -250,46 +245,127 @@ public class GpsLoader implements Runnable
 
        /**
         * Execute the call to gpsbabel and pass the results back to the app
-        * @param inWaypoints true to get waypoints, false to get track data
         */
-       private void callGpsBabel(boolean inWaypoints) throws Exception
+       private void callGpsBabel() throws Exception
        {
                // Set up command to call gpsbabel
-               String[] commands = {"gpsbabel", null, "-i", _formatField.getText(), "-f", _deviceField.getText(), "-o", "gpx", "-F", "-"};
-               commands[1] = inWaypoints?"-w":"-t";
+               final String device = _deviceField.getText().trim();
+               final String format = _formatField.getText().trim();
+               String[] commands = getCommandArray(device, format);
+               // Save GPS settings in config
+               Config.setConfigString(Config.KEY_GPS_DEVICE, device);
+               Config.setConfigString(Config.KEY_GPS_FORMAT, format);
 
-               String errorMessage = "";
+               String errorMessage = "", errorMessage2 = "";
                XmlHandler handler = null;
                Process process = Runtime.getRuntime().exec(commands);
+               String line = null;
 
-               // Pass input stream to try to parse the xml
-               try
+               if (_saveFile != null)
                {
-                       XmlFileLoader xmlLoader = new XmlFileLoader(_app, _parentFrame);
-                       SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
-                       saxParser.parse(process.getInputStream(), xmlLoader);
-                       handler = xmlLoader.getHandler();
-                       if (handler == null) {
-                               errorMessage = "Null handler";
+                       // data is being saved to file, so need to wait for it to finish
+                       process.waitFor();
+                       // try to read error message, if any
+                       try {
+                               BufferedReader r = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+                               while ((line = r.readLine()) != null) {
+                                       errorMessage += line + "\n";
+                               }
+                               // Close error stream
+                               try {
+                                       r.close();
+                               } catch (Exception e) {}
                        }
+                       catch (Exception e) {} // couldn't get error message
+
+                       // Trigger it to be loaded by app
+                       if (process.exitValue() == 0)
+                       {
+                               SwingUtilities.invokeLater(new Runnable() {
+                                       public void run() {
+                                               ArrayList<File> fileList = new ArrayList<File>();
+                                               fileList.add(_saveFile);
+                                               _app.loadDataFiles(fileList);
+                                       }
+                               });
+                       }
+                       else if (errorMessage.length() > 0) {
+                               throw new Exception(errorMessage);
+                       }
+                       else throw new Exception(I18nManager.getText("error.gpsload.unknown"));
                }
-               catch (Exception e) {
-                       errorMessage = e.getMessage();
-               }
+               else
+               {
+                       // Pass input stream to try to parse the xml
+                       try
+                       {
+                               XmlFileLoader xmlLoader = new XmlFileLoader(_app);
+                               SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
+                               saxParser.parse(process.getInputStream(), xmlLoader);
+                               handler = xmlLoader.getHandler();
+                               if (handler == null) {
+                                       errorMessage = "Null handler";
+                               }
+                       }
+                       catch (Exception e) {
+                               errorMessage = e.getMessage();
+                       }
 
-               // Read the error stream to see if there's a better error message there
-               BufferedReader r = new BufferedReader(new InputStreamReader(process.getErrorStream()));
-               String line = null;
-               String errorMessage2 = "";
-               while ((line = r.readLine()) != null) {
-                       errorMessage2 += line + "\n";
+                       // Read the error stream to see if there's a better error message there
+                       BufferedReader r = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+                       while ((line = r.readLine()) != null) {
+                               errorMessage2 += line + "\n";
+                       }
+                       // Close error stream
+                       try {
+                               r.close();
+                       } catch (Exception e) {}
+
+                       if (errorMessage2.length() > 0) {errorMessage = errorMessage2;}
+                       if (errorMessage.length() > 0) {throw new Exception(errorMessage);}
+
+                       // Send data back to app
+                       _app.informDataLoaded(handler.getFieldArray(), handler.getDataArray(), Altitude.Format.METRES,
+                               new SourceInfo(_deviceField.getText(), SourceInfo.FILE_TYPE.GPSBABEL),
+                               handler.getTrackNameList());
                }
-               if (errorMessage2.length() > 0) {errorMessage = errorMessage2;}
-               if (errorMessage.length() > 0) {throw new Exception(errorMessage);}
+       }
 
-               // Send data back to app
-               boolean append = _waypointCheckbox.isSelected() && !inWaypoints;
-               _app.informDataLoaded(handler.getFieldArray(), handler.getDataArray(),
-                       Altitude.FORMAT_METRES, _deviceField.getText(), append);
+
+       /**
+        * Get the commands to call
+        * @param inDevice device name to use
+        * @param inFormat format to use
+        * @return String array containing commands
+        */
+       private String[] getCommandArray(String inDevice, String inFormat)
+       {
+               String[] commands = null;
+               final String command = Config.getConfigString(Config.KEY_GPSBABEL_PATH);
+               final boolean loadWaypoints = _waypointCheckbox.isSelected();
+               final boolean loadTrack = _trackCheckbox.isSelected();
+               if (loadWaypoints && loadTrack) {
+                       // Both waypoints and track points selected
+                       commands = new String[] {command, "-w", "-t", "-i", inFormat,
+                               "-f", inDevice, "-o", "gpx", "-F", "-"};
+               }
+               else
+               {
+                       // Only waypoints OR track points selected
+                       commands = new String[] {command, "-w", "-i", inFormat,
+                               "-f", inDevice, "-o", "gpx", "-F", "-"};
+                       if (loadTrack) {
+                               commands[1] = "-t";
+                       }
+               }
+               // Do we want to save the gpx straight to file?
+               if (_saveCheckbox.isSelected()) {
+                       // Select file to save to
+                       _saveFile = GpxExporter.chooseGpxFile(_parentFrame);
+                       if (_saveFile != null) {
+                               commands[commands.length-1] = _saveFile.getAbsolutePath();
+                       }
+               }
+               return commands;
        }
 }