]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/load/JpegLoader.java
Version 8, September 2009
[GpsPrune.git] / tim / prune / load / JpegLoader.java
index cab6c565524bc5a48bcab9b9e4b80b56b36660ed..194f2b7f08b83a09d2a11b72fb2ac4e48f77038c 100644 (file)
@@ -13,18 +13,18 @@ import javax.swing.JDialog;
 import javax.swing.JFileChooser;
 import javax.swing.JFrame;
 import javax.swing.JLabel;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JProgressBar;
 
 import tim.prune.App;
+import tim.prune.Config;
 import tim.prune.I18nManager;
 import tim.prune.data.Altitude;
 import tim.prune.data.DataPoint;
+import tim.prune.data.LatLonRectangle;
 import tim.prune.data.Latitude;
 import tim.prune.data.Longitude;
 import tim.prune.data.Photo;
-import tim.prune.data.PhotoStatus;
 import tim.prune.data.Timestamp;
 import tim.prune.drew.jpeg.ExifReader;
 import tim.prune.drew.jpeg.JpegData;
@@ -39,13 +39,16 @@ public class JpegLoader implements Runnable
        private App _app = null;
        private JFrame _parentFrame = null;
        private JFileChooser _fileChooser = null;
+       private GenericFileFilter _fileFilter = null;
        private JCheckBox _subdirCheckbox = null;
        private JCheckBox _noExifCheckbox = null;
+       private JCheckBox _outsideAreaCheckbox = null;
        private JDialog _progressDialog   = null;
        private JProgressBar _progressBar = null;
        private int[] _fileCounts = null;
        private boolean _cancelled = false;
-       private TreeSet _photos = null;
+       private LatLonRectangle _trackRectangle = null;
+       private TreeSet<Photo> _photos = null;
 
 
        /**
@@ -57,31 +60,46 @@ public class JpegLoader implements Runnable
        {
                _app = inApp;
                _parentFrame = inParentFrame;
+               String[] fileTypes = {"jpg", "jpe", "jpeg"};
+               _fileFilter = new GenericFileFilter("filetype.jpeg", fileTypes);
        }
 
 
        /**
         * Open the GUI to select options and start the load
+        * @param inRectangle track rectangle
         */
