X-Git-Url: http://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2Fload%2FJpegLoader.java;fp=src%2Ftim%2Fprune%2Fload%2FJpegLoader.java;h=3e22eba029ccb76ce341a2fffaea6327669a28f1;hp=0000000000000000000000000000000000000000;hb=ce6f2161b8596f7018d6a76bff79bc9e571f35fd;hpb=2d8cb72e84d5cc1089ce77baf1e34ea3ea2f8465 diff --git a/src/tim/prune/load/JpegLoader.java b/src/tim/prune/load/JpegLoader.java new file mode 100644 index 0000000..3e22eba --- /dev/null +++ b/src/tim/prune/load/JpegLoader.java @@ -0,0 +1,384 @@ +package tim.prune.load; + +import java.io.File; +import java.util.TreeSet; + +import javax.swing.BoxLayout; +import javax.swing.JCheckBox; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JPanel; + +import tim.prune.App; +import tim.prune.I18nManager; +import tim.prune.config.Config; +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.Timestamp; +import tim.prune.data.TimestampLocal; +import tim.prune.data.TimestampUtc; +import tim.prune.data.UnitSetLibrary; +import tim.prune.function.Cancellable; +import tim.prune.jpeg.InternalExifLibrary; +import tim.prune.jpeg.JpegData; + +/** + * Class to manage the loading of Jpegs and dealing with the GPS data from them + */ +public class JpegLoader implements Runnable, Cancellable +{ + 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 MediaLoadProgressDialog _progressDialog = null; + private int[] _fileCounts = null; + private boolean _cancelled = false; + private LatLonRectangle _trackRectangle = null; + private TreeSet _photos = null; + + + /** + * Constructor + * @param inApp Application object to inform of photo load + * @param inParentFrame parent frame to reference for dialogs + */ + public JpegLoader(App inApp, JFrame inParentFrame) + { + _app = inApp; + _parentFrame = inParentFrame; + _fileFilter = new JpegFileFilter(); + } + + + /** + * Open the GUI to select options and start the load + * @param inRectangle track rectangle + */ + public void openDialog(LatLonRectangle inRectangle) + { + // 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 + _progressDialog = new MediaLoadProgressDialog(_parentFrame, this); + _progressDialog.show(); + // start thread for processing + new Thread(this).start(); + } + } + + /** Cancel */ + public void cancel() { + _cancelled = true; + } + + + /** + * Run method for performing tasks in separate thread + */ + public void run() + { + // Initialise arrays, errors, summaries + _fileCounts = new int[3]; // files, jpegs, gps + _photos = new TreeSet(new MediaSorter()); + File[] files = _fileChooser.getSelectedFiles(); + // Loop recursively over selected files/directories to count files + int numFiles = countFileList(files, true, _subdirCheckbox.isSelected()); + // Set up the progress bar for this number of files + _progressDialog.showProgress(0, numFiles); + _cancelled = false; + + // Process the files recursively and build lists of photos + processFileList(files, true, _subdirCheckbox.isSelected()); + _progressDialog.close(); + if (_cancelled) {return;} + + if (_fileCounts[0] == 0) + { + // No files found at all + _app.showErrorMessage("error.jpegload.dialogtitle", "error.jpegload.nofilesfound"); + } + else if (_fileCounts[1] == 0) + { + // No jpegs found + _app.showErrorMessage("error.jpegload.dialogtitle", "error.jpegload.nojpegsfound"); + } + else if (!_noExifCheckbox.isSelected() && _fileCounts[2] == 0) + { + // Need coordinates but no gps information found + _app.showErrorMessage("error.jpegload.dialogtitle", "error.jpegload.nogpsfound"); + } + else + { + // Found some photos to load - pass information back to app + _app.informPhotosLoaded(_photos); + } + } + + + /** + * Process a list of files and/or directories + * @param inFiles array of file/directories + * @param inFirstDir true if first directory + * @param inDescend true to descend to subdirectories + */ + private void processFileList(File[] inFiles, boolean inFirstDir, boolean inDescend) + { + if (inFiles == null) return; + // Loop over elements in array + for (int i=0; i