diff --git a/source/net/filebot/ui/rename/ConflictDialog.java b/source/net/filebot/ui/rename/ConflictDialog.java index e8ac33e9..7abee58f 100644 --- a/source/net/filebot/ui/rename/ConflictDialog.java +++ b/source/net/filebot/ui/rename/ConflictDialog.java @@ -15,7 +15,6 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -30,81 +29,15 @@ import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; -import javax.swing.SwingUtilities; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import net.filebot.ResourceManager; -import net.filebot.StandardRenameAction; import net.filebot.UserFiles; import net.miginfocom.swing.MigLayout; class ConflictDialog extends JDialog { - public static void main(String[] args) { - SwingUtilities.invokeLater(() -> { - File s = new File(args[0]); - File d = new File(args[1]); - - Map map = new HashMap<>(); - map.put(s, d); - - Map check = ConflictDialog.check(null, map); - System.out.println(check); - System.exit(0); - }); - } - - public static Map check(Component parent, Map renameMap) { - List conflicts = new ArrayList(); - - // sanity checks - Set destFiles = new HashSet(); - - renameMap.forEach((from, to) -> { - List issues = new ArrayList(); - - // resolve relative paths - to = resolve(from, to); - - // output files must have a valid file extension - if (getExtension(to) == null && to.isFile()) { - issues.add("Missing extension"); - } - - // one file per unique output path - if (!destFiles.add(to)) { - issues.add("Duplicate destination path"); - } - - // check if destination path already exists - if (to.exists() && !to.equals(from)) { - issues.add("File already exists"); - } - - if (issues.size() > 0) { - conflicts.add(new Conflict(from, to, issues)); - } - }); - - if (conflicts.isEmpty()) { - return renameMap; - } - - ConflictDialog dialog = new ConflictDialog(getWindow(parent), conflicts); - dialog.setVisible(true); - - if (dialog.cancel()) { - return emptyMap(); - } - - // exclude conflicts from rename map - for (Conflict it : dialog.getConflicts()) { - renameMap.remove(it.source); - } - return renameMap; - } - private ConflictTableModel model = new ConflictTableModel(); private boolean cancel = true; @@ -168,7 +101,7 @@ class ConflictDialog extends JDialog { if (c.destination.exists()) { try { - StandardRenameAction.trash(c.destination); + UserFiles.trash(c.destination); } catch (Exception e) { return new Conflict(c.source, c.destination, singletonList(e.getMessage())); } @@ -316,4 +249,55 @@ class ConflictDialog extends JDialog { } } + public static boolean check(Component parent, Map renameMap) { + List conflicts = new ArrayList(); + + // sanity checks + Set destFiles = new HashSet(); + + renameMap.forEach((from, to) -> { + List issues = new ArrayList(); + + // resolve relative paths + to = resolve(from, to); + + // output files must have a valid file extension + if (getExtension(to) == null && to.isFile()) { + issues.add("Missing extension"); + } + + // one file per unique output path + if (!destFiles.add(to)) { + issues.add("Duplicate destination path"); + } + + // check if destination path already exists + if (to.exists() && !to.equals(from)) { + issues.add("File already exists"); + } + + if (issues.size() > 0) { + conflicts.add(new Conflict(from, to, issues)); + } + }); + + if (conflicts.isEmpty()) { + return true; + } + + ConflictDialog dialog = new ConflictDialog(getWindow(parent), conflicts); + dialog.setLocation(getOffsetLocation(dialog.getOwner())); + dialog.setVisible(true); + + if (dialog.cancel()) { + return false; + } + + // exclude conflicts from rename map + for (Conflict it : dialog.getConflicts()) { + renameMap.remove(it.source); + } + return true; + } + } diff --git a/source/net/filebot/ui/rename/RenameAction.java b/source/net/filebot/ui/rename/RenameAction.java index 169ab05b..35c9510f 100644 --- a/source/net/filebot/ui/rename/RenameAction.java +++ b/source/net/filebot/ui/rename/RenameAction.java @@ -3,7 +3,6 @@ package net.filebot.ui.rename; import static java.util.Arrays.*; import static java.util.Collections.*; import static java.util.stream.Collectors.*; -import static javax.swing.JOptionPane.*; import static net.filebot.Logging.*; import static net.filebot.Settings.*; import static net.filebot.media.MediaDetection.*; @@ -12,16 +11,11 @@ import static net.filebot.util.ExceptionUtilities.*; import static net.filebot.util.FileUtilities.*; import static net.filebot.util.ui.SwingUI.*; -import java.awt.Dimension; import java.awt.Window; import java.awt.event.ActionEvent; import java.io.File; -import java.io.IOException; import java.util.AbstractList; -import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -36,14 +30,12 @@ import java.util.logging.Level; import java.util.stream.Stream; import javax.swing.AbstractAction; -import javax.swing.JList; -import javax.swing.JOptionPane; -import javax.swing.JScrollPane; import net.filebot.HistorySpooler; import net.filebot.NativeRenameAction; import net.filebot.ResourceManager; import net.filebot.StandardRenameAction; +import net.filebot.UserFiles; import net.filebot.mac.MacAppUtilities; import net.filebot.similarity.Match; import net.filebot.util.ui.ProgressMonitor; @@ -76,7 +68,8 @@ class RenameAction extends AbstractAction { try { Window window = getWindow(evt.getSource()); withWaitCursor(window, () -> { - Map renameMap = checkRenamePlan(validate(model.getRenameMap(), window), window); + Map renameMap = validate(model.getRenameMap(), window); + if (renameMap.isEmpty()) { return; } @@ -183,7 +176,7 @@ class RenameAction extends AbstractAction { try { for (File file : deleteFiles) { if (file.exists()) { - StandardRenameAction.trash(file); + UserFiles.trash(file); } } } catch (Throwable e) { @@ -191,101 +184,43 @@ class RenameAction extends AbstractAction { } } - private Map checkRenamePlan(List> renamePlan, Window parent) throws IOException { - // ask for user permissions to output paths - if (isMacSandbox()) { - if (!MacAppUtilities.askUnlockFolders(parent, renamePlan.stream().flatMap(e -> Stream.of(e.getKey(), resolve(e.getKey(), e.getValue()))).map(f -> new File(f.getAbsolutePath())).collect(toList()))) { - return emptyMap(); - } - } + private Map validate(Map renameMap, Window parent) { + // rename map values as modifiable list + List destinationPathView = new AbstractList() { - // build rename map and perform some sanity checks - Map renameMap = new HashMap(); - Set destinationFiles = new HashSet(); - List issues = new ArrayList(); - - for (Entry mapping : renamePlan) { - File source = mapping.getKey(); - File destination = resolve(source, mapping.getValue()); - - try { - if (renameMap.containsKey(source)) - throw new IllegalArgumentException("Duplicate input path: " + source.getPath()); - - if (destinationFiles.contains(destination)) - throw new IllegalArgumentException("Duplicate output path: " + mapping.getValue()); - - if (destination.exists() && !resolve(mapping.getKey(), mapping.getValue()).equals(mapping.getKey())) - throw new IllegalArgumentException("File already exists: " + mapping.getValue().getPath()); - - if (getExtension(destination) == null && destination.isFile()) - throw new IllegalArgumentException("Missing extension: " + mapping.getValue().getPath()); - - // use original mapping values - renameMap.put(mapping.getKey(), mapping.getValue()); - destinationFiles.add(destination); - } catch (Exception e) { - issues.add(e.getMessage()); - } - } - - if (issues.size() > 0) { - String text = "These files will be ignored. Do you want to continue?"; - JList issuesComponent = new JList(issues.toArray()) { - - @Override - public Dimension getPreferredScrollableViewportSize() { - // adjust component size - return new Dimension(80, 80); - } - }; - Object[] message = new Object[] { text, new JScrollPane(issuesComponent) }; - String[] actions = new String[] { "Continue", "Cancel" }; - JOptionPane pane = new JOptionPane(message, PLAIN_MESSAGE, YES_NO_OPTION, null, actions, actions[1]); - - // display option dialog - pane.createDialog(getWindow(parent), "Conflicting Files").setVisible(true); - - if (pane.getValue() != actions[0]) { - return emptyMap(); - } - } - - return renameMap; - } - - private List> validate(Map renameMap, Window parent) { - List> source = new ArrayList>(renameMap.size()); - - for (Entry entry : renameMap.entrySet()) { - source.add(new SimpleEntry(entry.getKey(), new File(entry.getValue()))); - } - - List destinationFileNameView = new AbstractList() { + private File[] keyIndex = renameMap.keySet().toArray(new File[0]); @Override - public File get(int index) { - return source.get(index).getValue(); + public File get(int i) { + return renameMap.get(keyIndex[i]); } @Override - public File set(int index, File name) { - return source.get(index).setValue(name); + public File set(int i, File value) { + return renameMap.put(keyIndex[i], value); } @Override public int size() { - return source.size(); + return keyIndex.length; } }; - if (ValidateDialog.validate(parent, destinationFileNameView)) { - // names have been validated via view - return source; + if (ValidateDialog.validate(parent, destinationPathView)) { + // ask for user permissions for output folders so we can check them + if (isMacSandbox()) { + if (!MacAppUtilities.askUnlockFolders(parent, renameMap.entrySet().stream().flatMap(e -> Stream.of(e.getKey(), resolve(e.getKey(), e.getValue()))).collect(toList()))) { + return emptyMap(); + } + } + + if (ConflictDialog.check(parent, renameMap)) { + return renameMap; + } } // return empty list if validation was cancelled - return emptyList(); + return emptyMap(); } protected static class StandardRenameWorker implements ProgressWorker> { diff --git a/source/net/filebot/ui/rename/RenameModel.java b/source/net/filebot/ui/rename/RenameModel.java index d28141f0..bd206ec9 100644 --- a/source/net/filebot/ui/rename/RenameModel.java +++ b/source/net/filebot/ui/rename/RenameModel.java @@ -73,8 +73,8 @@ public class RenameModel extends MatchModel { this.preserveExtension = preserveExtension; } - public Map getRenameMap() { - Map map = new LinkedHashMap(); + public Map getRenameMap() { + Map map = new LinkedHashMap(); for (int i = 0; i < names.size(); i++) { if (hasComplement(i)) { @@ -104,7 +104,7 @@ public class RenameModel extends MatchModel { } // insert mapping - if (map.put(source, destination.toString()) != null) { + if (map.put(source, new File(destination.toString())) != null) { throw new IllegalStateException("Duplicate source file: " + source.getName()); } }