-       public void openDialog()
+       public void openDialog(LatLonRectangle inRectangle)
        {
-               // TODO: Allow restriction of load area, either to current track or manually-entered range
+               // Create file chooser if necessary
                if (_fileChooser == null)
                {
                        _fileChooser = new JFileChooser();
                        _fileChooser.setMultiSelectionEnabled(true);
                        _fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
+                       _fileChooser.setFileFilter(_fileFilter);
                        _fileChooser.setDialogTitle(I18nManager.getText("menu.file.addphotos"));
                        _subdirCheckbox = new JCheckBox(I18nManager.getText("dialog.jpegload.subdirectories"));
                        _subdirCheckbox.setSelected(true);
                        _noExifCheckbox = new JCheckBox(I18nManager.getText("dialog.jpegload.loadjpegswithoutcoords"));
                        _noExifCheckbox.setSelected(true);
+                       _outsideAreaCheckbox = new JCheckBox(I18nManager.getText("dialog.jpegload.loadjpegsoutsidearea"));
+                       _outsideAreaCheckbox.setSelected(true);
                        JPanel panel = new JPanel();
                        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
                        panel.add(_subdirCheckbox);
                        panel.add(_noExifCheckbox);
+                       panel.add(_outsideAreaCheckbox);
                        _fileChooser.setAccessory(panel);
+                       // start from directory in config if already set by other operations
+                       String configDir = Config.getConfigString(Config.KEY_PHOTO_DIR);
+                       if (configDir == null) {configDir = Config.getConfigString(Config.KEY_TRACK_DIR);}
+                       if (configDir != null) {_fileChooser.setCurrentDirectory(new File(configDir));}
                }
+               // enable/disable track checkbox
+               _trackRectangle = inRectangle;
+               _outsideAreaCheckbox.setEnabled(_trackRectangle != null && !_trackRectangle.isEmpty());
+               // Show file dialog to choose file / directory(ies)
                if (_fileChooser.showOpenDialog(_parentFrame) == JFileChooser.APPROVE_OPTION)
                {
                        // Bring up dialog before starting
@@ -117,7 +135,7 @@ public class JpegLoader implements Runnable
                panel.add(cancelButton);
                _progressDialog.getContentPane().add(panel);
                _progressDialog.pack();
-               _progressDialog.show();
+               _progressDialog.setVisible(true);
        }
 
 
@@ -128,7 +146,7 @@ public class JpegLoader implements Runnable
        {
                // Initialise arrays, errors, summaries
                _fileCounts = new int[4]; // files, jpegs, exifs, gps
-               _photos = new TreeSet(new PhotoSorter());
+               _photos = new TreeSet<Photo>(new PhotoSorter());
                File[] files = _fileChooser.getSelectedFiles();
                // Loop recursively over selected files/directories to count files
                int numFiles = countFileList(files, true, _subdirCheckbox.isSelected());
@@ -139,7 +157,7 @@ public class JpegLoader implements Runnable
 
                // Process the files recursively and build lists of photos
                processFileList(files, true, _subdirCheckbox.isSelected());
-               _progressDialog.hide();
+               _progressDialog.setVisible(false);
                if (_cancelled) {return;}
 
                //System.out.println("Finished - counts are: " + _fileCounts[0] + ", " + _fileCounts[1]
@@ -147,32 +165,26 @@ public class JpegLoader implements Runnable
                if (_fileCounts[0] == 0)
                {
                        // No files found at all
-                       JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.jpegload.nofilesfound"),
-                               I18nManager.getText("error.jpegload.dialogtitle"), JOptionPane.ERROR_MESSAGE);
+                       _app.showErrorMessage("error.jpegload.dialogtitle", "error.jpegload.nofilesfound");
                }
                else if (_fileCounts[1] == 0)
                {
                        // No jpegs found
-                       JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.jpegload.nojpegsfound"),
-                               I18nManager.getText("error.jpegload.dialogtitle"), JOptionPane.ERROR_MESSAGE);
+                       _app.showErrorMessage("error.jpegload.dialogtitle", "error.jpegload.nojpegsfound");
                }
                else if (!_noExifCheckbox.isSelected() && _fileCounts[2] == 0)
                {
                        // Need coordinates but no exif found
-                       JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.jpegload.noexiffound"),
-                               I18nManager.getText("error.jpegload.dialogtitle"), JOptionPane.ERROR_MESSAGE);
+                       _app.showErrorMessage("error.jpegload.dialogtitle", "error.jpegload.noexiffound");
                }
                else if (!_noExifCheckbox.isSelected() && _fileCounts[3] == 0)
                {
                        // Need coordinates but no gps information found
-                       JOptionPane.showMessageDialog(_parentFrame, I18nManager.getText("error.jpegload.nogpsfound"),
-                               I18nManager.getText("error.jpegload.dialogtitle"), JOptionPane.ERROR_MESSAGE);
+                       _app.showErrorMessage("error.jpegload.dialogtitle", "error.jpegload.nogpsfound");
                }
                else
                {
-                       // Found some photos to load
-                       // TODO: Load jpeg information into dialog for confirmation?
-                       // Pass information back to app
+                       // Found some photos to load - pass information back to app
                        _app.informPhotosLoaded(_photos);
                }
        }
@@ -231,7 +243,8 @@ public class JpegLoader implements Runnable
                _progressBar.repaint();
 
                // Check whether filename corresponds with accepted filenames
-               if (!acceptPhotoFilename(inFile.getName())) {return;}
+               if (!_fileFilter.acceptFilename(inFile.getName())) {return;}
+               // If it's a Jpeg, we can use ExifReader to get coords, otherwise we could try exiftool (if it's installed)
 
                // Create Photo object
                Photo photo = new Photo(inFile);
