Ignore:
Timestamp:
2021-07-14T13:58:39+02:00 (3 years ago)
Author:
Bjoeni
Message:

fix #21019 - ask only once for photos that failed because of an ExifOverflowException

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/photo_geotagging/src/org/openstreetmap/josm/plugins/photo_geotagging/GeotaggingAction.java

    r35738 r35776  
    1212import java.io.File;
    1313import java.io.IOException;
    14 import java.lang.reflect.InvocationTargetException;
    1514import java.nio.file.Files;
    1615import java.nio.file.NoSuchFileException;
     
    4544import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
    4645import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry;
     46import org.openstreetmap.josm.gui.util.GuiHelper;
    4747import org.openstreetmap.josm.spi.preferences.Config;
    4848import org.openstreetmap.josm.tools.GBC;
    4949import org.openstreetmap.josm.tools.ImageProvider;
    50 import org.openstreetmap.josm.tools.JosmRuntimeException;
    5150import org.openstreetmap.josm.tools.Logging;
    5251import org.openstreetmap.josm.tools.Utils;
     
    211210        private boolean canceled = false;
    212211        private Boolean override_backup = null;
    213         private boolean lossy = false;
    214212
    215213        private File fileFrom;
     
    226224        }
    227225
    228         private void processEntry(ImageEntry e) throws IOException {
     226
     227        @Override
     228        protected void realRun() {
     229            List<ImageEntry> failedEntries = processEntries(images, false);
     230            if (!failedEntries.isEmpty()) {
     231                int ret = GuiHelper.runInEDTAndWaitAndReturn(() -> {
     232                    ExtendedDialog dlg = new ExtendedDialog(progressMonitor.getWindowParent(), tr("Warning"),
     233                            tr("Abort"), tr("Retry"));
     234
     235                    dlg.setButtonIcons("cancel", "dialogs/refresh")
     236                       .setIcon(JOptionPane.WARNING_MESSAGE);
     237
     238                    StringBuilder sb = new StringBuilder(trn(
     239                            "The GPS tag could not be added to the following file because there is not enough free space in the EXIF section:",
     240                            "The GPS tag could not be added to the following files because there is not enough free space in the EXIF section:",
     241                            failedEntries.size()));
     242
     243                    sb.append("<ul>");
     244                    for (int i = 0; i < failedEntries.size(); i++) {
     245                        sb.append("<li>");
     246
     247                        if (i == 5 && failedEntries.size() > i + 1) {
     248                            int remaining = failedEntries.size() - i;
     249                            sb.append("<i>")
     250                              .append(trn("({0} more file)", "({0} more files)", remaining, remaining))
     251                              .append("</i></li>");
     252                            break;
     253                        } else {
     254                            sb.append(failedEntries.get(i).getFile().getName()).append("</li>");
     255                        }
     256                    }
     257                    sb.append("</ul><br>")
     258                      .append(tr("This can likely be fixed by rewriting the entire EXIF section, however some metadata may get lost in the process.<br><br>"
     259                              + "Would you like to try again using the lossy approach?"));
     260
     261                    dlg.setContent(sb.toString())
     262                       .setDefaultButton(2)
     263                       .showDialog();
     264
     265                    return dlg.getValue();
     266                });
     267                if (ret == 2) {
     268                    processEntries(failedEntries, true);
     269                }
     270            }
     271        }
     272
     273        List<ImageEntry> processEntries(List<ImageEntry> entries, boolean lossy) {
     274            progressMonitor.subTask(tr("Writing position information to image files..."));
     275            progressMonitor.setTicksCount(entries.size());
     276            progressMonitor.setTicks(0);
     277
     278            final List<ImageEntry> exifFailedEntries = new ArrayList<>();
     279
     280            final long startTime = System.currentTimeMillis();
     281
     282            currentIndex = 0;
     283            while (currentIndex < entries.size()) {
     284                if (canceled)
     285                    return exifFailedEntries;
     286                ImageEntry e = entries.get(currentIndex);
     287                if (debug) {
     288                    System.err.print("i:" + currentIndex + " " + e.getFile().getName() + " ");
     289                }
     290                try {
     291                    processEntry(e, lossy);
     292                } catch (final IOException ioe) {
     293                    ioe.printStackTrace();
     294                    restoreFile();
     295                    if (!lossy && ioe.getCause() instanceof ExifRewriter.ExifOverflowException) {
     296                        exifFailedEntries.add(e);
     297                    } else {
     298                        int ret = GuiHelper.runInEDTAndWaitAndReturn(() -> {
     299                            ExtendedDialog dlg = new ExtendedDialog(progressMonitor.getWindowParent(),
     300                                    tr("Error"),
     301                                    tr("Abort"), tr("Retry"), tr("Ignore"));
     302                            dlg.setButtonIcons("cancel", "dialogs/refresh", "dialogs/next");
     303
     304                            String msg;
     305                            if (ioe instanceof NoSuchFileException) {
     306                                msg = tr("File not found.");
     307                            } else {
     308                                msg = ioe.toString();
     309                            }
     310
     311                            dlg.setIcon(JOptionPane.ERROR_MESSAGE)
     312                               .setContent(tr("Unable to process file ''{0}'':", e.getFile().toString()) + "<br/>" + msg)
     313                               .setDefaultButton(3)
     314                               .showDialog();
     315
     316                            return dlg.getValue();
     317                        });
     318
     319                        switch (ret) {
     320                            case 2: // retry
     321                                currentIndex--;
     322                                break;
     323                            case 3: // continue
     324                                break;
     325                            default: // abort
     326                                canceled = true;
     327                        }
     328                    }
     329                }
     330                progressMonitor.worked(1);
     331
     332                float millisecondsPerFile = (float) (System.currentTimeMillis() - startTime) / (currentIndex + 1); // currentIndex starts at 0
     333                int filesLeft = entries.size() - currentIndex - 1;
     334                String timeLeft = Utils.getDurationString((long) Math.ceil(millisecondsPerFile * filesLeft));
     335
     336                progressMonitor.subTask(tr("Writing position information to image files... Estimated time left: {0}", timeLeft));
     337
     338                if (debug) {
     339                    System.err.println("finished " + e.getFile());
     340                }
     341                currentIndex++;
     342            }
     343            return exifFailedEntries;
     344        }
     345
     346        private void processEntry(ImageEntry e, boolean lossy) throws IOException {
    229347            fileFrom = null;
    230348            fileTo = null;
     
    261379            ExifGPSTagger.setExifGPSTag(fileFrom, fileTo, e.getPos().lat(), e.getPos().lon(),
    262380                    e.getGpsTime(), e.getSpeed(), e.getElevation(), e.getExifImgDir(), lossy);
    263             lossy = false;
    264381
    265382            if (mTime != null) {
     
    270387            cleanupFiles();
    271388            e.unflagNewGpsData();
    272         }
    273 
    274         @Override
    275         protected void realRun() {
    276             progressMonitor.subTask(tr("Writing position information to image files..."));
    277             progressMonitor.setTicksCount(images.size());
    278 
    279             final long startTime = System.currentTimeMillis();
    280 
    281             currentIndex = 0;
    282             while (currentIndex < images.size()) {
    283                 if (canceled) return;
    284                 ImageEntry e = images.get(currentIndex);
    285                 if (debug) {
    286                     System.err.print("i:"+currentIndex+" "+e.getFile().getName()+" ");
    287                 }
    288                 try {
    289                     processEntry(e);
    290                 } catch (final IOException ioe) {
    291                     ioe.printStackTrace();
    292                     restoreFile();
    293                     try {
    294                         SwingUtilities.invokeAndWait(() -> {
    295                             ExtendedDialog dlg = new ExtendedDialog(progressMonitor.getWindowParent(), tr("Error"), new String[] {tr("Abort"), tr("Retry"), tr("Ignore")});
    296                             dlg.setButtonIcons("cancel", "dialogs/refresh", "dialogs/next");
    297                             String msg;
    298                             if (ioe instanceof NoSuchFileException) {
    299                                 msg = tr("File not found.");
    300                             } else {
    301                                 msg = ioe.toString();
    302                             }
    303                             boolean tmpLossy = false;
    304                             if (!lossy && ioe.getCause() instanceof ExifRewriter.ExifOverflowException) {
    305                                 tmpLossy = true;
    306                                 dlg.setIcon(JOptionPane.WARNING_MESSAGE);
    307                                 dlg.setContent(tr(
    308                                         "The GPS tag could not be added to the file \"{0}\" because there is not enough free space in the EXIF section.<br>"
    309                                                 + "This can likely be fixed by rewriting the entire EXIF section, however some metadata may get lost in the process.<br><br>"
    310                                                 + "Would you like to try again using the lossy approach?",
    311                                         e.getFile().getName()));
    312                                 dlg.setDefaultButton(2);
    313                             } else {
    314                                 dlg.setIcon(JOptionPane.ERROR_MESSAGE);
    315                                 dlg.setContent(tr("Unable to process file ''{0}'':", e.getFile().toString()) + "<br/>" + msg);
    316                                 dlg.setDefaultButton(3);
    317                             }
    318                             dlg.showDialog();
    319                             switch (dlg.getValue()) {
    320                                 case 2:  // retry
    321                                     currentIndex--;
    322                                     lossy = tmpLossy;
    323                                     break;
    324                                 case 3:  // continue
    325                                     break;
    326                                 default: // abort
    327                                     canceled = true;
    328                             }
    329                         });
    330                     } catch (InterruptedException | InvocationTargetException ex) {
    331                         throw new JosmRuntimeException(ex);
    332                     }
    333                 }
    334                 progressMonitor.worked(1);
    335 
    336                 float millisecondsPerFile = (float) (System.currentTimeMillis() - startTime)
    337                         / (currentIndex + 1); // currentIndex starts at 0
    338                 int filesLeft = images.size() - currentIndex - 1;
    339                 String timeLeft = Utils.getDurationString((long) Math.ceil(millisecondsPerFile * filesLeft));
    340                 progressMonitor.subTask(tr("Writing position information to image files... Estimated time left: {0}", timeLeft));
    341 
    342                 if (debug) {
    343                     System.err.println("finished " + e.getFile());
    344                 }
    345                 currentIndex++;
    346             }
    347389        }
    348390
Note: See TracChangeset for help on using the changeset viewer.