]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/load/GpsLoader.java
Version 7, February 2009
[GpsPrune.git] / tim / prune / load / GpsLoader.java
1 package tim.prune.load;
2
3 import java.awt.BorderLayout;
4 import java.awt.Component;
5 import java.awt.FlowLayout;
6 import java.awt.GridLayout;
7 import java.awt.event.ActionEvent;
8 import java.awt.event.ActionListener;
9 import java.io.BufferedReader;
10 import java.io.InputStreamReader;
11
12 import javax.swing.BorderFactory;
13 import javax.swing.BoxLayout;
14 import javax.swing.JButton;
15 import javax.swing.JCheckBox;
16 import javax.swing.JDialog;
17 import javax.swing.JLabel;
18 import javax.swing.JOptionPane;
19 import javax.swing.JPanel;
20 import javax.swing.JProgressBar;
21 import javax.swing.JTextField;
22 import javax.swing.SwingConstants;
23 import javax.swing.event.ChangeEvent;
24 import javax.swing.event.ChangeListener;
25 import javax.xml.parsers.SAXParser;
26 import javax.xml.parsers.SAXParserFactory;
27
28 import tim.prune.App;
29 import tim.prune.Config;
30 import tim.prune.ExternalTools;
31 import tim.prune.GenericFunction;
32 import tim.prune.I18nManager;
33 import tim.prune.data.Altitude;
34 import tim.prune.load.xml.XmlFileLoader;
35 import tim.prune.load.xml.XmlHandler;
36
37 /**
38  * Class to manage the loading of GPS data using GpsBabel
39  */
40 public class GpsLoader extends GenericFunction implements Runnable
41 {
42         private boolean _gpsBabelChecked = false;
43         private JDialog _dialog = null;
44         private JTextField _deviceField = null, _formatField = null;
45         private JCheckBox _waypointCheckbox = null, _trackCheckbox = null;
46         private JButton _okButton = null;
47         private JProgressBar _progressBar = null;
48         private boolean _cancelled = false;
49
50
51         /**
52          * Constructor
53          * @param inApp Application object to inform of data load
54          */
55         public GpsLoader(App inApp)
56         {
57                 super(inApp);
58         }
59
60         /** Get the name key */
61         public String getNameKey() {
62                 return "function.loadfromgps";
63         }
64
65         /**
66          * Open the GUI to select options and start the load
67          */
68         public void begin()
69         {
70                 // Check if gpsbabel looks like it's installed
71                 if (_gpsBabelChecked || ExternalTools.isGpsbabelInstalled()
72                         || JOptionPane.showConfirmDialog(_dialog,
73                                 I18nManager.getText("dialog.gpsload.nogpsbabel"),
74                                 I18nManager.getText(getNameKey()),
75                                 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION)
76                 {
77                         _gpsBabelChecked = true;
78                         // Make dialog window
79                         if (_dialog == null)
80                         {
81                                 _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
82                                 _dialog.setLocationRelativeTo(_parentFrame);
83                                 _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
84                                 _dialog.getContentPane().add(makeDialogComponents());
85                                 _dialog.pack();
86                         }
87                         // Initialise progress bars, buttons
88                         enableOkButton();
89                         setupProgressBar(true);
90                         _dialog.setVisible(true);
91                 }
92         }
93
94
95         /**
96          * @return a panel containing the main dialog components
97          */
98         private JPanel makeDialogComponents()
99         {
100                 JPanel outerPanel = new JPanel();
101                 outerPanel.setLayout(new BorderLayout());
102                 // Main panel with options etc
103                 JPanel mainPanel = new JPanel();
104                 mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
105
106                 // text fields for options
107                 JPanel gridPanel = new JPanel();
108                 gridPanel.setLayout(new GridLayout(0, 2, 10, 3));
109                 JLabel deviceLabel = new JLabel(I18nManager.getText("dialog.gpsload.device"));
110                 deviceLabel.setHorizontalAlignment(SwingConstants.RIGHT);
111                 gridPanel.add(deviceLabel);
112                 _deviceField = new JTextField(Config.getGpsDevice(), 12);
113                 gridPanel.add(_deviceField);
114                 JLabel formatLabel = new JLabel(I18nManager.getText("dialog.gpsload.format"));
115                 formatLabel.setHorizontalAlignment(SwingConstants.RIGHT);
116                 gridPanel.add(formatLabel);
117                 _formatField = new JTextField(Config.getGpsFormat(), 12);
118                 gridPanel.add(_formatField);
119                 gridPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
120                 gridPanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 20));
121                 mainPanel.add(gridPanel);
122
123                 // checkboxes
124                 ChangeListener checkboxListener = new ChangeListener() {
125                         public void stateChanged(ChangeEvent e)
126                         {
127                                 enableOkButton();
128                         }
129                 };
130                 _waypointCheckbox = new JCheckBox(I18nManager.getText("dialog.gpsload.getwaypoints"), true);
131                 _waypointCheckbox.addChangeListener(checkboxListener);
132                 _waypointCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
133                 mainPanel.add(_waypointCheckbox);
134                 _trackCheckbox = new JCheckBox(I18nManager.getText("dialog.gpsload.gettracks"), true);
135                 _trackCheckbox.addChangeListener(checkboxListener);
136                 _trackCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
137                 mainPanel.add(_trackCheckbox);
138                 // progress bar (initially invisible)
139                 _progressBar = new JProgressBar(0, 10);
140                 mainPanel.add(_progressBar);
141                 outerPanel.add(mainPanel, BorderLayout.NORTH);
142
143                 // Lower panel with ok and cancel buttons
144                 JPanel buttonPanel = new JPanel();
145                 buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
146                 _okButton = new JButton(I18nManager.getText("button.ok"));
147                 _okButton.addActionListener(new ActionListener() {
148                         public void actionPerformed(ActionEvent e)
149                         {
150                                 // start thread to call gpsbabel
151                                 _cancelled = false;
152                                 new Thread(GpsLoader.this).start();
153                         }
154                 });
155                 buttonPanel.add(_okButton);
156                 JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
157                 cancelButton.addActionListener(new ActionListener() {
158                         public void actionPerformed(ActionEvent e)
159                         {
160                                 _cancelled = true;
161                                 _dialog.dispose();
162                         }
163                 });
164                 buttonPanel.add(cancelButton);
165                 outerPanel.add(buttonPanel, BorderLayout.SOUTH);
166                 return outerPanel;
167         }
168
169
170         /**
171          * @param inStart true if the dialog is restarting
172          */
173         private void setupProgressBar(boolean inStart)
174         {
175                 // set visibility
176                 _progressBar.setVisible(!inStart);
177                 // set indeterminate flags, initial value
178                 _progressBar.setIndeterminate(false);
179                 _progressBar.setValue(0);
180         }
181
182
183         /**
184          * Enable or disable the ok button
185          */
186         private void enableOkButton()
187         {
188                 _okButton.setEnabled(_waypointCheckbox.isSelected() || _trackCheckbox.isSelected());
189         }
190
191
192         /**
193          * Run method for performing tasks in separate thread
194          */
195         public void run()
196         {
197                 _okButton.setEnabled(false);
198                 setupProgressBar(false);
199                 if (_waypointCheckbox.isSelected() || _trackCheckbox.isSelected())
200                 {
201                         _progressBar.setIndeterminate(true);
202                         try
203                         {
204                                 callGpsBabel(_waypointCheckbox.isSelected(), _trackCheckbox.isSelected());
205                         }
206                         catch (Exception e)
207                         {
208                                 // System.err.println("Error: " + e.getClass().getName());
209                                 // System.err.println("Error: " + e.getMessage());
210                                 _app.showErrorMessageNoLookup(getNameKey(), e.getMessage());
211                                 _cancelled = true;
212                         }
213                 }
214                 setupProgressBar(true);
215                 enableOkButton();
216
217                 // Close dialog
218                 if (!_cancelled) {
219                         _dialog.dispose();
220                 }
221         }
222
223
224         /**
225          * Execute the call to gpsbabel and pass the results back to the app
226          * @param inWaypoints true to load waypoints
227          * @param inTracks true to load track points
228          */
229         private void callGpsBabel(boolean inWaypoints, boolean inTracks) throws Exception
230         {
231                 // Set up command to call gpsbabel
232                 String[] commands = null;
233                 if (inWaypoints && inTracks) {
234                         // Both waypoints and track points selected
235                         commands = new String[] {"gpsbabel", "-w", "-t", "-i", _formatField.getText(),
236                                 "-f", _deviceField.getText(), "-o", "gpx", "-F", "-"};
237                 }
238                 else
239                 {
240                         // Only waypoints OR track points selected
241                         commands = new String[] {"gpsbabel", "-w", "-i", _formatField.getText(),
242                                 "-f", _deviceField.getText(), "-o", "gpx", "-F", "-"};
243                         if (inTracks) {
244                                 commands[1] = "-t";
245                         }
246                 }
247
248                 String errorMessage = "";
249                 XmlHandler handler = null;
250                 Process process = Runtime.getRuntime().exec(commands);
251
252                 // Pass input stream to try to parse the xml
253                 try
254                 {
255                         XmlFileLoader xmlLoader = new XmlFileLoader(_app);
256                         SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
257                         saxParser.parse(process.getInputStream(), xmlLoader);
258                         handler = xmlLoader.getHandler();
259                         if (handler == null) {
260                                 errorMessage = "Null handler";
261                         }
262                 }
263                 catch (Exception e) {
264                         errorMessage = e.getMessage();
265                 }
266
267                 // Read the error stream to see if there's a better error message there
268                 BufferedReader r = new BufferedReader(new InputStreamReader(process.getErrorStream()));
269                 String line = null;
270                 String errorMessage2 = "";
271                 while ((line = r.readLine()) != null) {
272                         errorMessage2 += line + "\n";
273                 }
274                 // Close error stream
275                 try {
276                         r.close();
277                 } catch (Exception e) {}
278
279                 if (errorMessage2.length() > 0) {errorMessage = errorMessage2;}
280                 if (errorMessage.length() > 0) {throw new Exception(errorMessage);}
281
282                 // Send data back to app
283                 _app.informDataLoaded(handler.getFieldArray(), handler.getDataArray(),
284                         Altitude.Format.METRES, _deviceField.getText());
285         }
286 }