@@ -251,8 +264,9 @@ public class JpegLoader implements Runnable
                                // Make DataPoint and attach to Photo
                                DataPoint point = createDataPoint(jpegData);
                                point.setPhoto(photo);
+                               point.setSegmentStart(true);
                                photo.setDataPoint(point);
-                               photo.setOriginalStatus(PhotoStatus.TAGGED);
+                               photo.setOriginalStatus(Photo.Status.TAGGED);
                                _fileCounts[3]++;
                        }
                        // Use exif timestamp if gps timestamp not available
@@ -265,17 +279,13 @@ public class JpegLoader implements Runnable
                catch (JpegException jpe) { // don't list errors, just count them
                }
                // Use file timestamp if exif timestamp isn't available
-               if (photo.getTimestamp() == null)
-               {
+               if (photo.getTimestamp() == null) {
                        photo.setTimestamp(new Timestamp(inFile.lastModified()));
-                       //System.out.println("No exif, using timestamp from file: " + inFile.lastModified() + " -> " + photo.getTimestamp().getText());
                }
-               else
-               {
-                       //System.out.println("timestamp from file = " + photo.getTimestamp().getText());
-               }
-               // Add the photo if it's got a point or if pointless photos should be added
-               if (photo.getDataPoint() != null || _noExifCheckbox.isSelected())
+               // Check the criteria for adding the photo - check whether the photo has coordinates and if so if they're within the rectangle
+               if ( (photo.getDataPoint() != null || _noExifCheckbox.isSelected())
+                       && (photo.getDataPoint() == null || !_outsideAreaCheckbox.isEnabled()
+                               || _outsideAreaCheckbox.isSelected() || _trackRectangle.containsPoint(photo.getDataPoint())))
                {
                        _photos.add(photo);
                }
@@ -300,6 +310,11 @@ public class JpegLoader implements Runnable
                                File file = inFiles[i];
                                if (file.exists() && file.canRead())
                                {
+                                       // Store first directory in config for later
+                                       if (i == 0 && inFirstDir) {
+                                               File workingDir = file.isDirectory()?file:file.getParentFile();
+                                               Config.setConfigString(Config.KEY_PHOTO_DIR, workingDir.getAbsolutePath());
+                                       }
                                        // Check whether it's a file or a directory
                                        if (file.isFile())
                                        {
@@ -333,7 +348,7 @@ public class JpegLoader implements Runnable
                Altitude altitude = null;
                if (inData.getAltitude() != null)
                {
-                       altitude = new Altitude(inData.getAltitude().intValue(), Altitude.FORMAT_METRES);
+                       altitude = new Altitude(inData.getAltitude().intValue(), Altitude.Format.METRES);
                }
                return new DataPoint(latitude, longitude, altitude);
        }
@@ -393,34 +408,4 @@ public class JpegLoader implements Runnable
                catch (NumberFormatException nfe) {}
                return stamp;
        }
-
-
-       /**
-        * Check whether to accept the given filename
-        * @param inName name of file
-        * @return true if accepted, false otherwise
-        */
-       private static boolean acceptPhotoFilename(String inName)
-       {
-               if (inName != null && inName.length() > 4)
-               {
-                       // Check for three-character file extensions jpg and jpe
-                       String lastFour = inName.substring(inName.length() - 4).toLowerCase();
-                       if (lastFour.equals(".jpg") || lastFour.equals(".jpe"))
-                       {
-                               return true;
-                       }
-                       // If not found, check for file extension jpeg
-                       if (inName.length() > 5)
-                       {
-                               String lastFive = inName.substring(inName.length() - 5).toLowerCase();
-                               if (lastFive.equals(".jpeg"))
-                               {
-                                       return true;
-                               }
-                       }
-               }
-               // Not matched so don't accept
-               return false;
-       }
 }