Index: applications/editors/josm/plugins/photo_geotagging/src/org/openstreetmap/josm/plugins/photo_geotagging/GeotaggingAction.java
===================================================================
--- applications/editors/josm/plugins/photo_geotagging/src/org/openstreetmap/josm/plugins/photo_geotagging/GeotaggingAction.java	(revision 33493)
+++ applications/editors/josm/plugins/photo_geotagging/src/org/openstreetmap/josm/plugins/photo_geotagging/GeotaggingAction.java	(revision 33494)
@@ -8,8 +8,9 @@
 import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
 import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
 import java.text.DecimalFormat;
 import java.util.ArrayList;
@@ -42,4 +43,5 @@
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.JosmRuntimeException;
 
 /**
@@ -113,13 +115,10 @@
         settingsPanel.add(mTimeMode, GBC.eol().insets(3,3,3,3));
 
-        setMTime.addActionListener(new ActionListener(){
-            @Override
-            public void actionPerformed(ActionEvent e) {
-                if (setMTime.isSelected()) {
-                    mTimeMode.setEnabled(true);
-                } else {
-                    mTimeMode.setSelectedIndex(0);
-                    mTimeMode.setEnabled(false);
-                }
+        setMTime.addActionListener(e -> {
+            if (setMTime.isSelected()) {
+                mTimeMode.setEnabled(true);
+            } else {
+                mTimeMode.setSelectedIndex(0);
+                mTimeMode.setEnabled(false);
             }
         });
@@ -177,4 +176,6 @@
         private File fileDelete;
 
+        private int currentIndex;
+
         public GeoTaggingRunnable(List<ImageEntry> images, boolean keep_backup, int mTimeMode) {
             super(tr("Photo Geotagging Plugin"));
@@ -183,4 +184,50 @@
             this.mTimeMode = mTimeMode;
         }
+
+        private void processEntry(ImageEntry e) throws IOException {
+            fileFrom = null;
+            fileTo = null;
+            fileDelete = null;
+
+            if (mTimeMode != 0) {
+                testMTimeReadAndWrite(e.getFile());
+            }
+
+            Long mTime = null;
+            if (mTimeMode == MTIME_MODE_GPS) {
+                // check GPS time fields, do nothing if all fails
+                Date time;
+                if (e.hasGpsTime()) {
+                    time = e.getGpsTime();
+                } else {
+                    time = e.getExifGpsTime();
+                }
+                if (time != null) {
+                    mTime = time.getTime();
+                }
+            }
+            if ( mTimeMode == MTIME_MODE_PREVIOUS_VALUE
+                 // this is also the fallback if one of the other
+                 // modes failed to determine the modification time
+                 || (mTimeMode != 0 && mTime == null)) {
+                mTime = e.getFile().lastModified();
+                if (mTime.equals(0L))
+                    throw new IOException(tr("Could not read mtime."));
+            }
+
+            chooseFiles(e.getFile());
+            if (canceled) return;
+            ExifGPSTagger.setExifGPSTag(fileFrom, fileTo, e.getPos().lat(), e.getPos().lon(),
+                    e.getGpsTime(), e.getSpeed(), e.getElevation(), e.getExifImgDir());
+
+            if (mTime != null) {
+                if (!fileTo.setLastModified(mTime))
+                    throw new IOException(tr("Could not write mtime."));
+            }
+
+            cleanupFiles();
+            e.unflagNewGpsData();
+        }
+
         @Override
         protected void realRun() {
@@ -188,71 +235,47 @@
             progressMonitor.setTicksCount(images.size());
 
-            for (int i=0; i<images.size(); ++i) {
+            currentIndex = 0;
+            while (currentIndex < images.size()) {
                 if (canceled) return;
-
-                ImageEntry e = images.get(i);
+                ImageEntry e = images.get(currentIndex);
                 if (debug) {
-                    System.err.print("i:"+i+" "+e.getFile().getName()+" ");
-                }
-
-                fileFrom = null;
-                fileTo = null;
-                fileDelete = null;
-
+                    System.err.print("i:"+currentIndex+" "+e.getFile().getName()+" ");
+                }
                 try {
-                    if (mTimeMode != 0) {
-                        testMTimeReadAndWrite(e.getFile());
-                    }
-
-                    Long mTime = null;
-                    if (mTimeMode == MTIME_MODE_GPS) {
-                        // check GPS time fields, do nothing if all fails
-                        Date time;
-                        if (e.hasGpsTime()) {
-                            time = e.getGpsTime();
-                        } else {
-                            time = e.getExifGpsTime();
-                        }
-                        if (time != null) {
-                            mTime = time.getTime();
-                        }
-                    }
-                    if ( mTimeMode == MTIME_MODE_PREVIOUS_VALUE
-                         // this is also the fallback if one of the other
-                         // modes failed to determine the modification time
-                         || (mTimeMode != 0 && mTime == null)) {
-                        mTime = e.getFile().lastModified();
-                        if (mTime.equals(0L))
-                            throw new IOException(tr("Could not read mtime."));
-                    }
-
-                    chooseFiles(e.getFile());
-                    if (canceled) return;
-                    ExifGPSTagger.setExifGPSTag(fileFrom, fileTo, e.getPos().lat(), e.getPos().lon(),
-                            e.getGpsTime(), e.getSpeed(), e.getElevation(), e.getExifImgDir());
-
-                    if (mTime != null) {
-                        if (!fileTo.setLastModified(mTime))
-                            throw new IOException(tr("Could not write mtime."));
-                    }
-
-                    cleanupFiles();
-                    e.unflagNewGpsData();
-
+                    processEntry(e);
                 } catch (final IOException ioe) {
                     ioe.printStackTrace();
-                    // need this so the dialogs don't block
-                    SwingUtilities.invokeLater(new Runnable() {
-                        @Override
-                        public void run() {
-                            JOptionPane.showMessageDialog(Main.parent, ioe.getMessage(), tr("Error"), JOptionPane.ERROR_MESSAGE);
-                        }
-                    });
-                    return;
+                    try {
+                        SwingUtilities.invokeAndWait(() -> {
+                            ExtendedDialog dlg = new ExtendedDialog(progressMonitor.getWindowParent(), tr("Error"), new String[] {tr("Abort"), tr("Retry"), tr("Ignore")});
+                            dlg.setIcon(JOptionPane.ERROR_MESSAGE);
+                            dlg.setButtonIcons("cancel", "dialogs/refresh", "dialogs/next");
+                            String msg;
+                            if (ioe instanceof NoSuchFileException) {
+                                msg = tr("File not found.");
+                            } else {
+                                msg = ioe.toString();
+                            }
+                            dlg.setContent(tr("Unable to process file ''{0}'':", e.getFile().toString()) + "<br/>" + msg);
+                            dlg.showDialog();
+                            switch (dlg.getValue()) {
+                                case 2:  // retry
+                                    currentIndex--;
+                                    break;
+                                case 3:  // continue
+                                    break;
+                                default: // abort
+                                    canceled = true;
+                            }
+                        });
+                    } catch (InterruptedException | InvocationTargetException ex) {
+                        throw new JosmRuntimeException(ex);
+                    }
                 }
                 progressMonitor.worked(1);
                 if (debug) {
-                    System.err.println("");
-                }
+                    System.err.println("finished " + e.getFile());
+                }
+                currentIndex++;
             }
         }
@@ -319,26 +342,23 @@
                 return;
             try {
-                SwingUtilities.invokeAndWait(new Runnable() {
-                    @Override
-                    public void run() {
-                        JLabel l = new JLabel(tr("<html><h3>There are old backup files in the image directory!</h3>"));
-                        l.setIcon(UIManager.getIcon("OptionPane.warningIcon"));
-                        int override = new ExtendedDialog(
-                                progressMonitor.getWindowParent(),
-                                tr("Override old backup files?"),
-                                new String[] {tr("Cancel"), tr("Keep old backups and continue"), tr("Override")})
-                            .setButtonIcons(new String[] {"cancel.png", "ok.png", "dialogs/delete.png"})
-                            .setContent(l)
-                            .setCancelButton(1)
-                            .setDefaultButton(2)
-                            .showDialog()
-                            .getValue();
-                        if (override == 2) {
-                            override_backup = false;
-                        } else if (override == 3) {
-                            override_backup = true;
-                        } else {
-                            canceled = true;
-                        }
+                SwingUtilities.invokeAndWait(() -> {
+                    JLabel l = new JLabel(tr("<html><h3>There are old backup files in the image directory!</h3>"));
+                    l.setIcon(UIManager.getIcon("OptionPane.warningIcon"));
+                    int override = new ExtendedDialog(
+                            progressMonitor.getWindowParent(),
+                            tr("Override old backup files?"),
+                            new String[] {tr("Cancel"), tr("Keep old backups and continue"), tr("Override")})
+                        .setButtonIcons(new String[] {"cancel.png", "ok.png", "dialogs/delete.png"})
+                        .setContent(l)
+                        .setCancelButton(1)
+                        .setDefaultButton(2)
+                        .showDialog()
+                        .getValue();
+                    if (override == 2) {
+                        override_backup = false;
+                    } else if (override == 3) {
+                        override_backup = true;
+                    } else {
+                        canceled = true;
                     }
                 });
